mirror of
https://github.com/tobspr/shapez.io.git
synced 2024-10-27 20:34:29 +00:00
Merge branch 'tobspr:master' into zone_indicators
This commit is contained in:
commit
bb0c58e784
@ -39,7 +39,7 @@ You can use [Gitpod](https://www.gitpod.io/) (an Online Open Source VS Code-like
|
||||
- install all of the dependencies.
|
||||
- start `gulp` in `gulp/` directory.
|
||||
|
||||
[](https://gitpod.io/from-referrer/)
|
||||
[](https://gitpod.io/#https://github.com/tobspr/shapez.io)
|
||||
|
||||
## Helping translate
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
const railsdk = require("./wegame_sdk/railsdk.js");
|
||||
const { dialog, remote } = require("electron");
|
||||
const { dialog, app, remote, ipcMain } = require("electron");
|
||||
|
||||
function init(isDev) {
|
||||
console.log("Step 1: wegame: init");
|
||||
@ -39,7 +39,7 @@ function init(isDev) {
|
||||
event.state === railsdk.RailSystemState.kSystemStatePlatformExit ||
|
||||
event.state === railsdk.RailSystemState.kSystemStateGameExitByAntiAddiction
|
||||
) {
|
||||
remote.app.exit();
|
||||
app.exit();
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -47,6 +47,17 @@ function init(isDev) {
|
||||
|
||||
function listen() {
|
||||
console.log("wegame: listen");
|
||||
ipcMain.handle("profanity-check", async (event, data) => {
|
||||
if (data.length === 0) {
|
||||
return "";
|
||||
}
|
||||
const result = railsdk.RailUtils.DirtyWordsFilter(data, true);
|
||||
if (result.check_result.dirty_type !== 0 /** kRailDirtyWordsTypeNormalAllowWords */) {
|
||||
return result.check_result.replace_string;
|
||||
}
|
||||
|
||||
return data;
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { init, listen };
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 37 KiB |
BIN
res/ui/wegame_isbn_rating.jpg
Normal file
BIN
res/ui/wegame_isbn_rating.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.8 KiB |
@ -21,6 +21,7 @@
|
||||
@import "adinplay";
|
||||
@import "changelog_skins";
|
||||
|
||||
@import "states/wegame_splash";
|
||||
@import "states/preload";
|
||||
@import "states/main_menu";
|
||||
@import "states/ingame";
|
||||
|
@ -550,6 +550,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
#crosspromo {
|
||||
position: absolute;
|
||||
@include S(bottom, 50px);
|
||||
@include S(right, 20px);
|
||||
@include S(width, 190px);
|
||||
@include S(height, 100px);
|
||||
pointer-events: all;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.footer {
|
||||
display: grid;
|
||||
flex-grow: 1;
|
||||
@ -565,6 +575,40 @@
|
||||
grid-template-columns: auto 1fr;
|
||||
}
|
||||
|
||||
&.wegameDisclaimer {
|
||||
@include SuperSmallText;
|
||||
display: grid;
|
||||
justify-content: center;
|
||||
grid-template-columns: 1fr auto 1fr;
|
||||
|
||||
> .disclaimer {
|
||||
grid-column: 2 / 3;
|
||||
|
||||
@include DarkThemeOverride {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
> .rating {
|
||||
grid-column: 3 / 4;
|
||||
justify-self: end;
|
||||
align-self: end;
|
||||
|
||||
@include S(width, 32px);
|
||||
@include S(height, 40px);
|
||||
background: green;
|
||||
cursor: pointer !important;
|
||||
pointer-events: all;
|
||||
@include S(border-radius, 4px);
|
||||
overflow: hidden;
|
||||
|
||||
& {
|
||||
/* @load-async */
|
||||
background: #fff uiResource("wegame_isbn_rating.jpg") center center / contain no-repeat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.author {
|
||||
flex-grow: 1;
|
||||
text-align: right;
|
||||
|
38
src/css/states/wegame_splash.scss
Normal file
38
src/css/states/wegame_splash.scss
Normal file
@ -0,0 +1,38 @@
|
||||
#state_WegameSplashState {
|
||||
background: #000 !important;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.wrapper {
|
||||
opacity: 0;
|
||||
@include InlineAnimation(5.9s ease-in-out) {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
20% {
|
||||
opacity: 1;
|
||||
}
|
||||
90% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
@include Heading;
|
||||
|
||||
strong {
|
||||
display: block;
|
||||
@include SuperHeading;
|
||||
@include S(margin-bottom, 20px);
|
||||
}
|
||||
|
||||
div {
|
||||
@include S(margin-bottom, 10px);
|
||||
}
|
||||
}
|
||||
}
|
@ -34,6 +34,7 @@ import { RestrictionManager } from "./core/restriction_manager";
|
||||
import { PuzzleMenuState } from "./states/puzzle_menu";
|
||||
import { ClientAPI } from "./platform/api";
|
||||
import { LoginState } from "./states/login";
|
||||
import { WegameSplashState } from "./states/wegame_splash";
|
||||
|
||||
/**
|
||||
* @typedef {import("./platform/achievement_provider").AchievementProviderInterface} AchievementProviderInterface
|
||||
@ -155,6 +156,7 @@ export class Application {
|
||||
registerStates() {
|
||||
/** @type {Array<typeof GameState>} */
|
||||
const states = [
|
||||
WegameSplashState,
|
||||
PreloadState,
|
||||
MobileWarningState,
|
||||
MainMenuState,
|
||||
@ -330,8 +332,12 @@ export class Application {
|
||||
|
||||
Loader.linkAppAfterBoot(this);
|
||||
|
||||
if (G_WEGAME_VERSION) {
|
||||
this.stateMgr.moveToState("WegameSplashState");
|
||||
}
|
||||
|
||||
// Check for mobile
|
||||
if (IS_MOBILE) {
|
||||
else if (IS_MOBILE) {
|
||||
this.stateMgr.moveToState("MobileWarningState");
|
||||
} else {
|
||||
this.stateMgr.moveToState("PreloadState");
|
||||
|
@ -1,4 +1,16 @@
|
||||
export const CHANGELOG = [
|
||||
// Not finished yet
|
||||
{
|
||||
version: "1.4.3",
|
||||
date: "preview",
|
||||
entries: [
|
||||
"Edit signal dialog now has the previous signal filled (Thanks to EmeraldBlock)",
|
||||
"Further performance improvements (Thanks to PFedak)",
|
||||
"Improved puzzle validation (Thanks to Sense101)",
|
||||
"Input fields in dialogs should now automatically focus",
|
||||
"Updated translations",
|
||||
],
|
||||
},
|
||||
{
|
||||
version: "1.4.2",
|
||||
date: "24.06.2021",
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { BaseItem } from "../game/base_item";
|
||||
import { ClickDetector } from "./click_detector";
|
||||
import { Signal } from "./signal";
|
||||
import { getIPCRenderer } from "./utils";
|
||||
|
||||
/*
|
||||
* ***************************************************
|
||||
@ -107,6 +108,19 @@ export class FormElementInput extends FormElement {
|
||||
|
||||
updateErrorState() {
|
||||
this.element.classList.toggle("errored", !this.isValid());
|
||||
|
||||
// profanity filter
|
||||
if (G_WEGAME_VERSION) {
|
||||
const value = String(this.element.value);
|
||||
|
||||
getIPCRenderer()
|
||||
.invoke("profanity-check", value)
|
||||
.then(newValue => {
|
||||
if (value !== newValue && this.element) {
|
||||
this.element.value = newValue;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
isValid() {
|
||||
@ -124,6 +138,7 @@ export class FormElementInput extends FormElement {
|
||||
|
||||
focus() {
|
||||
this.element.focus();
|
||||
this.element.select();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,6 +73,12 @@ export class ItemProcessorComponent extends Component {
|
||||
// Type of processing requirement
|
||||
this.processingRequirement = processingRequirement;
|
||||
|
||||
/**
|
||||
* Our current inputs
|
||||
* @type {Map<number, BaseItem>}
|
||||
*/
|
||||
this.inputSlots = new Map();
|
||||
|
||||
this.clear();
|
||||
}
|
||||
|
||||
@ -82,11 +88,13 @@ export class ItemProcessorComponent extends Component {
|
||||
// sure the outputs always match
|
||||
this.nextOutputSlot = 0;
|
||||
|
||||
this.inputSlots.clear();
|
||||
|
||||
/**
|
||||
* Our current inputs
|
||||
* @type {Array<{ item: BaseItem, sourceSlot: number }>}
|
||||
* Current input count
|
||||
* @type {number}
|
||||
*/
|
||||
this.inputSlots = [];
|
||||
this.inputCount = 0;
|
||||
|
||||
/**
|
||||
* What we are currently processing, empty if we don't produce anything rn
|
||||
@ -115,19 +123,17 @@ export class ItemProcessorComponent extends Component {
|
||||
this.type === enumItemProcessorTypes.goal
|
||||
) {
|
||||
// Hub has special logic .. not really nice but efficient.
|
||||
this.inputSlots.push({ item, sourceSlot });
|
||||
this.inputSlots.set(this.inputCount, item);
|
||||
this.inputCount++;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check that we only take one item per slot
|
||||
for (let i = 0; i < this.inputSlots.length; ++i) {
|
||||
const slot = this.inputSlots[i];
|
||||
if (slot.sourceSlot === sourceSlot) {
|
||||
if (this.inputSlots.has(sourceSlot)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
this.inputSlots.push({ item, sourceSlot });
|
||||
this.inputSlots.set(sourceSlot, item);
|
||||
this.inputCount++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ export class HUDPuzzleEditorReview extends BaseHUDPart {
|
||||
closeLoading();
|
||||
|
||||
//if it took so little ticks that it must have autocompeted
|
||||
if (simulatedTicks <= 300) {
|
||||
if (simulatedTicks <= 500) {
|
||||
this.root.hud.parts.dialogs.showWarning(
|
||||
T.puzzleMenu.validation.title,
|
||||
T.puzzleMenu.validation.autoComplete
|
||||
|
@ -585,12 +585,12 @@ export class RegularGameMode extends GameMode {
|
||||
}
|
||||
|
||||
/** @type {(typeof MetaBuilding)[]} */
|
||||
this.hiddenBuildings = [
|
||||
MetaConstantProducerBuilding,
|
||||
MetaGoalAcceptorBuilding,
|
||||
MetaBlockBuilding,
|
||||
MetaItemProducerBuilding,
|
||||
];
|
||||
this.hiddenBuildings = [MetaConstantProducerBuilding, MetaGoalAcceptorBuilding, MetaBlockBuilding];
|
||||
|
||||
// @ts-expect-error
|
||||
if (!(G_IS_DEV || window.sandboxMode || queryParamOptions.sandboxMode)) {
|
||||
this.hiddenBuildings.push(MetaItemProducerBuilding);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -49,11 +49,12 @@ export class ConstantSignalSystem extends GameSystemWithFilter {
|
||||
// Ok, query, but also save the uid because it could get stale
|
||||
const uid = entity.uid;
|
||||
|
||||
const signal = entity.components.ConstantSignal.signal;
|
||||
const signalValueInput = new FormElementInput({
|
||||
id: "signalValue",
|
||||
label: fillInLinkIntoTranslation(T.dialogs.editSignal.descShortKey, THIRDPARTY_URLS.shapeViewer),
|
||||
placeholder: "",
|
||||
defaultValue: "",
|
||||
defaultValue: signal ? signal.getAsCopyableKey() : "",
|
||||
validator: val => this.parseSignalCode(entity, val),
|
||||
});
|
||||
|
||||
|
@ -32,8 +32,8 @@ const MAX_QUEUED_CHARGES = 2;
|
||||
* Type of a processor implementation
|
||||
* @typedef {{
|
||||
* entity: Entity,
|
||||
* items: Array<{ item: BaseItem, sourceSlot: number }>,
|
||||
* itemsBySlot: Object<number, BaseItem>,
|
||||
* items: Map<number, BaseItem>,
|
||||
* inputCount: number,
|
||||
* outItems: Array<ProducedItem>
|
||||
* }} ProcessorImplementationPayload
|
||||
*/
|
||||
@ -189,7 +189,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
// DEFAULT
|
||||
// By default, we can start processing once all inputs are there
|
||||
case null: {
|
||||
return processorComp.inputSlots.length >= processorComp.inputsPerCharge;
|
||||
return processorComp.inputCount >= processorComp.inputsPerCharge;
|
||||
}
|
||||
|
||||
// QUAD PAINTER
|
||||
@ -197,18 +197,12 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
case enumItemProcessorRequirements.painterQuad: {
|
||||
const pinsComp = entity.components.WiredPins;
|
||||
|
||||
/** @type {Object.<number, { item: BaseItem, sourceSlot: number }>} */
|
||||
const itemsBySlot = {};
|
||||
for (let i = 0; i < processorComp.inputSlots.length; ++i) {
|
||||
itemsBySlot[processorComp.inputSlots[i].sourceSlot] = processorComp.inputSlots[i];
|
||||
}
|
||||
|
||||
// First slot is the shape, so if it's not there we can't do anything
|
||||
if (!itemsBySlot[0]) {
|
||||
const shapeItem = /** @type {ShapeItem} */ (processorComp.inputSlots.get(0));
|
||||
if (!shapeItem) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const shapeItem = /** @type {ShapeItem} */ (itemsBySlot[0].item);
|
||||
const slotStatus = [];
|
||||
|
||||
// Check which slots are enabled
|
||||
@ -233,7 +227,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
|
||||
// Check if all colors of the enabled slots are there
|
||||
for (let i = 0; i < slotStatus.length; ++i) {
|
||||
if (slotStatus[i] && !itemsBySlot[1 + i]) {
|
||||
if (slotStatus[i] && !processorComp.inputSlots.get(1 + i)) {
|
||||
// A slot which is enabled wasn't enabled. Make sure if there is anything on the quadrant,
|
||||
// it is not possible to paint, but if there is nothing we can ignore it
|
||||
for (let j = 0; j < 4; ++j) {
|
||||
@ -262,13 +256,6 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
|
||||
// First, take items
|
||||
const items = processorComp.inputSlots;
|
||||
processorComp.inputSlots = [];
|
||||
|
||||
/** @type {Object<string, BaseItem>} */
|
||||
const itemsBySlot = {};
|
||||
for (let i = 0; i < items.length; ++i) {
|
||||
itemsBySlot[items[i].sourceSlot] = items[i].item;
|
||||
}
|
||||
|
||||
/** @type {Array<ProducedItem>} */
|
||||
const outItems = [];
|
||||
@ -281,8 +268,8 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
handler({
|
||||
entity,
|
||||
items,
|
||||
itemsBySlot,
|
||||
outItems,
|
||||
inputCount: processorComp.inputCount,
|
||||
});
|
||||
|
||||
// Track produced items
|
||||
@ -304,6 +291,9 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
items: outItems,
|
||||
remainingTime: timeToProcess,
|
||||
});
|
||||
|
||||
processorComp.inputSlots.clear();
|
||||
processorComp.inputCount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -319,9 +309,14 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
|
||||
const nextSlot = processorComp.nextOutputSlot++ % availableSlots;
|
||||
|
||||
for (let i = 0; i < payload.items.length; ++i) {
|
||||
// Hardcoded to 2, to avoid accessing the length
|
||||
for (let i = 0; i < 2; ++i) {
|
||||
const item = payload.items.get(i);
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
payload.outItems.push({
|
||||
item: payload.items[i].item,
|
||||
item,
|
||||
preferredSlot: (nextSlot + i) % availableSlots,
|
||||
doNotTrack: true,
|
||||
});
|
||||
@ -333,7 +328,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
* @param {ProcessorImplementationPayload} payload
|
||||
*/
|
||||
process_CUTTER(payload) {
|
||||
const inputItem = /** @type {ShapeItem} */ (payload.items[0].item);
|
||||
const inputItem = /** @type {ShapeItem} */ (payload.items.get(0));
|
||||
assert(inputItem instanceof ShapeItem, "Input for cut is not a shape");
|
||||
const inputDefinition = inputItem.definition;
|
||||
|
||||
@ -354,7 +349,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
* @param {ProcessorImplementationPayload} payload
|
||||
*/
|
||||
process_CUTTER_QUAD(payload) {
|
||||
const inputItem = /** @type {ShapeItem} */ (payload.items[0].item);
|
||||
const inputItem = /** @type {ShapeItem} */ (payload.items.get(0));
|
||||
assert(inputItem instanceof ShapeItem, "Input for cut is not a shape");
|
||||
const inputDefinition = inputItem.definition;
|
||||
|
||||
@ -375,7 +370,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
* @param {ProcessorImplementationPayload} payload
|
||||
*/
|
||||
process_ROTATER(payload) {
|
||||
const inputItem = /** @type {ShapeItem} */ (payload.items[0].item);
|
||||
const inputItem = /** @type {ShapeItem} */ (payload.items.get(0));
|
||||
assert(inputItem instanceof ShapeItem, "Input for rotation is not a shape");
|
||||
const inputDefinition = inputItem.definition;
|
||||
|
||||
@ -389,7 +384,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
* @param {ProcessorImplementationPayload} payload
|
||||
*/
|
||||
process_ROTATER_CCW(payload) {
|
||||
const inputItem = /** @type {ShapeItem} */ (payload.items[0].item);
|
||||
const inputItem = /** @type {ShapeItem} */ (payload.items.get(0));
|
||||
assert(inputItem instanceof ShapeItem, "Input for rotation is not a shape");
|
||||
const inputDefinition = inputItem.definition;
|
||||
|
||||
@ -403,7 +398,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
* @param {ProcessorImplementationPayload} payload
|
||||
*/
|
||||
process_ROTATER_180(payload) {
|
||||
const inputItem = /** @type {ShapeItem} */ (payload.items[0].item);
|
||||
const inputItem = /** @type {ShapeItem} */ (payload.items.get(0));
|
||||
assert(inputItem instanceof ShapeItem, "Input for rotation is not a shape");
|
||||
const inputDefinition = inputItem.definition;
|
||||
|
||||
@ -417,8 +412,8 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
* @param {ProcessorImplementationPayload} payload
|
||||
*/
|
||||
process_STACKER(payload) {
|
||||
const lowerItem = /** @type {ShapeItem} */ (payload.itemsBySlot[0]);
|
||||
const upperItem = /** @type {ShapeItem} */ (payload.itemsBySlot[1]);
|
||||
const lowerItem = /** @type {ShapeItem} */ (payload.items.get(0));
|
||||
const upperItem = /** @type {ShapeItem} */ (payload.items.get(1));
|
||||
|
||||
assert(lowerItem instanceof ShapeItem, "Input for lower stack is not a shape");
|
||||
assert(upperItem instanceof ShapeItem, "Input for upper stack is not a shape");
|
||||
@ -444,8 +439,8 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
*/
|
||||
process_MIXER(payload) {
|
||||
// Find both colors and combine them
|
||||
const item1 = /** @type {ColorItem} */ (payload.items[0].item);
|
||||
const item2 = /** @type {ColorItem} */ (payload.items[1].item);
|
||||
const item1 = /** @type {ColorItem} */ (payload.items.get(0));
|
||||
const item2 = /** @type {ColorItem} */ (payload.items.get(1));
|
||||
assert(item1 instanceof ColorItem, "Input for color mixer is not a color");
|
||||
assert(item2 instanceof ColorItem, "Input for color mixer is not a color");
|
||||
|
||||
@ -467,8 +462,8 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
* @param {ProcessorImplementationPayload} payload
|
||||
*/
|
||||
process_PAINTER(payload) {
|
||||
const shapeItem = /** @type {ShapeItem} */ (payload.itemsBySlot[0]);
|
||||
const colorItem = /** @type {ColorItem} */ (payload.itemsBySlot[1]);
|
||||
const shapeItem = /** @type {ShapeItem} */ (payload.items.get(0));
|
||||
const colorItem = /** @type {ColorItem} */ (payload.items.get(1));
|
||||
|
||||
const colorizedDefinition = this.root.shapeDefinitionMgr.shapeActionPaintWith(
|
||||
shapeItem.definition,
|
||||
@ -484,9 +479,9 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
* @param {ProcessorImplementationPayload} payload
|
||||
*/
|
||||
process_PAINTER_DOUBLE(payload) {
|
||||
const shapeItem1 = /** @type {ShapeItem} */ (payload.itemsBySlot[0]);
|
||||
const shapeItem2 = /** @type {ShapeItem} */ (payload.itemsBySlot[1]);
|
||||
const colorItem = /** @type {ColorItem} */ (payload.itemsBySlot[2]);
|
||||
const shapeItem1 = /** @type {ShapeItem} */ (payload.items.get(0));
|
||||
const shapeItem2 = /** @type {ShapeItem} */ (payload.items.get(1));
|
||||
const colorItem = /** @type {ColorItem} */ (payload.items.get(2));
|
||||
|
||||
assert(shapeItem1 instanceof ShapeItem, "Input for painter is not a shape");
|
||||
assert(shapeItem2 instanceof ShapeItem, "Input for painter is not a shape");
|
||||
@ -514,14 +509,15 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
* @param {ProcessorImplementationPayload} payload
|
||||
*/
|
||||
process_PAINTER_QUAD(payload) {
|
||||
const shapeItem = /** @type {ShapeItem} */ (payload.itemsBySlot[0]);
|
||||
const shapeItem = /** @type {ShapeItem} */ (payload.items.get(0));
|
||||
assert(shapeItem instanceof ShapeItem, "Input for painter is not a shape");
|
||||
|
||||
/** @type {Array<enumColors>} */
|
||||
const colors = [null, null, null, null];
|
||||
for (let i = 0; i < 4; ++i) {
|
||||
if (payload.itemsBySlot[i + 1]) {
|
||||
colors[i] = /** @type {ColorItem} */ (payload.itemsBySlot[i + 1]).color;
|
||||
const colorItem = /** @type {ColorItem} */ (payload.items.get(i + 1));
|
||||
if (colorItem) {
|
||||
colors[i] = colorItem.color;
|
||||
}
|
||||
}
|
||||
|
||||
@ -540,7 +536,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
*/
|
||||
process_READER(payload) {
|
||||
// Pass through the item
|
||||
const item = payload.itemsBySlot[0];
|
||||
const item = payload.items.get(0);
|
||||
payload.outItems.push({
|
||||
item,
|
||||
doNotTrack: true,
|
||||
@ -559,8 +555,12 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
const hubComponent = payload.entity.components.Hub;
|
||||
assert(hubComponent, "Hub item processor has no hub component");
|
||||
|
||||
for (let i = 0; i < payload.items.length; ++i) {
|
||||
const item = /** @type {ShapeItem} */ (payload.items[i].item);
|
||||
// Hardcoded
|
||||
for (let i = 0; i < payload.inputCount; ++i) {
|
||||
const item = /** @type {ShapeItem} */ (payload.items.get(i));
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
this.root.hubGoals.handleDefinitionDelivered(item.definition);
|
||||
}
|
||||
}
|
||||
@ -570,7 +570,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
*/
|
||||
process_GOAL(payload) {
|
||||
const goalComp = payload.entity.components.GoalAcceptor;
|
||||
const item = payload.items[0].item;
|
||||
const item = payload.items.get(0);
|
||||
const now = this.root.time.now();
|
||||
|
||||
if (goalComp.item && !item.equals(goalComp.item)) {
|
||||
@ -584,7 +584,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
|
||||
|
||||
if (this.root.gameMode.getIsEditor()) {
|
||||
// while playing in editor, assign the item
|
||||
goalComp.item = payload.items[0].item;
|
||||
goalComp.item = item;
|
||||
}
|
||||
|
||||
goalComp.lastDelivery = {
|
||||
|
@ -111,6 +111,10 @@ export class ShapezGameAnalytics extends GameAnalyticsInterface {
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
sendToApi(endpoint, data) {
|
||||
if (G_WEGAME_VERSION) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const timeout = setTimeout(() => reject("Request to " + endpoint + " timed out"), 20000);
|
||||
|
||||
|
@ -130,7 +130,17 @@ export class MainMenuState extends GameState {
|
||||
|
||||
${
|
||||
G_WEGAME_VERSION
|
||||
? "<div class='footer wegame'></div>"
|
||||
? `<div class='footer wegameDisclaimer'>
|
||||
<div class="disclaimer">
|
||||
健康游戏忠告
|
||||
<br>
|
||||
抵制不良游戏,拒绝盗版游戏。注意自我保护,谨防受骗上当。<br>
|
||||
适度游戏益脑,沉迷游戏伤身。合理安排时间,享受健康生活。
|
||||
</div>
|
||||
|
||||
<div class="rating"></div>
|
||||
</div>
|
||||
`
|
||||
: `
|
||||
<div class="footer ${G_CHINA_VERSION ? "china" : ""} ">
|
||||
|
||||
@ -163,6 +173,15 @@ export class MainMenuState extends GameState {
|
||||
'<a class="producerLink" target="_blank">Tobias Springer</a>'
|
||||
)}</div>
|
||||
</div>
|
||||
|
||||
${
|
||||
G_IS_STANDALONE
|
||||
? ""
|
||||
: `
|
||||
<iframe id="crosspromo" src="https://crosspromo.tobspr.io?src=shapez_web"></iframe>
|
||||
|
||||
`
|
||||
}
|
||||
`
|
||||
}
|
||||
`;
|
||||
@ -341,6 +360,11 @@ export class MainMenuState extends GameState {
|
||||
if (puzzleWishlistButton) {
|
||||
this.trackClicks(puzzleWishlistButton, () => this.onPuzzleWishlistButtonClicked());
|
||||
}
|
||||
|
||||
const wegameRating = qs(".wegameDisclaimer > .rating");
|
||||
if (wegameRating) {
|
||||
this.trackClicks(wegameRating, () => this.onWegameRatingClicked());
|
||||
}
|
||||
}
|
||||
|
||||
renderMainMenu() {
|
||||
@ -675,6 +699,22 @@ export class MainMenuState extends GameState {
|
||||
});
|
||||
}
|
||||
|
||||
onWegameRatingClicked() {
|
||||
this.dialogs.showInfo(
|
||||
"",
|
||||
`
|
||||
1)本游戏是一款休闲建造类单机游戏,适用于年满8周岁及以上的用户。<br>
|
||||
2)本游戏模拟简单的生产流水线,剧情简单且积极向上,没有基于真实
|
||||
历史和现实事件的改编内容。游戏玩法为摆放简单的部件,完成生产目标。
|
||||
游戏为单机作品,没有基于文字和语音的陌生人社交系统。<br>
|
||||
3)游戏中有用户实名认证系统,认证为未成年人的用户将接受以下管理:
|
||||
游戏为买断制,不存在后续充值付费内容。未成年人用户每日22点到次日
|
||||
8点不得使用,法定节假日每天不得使用超过3小时,其它时间每天使用游
|
||||
戏不得超过1.5小时。
|
||||
`
|
||||
);
|
||||
}
|
||||
|
||||
onContinueButtonClicked() {
|
||||
let latestLastUpdate = 0;
|
||||
let latestInternalId;
|
||||
|
27
src/js/states/wegame_splash.js
Normal file
27
src/js/states/wegame_splash.js
Normal file
@ -0,0 +1,27 @@
|
||||
import { GameState } from "../core/game_state";
|
||||
|
||||
export class WegameSplashState extends GameState {
|
||||
constructor() {
|
||||
super("WegameSplashState");
|
||||
}
|
||||
|
||||
getInnerHTML() {
|
||||
return `
|
||||
<div class="wrapper">
|
||||
<strong>健康游戏忠告</strong>
|
||||
<div>抵制不良游戏,拒绝盗版游戏。</div>
|
||||
<div>注意自我保护,谨防受骗上当。</div>
|
||||
<div>适度游戏益脑,沉迷游戏伤身。</div>
|
||||
<div>适度游戏益脑,沉迷游戏伤身。</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
onEnter() {
|
||||
setTimeout(
|
||||
() => {
|
||||
this.app.stateMgr.moveToState("PreloadState");
|
||||
},
|
||||
G_IS_DEV ? 1 : 6000
|
||||
);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -11,14 +11,14 @@ steamPage:
|
||||
Et en plus, vous devrez aussi produire de plus en plus pour satisfaire la demande. La seule solution est de construire en plus grand ! Au début vous ne ferez que découper les formes, mais plus tard vous devrez les peindre — et pour ça vous devrez extraire et mélanger des couleurs !
|
||||
|
||||
En achetant le jeu sur Steam, vous aurez accès à la version complète, mais vous pouvez aussi jouer à une démo sur shapez.io et vous décider ensuite !
|
||||
what_others_say: Ce que les gens pensent de shapez.io
|
||||
nothernlion_comment: This game is great - I'm having a wonderful time playing,
|
||||
and time has flown by.
|
||||
notch_comment: Mince ! Je devrais vraiment me coucher, mais je crois que j'ai
|
||||
trouvé comment faire un ordinateur dans shapez.io
|
||||
steam_review_comment: This game has stolen my life and I don't want it back.
|
||||
Very chill factory game that won't let me stop making my lines more
|
||||
efficient.
|
||||
what_others_say: Ce que les gens pensent de Shapez.io
|
||||
nothernlion_comment: Ce jeu est génial - Je passe un merveilleux moment à jouer,
|
||||
et le temps s'est envolé.
|
||||
notch_comment: Mince ! Je devrais vraiment me coucher, mais je crois que j'ai trouvé
|
||||
comment faire un ordinateur dans Shapez.io
|
||||
steam_review_comment: Ce jeu a volé ma vie et je ne veux pas la récupérer.
|
||||
Jeu d'usine très cool qui ne me laissera pas arrêter de rendre mes lignes plus
|
||||
efficaces.
|
||||
global:
|
||||
loading: Chargement
|
||||
error: Erreur
|
||||
@ -71,11 +71,11 @@ mainMenu:
|
||||
savegameLevel: Niveau <x>
|
||||
savegameLevelUnknown: Niveau inconnu
|
||||
savegameUnnamed: Sans titre
|
||||
puzzleMode: Puzzle Mode
|
||||
back: Back
|
||||
puzzleDlcText: Vous aimez compacter et optimiser vos usines ? Achetez le DLC sur
|
||||
Steam dés maintenant pour encore plus d'amusement !
|
||||
puzzleDlcWishlist: Wishlist now!
|
||||
puzzleMode: Mode Puzzle
|
||||
back: Retour
|
||||
puzzleDlcText: Vous aimez compacter et optimiser vos usines ? Achetez le DLC
|
||||
sur Steam dès maintenant pour encore plus d'amusement!
|
||||
puzzleDlcWishlist: Ajoute à ta liste de souhaits maintenant !
|
||||
puzzleDlcViewNow: View Dlc
|
||||
dialogs:
|
||||
buttons:
|
||||
@ -90,7 +90,7 @@ dialogs:
|
||||
viewUpdate: Voir les mises à jour
|
||||
showUpgrades: Montrer les améliorations
|
||||
showKeybindings: Montrer les raccourcis
|
||||
retry: Réesayer
|
||||
retry: Réessayer
|
||||
continue: Continuer
|
||||
playOffline: Jouer Hors-ligne
|
||||
importSavegameError:
|
||||
@ -200,63 +200,61 @@ dialogs:
|
||||
desc: "Malheuresement, le puzzle n'a pas pu être chargé :"
|
||||
submitPuzzle:
|
||||
title: Envoyer le Puzzle
|
||||
descName: "Donnez un nom à votre puzzle :"
|
||||
descIcon: "Please enter a unique short key, which will be shown as the icon of
|
||||
your puzzle (You can generate them <link>here</link>, or choose one
|
||||
of the randomly suggested shapes below):"
|
||||
placeholderName: Puzzle Title
|
||||
descName: "Donnez un nom à votre puzzle:"
|
||||
descIcon: "Veuillez entrer un raccourci de forme unique, qui sera affichée comme icône de
|
||||
votre puzzle (Vous pouvez générer le raccourci d'une forme <link>ici</link>, ou en choisir une
|
||||
parmi les formes suggérées alétoirement ci-dessous):"
|
||||
placeholderName: Titre du Puzzle
|
||||
puzzleResizeBadBuildings:
|
||||
title: Resize not possible
|
||||
desc: You can't make the zone any smaller, because then some buildings would be
|
||||
outside the zone.
|
||||
title: Impossible de redimensionner
|
||||
desc: Vous ne pouvez pas rétrécir la zone, car certains bâtiments seraient en dehors de la zone
|
||||
puzzleLoadError:
|
||||
title: Mauvais Puzzle
|
||||
desc: "Le chargement du puzzle a échoué :"
|
||||
desc: "Le chargement du puzzle a échoué:"
|
||||
offlineMode:
|
||||
title: Mode hors-ligne
|
||||
desc: We couldn't reach the servers, so the game has to run in offline mode.
|
||||
Please make sure you have an active internet connection.
|
||||
desc: Nous n'avons pas pu atteindre les serveurs, donc le jeu doit être mis en mode hors ligne.
|
||||
Veuillez vous assurez que vous disposez d'une connexion Internet active.
|
||||
puzzleDownloadError:
|
||||
title: Erreur de téléchargment
|
||||
desc: "Le téléchargement à échoué :"
|
||||
desc: "Le téléchargement a échoué:"
|
||||
puzzleSubmitError:
|
||||
title: Erreur d'envoi
|
||||
desc: "L'envoi à échoué :"
|
||||
desc: "L'envoi a échoué:"
|
||||
puzzleSubmitOk:
|
||||
title: Puzzle envoyé
|
||||
desc: Félicitation ! Votre puzzle à été envoyé et peut maintenant être joué.
|
||||
desc: Félicitations ! Votre puzzle a été envoyé et peut maintenant être joué.
|
||||
Vous pouvez maintenant le retrouver dans la section "Mes Puzzles".
|
||||
puzzleCreateOffline:
|
||||
title: Mode Hors-ligne
|
||||
desc: Since you are offline, you will not be able to save and/or publish your
|
||||
puzzle. Would you still like to continue?
|
||||
desc: Puisque vous êtes hors ligne, vous ne pourrez pas enregistrer et/ou publier votre puzzle. Souhaitez-vous toujours continuer ?
|
||||
puzzlePlayRegularRecommendation:
|
||||
title: Recommendation
|
||||
desc: I <strong>strongly</strong> recommend playing the normal game to level 12
|
||||
before attempting the puzzle DLC, otherwise you may encounter
|
||||
mechanics not yet introduced. Do you still want to continue?
|
||||
title: Recommandation
|
||||
desc: Je recommande <strong>fortement</strong> de jouer au jeu normal jusqu'au niveau 12
|
||||
avant d'essayer le Puzzle DLC, sinon vous risqez de rencontrer
|
||||
des méchanismes pas encore introduits. Voulez-vous toujours continuer ?
|
||||
puzzleShare:
|
||||
title: Short Key Copied
|
||||
desc: The short key of the puzzle (<key>) has been copied to your clipboard! It
|
||||
can be entered in the puzzle menu to access the puzzle.
|
||||
title: Code copié
|
||||
desc: Le code du puzzle (<key>) a été copié dans ton presse-papiers ! Il
|
||||
peut être entré dans le menu des puzzles pour accéder au puzzle.
|
||||
puzzleReport:
|
||||
title: Report Puzzle
|
||||
title: Signaler le Puzzle
|
||||
options:
|
||||
profane: Profane
|
||||
unsolvable: Not solvable
|
||||
trolling: Trolling
|
||||
unsolvable: Irrésolvable
|
||||
trolling: Troll
|
||||
puzzleReportComplete:
|
||||
title: Merci pour votre retour !
|
||||
title: Merci pour votre retour!
|
||||
desc: Le puzzle a été marqué.
|
||||
puzzleReportError:
|
||||
title: Failed to report
|
||||
desc: "Your report could not get processed:"
|
||||
title: Échec du signalement
|
||||
desc: "Votre signalement n'a pas pu être effectué:"
|
||||
puzzleLoadShortKey:
|
||||
title: Enter short key
|
||||
desc: Enter the short key of the puzzle to load it.
|
||||
title: Entrer un code
|
||||
desc: Entrer le code du puzzle pour le charger.
|
||||
puzzleDelete:
|
||||
title: Delete Puzzle?
|
||||
desc: Are you sure you want to delete '<title>'? This can not be undone!
|
||||
title: Supprimer le puzzle ?
|
||||
desc: Êtes-vous sûr de vouloir supprimer '<title>' ? Cela sera irréversible !
|
||||
ingame:
|
||||
keybindingsOverlay:
|
||||
moveMap: Déplacer
|
||||
@ -430,28 +428,26 @@ ingame:
|
||||
title: Me soutenir
|
||||
desc: Je le développe pendant mon temps libre !
|
||||
achievements:
|
||||
title: Achievements
|
||||
desc: Hunt them all!
|
||||
title: Succès
|
||||
desc: Débloquez-les tous !
|
||||
puzzleEditorSettings:
|
||||
zoneTitle: Zone
|
||||
zoneWidth: Width
|
||||
zoneHeight: Height
|
||||
trimZone: Trim
|
||||
clearItems: Clear Items
|
||||
share: Share
|
||||
report: Report
|
||||
clearBuildings: Clear Buildings
|
||||
resetPuzzle: Reset Puzzle
|
||||
zoneWidth: Largeur
|
||||
zoneHeight: Hauteur
|
||||
trimZone: Optimiser la taille
|
||||
clearItems: Supprimer les objets
|
||||
share: Partager
|
||||
report: Signaler
|
||||
puzzleEditorControls:
|
||||
title: Puzzle Creator
|
||||
title: Créateur de Puzzles
|
||||
instructions:
|
||||
- 1. Place <strong>Constant Producers</strong> to provide shapes and
|
||||
colors to the player
|
||||
- 2. Build one or more shapes you want the player to build later and
|
||||
deliver it to one or more <strong>Goal Acceptors</strong>
|
||||
- 3. Once a Goal Acceptor receives a shape for a certain amount of
|
||||
time, it <strong>saves it as a goal</strong> that the player must
|
||||
produce later (Indicated by the <strong>green badge</strong>).
|
||||
- 1. Placez des <strong>Producteurs Constants</strong> pour fournir des formes et
|
||||
des couleurs au joueur
|
||||
- 2. Fabriquez une ou plusieurs formes que vous voulez que le joueur fabrique plus tard et
|
||||
délivrez-la/les à un ou plusieurs <strong>Récepteurs d'Objectif</strong>
|
||||
- 3. Une fois qu'un Récépteur d'Objectif a reçu une forme pendant un certain
|
||||
temps, il <strong>l'enregistre zn tant qu'objectif</strong> que le joueur devra
|
||||
produire plus tard (Indiqué par le <strong>badge vert</strong>).
|
||||
- 4. Click the <strong>lock button</strong> on a building to disable
|
||||
it.
|
||||
- 5. Once you click review, your puzzle will be validated and you
|
||||
@ -460,18 +456,18 @@ ingame:
|
||||
except for the Producers and Goal Acceptors - That's the part that
|
||||
the player is supposed to figure out for themselves, after all :)
|
||||
puzzleCompletion:
|
||||
title: Puzzle Completed!
|
||||
titleLike: "Click the heart if you liked the puzzle:"
|
||||
titleRating: How difficult did you find the puzzle?
|
||||
titleRatingDesc: Your rating will help me to make you better suggestions in the future
|
||||
continueBtn: Keep Playing
|
||||
title: Puzzle Résolu !
|
||||
titleLike: "Cliquez sur le cœur si vous avez aimé le Puzzle:"
|
||||
titleRating: À quel point avez-vous trouvé le puzzle diffcile ?
|
||||
titleRatingDesc: Votre note m'aidera à vous faire de meilleures suggestions à l'avenir
|
||||
continueBtn: Continuer à jouer
|
||||
menuBtn: Menu
|
||||
puzzleMetadata:
|
||||
author: Author
|
||||
author: Auteur
|
||||
shortKey: Short Key
|
||||
rating: Difficulty score
|
||||
averageDuration: Avg. Duration
|
||||
completionRate: Completion rate
|
||||
rating: Niveau de difficulté
|
||||
averageDuration: Durée moyenne
|
||||
completionRate: Taux de réussite
|
||||
shopUpgrades:
|
||||
belt:
|
||||
name: Convoyeurs, distributeurs et tunnels
|
||||
@ -691,25 +687,25 @@ buildings:
|
||||
calque de câblage sur le calque normal.
|
||||
constant_producer:
|
||||
default:
|
||||
name: Constant Producer
|
||||
description: Constantly outputs a specified shape or color.
|
||||
name: Producteur Constabnt
|
||||
description: Sort constamment une forme ou une couleur spécifiée.
|
||||
goal_acceptor:
|
||||
default:
|
||||
name: Goal Acceptor
|
||||
description: Deliver shapes to the goal acceptor to set them as a goal.
|
||||
name: Récepteur d'Objetcif
|
||||
description: Délivrez des formes au récepteur d'objectif pour les définir comme objectif.
|
||||
block:
|
||||
default:
|
||||
name: Block
|
||||
description: Allows you to block a tile.
|
||||
name: Bloc
|
||||
description: Permet de bloquer une case.
|
||||
storyRewards:
|
||||
reward_cutter_and_trash:
|
||||
title: Découpage de formes
|
||||
desc: You just unlocked the <strong>cutter</strong>, which cuts shapes in half
|
||||
from top to bottom <strong>regardless of its
|
||||
orientation</strong>!<br><br>Be sure to get rid of the waste, or
|
||||
otherwise <strong>it will clog and stall</strong> - For this purpose
|
||||
I have given you the <strong>trash</strong>, which destroys
|
||||
everything you put into it!
|
||||
desc: Vous venez de déverrouiller le <strong>découpeur</strong>, qui coupe les formes en deux
|
||||
de haut en bas <strong>indépendamment de son
|
||||
orientation</strong>!<br><br>Assurez-vous de vous débarrasser des déchets, ou
|
||||
sinon <strong>il se bouchera et se bloquera</strong> - À cet effet,
|
||||
Je vous ai donné la <strong>poubelle</strong>, qui détruit
|
||||
tout ce que vous mettez dedans !
|
||||
reward_rotater:
|
||||
title: Rotation
|
||||
desc: Le <strong>pivoteur</strong> a été débloqué ! Il pivote les formes de 90
|
||||
@ -735,9 +731,9 @@ storyRewards:
|
||||
<strong>placée au-dessus</strong> de la forme de gauche.
|
||||
reward_balancer:
|
||||
title: Répartiteur
|
||||
desc: The multifunctional <strong>balancer</strong> has been unlocked - It can
|
||||
be used to build bigger factories by <strong>splitting and merging
|
||||
items</strong> onto multiple belts!
|
||||
desc: Le <strong>répartiteur</strong> multifonctionnel a été débloqué - Il peut
|
||||
être utilisé pour construire de plus grandes usines en <strong>divisant et en rassemblant
|
||||
des objets</strong> sur plusieurs convoyeurs !
|
||||
reward_tunnel:
|
||||
title: Tunnel
|
||||
desc: Le <strong>tunnel</strong> a été débloqué. Vous pouvez maintenant faire
|
||||
@ -843,14 +839,14 @@ storyRewards:
|
||||
gâteau : je vous donne aussi le <strong>transistor</strong> !"
|
||||
reward_virtual_processing:
|
||||
title: Traitement virtuel
|
||||
desc: I just gave a whole bunch of new buildings which allow you to
|
||||
<strong>simulate the processing of shapes</strong>!<br><br> You can
|
||||
now simulate a cutter, rotator, stacker and more on the wires layer!
|
||||
With this you now have three options to continue the game:<br><br> -
|
||||
Build an <strong>automated machine</strong> to create any possible
|
||||
shape requested by the HUB (I recommend to try it!).<br><br> - Build
|
||||
something cool with wires.<br><br> - Continue to play
|
||||
normally.<br><br> Whatever you choose, remember to have fun!
|
||||
desc: Je viens de vous donner tout un tas de nouveaux bâtiments qui vous permettent de
|
||||
<strong>simuler le traitement des formes</strong>!<br><br> Vous pouvez
|
||||
maintenant simuler un découpeur, un pivoteur, un assembleur et plus encore sur la couche des fils !
|
||||
Avec cela vous avez maintenant trois options pour continuer le jeu:<br><br> -
|
||||
Construire une <strong>machine automatique</strong> pour créer toute forme
|
||||
possible demandée par le HUB (Je recommande d'essayer de le faire !).<br><br> - Construire
|
||||
quelque chose de cool avec les fils.<br><br> - Continuer à jouer
|
||||
normalement.<br><br> Quoi que vous choisissiez, n'oubliez pas de vous amuser !
|
||||
no_reward:
|
||||
title: Niveau suivant
|
||||
desc: "Ce niveau n’a pas de récompense mais le prochain, si !<br><br> PS : Ne
|
||||
@ -1127,10 +1123,10 @@ keybindings:
|
||||
rotateToDown: "Rotate: Point Down"
|
||||
rotateToRight: "Rotate: Point Right"
|
||||
rotateToLeft: "Rotate: Point Left"
|
||||
constant_producer: Constant Producer
|
||||
goal_acceptor: Goal Acceptor
|
||||
block: Block
|
||||
massSelectClear: Clear belts
|
||||
constant_producer: Producteur Constant
|
||||
goal_acceptor: Récepteur d'Objectif
|
||||
block: Bloc
|
||||
massSelectClear: Vider les convoyeurs
|
||||
about:
|
||||
title: À propos de ce jeu
|
||||
body: >-
|
||||
@ -1156,7 +1152,7 @@ demo:
|
||||
exportingBase: Exporter une image de toute la base
|
||||
settingNotAvailable: Indisponible dans la démo.
|
||||
tips:
|
||||
- Le centre n’importe quelle forme, pas seulement la forme actuelle !
|
||||
- Le centre accepte n’importe quelle forme, pas seulement la forme actuelle !
|
||||
- Assurez-vous que vos usines soient modulaires, cela paiera !
|
||||
- Ne construisez pas trop près du centre, ou ce sera un énorme chaos !
|
||||
- Si l’empilement ne fonctionne pas, essayez d’échanger les entrées.
|
||||
@ -1237,7 +1233,7 @@ puzzleMenu:
|
||||
edit: Éditer
|
||||
title: Mode Puzzle
|
||||
createPuzzle: Créer un Puzzle
|
||||
loadPuzzle: charger
|
||||
loadPuzzle: Charger
|
||||
reviewPuzzle: Revoir & Publier
|
||||
validatingPuzzle: Validation du Puzzle
|
||||
submittingPuzzle: Publication du Puzzle
|
||||
@ -1245,19 +1241,19 @@ puzzleMenu:
|
||||
categories:
|
||||
levels: Niveaux
|
||||
new: Nouveau
|
||||
top-rated: Les-mieux notés
|
||||
top-rated: Les mieux notés
|
||||
mine: Mes puzzles
|
||||
easy: Facile
|
||||
hard: Difficile
|
||||
completed: Complété
|
||||
medium: Medium
|
||||
official: Official
|
||||
official: Officiel
|
||||
trending: Trending today
|
||||
trending-weekly: Trending weekly
|
||||
categories: Categories
|
||||
difficulties: By Difficulty
|
||||
account: My Puzzles
|
||||
search: Search
|
||||
categories: Catégories
|
||||
difficulties: Par Difficulté
|
||||
account: Mes Puzzles
|
||||
search: Rechercher
|
||||
validation:
|
||||
title: Puzzle invalide
|
||||
noProducers: Veuillez placer un producteur constant !
|
||||
@ -1302,6 +1298,6 @@ backendErrors:
|
||||
bad-payload: La demande contient des données invalides.
|
||||
bad-building-placement: Votre puzzle contient des bâtiments placés non valides.
|
||||
timeout: La demande a expiré.
|
||||
too-many-likes-already: The puzzle alreay got too many likes. If you still want
|
||||
too-many-likes-already: The puzzle already got too many likes. If you still want
|
||||
to remove it, please contact support@shapez.io!
|
||||
no-permission: You do not have the permission to perform this action.
|
||||
|
@ -14,7 +14,7 @@ steamPage:
|
||||
Ondanks het feit dat je in het begin alleen vormen maakt, komt er een punt waarop je ze gaat kleuren. Deze kleuren kun je vinden en mengen!
|
||||
|
||||
Door het spel op Steam te kopen kun je de volledige versie spelen. Je kunt echter ook een demo versie spelen op shapez.io en later beslissen om over te schakelen zonder voortgang te verliezen.
|
||||
what_others_say: What people say about shapez.io
|
||||
what_others_say: Wat anderen vinden van shapez.io
|
||||
nothernlion_comment: This game is great - I'm having a wonderful time playing,
|
||||
and time has flown by.
|
||||
notch_comment: Oh crap. I really should sleep, but I think I just figured out
|
||||
@ -1166,7 +1166,6 @@ tips:
|
||||
wordt de planner geactiveerd, zodat je gemakkelijk lange rijen kunt
|
||||
plaatsen.
|
||||
- Knippers knippen altijd verticaal, ongeacht hun oriëntatie.
|
||||
- Meng alle drie de kleuren om wit te krijgen.
|
||||
- De opslagbuffer geeft prioriteit aan de eerste uitvoer.
|
||||
- Investeer tijd om herhaalbare ontwerpen te maken - het is het waard!
|
||||
- Door <b>SHIFT</b> ingedrukt te houden, kunnen meerdere gebouwen worden
|
||||
|
@ -1108,10 +1108,10 @@ keybindings:
|
||||
placementDisableAutoOrientation: Отключить автоопределение направления
|
||||
placeMultiple: Оставаться в режиме размещения
|
||||
placeInverse: Инвертировать автоопределение направления конвейеров
|
||||
constant_producer: Constant Producer
|
||||
goal_acceptor: Goal Acceptor
|
||||
block: Block
|
||||
massSelectClear: Clear belts
|
||||
constant_producer: Постоянный генератор
|
||||
goal_acceptor: Приёмник предметов
|
||||
block: Блок
|
||||
massSelectClear: Очистить конвейеры
|
||||
about:
|
||||
title: Об игре
|
||||
body: >-
|
||||
@ -1245,11 +1245,11 @@ puzzleMenu:
|
||||
постоянные производители не доставляют фигуры напрямую приемникам
|
||||
цели.
|
||||
difficulties:
|
||||
easy: Лего
|
||||
easy: Легко
|
||||
medium: Средне
|
||||
hard: Сложно
|
||||
dlcHint: Purchased the DLC already? Make sure it is activated by right clicking
|
||||
shapez.io in your library, selecting Properties > DLCs.
|
||||
dlcHint: Уже купили DLC? Проверьте, что оно активировано, нажав правый клик на
|
||||
shapez.io в своей библиотеке, и далее Свойства > Доп. Контент
|
||||
backendErrors:
|
||||
ratelimit: Вы слишком часто выполняете свои действия. Подождите немного.
|
||||
invalid-api-key: Не удалось связаться с сервером, попробуйте
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user