diff --git a/README.md b/README.md
index 2b8d208b..3d93ece5 100644
--- a/README.md
+++ b/README.md
@@ -23,7 +23,7 @@ Your goal is to produce shapes by cutting, rotating, merging and painting parts
## Building
- Make sure `ffmpeg` is on your path
-- Install Node.js and Yarn
+- Install Node.js (v16.0 or earlier) and Yarn
- Install Java (required for textures)
- Run `yarn` in the root folder
- Cd into `gulp` folder
diff --git a/gulp/webpack.config.js b/gulp/webpack.config.js
index c696d2bd..3c07d7cc 100644
--- a/gulp/webpack.config.js
+++ b/gulp/webpack.config.js
@@ -97,7 +97,6 @@ module.exports = ({ watch = false, standalone = false, chineseVersion = false, w
loader: path.resolve(__dirname, "mod.js"),
},
],
- ],
},
{
test: /\.worker\.js$/,
diff --git a/mod_examples/README.md b/mod_examples/README.md
index c0b101e4..b8e501c8 100644
--- a/mod_examples/README.md
+++ b/mod_examples/README.md
@@ -50,7 +50,7 @@ To get into shapez.io modding, I highly recommend checking out all of the exampl
| [usage_statistics.js](usage_statistics.js) | Displays a percentage on every building showing its utilization | Adding a new component, Adding a new GameSystem, Drawing within a GameSystem, Modifying builtin buildings, Adding custom game logic |
| [new_item_type.js](new_item_type.js) | Adds a new type of items to the map (fluids) | Adding a new item type, modifying map generation |
| [buildings_have_cost.js](buildings_have_cost.js) | Adds a new currency, and belts cost 1 of that currency | Extending and replacing builtin methods, Adding CSS and custom sprites |
-| [mirrored_cutter.js](mirrored_cutter.js) | Adds a mirorred variant of the cutter | Adding a new variant to existing buildings |
+| [mirrored_cutter.js](mirrored_cutter.js) | Adds a mirrored variant of the cutter | Adding a new variant to existing buildings |
### Creating new sprites
diff --git a/mod_examples/class_extensions.js b/mod_examples/class_extensions.js
index 8647fd45..ace5aae9 100644
--- a/mod_examples/class_extensions.js
+++ b/mod_examples/class_extensions.js
@@ -15,9 +15,9 @@ const BeltExtension = ({ $super, $old }) => ({
return !$old.getShowWiresLayerPreview();
},
- getIsReplaceable() {
+ getIsReplaceable(variant, rotationVariant) {
// Instead of super, use $super
- return $super.getIsReplaceable.call(this);
+ return $super.getIsReplaceable.call(this, variant, rotationVariant);
},
getIsRemoveable() {
diff --git a/mod_examples/new_item_type.js b/mod_examples/new_item_type.js
index 3f47d4d2..104ef0a0 100644
--- a/mod_examples/new_item_type.js
+++ b/mod_examples/new_item_type.js
@@ -87,7 +87,7 @@ class FluidItem extends shapez.BaseItem {
* @param {number} diameter
* @param {DrawParameters} parameters
*/
- drawItemCenteredClipped(x, y, parameters, diameter = globalConfig.defaultItemDiameter) {
+ drawItemCenteredClipped(x, y, parameters, diameter = shapez.globalConfig.defaultItemDiameter) {
const realDiameter = diameter * 0.6;
if (!this.cachedSprite) {
this.cachedSprite = shapez.Loader.getSprite(`sprites/fluids/${this.fluidType}.png`);
@@ -120,19 +120,19 @@ class Mod extends shapez.Mod {
this.modInterface.registerSprite("sprites/fluids/water.png", RESOURCES["water.png"]);
// Make the item spawn on the map
- this.modInterface.runAfterMethod(
- shapez.MapChunk,
- "generatePatches",
- function ({ rng, chunkCenter, distanceToOriginInChunks }) {
- // Generate a simple patch
- // ALWAYS use rng and NEVER use Math.random() otherwise the map will look different
- // every time you resume the game
- if (rng.next() > 0.8) {
- const fluidType = rng.choice(Array.from(Object.keys(enumFluidType)));
- this.internalGeneratePatch(rng, 4, FLUID_ITEM_SINGLETONS[fluidType]);
- }
+ this.modInterface.runAfterMethod(shapez.MapChunk, "generatePatches", function ({
+ rng,
+ chunkCenter,
+ distanceToOriginInChunks,
+ }) {
+ // Generate a simple patch
+ // ALWAYS use rng and NEVER use Math.random() otherwise the map will look different
+ // every time you resume the game
+ if (rng.next() > 0.8) {
+ const fluidType = rng.choice(Array.from(Object.keys(enumFluidType)));
+ this.internalGeneratePatch(rng, 4, FLUID_ITEM_SINGLETONS[fluidType]);
}
- );
+ });
this.modInterface.registerItem(FluidItem, itemData => FLUID_ITEM_SINGLETONS[itemData]);
}
diff --git a/src/js/changelog.js b/src/js/changelog.js
index 05c7395c..6640dd9e 100644
--- a/src/js/changelog.js
+++ b/src/js/changelog.js
@@ -1,9 +1,10 @@
export const CHANGELOG = [
{
- version: "1.5.0",
- date: "unreleased",
+ version: "1.5.1",
+ date: "25.02.2022",
entries: [
- "This version adds an official modloader! You can now load mods by placing it in the mods/ folder of the game.",
+ "This version adds an official modloader! You can now load mods by extracting them and placing the .js file in the mods/ folder of the game.",
+ "Mods can be found here",
"When holding shift while placing a belt, the indicator now becomes red when crossing buildings",
"Lots of performance improvements, leading to up to 50% more FPS",
],
diff --git a/src/js/core/game_state.js b/src/js/core/game_state.js
index b08bef77..fb08e28d 100644
--- a/src/js/core/game_state.js
+++ b/src/js/core/game_state.js
@@ -211,6 +211,7 @@ export class GameState {
/**
* Should return the html code of the state.
* @returns {string}
+ * @abstract
*/
getInnerHTML() {
abstract;
diff --git a/src/js/core/query_parameters.js b/src/js/core/query_parameters.js
index 7837acb5..b3dab1b3 100644
--- a/src/js/core/query_parameters.js
+++ b/src/js/core/query_parameters.js
@@ -3,20 +3,8 @@ const options = queryString.parse(location.search);
export let queryParamOptions = {
embedProvider: null,
- fullVersion: false,
- sandboxMode: false,
};
if (options.embed) {
queryParamOptions.embedProvider = options.embed;
}
-
-// Allow testing full version outside of standalone
-if (options.fullVersion && !G_IS_RELEASE) {
- queryParamOptions.fullVersion = true;
-}
-
-// Allow testing full version outside of standalone
-if (options.sandboxMode && !G_IS_RELEASE) {
- queryParamOptions.sandboxMode = true;
-}
diff --git a/src/js/core/rectangle.js b/src/js/core/rectangle.js
index bd3421d9..e2c85082 100644
--- a/src/js/core/rectangle.js
+++ b/src/js/core/rectangle.js
@@ -268,7 +268,7 @@ export class Rectangle {
}
/**
- * Returns if hte rectangle contains the given point
+ * Returns if the rectangle contains the given point
* @param {number} x
* @param {number} y
* @returns {boolean}
diff --git a/src/js/core/restriction_manager.js b/src/js/core/restriction_manager.js
index c899b494..3ca30597 100644
--- a/src/js/core/restriction_manager.js
+++ b/src/js/core/restriction_manager.js
@@ -84,11 +84,6 @@ export class RestrictionManager extends ReadWriteProxy {
return false;
}
- if (queryParamOptions.fullVersion) {
- // Full version is activated via flag
- return false;
- }
-
if (queryParamOptions.embedProvider === "gamedistribution") {
// also full version on gamedistribution
return false;
diff --git a/src/js/core/sprites.js b/src/js/core/sprites.js
index 51032e4e..d568f994 100644
--- a/src/js/core/sprites.js
+++ b/src/js/core/sprites.js
@@ -11,6 +11,7 @@ export class BaseSprite {
/**
* Returns the raw handle
* @returns {HTMLImageElement|HTMLCanvasElement}
+ * @abstract
*/
getRawTexture() {
abstract;
diff --git a/src/js/game/base_item.js b/src/js/game/base_item.js
index f6ed1672..a6b38a08 100644
--- a/src/js/game/base_item.js
+++ b/src/js/game/base_item.js
@@ -29,6 +29,7 @@ export class BaseItem extends BasicSerializableObject {
/**
* Returns a string id of the item
* @returns {string}
+ * @abstract
*/
getAsCopyableKey() {
abstract;
@@ -49,9 +50,9 @@ export class BaseItem extends BasicSerializableObject {
/**
* Override for custom comparison
- * @abstract
* @param {BaseItem} other
* @returns {boolean}
+ * @abstract
*/
equalsImpl(other) {
abstract;
@@ -62,6 +63,7 @@ export class BaseItem extends BasicSerializableObject {
* Draws the item to a canvas
* @param {CanvasRenderingContext2D} context
* @param {number} size
+ * @abstract
*/
drawFullSizeOnCanvas(context, size) {
abstract;
@@ -86,6 +88,7 @@ export class BaseItem extends BasicSerializableObject {
* @param {number} y
* @param {DrawParameters} parameters
* @param {number=} diameter
+ * @abstract
*/
drawItemCenteredImpl(x, y, parameters, diameter = globalConfig.defaultItemDiameter) {
abstract;
diff --git a/src/js/game/belt_path.js b/src/js/game/belt_path.js
index bb59b19b..6cda9f22 100644
--- a/src/js/game/belt_path.js
+++ b/src/js/game/belt_path.js
@@ -1526,7 +1526,17 @@ export class BeltPath extends BasicSerializableObject {
const sprite = this.root.buffers.getForKey({
key: "beltpaths",
- subKey: "stack-" + directionProp + "-" + dpi + "-" + stack.length + firstItem[1].serialize(),
+ subKey:
+ "stack-" +
+ directionProp +
+ "-" +
+ dpi +
+ "#" +
+ stack.length +
+ "#" +
+ firstItem[1].getItemType() +
+ "#" +
+ firstItem[1].serialize(),
dpi,
w: dimensions.x,
h: dimensions.y,
diff --git a/src/js/game/component.js b/src/js/game/component.js
index cff14d62..9e1b63f4 100644
--- a/src/js/game/component.js
+++ b/src/js/game/component.js
@@ -4,6 +4,7 @@ export class Component extends BasicSerializableObject {
/**
* Returns the components unique id
* @returns {string}
+ * @abstract
*/
static getId() {
abstract;
diff --git a/src/js/game/entity.js b/src/js/game/entity.js
index 3010f067..9acaf26b 100644
--- a/src/js/game/entity.js
+++ b/src/js/game/entity.js
@@ -224,6 +224,7 @@ export class Entity extends BasicSerializableObject {
/**
* override, should draw the entity
* @param {DrawParameters} parameters
+ * @abstract
*/
drawImpl(parameters) {
abstract;
diff --git a/src/js/game/game_mode.js b/src/js/game/game_mode.js
index 5414306c..2c4527e3 100644
--- a/src/js/game/game_mode.js
+++ b/src/js/game/game_mode.js
@@ -144,6 +144,7 @@ export class GameMode extends BasicSerializableObject {
/**
* @param {number} w
* @param {number} h
+ * @abstract
*/
adjustZone(w = 0, h = 0) {
abstract;
diff --git a/src/js/game/hud/base_hud_part.js b/src/js/game/hud/base_hud_part.js
index 84b6d619..91b3fd3a 100644
--- a/src/js/game/hud/base_hud_part.js
+++ b/src/js/game/hud/base_hud_part.js
@@ -25,6 +25,7 @@ export class BaseHUDPart {
/**
* Should initialize the element, called *after* the elements have been created
+ * @abstract
*/
initialize() {
abstract;
diff --git a/src/js/game/hud/parts/building_placer_logic.js b/src/js/game/hud/parts/building_placer_logic.js
index 7ed412f6..23ac6df3 100644
--- a/src/js/game/hud/parts/building_placer_logic.js
+++ b/src/js/game/hud/parts/building_placer_logic.js
@@ -192,7 +192,7 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart {
const metaBuilding = this.currentMetaBuilding.get();
return (
metaBuilding &&
- metaBuilding.getHasDirectionLockAvailable() &&
+ metaBuilding.getHasDirectionLockAvailable(this.currentVariant.get()) &&
this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.lockBeltDirection).pressed
);
}
diff --git a/src/js/game/hud/parts/keybinding_overlay.js b/src/js/game/hud/parts/keybinding_overlay.js
index 2384ab84..0a050484 100644
--- a/src/js/game/hud/parts/keybinding_overlay.js
+++ b/src/js/game/hud/parts/keybinding_overlay.js
@@ -49,7 +49,7 @@ export class HUDKeybindingOverlay extends BaseHUDPart {
!this.mapOverviewActive &&
placer &&
placer.currentMetaBuilding.get() &&
- placer.currentMetaBuilding.get().getHasDirectionLockAvailable()
+ placer.currentMetaBuilding.get().getHasDirectionLockAvailable(placer.currentVariant.get())
);
}
diff --git a/src/js/game/item_resolver.js b/src/js/game/item_resolver.js
index ff91b0a3..3e7c87af 100644
--- a/src/js/game/item_resolver.js
+++ b/src/js/game/item_resolver.js
@@ -16,7 +16,7 @@ export function itemResolverSingleton(root, data) {
const itemData = data.data;
if (MODS_ADDITIONAL_ITEMS[itemType]) {
- return MODS_ADDITIONAL_ITEMS[itemType](itemData);
+ return MODS_ADDITIONAL_ITEMS[itemType](itemData, root);
}
switch (itemType) {
diff --git a/src/js/game/logic.js b/src/js/game/logic.js
index 0e915fea..3fdc871e 100644
--- a/src/js/game/logic.js
+++ b/src/js/game/logic.js
@@ -72,8 +72,13 @@ export class GameLogic {
// Check if there is any direct collision
const otherEntity = this.root.map.getLayerContentXY(x, y, entity.layer);
if (otherEntity) {
- const metaClass = otherEntity.components.StaticMapEntity.getMetaBuilding();
- if (!allowReplaceBuildings || !metaClass.getIsReplaceable()) {
+ const staticComp = otherEntity.components.StaticMapEntity;
+ if (
+ !allowReplaceBuildings ||
+ !staticComp
+ .getMetaBuilding()
+ .getIsReplaceable(staticComp.getVariant(), staticComp.getRotationVariant())
+ ) {
// This one is a direct blocker
return false;
}
@@ -140,8 +145,11 @@ export class GameLogic {
for (let y = rect.y; y < rect.y + rect.h; ++y) {
const contents = this.root.map.getLayerContentXY(x, y, entity.layer);
if (contents) {
+ const staticComp = contents.components.StaticMapEntity;
assertAlways(
- contents.components.StaticMapEntity.getMetaBuilding().getIsReplaceable(),
+ staticComp
+ .getMetaBuilding()
+ .getIsReplaceable(staticComp.getVariant(), staticComp.getRotationVariant()),
"Tried to replace non-repleaceable entity"
);
if (!this.tryDeleteBuilding(contents)) {
diff --git a/src/js/game/meta_building.js b/src/js/game/meta_building.js
index 0e92d3d9..c661b84f 100644
--- a/src/js/game/meta_building.js
+++ b/src/js/game/meta_building.js
@@ -52,8 +52,9 @@ export class MetaBuilding {
/**
* Returns whether the building has the direction lock switch available
+ * @param {string} variant
*/
- getHasDirectionLockAvailable() {
+ getHasDirectionLockAvailable(variant) {
return false;
}
@@ -88,8 +89,10 @@ export class MetaBuilding {
/**
* Returns whether this building can get replaced
+ * @param {string} variant
+ * @param {number} rotationVariant
*/
- getIsReplaceable() {
+ getIsReplaceable(variant, rotationVariant) {
return false;
}
@@ -278,6 +281,7 @@ export class MetaBuilding {
* Should setup the entity components
* @param {Entity} entity
* @param {GameRoot} root
+ * @abstract
*/
setupEntityComponents(entity, root) {
abstract;
diff --git a/src/js/game/modes/puzzle_edit.js b/src/js/game/modes/puzzle_edit.js
index e3d2e40d..28b59184 100644
--- a/src/js/game/modes/puzzle_edit.js
+++ b/src/js/game/modes/puzzle_edit.js
@@ -22,6 +22,7 @@ import { MetaTransistorBuilding } from "../buildings/transistor";
import { HUDPuzzleEditorControls } from "../hud/parts/puzzle_editor_controls";
import { HUDPuzzleEditorReview } from "../hud/parts/puzzle_editor_review";
import { HUDPuzzleEditorSettings } from "../hud/parts/puzzle_editor_settings";
+import { HUDConstantSignalEdit } from "../hud/parts/constant_signal_edit";
export class PuzzleEditGameMode extends PuzzleGameMode {
static getId() {
@@ -58,6 +59,7 @@ export class PuzzleEditGameMode extends PuzzleGameMode {
this.additionalHudParts.puzzleEditorControls = HUDPuzzleEditorControls;
this.additionalHudParts.puzzleEditorReview = HUDPuzzleEditorReview;
this.additionalHudParts.puzzleEditorSettings = HUDPuzzleEditorSettings;
+ this.additionalHudParts.constantSignalEdit = HUDConstantSignalEdit;
}
getIsEditor() {
diff --git a/src/js/game/modes/regular.js b/src/js/game/modes/regular.js
index cd14833e..68fbb3ad 100644
--- a/src/js/game/modes/regular.js
+++ b/src/js/game/modes/regular.js
@@ -594,18 +594,13 @@ export class RegularGameMode extends GameMode {
this.additionalHudParts.interactiveTutorial = HUDInteractiveTutorial;
}
- // @ts-ignore
- if (queryParamOptions.sandboxMode || window.sandboxMode || G_IS_DEV) {
- this.additionalHudParts.sandboxController = HUDSandboxController;
- }
-
/** @type {(typeof MetaBuilding)[]} */
- this.hiddenBuildings = [MetaConstantProducerBuilding, MetaGoalAcceptorBuilding, MetaBlockBuilding];
-
- // @ts-ignore
- if (!(G_IS_DEV || window.sandboxMode || queryParamOptions.sandboxMode)) {
- this.hiddenBuildings.push(MetaItemProducerBuilding);
- }
+ this.hiddenBuildings = [
+ MetaConstantProducerBuilding,
+ MetaGoalAcceptorBuilding,
+ MetaBlockBuilding,
+ MetaItemProducerBuilding,
+ ];
}
/**
diff --git a/src/js/game/systems/item_processor.js b/src/js/game/systems/item_processor.js
index 1790525c..c5294427 100644
--- a/src/js/game/systems/item_processor.js
+++ b/src/js/game/systems/item_processor.js
@@ -39,6 +39,11 @@ import { ShapeItem } from "../items/shape_item";
*/
export const MOD_ITEM_PROCESSOR_HANDLERS = {};
+/**
+ * @type {Object boolean>}
+ */
+export const MODS_CAN_PROCESS = {};
+
export class ItemProcessorSystem extends GameSystemWithFilter {
constructor(root) {
super(root, [ItemProcessorComponent]);
@@ -168,6 +173,12 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
const acceptorComp = entity.components.ItemAcceptor;
const processorComp = entity.components.ItemProcessor;
+ if (MODS_CAN_PROCESS[processorComp.processingRequirement]) {
+ return MODS_CAN_PROCESS[processorComp.processingRequirement].bind(this)({
+ entity,
+ });
+ }
+
switch (processorComp.processingRequirement) {
// DEFAULT
// By default, we can start processing once all inputs are there
diff --git a/src/js/game/systems/wired_pins.js b/src/js/game/systems/wired_pins.js
index e8bc1882..e73e85f0 100644
--- a/src/js/game/systems/wired_pins.js
+++ b/src/js/game/systems/wired_pins.js
@@ -59,7 +59,11 @@ export class WiredPinsSystem extends GameSystemWithFilter {
continue;
}
- if (staticComp.getMetaBuilding().getIsReplaceable()) {
+ if (
+ staticComp
+ .getMetaBuilding()
+ .getIsReplaceable(staticComp.getVariant(), staticComp.getRotationVariant())
+ ) {
// Don't mind here, even if there would be a collision we
// could replace it
continue;
@@ -113,7 +117,12 @@ export class WiredPinsSystem extends GameSystemWithFilter {
// If there's an entity, and it can't get removed -> That's a collision
if (collidingEntity) {
- if (!collidingEntity.components.StaticMapEntity.getMetaBuilding().getIsReplaceable()) {
+ const staticComp = collidingEntity.components.StaticMapEntity;
+ if (
+ !staticComp
+ .getMetaBuilding()
+ .getIsReplaceable(staticComp.getVariant(), staticComp.getRotationVariant())
+ ) {
return true;
}
}
@@ -138,8 +147,11 @@ export class WiredPinsSystem extends GameSystemWithFilter {
const worldPos = entity.components.StaticMapEntity.localTileToWorld(slot.pos);
const collidingEntity = this.root.map.getLayerContentXY(worldPos.x, worldPos.y, "wires");
if (collidingEntity) {
+ const staticComp = collidingEntity.components.StaticMapEntity;
assertAlways(
- collidingEntity.components.StaticMapEntity.getMetaBuilding().getIsReplaceable(),
+ staticComp
+ .getMetaBuilding()
+ .getIsReplaceable(staticComp.getVariant(), staticComp.getRotationVariant()),
"Tried to replace non-repleaceable entity for pins"
);
if (!this.root.logic.tryDeleteBuilding(collidingEntity)) {
diff --git a/src/js/platform/achievement_provider.js b/src/js/platform/achievement_provider.js
index 583dbfb2..3b60ad95 100644
--- a/src/js/platform/achievement_provider.js
+++ b/src/js/platform/achievement_provider.js
@@ -92,6 +92,7 @@ export class AchievementProviderInterface {
/**
* Initializes the achievement provider.
* @returns {Promise}
+ * @abstract
*/
initialize() {
abstract;
@@ -102,6 +103,7 @@ export class AchievementProviderInterface {
* Opportunity to do additional initialization work with the GameRoot.
* @param {GameRoot} root
* @returns {Promise}
+ * @abstract
*/
onLoad(root) {
abstract;
@@ -118,6 +120,7 @@ export class AchievementProviderInterface {
* Call to activate an achievement with the provider
* @param {string} key - Maps to an Achievement
* @returns {Promise}
+ * @abstract
*/
activate(key) {
abstract;
@@ -127,6 +130,7 @@ export class AchievementProviderInterface {
/**
* Checks if achievements are supported in the current build
* @returns {boolean}
+ * @abstract
*/
hasAchievements() {
abstract;
diff --git a/src/js/platform/ad_provider.js b/src/js/platform/ad_provider.js
index a614a793..4aa8949c 100644
--- a/src/js/platform/ad_provider.js
+++ b/src/js/platform/ad_provider.js
@@ -19,6 +19,7 @@ export class AdProviderInterface {
/**
* Returns if this provider serves ads at all
* @returns {boolean}
+ * @abstract
*/
getHasAds() {
abstract;
@@ -29,6 +30,7 @@ export class AdProviderInterface {
* Returns if it would be possible to show a video ad *now*. This can be false if for
* example the last video ad is
* @returns {boolean}
+ * @abstract
*/
getCanShowVideoAd() {
abstract;
diff --git a/src/js/platform/analytics.js b/src/js/platform/analytics.js
index 7bd7ae50..cf839aca 100644
--- a/src/js/platform/analytics.js
+++ b/src/js/platform/analytics.js
@@ -11,6 +11,7 @@ export class AnalyticsInterface {
/**
* Initializes the analytics
* @returns {Promise}
+ * @abstract
*/
initialize() {
abstract;
diff --git a/src/js/platform/browser/game_analytics.js b/src/js/platform/browser/game_analytics.js
index 9411b258..aa0ac796 100644
--- a/src/js/platform/browser/game_analytics.js
+++ b/src/js/platform/browser/game_analytics.js
@@ -1,6 +1,5 @@
import { globalConfig } from "../../core/config";
import { createLogger } from "../../core/logging";
-import { queryParamOptions } from "../../core/query_parameters";
import { BeltComponent } from "../../game/components/belt";
import { StaticMapEntityComponent } from "../../game/components/static_map_entity";
import { RegularGameMode } from "../../game/modes/regular";
@@ -24,9 +23,6 @@ export class ShapezGameAnalytics extends GameAnalyticsInterface {
}
if (G_IS_STANDALONE) {
- if (queryParamOptions.sandboxMode) {
- return "steam-sandbox";
- }
return "steam";
}
@@ -35,14 +31,8 @@ export class ShapezGameAnalytics extends GameAnalyticsInterface {
}
if (window.location.host.indexOf("alpha") >= 0) {
- if (queryParamOptions.sandboxMode) {
- return "alpha-sandbox";
- }
return "alpha";
} else {
- if (queryParamOptions.sandboxMode) {
- return "beta-sandbox";
- }
return "beta";
}
}
diff --git a/src/js/platform/game_analytics.js b/src/js/platform/game_analytics.js
index 00286fc2..19fdf752 100644
--- a/src/js/platform/game_analytics.js
+++ b/src/js/platform/game_analytics.js
@@ -11,6 +11,7 @@ export class GameAnalyticsInterface {
/**
* Initializes the analytics
* @returns {Promise}
+ * @abstract
*/
initialize() {
abstract;
@@ -43,6 +44,7 @@ export class GameAnalyticsInterface {
/**
* Activates a DLC
* @param {string} dlc
+ * @abstract
*/
activateDlc(dlc) {
abstract;
diff --git a/src/js/platform/storage.js b/src/js/platform/storage.js
index 165ee828..c5c3701c 100644
--- a/src/js/platform/storage.js
+++ b/src/js/platform/storage.js
@@ -13,6 +13,7 @@ export class StorageInterface {
/**
* Initializes the storage
* @returns {Promise}
+ * @abstract
*/
initialize() {
abstract;
@@ -24,6 +25,7 @@ export class StorageInterface {
* @param {string} filename
* @param {string} contents
* @returns {Promise}
+ * @abstract
*/
writeFileAsync(filename, contents) {
abstract;
@@ -34,6 +36,7 @@ export class StorageInterface {
* Reads a string asynchronously. Returns Promise if file was not found.
* @param {string} filename
* @returns {Promise}
+ * @abstract
*/
readFileAsync(filename) {
abstract;
diff --git a/src/js/platform/wrapper.js b/src/js/platform/wrapper.js
index f80c2fd6..e0a896fb 100644
--- a/src/js/platform/wrapper.js
+++ b/src/js/platform/wrapper.js
@@ -81,6 +81,7 @@ export class PlatformWrapperInterface {
* Attempt to open an external url
* @param {string} url
* @param {boolean=} force Whether to always open the url even if not allowed
+ * @abstract
*/
openExternalLink(url, force = false) {
abstract;
@@ -88,6 +89,7 @@ export class PlatformWrapperInterface {
/**
* Attempt to restart the app
+ * @abstract
*/
performRestart() {
abstract;
@@ -103,6 +105,7 @@ export class PlatformWrapperInterface {
/**
* Should set the apps fullscreen state to the desired state
* @param {boolean} flag
+ * @abstract
*/
setFullscreen(flag) {
abstract;
@@ -117,6 +120,7 @@ export class PlatformWrapperInterface {
/**
* Attempts to quit the app
+ * @abstract
*/
exitApp() {
abstract;
diff --git a/src/js/profile/setting_types.js b/src/js/profile/setting_types.js
index 4df02892..943e8e53 100644
--- a/src/js/profile/setting_types.js
+++ b/src/js/profile/setting_types.js
@@ -64,6 +64,7 @@ export class BaseSetting {
/**
* Returns the HTML for this setting
* @param {Application} app
+ * @abstract
*/
getHtml(app) {
abstract;
@@ -84,6 +85,7 @@ export class BaseSetting {
/**
* Attempts to modify the setting
+ * @abstract
*/
modify() {
abstract;
@@ -107,6 +109,7 @@ export class BaseSetting {
* Validates the set value
* @param {any} value
* @returns {boolean}
+ * @abstract
*/
validate(value) {
abstract;
diff --git a/src/js/savegame/serialization_data_types.js b/src/js/savegame/serialization_data_types.js
index df352e78..c27e2295 100644
--- a/src/js/savegame/serialization_data_types.js
+++ b/src/js/savegame/serialization_data_types.js
@@ -48,6 +48,7 @@ export class BaseDataType {
/**
* Serializes a given raw value
* @param {any} value
+ * @abstract
*/
serialize(value) {
abstract;
@@ -68,6 +69,7 @@ export class BaseDataType {
* @param {object} targetObject
* @param {string|number} targetKey
* @returns {string|void} String error code or null on success
+ * @abstract
*/
deserialize(value, targetObject, targetKey, root) {
abstract;
@@ -92,6 +94,7 @@ export class BaseDataType {
/**
* INTERNAL Should return the json schema representation
+ * @abstract
*/
getAsJsonSchemaUncached() {
abstract;
@@ -131,6 +134,7 @@ export class BaseDataType {
/**
* Should return a cacheable key
+ * @abstract
*/
getCacheKey() {
abstract;
diff --git a/translations/base-ja.yaml b/translations/base-ja.yaml
index c98a1b85..ebce66dd 100644
--- a/translations/base-ja.yaml
+++ b/translations/base-ja.yaml
@@ -1013,10 +1013,8 @@ tips:
- SHIFTを押したままにするとベルトプランナーが有効になり、長距離のベルトを簡単に配置できます。
- 切断機は配置された向きを考慮せず、常に垂直に切断します。
- ストレージは左側の出力を優先します。
- - 増築可能なデザインを作るために時間を使ってください。それだけの価値があります!
- - Invest time to build repeatable designs - it's worth it!
+ - 増築可能なデザインを目指してみましょう。それだけの価値があります!
- ALTを押しながらベルトを設置すると、向きを逆転できます。
- - You can hold ALT to invert the direction of placed belts.
- ハブから遠くに離れるほど、形状資源はより複雑な形になります。
- 機械の速度には上限があるので、最大効率を得るためには入力を分割してください。
- 効率を最大化するために分配機/合流機を使用できます。
@@ -1032,8 +1030,7 @@ tips:
- モジュールがあれば、空間はただの認識に過ぎなくなる――生ある人間に対する気遣いだ。
- 設計図としての工場を別に作っておくと、工場のモジュール化において重要な役割を果たします。
- 混色機をよく見ると、色の混ぜ方が解ります。
- - Have a closer look at the color mixer, and your questions will be answered.
- - Use CTRL + Click to select an area.
+ - CTRLを押したままクリックすると、領域を選択できます。
- アップグレードリストの各形状の横にあるピンのアイコンは、その形状を画面左に固定表示します。
- 三原色全てを混ぜ合わせると白になります!
- マップは無限の広さがあります。臆せずに拡張してください。
@@ -1046,8 +1043,7 @@ tips:
- ベルトの中身をクリアするには、範囲選択して同じ場所に貼り付けをします。
- F4を押すことで、FPSとTickレートを表示できます。
- F4を2回押すと、マウスとカメラの座標を表示できます。
- - 左のピン留めされた図形をクリックすると、固定を解除できます。
- - You can click a pinned shape on the left side to unpin it.
+ - 左のピン留めされた図形をクリックすると、ピン留めを解除できます。
puzzleMenu:
play: Play
edit: Edit
diff --git a/translations/base-ru.yaml b/translations/base-ru.yaml
index f3bb7c95..b605180e 100644
--- a/translations/base-ru.yaml
+++ b/translations/base-ru.yaml
@@ -50,7 +50,7 @@ global:
escape: ESC
shift: SHIFT
space: ПРОБЕЛ
- loggingIn: Logging in
+ loggingIn: Вход
demoBanners:
title: Демоверсия
intro: Приобретите полную версию, чтобы разблокировать все возможности!
@@ -74,14 +74,14 @@ mainMenu:
puzzleMode: Головоломка
back: Назад
puzzleDlcText: Нравится оптимизировать фабрики и делать их меньше? Купите
- обновление "Головоломка" в Steam сейчас и получите еще больше
+ обновление «Головоломка» в Steam сейчас и получите еще больше
удовольствия!
puzzleDlcWishlist: Добавь в список желаемого!
puzzleDlcViewNow: Посмотреть
mods:
- title: Active Mods
- warningPuzzleDLC: Playing the Puzzle DLC is not possible with mods. Please
- disable all mods to play the DLC.
+ title: Активные моды
+ warningPuzzleDLC: Обновление «Головоломка» невозможна с модами. Пожалуйста,
+ отключите все моды, чтобы играть в DLC.
dialogs:
buttons:
ok: OK
@@ -230,8 +230,8 @@ dialogs:
desc: "Не удалось отправить вашу головоломку:"
puzzleSubmitOk:
title: Головоломка опубликована
- desc: Поздравляю! Ваша головоломка была опубликована, и теперь в нее могут
- играть остальные. Теперь вы можете найти ее в разделе "Мои
+ desc: Поздравляю! Ваша головоломка была опубликована, и теперь в неё могут
+ играть остальные. Теперь вы можете найти её в разделе "Мои
головоломки".
puzzleCreateOffline:
title: Оффлайн режим
@@ -265,12 +265,13 @@ dialogs:
title: Удалить головоломку?
desc: Вы уверены, что хотите удалить ''? Это действие нельзя отменить!
modsDifference:
- title: Mod Warning
- desc: The currently installed mods differ from the mods the savegame was created
- with. This might cause the savegame to break or not load at all. Are
- you sure you want to continue?
- missingMods: Missing Mods
- newMods: Newly installed Mods
+ title: Предупреждение Мода
+ desc: Установленные в данный момент моды отличаются от модов, с которыми была
+ создана игра сохранения с ним. Это может привести к тому, что сохранение
+ не загрузится или вообще ничего не загрузится. Вы вы уверены, что хотите
+ продолжить?
+ missingMods: Отсутствуют Моды
+ newMods: Недавно установленные Моды
ingame:
keybindingsOverlay:
moveMap: Передвижение
@@ -1312,19 +1313,19 @@ backendErrors:
все еще хотите удалить ее, обратитесь в support@shapez.io!
no-permission: У вас нет прав на выполнение этого действия.
mods:
- title: Mods
- author: Author
- version: Version
- modWebsite: Website
- openFolder: Open Mods Folder
- folderOnlyStandalone: Opening the mod folder is only possible when running the standalone.
- browseMods: Browse Mods
- modsInfo: To install and manage mods, copy them to the mods folder within the
- game directory. You can also use the 'Open Mods Folder' button on the
- top right.
- noModSupport: You need the standalone version on Steam to install mods.
+ title: Моды
+ author: Автор
+ version: Версия
+ modWebsite: Веб-сайт
+ openFolder: Открыть папку с Модами
+ folderOnlyStandalone: Открытие папки Модов возможно только при запуске автономного режима.
+ browseMods: Просмотреть Моды
+ modsInfo: Чтобы установить и управлять модами, скопируйте их в папку модов в
+ директории игры. Вы также можете воспользоваться кнопкой "Открыть папку модов" в
+ справа вверху.
+ noModSupport: Для установки модов вам нужна автономная версия в Steam.
togglingComingSoon:
- title: Coming Soon
- description: Enabling or disabling mods is currently only possible by copying
- the mod file from or to the mods/ folder. However, being able to
- toggle them here is planned for a future update!
+ title: Совсем скоро
+ description: Включение или отключение модов в настоящее время возможно только
+ путем копирования файла мода из/в папку mods/. Однако, возможность
+ управлять ими здесь планируется в будущем обновлении!
diff --git a/translations/base-sv.yaml b/translations/base-sv.yaml
index 5ad75c0c..617ffa27 100644
--- a/translations/base-sv.yaml
+++ b/translations/base-sv.yaml
@@ -52,7 +52,7 @@ global:
escape: ESC
shift: SKIFT
space: MELLANSLAG
- loggingIn: Logging in
+ loggingIn: Loggar in
demoBanners:
title: Demo-version
intro: Skaffa den fristående versionen för att låsa upp alla funktioner!
diff --git a/version b/version
index 3e1ad720..8e03717d 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-1.5.0
\ No newline at end of file
+1.5.1
\ No newline at end of file