mirror of
https://github.com/tobspr/shapez.io.git
synced 2025-06-13 13:04:03 +00:00
Update to latest version
This commit is contained in:
parent
55f968ea4a
commit
bf17ccf202
@ -23,7 +23,7 @@ Your goal is to produce shapes by cutting, rotating, merging and painting parts
|
|||||||
## Building
|
## Building
|
||||||
|
|
||||||
- Make sure `ffmpeg` is on your path
|
- 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)
|
- Install Java (required for textures)
|
||||||
- Run `yarn` in the root folder
|
- Run `yarn` in the root folder
|
||||||
- Cd into `gulp` folder
|
- Cd into `gulp` folder
|
||||||
|
@ -97,7 +97,6 @@ module.exports = ({ watch = false, standalone = false, chineseVersion = false, w
|
|||||||
loader: path.resolve(__dirname, "mod.js"),
|
loader: path.resolve(__dirname, "mod.js"),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.worker\.js$/,
|
test: /\.worker\.js$/,
|
||||||
|
@ -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 |
|
| [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 |
|
| [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 |
|
| [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
|
### Creating new sprites
|
||||||
|
|
||||||
|
@ -15,9 +15,9 @@ const BeltExtension = ({ $super, $old }) => ({
|
|||||||
return !$old.getShowWiresLayerPreview();
|
return !$old.getShowWiresLayerPreview();
|
||||||
},
|
},
|
||||||
|
|
||||||
getIsReplaceable() {
|
getIsReplaceable(variant, rotationVariant) {
|
||||||
// Instead of super, use $super
|
// Instead of super, use $super
|
||||||
return $super.getIsReplaceable.call(this);
|
return $super.getIsReplaceable.call(this, variant, rotationVariant);
|
||||||
},
|
},
|
||||||
|
|
||||||
getIsRemoveable() {
|
getIsRemoveable() {
|
||||||
|
@ -87,7 +87,7 @@ class FluidItem extends shapez.BaseItem {
|
|||||||
* @param {number} diameter
|
* @param {number} diameter
|
||||||
* @param {DrawParameters} parameters
|
* @param {DrawParameters} parameters
|
||||||
*/
|
*/
|
||||||
drawItemCenteredClipped(x, y, parameters, diameter = globalConfig.defaultItemDiameter) {
|
drawItemCenteredClipped(x, y, parameters, diameter = shapez.globalConfig.defaultItemDiameter) {
|
||||||
const realDiameter = diameter * 0.6;
|
const realDiameter = diameter * 0.6;
|
||||||
if (!this.cachedSprite) {
|
if (!this.cachedSprite) {
|
||||||
this.cachedSprite = shapez.Loader.getSprite(`sprites/fluids/${this.fluidType}.png`);
|
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"]);
|
this.modInterface.registerSprite("sprites/fluids/water.png", RESOURCES["water.png"]);
|
||||||
|
|
||||||
// Make the item spawn on the map
|
// Make the item spawn on the map
|
||||||
this.modInterface.runAfterMethod(
|
this.modInterface.runAfterMethod(shapez.MapChunk, "generatePatches", function ({
|
||||||
shapez.MapChunk,
|
rng,
|
||||||
"generatePatches",
|
chunkCenter,
|
||||||
function ({ rng, chunkCenter, distanceToOriginInChunks }) {
|
distanceToOriginInChunks,
|
||||||
// Generate a simple patch
|
}) {
|
||||||
// ALWAYS use rng and NEVER use Math.random() otherwise the map will look different
|
// Generate a simple patch
|
||||||
// every time you resume the game
|
// ALWAYS use rng and NEVER use Math.random() otherwise the map will look different
|
||||||
if (rng.next() > 0.8) {
|
// every time you resume the game
|
||||||
const fluidType = rng.choice(Array.from(Object.keys(enumFluidType)));
|
if (rng.next() > 0.8) {
|
||||||
this.internalGeneratePatch(rng, 4, FLUID_ITEM_SINGLETONS[fluidType]);
|
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]);
|
this.modInterface.registerItem(FluidItem, itemData => FLUID_ITEM_SINGLETONS[itemData]);
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
export const CHANGELOG = [
|
export const CHANGELOG = [
|
||||||
{
|
{
|
||||||
version: "1.5.0",
|
version: "1.5.1",
|
||||||
date: "unreleased",
|
date: "25.02.2022",
|
||||||
entries: [
|
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 <a href='https://shapez.mod.io'>here</a>",
|
||||||
"When holding shift while placing a belt, the indicator now becomes red when crossing buildings",
|
"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",
|
"Lots of performance improvements, leading to up to 50% more FPS",
|
||||||
],
|
],
|
||||||
|
@ -211,6 +211,7 @@ export class GameState {
|
|||||||
/**
|
/**
|
||||||
* Should return the html code of the state.
|
* Should return the html code of the state.
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
getInnerHTML() {
|
getInnerHTML() {
|
||||||
abstract;
|
abstract;
|
||||||
|
@ -3,20 +3,8 @@ const options = queryString.parse(location.search);
|
|||||||
|
|
||||||
export let queryParamOptions = {
|
export let queryParamOptions = {
|
||||||
embedProvider: null,
|
embedProvider: null,
|
||||||
fullVersion: false,
|
|
||||||
sandboxMode: false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (options.embed) {
|
if (options.embed) {
|
||||||
queryParamOptions.embedProvider = 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;
|
|
||||||
}
|
|
||||||
|
@ -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} x
|
||||||
* @param {number} y
|
* @param {number} y
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
|
@ -84,11 +84,6 @@ export class RestrictionManager extends ReadWriteProxy {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (queryParamOptions.fullVersion) {
|
|
||||||
// Full version is activated via flag
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (queryParamOptions.embedProvider === "gamedistribution") {
|
if (queryParamOptions.embedProvider === "gamedistribution") {
|
||||||
// also full version on gamedistribution
|
// also full version on gamedistribution
|
||||||
return false;
|
return false;
|
||||||
|
@ -11,6 +11,7 @@ export class BaseSprite {
|
|||||||
/**
|
/**
|
||||||
* Returns the raw handle
|
* Returns the raw handle
|
||||||
* @returns {HTMLImageElement|HTMLCanvasElement}
|
* @returns {HTMLImageElement|HTMLCanvasElement}
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
getRawTexture() {
|
getRawTexture() {
|
||||||
abstract;
|
abstract;
|
||||||
|
@ -29,6 +29,7 @@ export class BaseItem extends BasicSerializableObject {
|
|||||||
/**
|
/**
|
||||||
* Returns a string id of the item
|
* Returns a string id of the item
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
getAsCopyableKey() {
|
getAsCopyableKey() {
|
||||||
abstract;
|
abstract;
|
||||||
@ -49,9 +50,9 @@ export class BaseItem extends BasicSerializableObject {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Override for custom comparison
|
* Override for custom comparison
|
||||||
* @abstract
|
|
||||||
* @param {BaseItem} other
|
* @param {BaseItem} other
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
equalsImpl(other) {
|
equalsImpl(other) {
|
||||||
abstract;
|
abstract;
|
||||||
@ -62,6 +63,7 @@ export class BaseItem extends BasicSerializableObject {
|
|||||||
* Draws the item to a canvas
|
* Draws the item to a canvas
|
||||||
* @param {CanvasRenderingContext2D} context
|
* @param {CanvasRenderingContext2D} context
|
||||||
* @param {number} size
|
* @param {number} size
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
drawFullSizeOnCanvas(context, size) {
|
drawFullSizeOnCanvas(context, size) {
|
||||||
abstract;
|
abstract;
|
||||||
@ -86,6 +88,7 @@ export class BaseItem extends BasicSerializableObject {
|
|||||||
* @param {number} y
|
* @param {number} y
|
||||||
* @param {DrawParameters} parameters
|
* @param {DrawParameters} parameters
|
||||||
* @param {number=} diameter
|
* @param {number=} diameter
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
drawItemCenteredImpl(x, y, parameters, diameter = globalConfig.defaultItemDiameter) {
|
drawItemCenteredImpl(x, y, parameters, diameter = globalConfig.defaultItemDiameter) {
|
||||||
abstract;
|
abstract;
|
||||||
|
@ -1526,7 +1526,17 @@ export class BeltPath extends BasicSerializableObject {
|
|||||||
|
|
||||||
const sprite = this.root.buffers.getForKey({
|
const sprite = this.root.buffers.getForKey({
|
||||||
key: "beltpaths",
|
key: "beltpaths",
|
||||||
subKey: "stack-" + directionProp + "-" + dpi + "-" + stack.length + firstItem[1].serialize(),
|
subKey:
|
||||||
|
"stack-" +
|
||||||
|
directionProp +
|
||||||
|
"-" +
|
||||||
|
dpi +
|
||||||
|
"#" +
|
||||||
|
stack.length +
|
||||||
|
"#" +
|
||||||
|
firstItem[1].getItemType() +
|
||||||
|
"#" +
|
||||||
|
firstItem[1].serialize(),
|
||||||
dpi,
|
dpi,
|
||||||
w: dimensions.x,
|
w: dimensions.x,
|
||||||
h: dimensions.y,
|
h: dimensions.y,
|
||||||
|
@ -4,6 +4,7 @@ export class Component extends BasicSerializableObject {
|
|||||||
/**
|
/**
|
||||||
* Returns the components unique id
|
* Returns the components unique id
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
static getId() {
|
static getId() {
|
||||||
abstract;
|
abstract;
|
||||||
|
@ -224,6 +224,7 @@ export class Entity extends BasicSerializableObject {
|
|||||||
/**
|
/**
|
||||||
* override, should draw the entity
|
* override, should draw the entity
|
||||||
* @param {DrawParameters} parameters
|
* @param {DrawParameters} parameters
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
drawImpl(parameters) {
|
drawImpl(parameters) {
|
||||||
abstract;
|
abstract;
|
||||||
|
@ -144,6 +144,7 @@ export class GameMode extends BasicSerializableObject {
|
|||||||
/**
|
/**
|
||||||
* @param {number} w
|
* @param {number} w
|
||||||
* @param {number} h
|
* @param {number} h
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
adjustZone(w = 0, h = 0) {
|
adjustZone(w = 0, h = 0) {
|
||||||
abstract;
|
abstract;
|
||||||
|
@ -25,6 +25,7 @@ export class BaseHUDPart {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Should initialize the element, called *after* the elements have been created
|
* Should initialize the element, called *after* the elements have been created
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
initialize() {
|
initialize() {
|
||||||
abstract;
|
abstract;
|
||||||
|
@ -192,7 +192,7 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart {
|
|||||||
const metaBuilding = this.currentMetaBuilding.get();
|
const metaBuilding = this.currentMetaBuilding.get();
|
||||||
return (
|
return (
|
||||||
metaBuilding &&
|
metaBuilding &&
|
||||||
metaBuilding.getHasDirectionLockAvailable() &&
|
metaBuilding.getHasDirectionLockAvailable(this.currentVariant.get()) &&
|
||||||
this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.lockBeltDirection).pressed
|
this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.lockBeltDirection).pressed
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ export class HUDKeybindingOverlay extends BaseHUDPart {
|
|||||||
!this.mapOverviewActive &&
|
!this.mapOverviewActive &&
|
||||||
placer &&
|
placer &&
|
||||||
placer.currentMetaBuilding.get() &&
|
placer.currentMetaBuilding.get() &&
|
||||||
placer.currentMetaBuilding.get().getHasDirectionLockAvailable()
|
placer.currentMetaBuilding.get().getHasDirectionLockAvailable(placer.currentVariant.get())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ export function itemResolverSingleton(root, data) {
|
|||||||
const itemData = data.data;
|
const itemData = data.data;
|
||||||
|
|
||||||
if (MODS_ADDITIONAL_ITEMS[itemType]) {
|
if (MODS_ADDITIONAL_ITEMS[itemType]) {
|
||||||
return MODS_ADDITIONAL_ITEMS[itemType](itemData);
|
return MODS_ADDITIONAL_ITEMS[itemType](itemData, root);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (itemType) {
|
switch (itemType) {
|
||||||
|
@ -72,8 +72,13 @@ export class GameLogic {
|
|||||||
// Check if there is any direct collision
|
// Check if there is any direct collision
|
||||||
const otherEntity = this.root.map.getLayerContentXY(x, y, entity.layer);
|
const otherEntity = this.root.map.getLayerContentXY(x, y, entity.layer);
|
||||||
if (otherEntity) {
|
if (otherEntity) {
|
||||||
const metaClass = otherEntity.components.StaticMapEntity.getMetaBuilding();
|
const staticComp = otherEntity.components.StaticMapEntity;
|
||||||
if (!allowReplaceBuildings || !metaClass.getIsReplaceable()) {
|
if (
|
||||||
|
!allowReplaceBuildings ||
|
||||||
|
!staticComp
|
||||||
|
.getMetaBuilding()
|
||||||
|
.getIsReplaceable(staticComp.getVariant(), staticComp.getRotationVariant())
|
||||||
|
) {
|
||||||
// This one is a direct blocker
|
// This one is a direct blocker
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -140,8 +145,11 @@ export class GameLogic {
|
|||||||
for (let y = rect.y; y < rect.y + rect.h; ++y) {
|
for (let y = rect.y; y < rect.y + rect.h; ++y) {
|
||||||
const contents = this.root.map.getLayerContentXY(x, y, entity.layer);
|
const contents = this.root.map.getLayerContentXY(x, y, entity.layer);
|
||||||
if (contents) {
|
if (contents) {
|
||||||
|
const staticComp = contents.components.StaticMapEntity;
|
||||||
assertAlways(
|
assertAlways(
|
||||||
contents.components.StaticMapEntity.getMetaBuilding().getIsReplaceable(),
|
staticComp
|
||||||
|
.getMetaBuilding()
|
||||||
|
.getIsReplaceable(staticComp.getVariant(), staticComp.getRotationVariant()),
|
||||||
"Tried to replace non-repleaceable entity"
|
"Tried to replace non-repleaceable entity"
|
||||||
);
|
);
|
||||||
if (!this.tryDeleteBuilding(contents)) {
|
if (!this.tryDeleteBuilding(contents)) {
|
||||||
|
@ -52,8 +52,9 @@ export class MetaBuilding {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the building has the direction lock switch available
|
* Returns whether the building has the direction lock switch available
|
||||||
|
* @param {string} variant
|
||||||
*/
|
*/
|
||||||
getHasDirectionLockAvailable() {
|
getHasDirectionLockAvailable(variant) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,8 +89,10 @@ export class MetaBuilding {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether this building can get replaced
|
* Returns whether this building can get replaced
|
||||||
|
* @param {string} variant
|
||||||
|
* @param {number} rotationVariant
|
||||||
*/
|
*/
|
||||||
getIsReplaceable() {
|
getIsReplaceable(variant, rotationVariant) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,6 +281,7 @@ export class MetaBuilding {
|
|||||||
* Should setup the entity components
|
* Should setup the entity components
|
||||||
* @param {Entity} entity
|
* @param {Entity} entity
|
||||||
* @param {GameRoot} root
|
* @param {GameRoot} root
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
setupEntityComponents(entity, root) {
|
setupEntityComponents(entity, root) {
|
||||||
abstract;
|
abstract;
|
||||||
|
@ -22,6 +22,7 @@ import { MetaTransistorBuilding } from "../buildings/transistor";
|
|||||||
import { HUDPuzzleEditorControls } from "../hud/parts/puzzle_editor_controls";
|
import { HUDPuzzleEditorControls } from "../hud/parts/puzzle_editor_controls";
|
||||||
import { HUDPuzzleEditorReview } from "../hud/parts/puzzle_editor_review";
|
import { HUDPuzzleEditorReview } from "../hud/parts/puzzle_editor_review";
|
||||||
import { HUDPuzzleEditorSettings } from "../hud/parts/puzzle_editor_settings";
|
import { HUDPuzzleEditorSettings } from "../hud/parts/puzzle_editor_settings";
|
||||||
|
import { HUDConstantSignalEdit } from "../hud/parts/constant_signal_edit";
|
||||||
|
|
||||||
export class PuzzleEditGameMode extends PuzzleGameMode {
|
export class PuzzleEditGameMode extends PuzzleGameMode {
|
||||||
static getId() {
|
static getId() {
|
||||||
@ -58,6 +59,7 @@ export class PuzzleEditGameMode extends PuzzleGameMode {
|
|||||||
this.additionalHudParts.puzzleEditorControls = HUDPuzzleEditorControls;
|
this.additionalHudParts.puzzleEditorControls = HUDPuzzleEditorControls;
|
||||||
this.additionalHudParts.puzzleEditorReview = HUDPuzzleEditorReview;
|
this.additionalHudParts.puzzleEditorReview = HUDPuzzleEditorReview;
|
||||||
this.additionalHudParts.puzzleEditorSettings = HUDPuzzleEditorSettings;
|
this.additionalHudParts.puzzleEditorSettings = HUDPuzzleEditorSettings;
|
||||||
|
this.additionalHudParts.constantSignalEdit = HUDConstantSignalEdit;
|
||||||
}
|
}
|
||||||
|
|
||||||
getIsEditor() {
|
getIsEditor() {
|
||||||
|
@ -594,18 +594,13 @@ export class RegularGameMode extends GameMode {
|
|||||||
this.additionalHudParts.interactiveTutorial = HUDInteractiveTutorial;
|
this.additionalHudParts.interactiveTutorial = HUDInteractiveTutorial;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
if (queryParamOptions.sandboxMode || window.sandboxMode || G_IS_DEV) {
|
|
||||||
this.additionalHudParts.sandboxController = HUDSandboxController;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @type {(typeof MetaBuilding)[]} */
|
/** @type {(typeof MetaBuilding)[]} */
|
||||||
this.hiddenBuildings = [MetaConstantProducerBuilding, MetaGoalAcceptorBuilding, MetaBlockBuilding];
|
this.hiddenBuildings = [
|
||||||
|
MetaConstantProducerBuilding,
|
||||||
// @ts-ignore
|
MetaGoalAcceptorBuilding,
|
||||||
if (!(G_IS_DEV || window.sandboxMode || queryParamOptions.sandboxMode)) {
|
MetaBlockBuilding,
|
||||||
this.hiddenBuildings.push(MetaItemProducerBuilding);
|
MetaItemProducerBuilding,
|
||||||
}
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,6 +39,11 @@ import { ShapeItem } from "../items/shape_item";
|
|||||||
*/
|
*/
|
||||||
export const MOD_ITEM_PROCESSOR_HANDLERS = {};
|
export const MOD_ITEM_PROCESSOR_HANDLERS = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Object<string, ({entity: Entity}) => boolean>}
|
||||||
|
*/
|
||||||
|
export const MODS_CAN_PROCESS = {};
|
||||||
|
|
||||||
export class ItemProcessorSystem extends GameSystemWithFilter {
|
export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||||
constructor(root) {
|
constructor(root) {
|
||||||
super(root, [ItemProcessorComponent]);
|
super(root, [ItemProcessorComponent]);
|
||||||
@ -168,6 +173,12 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
|||||||
const acceptorComp = entity.components.ItemAcceptor;
|
const acceptorComp = entity.components.ItemAcceptor;
|
||||||
const processorComp = entity.components.ItemProcessor;
|
const processorComp = entity.components.ItemProcessor;
|
||||||
|
|
||||||
|
if (MODS_CAN_PROCESS[processorComp.processingRequirement]) {
|
||||||
|
return MODS_CAN_PROCESS[processorComp.processingRequirement].bind(this)({
|
||||||
|
entity,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
switch (processorComp.processingRequirement) {
|
switch (processorComp.processingRequirement) {
|
||||||
// DEFAULT
|
// DEFAULT
|
||||||
// By default, we can start processing once all inputs are there
|
// By default, we can start processing once all inputs are there
|
||||||
|
@ -59,7 +59,11 @@ export class WiredPinsSystem extends GameSystemWithFilter {
|
|||||||
continue;
|
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
|
// Don't mind here, even if there would be a collision we
|
||||||
// could replace it
|
// could replace it
|
||||||
continue;
|
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 there's an entity, and it can't get removed -> That's a collision
|
||||||
if (collidingEntity) {
|
if (collidingEntity) {
|
||||||
if (!collidingEntity.components.StaticMapEntity.getMetaBuilding().getIsReplaceable()) {
|
const staticComp = collidingEntity.components.StaticMapEntity;
|
||||||
|
if (
|
||||||
|
!staticComp
|
||||||
|
.getMetaBuilding()
|
||||||
|
.getIsReplaceable(staticComp.getVariant(), staticComp.getRotationVariant())
|
||||||
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -138,8 +147,11 @@ export class WiredPinsSystem extends GameSystemWithFilter {
|
|||||||
const worldPos = entity.components.StaticMapEntity.localTileToWorld(slot.pos);
|
const worldPos = entity.components.StaticMapEntity.localTileToWorld(slot.pos);
|
||||||
const collidingEntity = this.root.map.getLayerContentXY(worldPos.x, worldPos.y, "wires");
|
const collidingEntity = this.root.map.getLayerContentXY(worldPos.x, worldPos.y, "wires");
|
||||||
if (collidingEntity) {
|
if (collidingEntity) {
|
||||||
|
const staticComp = collidingEntity.components.StaticMapEntity;
|
||||||
assertAlways(
|
assertAlways(
|
||||||
collidingEntity.components.StaticMapEntity.getMetaBuilding().getIsReplaceable(),
|
staticComp
|
||||||
|
.getMetaBuilding()
|
||||||
|
.getIsReplaceable(staticComp.getVariant(), staticComp.getRotationVariant()),
|
||||||
"Tried to replace non-repleaceable entity for pins"
|
"Tried to replace non-repleaceable entity for pins"
|
||||||
);
|
);
|
||||||
if (!this.root.logic.tryDeleteBuilding(collidingEntity)) {
|
if (!this.root.logic.tryDeleteBuilding(collidingEntity)) {
|
||||||
|
@ -92,6 +92,7 @@ export class AchievementProviderInterface {
|
|||||||
/**
|
/**
|
||||||
* Initializes the achievement provider.
|
* Initializes the achievement provider.
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
initialize() {
|
initialize() {
|
||||||
abstract;
|
abstract;
|
||||||
@ -102,6 +103,7 @@ export class AchievementProviderInterface {
|
|||||||
* Opportunity to do additional initialization work with the GameRoot.
|
* Opportunity to do additional initialization work with the GameRoot.
|
||||||
* @param {GameRoot} root
|
* @param {GameRoot} root
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
onLoad(root) {
|
onLoad(root) {
|
||||||
abstract;
|
abstract;
|
||||||
@ -118,6 +120,7 @@ export class AchievementProviderInterface {
|
|||||||
* Call to activate an achievement with the provider
|
* Call to activate an achievement with the provider
|
||||||
* @param {string} key - Maps to an Achievement
|
* @param {string} key - Maps to an Achievement
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
activate(key) {
|
activate(key) {
|
||||||
abstract;
|
abstract;
|
||||||
@ -127,6 +130,7 @@ export class AchievementProviderInterface {
|
|||||||
/**
|
/**
|
||||||
* Checks if achievements are supported in the current build
|
* Checks if achievements are supported in the current build
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
hasAchievements() {
|
hasAchievements() {
|
||||||
abstract;
|
abstract;
|
||||||
|
@ -19,6 +19,7 @@ export class AdProviderInterface {
|
|||||||
/**
|
/**
|
||||||
* Returns if this provider serves ads at all
|
* Returns if this provider serves ads at all
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
getHasAds() {
|
getHasAds() {
|
||||||
abstract;
|
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
|
* Returns if it would be possible to show a video ad *now*. This can be false if for
|
||||||
* example the last video ad is
|
* example the last video ad is
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
getCanShowVideoAd() {
|
getCanShowVideoAd() {
|
||||||
abstract;
|
abstract;
|
||||||
|
@ -11,6 +11,7 @@ export class AnalyticsInterface {
|
|||||||
/**
|
/**
|
||||||
* Initializes the analytics
|
* Initializes the analytics
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
initialize() {
|
initialize() {
|
||||||
abstract;
|
abstract;
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { globalConfig } from "../../core/config";
|
import { globalConfig } from "../../core/config";
|
||||||
import { createLogger } from "../../core/logging";
|
import { createLogger } from "../../core/logging";
|
||||||
import { queryParamOptions } from "../../core/query_parameters";
|
|
||||||
import { BeltComponent } from "../../game/components/belt";
|
import { BeltComponent } from "../../game/components/belt";
|
||||||
import { StaticMapEntityComponent } from "../../game/components/static_map_entity";
|
import { StaticMapEntityComponent } from "../../game/components/static_map_entity";
|
||||||
import { RegularGameMode } from "../../game/modes/regular";
|
import { RegularGameMode } from "../../game/modes/regular";
|
||||||
@ -24,9 +23,6 @@ export class ShapezGameAnalytics extends GameAnalyticsInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (G_IS_STANDALONE) {
|
if (G_IS_STANDALONE) {
|
||||||
if (queryParamOptions.sandboxMode) {
|
|
||||||
return "steam-sandbox";
|
|
||||||
}
|
|
||||||
return "steam";
|
return "steam";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,14 +31,8 @@ export class ShapezGameAnalytics extends GameAnalyticsInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (window.location.host.indexOf("alpha") >= 0) {
|
if (window.location.host.indexOf("alpha") >= 0) {
|
||||||
if (queryParamOptions.sandboxMode) {
|
|
||||||
return "alpha-sandbox";
|
|
||||||
}
|
|
||||||
return "alpha";
|
return "alpha";
|
||||||
} else {
|
} else {
|
||||||
if (queryParamOptions.sandboxMode) {
|
|
||||||
return "beta-sandbox";
|
|
||||||
}
|
|
||||||
return "beta";
|
return "beta";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ export class GameAnalyticsInterface {
|
|||||||
/**
|
/**
|
||||||
* Initializes the analytics
|
* Initializes the analytics
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
initialize() {
|
initialize() {
|
||||||
abstract;
|
abstract;
|
||||||
@ -43,6 +44,7 @@ export class GameAnalyticsInterface {
|
|||||||
/**
|
/**
|
||||||
* Activates a DLC
|
* Activates a DLC
|
||||||
* @param {string} dlc
|
* @param {string} dlc
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
activateDlc(dlc) {
|
activateDlc(dlc) {
|
||||||
abstract;
|
abstract;
|
||||||
|
@ -13,6 +13,7 @@ export class StorageInterface {
|
|||||||
/**
|
/**
|
||||||
* Initializes the storage
|
* Initializes the storage
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
initialize() {
|
initialize() {
|
||||||
abstract;
|
abstract;
|
||||||
@ -24,6 +25,7 @@ export class StorageInterface {
|
|||||||
* @param {string} filename
|
* @param {string} filename
|
||||||
* @param {string} contents
|
* @param {string} contents
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
writeFileAsync(filename, contents) {
|
writeFileAsync(filename, contents) {
|
||||||
abstract;
|
abstract;
|
||||||
@ -34,6 +36,7 @@ export class StorageInterface {
|
|||||||
* Reads a string asynchronously. Returns Promise<FILE_NOT_FOUND> if file was not found.
|
* Reads a string asynchronously. Returns Promise<FILE_NOT_FOUND> if file was not found.
|
||||||
* @param {string} filename
|
* @param {string} filename
|
||||||
* @returns {Promise<string>}
|
* @returns {Promise<string>}
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
readFileAsync(filename) {
|
readFileAsync(filename) {
|
||||||
abstract;
|
abstract;
|
||||||
|
@ -81,6 +81,7 @@ export class PlatformWrapperInterface {
|
|||||||
* Attempt to open an external url
|
* Attempt to open an external url
|
||||||
* @param {string} url
|
* @param {string} url
|
||||||
* @param {boolean=} force Whether to always open the url even if not allowed
|
* @param {boolean=} force Whether to always open the url even if not allowed
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
openExternalLink(url, force = false) {
|
openExternalLink(url, force = false) {
|
||||||
abstract;
|
abstract;
|
||||||
@ -88,6 +89,7 @@ export class PlatformWrapperInterface {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to restart the app
|
* Attempt to restart the app
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
performRestart() {
|
performRestart() {
|
||||||
abstract;
|
abstract;
|
||||||
@ -103,6 +105,7 @@ export class PlatformWrapperInterface {
|
|||||||
/**
|
/**
|
||||||
* Should set the apps fullscreen state to the desired state
|
* Should set the apps fullscreen state to the desired state
|
||||||
* @param {boolean} flag
|
* @param {boolean} flag
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
setFullscreen(flag) {
|
setFullscreen(flag) {
|
||||||
abstract;
|
abstract;
|
||||||
@ -117,6 +120,7 @@ export class PlatformWrapperInterface {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to quit the app
|
* Attempts to quit the app
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
exitApp() {
|
exitApp() {
|
||||||
abstract;
|
abstract;
|
||||||
|
@ -64,6 +64,7 @@ export class BaseSetting {
|
|||||||
/**
|
/**
|
||||||
* Returns the HTML for this setting
|
* Returns the HTML for this setting
|
||||||
* @param {Application} app
|
* @param {Application} app
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
getHtml(app) {
|
getHtml(app) {
|
||||||
abstract;
|
abstract;
|
||||||
@ -84,6 +85,7 @@ export class BaseSetting {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to modify the setting
|
* Attempts to modify the setting
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
modify() {
|
modify() {
|
||||||
abstract;
|
abstract;
|
||||||
@ -107,6 +109,7 @@ export class BaseSetting {
|
|||||||
* Validates the set value
|
* Validates the set value
|
||||||
* @param {any} value
|
* @param {any} value
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
validate(value) {
|
validate(value) {
|
||||||
abstract;
|
abstract;
|
||||||
|
@ -48,6 +48,7 @@ export class BaseDataType {
|
|||||||
/**
|
/**
|
||||||
* Serializes a given raw value
|
* Serializes a given raw value
|
||||||
* @param {any} value
|
* @param {any} value
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
serialize(value) {
|
serialize(value) {
|
||||||
abstract;
|
abstract;
|
||||||
@ -68,6 +69,7 @@ export class BaseDataType {
|
|||||||
* @param {object} targetObject
|
* @param {object} targetObject
|
||||||
* @param {string|number} targetKey
|
* @param {string|number} targetKey
|
||||||
* @returns {string|void} String error code or null on success
|
* @returns {string|void} String error code or null on success
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
deserialize(value, targetObject, targetKey, root) {
|
deserialize(value, targetObject, targetKey, root) {
|
||||||
abstract;
|
abstract;
|
||||||
@ -92,6 +94,7 @@ export class BaseDataType {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* INTERNAL Should return the json schema representation
|
* INTERNAL Should return the json schema representation
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
getAsJsonSchemaUncached() {
|
getAsJsonSchemaUncached() {
|
||||||
abstract;
|
abstract;
|
||||||
@ -131,6 +134,7 @@ export class BaseDataType {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Should return a cacheable key
|
* Should return a cacheable key
|
||||||
|
* @abstract
|
||||||
*/
|
*/
|
||||||
getCacheKey() {
|
getCacheKey() {
|
||||||
abstract;
|
abstract;
|
||||||
|
@ -1013,10 +1013,8 @@ tips:
|
|||||||
- <b>SHIFT</b>を押したままにするとベルトプランナーが有効になり、長距離のベルトを簡単に配置できます。
|
- <b>SHIFT</b>を押したままにするとベルトプランナーが有効になり、長距離のベルトを簡単に配置できます。
|
||||||
- 切断機は配置された向きを考慮せず、常に垂直に切断します。
|
- 切断機は配置された向きを考慮せず、常に垂直に切断します。
|
||||||
- ストレージは左側の出力を優先します。
|
- ストレージは左側の出力を優先します。
|
||||||
- 増築可能なデザインを作るために時間を使ってください。それだけの価値があります!
|
- 増築可能なデザインを目指してみましょう。それだけの価値があります!
|
||||||
- Invest time to build repeatable designs - it's worth it!
|
|
||||||
- <b>ALT</b>を押しながらベルトを設置すると、向きを逆転できます。
|
- <b>ALT</b>を押しながらベルトを設置すると、向きを逆転できます。
|
||||||
- You can hold <b>ALT</b> 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.
|
- <b>CTRL</b>を押したままクリックすると、領域を選択できます。
|
||||||
- Use <b>CTRL</b> + Click to select an area.
|
|
||||||
- アップグレードリストの各形状の横にあるピンのアイコンは、その形状を画面左に固定表示します。
|
- アップグレードリストの各形状の横にあるピンのアイコンは、その形状を画面左に固定表示します。
|
||||||
- 三原色全てを混ぜ合わせると白になります!
|
- 三原色全てを混ぜ合わせると白になります!
|
||||||
- マップは無限の広さがあります。臆せずに拡張してください。
|
- マップは無限の広さがあります。臆せずに拡張してください。
|
||||||
@ -1046,8 +1043,7 @@ tips:
|
|||||||
- ベルトの中身をクリアするには、範囲選択して同じ場所に貼り付けをします。
|
- ベルトの中身をクリアするには、範囲選択して同じ場所に貼り付けをします。
|
||||||
- F4を押すことで、FPSとTickレートを表示できます。
|
- F4を押すことで、FPSとTickレートを表示できます。
|
||||||
- F4を2回押すと、マウスとカメラの座標を表示できます。
|
- F4を2回押すと、マウスとカメラの座標を表示できます。
|
||||||
- 左のピン留めされた図形をクリックすると、固定を解除できます。
|
- 左のピン留めされた図形をクリックすると、ピン留めを解除できます。
|
||||||
- You can click a pinned shape on the left side to unpin it.
|
|
||||||
puzzleMenu:
|
puzzleMenu:
|
||||||
play: Play
|
play: Play
|
||||||
edit: Edit
|
edit: Edit
|
||||||
|
@ -50,7 +50,7 @@ global:
|
|||||||
escape: ESC
|
escape: ESC
|
||||||
shift: SHIFT
|
shift: SHIFT
|
||||||
space: ПРОБЕЛ
|
space: ПРОБЕЛ
|
||||||
loggingIn: Logging in
|
loggingIn: Вход
|
||||||
demoBanners:
|
demoBanners:
|
||||||
title: Демоверсия
|
title: Демоверсия
|
||||||
intro: Приобретите полную версию, чтобы разблокировать все возможности!
|
intro: Приобретите полную версию, чтобы разблокировать все возможности!
|
||||||
@ -74,14 +74,14 @@ mainMenu:
|
|||||||
puzzleMode: Головоломка
|
puzzleMode: Головоломка
|
||||||
back: Назад
|
back: Назад
|
||||||
puzzleDlcText: Нравится оптимизировать фабрики и делать их меньше? Купите
|
puzzleDlcText: Нравится оптимизировать фабрики и делать их меньше? Купите
|
||||||
обновление "Головоломка" в Steam сейчас и получите еще больше
|
обновление «Головоломка» в Steam сейчас и получите еще больше
|
||||||
удовольствия!
|
удовольствия!
|
||||||
puzzleDlcWishlist: Добавь в список желаемого!
|
puzzleDlcWishlist: Добавь в список желаемого!
|
||||||
puzzleDlcViewNow: Посмотреть
|
puzzleDlcViewNow: Посмотреть
|
||||||
mods:
|
mods:
|
||||||
title: Active Mods
|
title: Активные моды
|
||||||
warningPuzzleDLC: Playing the Puzzle DLC is not possible with mods. Please
|
warningPuzzleDLC: Обновление «Головоломка» невозможна с модами. Пожалуйста,
|
||||||
disable all mods to play the DLC.
|
отключите все моды, чтобы играть в DLC.
|
||||||
dialogs:
|
dialogs:
|
||||||
buttons:
|
buttons:
|
||||||
ok: OK
|
ok: OK
|
||||||
@ -230,8 +230,8 @@ dialogs:
|
|||||||
desc: "Не удалось отправить вашу головоломку:"
|
desc: "Не удалось отправить вашу головоломку:"
|
||||||
puzzleSubmitOk:
|
puzzleSubmitOk:
|
||||||
title: Головоломка опубликована
|
title: Головоломка опубликована
|
||||||
desc: Поздравляю! Ваша головоломка была опубликована, и теперь в нее могут
|
desc: Поздравляю! Ваша головоломка была опубликована, и теперь в неё могут
|
||||||
играть остальные. Теперь вы можете найти ее в разделе "Мои
|
играть остальные. Теперь вы можете найти её в разделе "Мои
|
||||||
головоломки".
|
головоломки".
|
||||||
puzzleCreateOffline:
|
puzzleCreateOffline:
|
||||||
title: Оффлайн режим
|
title: Оффлайн режим
|
||||||
@ -265,12 +265,13 @@ dialogs:
|
|||||||
title: Удалить головоломку?
|
title: Удалить головоломку?
|
||||||
desc: Вы уверены, что хотите удалить '<title>'? Это действие нельзя отменить!
|
desc: Вы уверены, что хотите удалить '<title>'? Это действие нельзя отменить!
|
||||||
modsDifference:
|
modsDifference:
|
||||||
title: Mod Warning
|
title: Предупреждение Мода
|
||||||
desc: The currently installed mods differ from the mods the savegame was created
|
desc: Установленные в данный момент моды отличаются от модов, с которыми была
|
||||||
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
|
missingMods: Отсутствуют Моды
|
||||||
|
newMods: Недавно установленные Моды
|
||||||
ingame:
|
ingame:
|
||||||
keybindingsOverlay:
|
keybindingsOverlay:
|
||||||
moveMap: Передвижение
|
moveMap: Передвижение
|
||||||
@ -1312,19 +1313,19 @@ backendErrors:
|
|||||||
все еще хотите удалить ее, обратитесь в support@shapez.io!
|
все еще хотите удалить ее, обратитесь в support@shapez.io!
|
||||||
no-permission: У вас нет прав на выполнение этого действия.
|
no-permission: У вас нет прав на выполнение этого действия.
|
||||||
mods:
|
mods:
|
||||||
title: Mods
|
title: Моды
|
||||||
author: Author
|
author: Автор
|
||||||
version: Version
|
version: Версия
|
||||||
modWebsite: Website
|
modWebsite: Веб-сайт
|
||||||
openFolder: Open Mods Folder
|
openFolder: Открыть папку с Модами
|
||||||
folderOnlyStandalone: Opening the mod folder is only possible when running the standalone.
|
folderOnlyStandalone: Открытие папки Модов возможно только при запуске автономного режима.
|
||||||
browseMods: Browse Mods
|
browseMods: Просмотреть Моды
|
||||||
modsInfo: To install and manage mods, copy them to the mods folder within the
|
modsInfo: Чтобы установить и управлять модами, скопируйте их в папку модов в
|
||||||
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.
|
noModSupport: Для установки модов вам нужна автономная версия в Steam.
|
||||||
togglingComingSoon:
|
togglingComingSoon:
|
||||||
title: Coming Soon
|
title: Совсем скоро
|
||||||
description: Enabling or disabling mods is currently only possible by copying
|
description: Включение или отключение модов в настоящее время возможно только
|
||||||
the mod file from or to the mods/ folder. However, being able to
|
путем копирования файла мода из/в папку mods/. Однако, возможность
|
||||||
toggle them here is planned for a future update!
|
управлять ими здесь планируется в будущем обновлении!
|
||||||
|
@ -52,7 +52,7 @@ global:
|
|||||||
escape: ESC
|
escape: ESC
|
||||||
shift: SKIFT
|
shift: SKIFT
|
||||||
space: MELLANSLAG
|
space: MELLANSLAG
|
||||||
loggingIn: Logging in
|
loggingIn: Loggar in
|
||||||
demoBanners:
|
demoBanners:
|
||||||
title: Demo-version
|
title: Demo-version
|
||||||
intro: Skaffa den fristående versionen för att låsa upp alla funktioner!
|
intro: Skaffa den fristående versionen för att låsa upp alla funktioner!
|
||||||
|
Loading…
Reference in New Issue
Block a user