This commit is contained in:
tobspr 2021-08-04 13:46:05 +02:00
commit 97b44a8767
23 changed files with 1237 additions and 1032 deletions

View File

@ -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.
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/from-referrer/)
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/tobspr/shapez.io)
## Helping translate

View File

@ -1,5 +1,5 @@
const railsdk = require("./wegame_sdk/railsdk.js");
const { dialog, app } = require("electron");
const { dialog, app, remote, ipcMain } = require("electron");
function init(isDev) {
console.log("Step 1: wegame: init");
@ -47,6 +47,14 @@ function init(isDev) {
function listen() {
console.log("wegame: listen");
ipcMain.handle("profanity-check", async (event, data) => {
const result = railsdk.RailUtils.DirtyWordsFilter(data, true);
if (result.check_result.dirty_type !== 0 /** kRailDirtyWordsTypeNormalAllowWords */) {
return result.check_result;
}
return data;
});
}
module.exports = { init, listen };

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@ -21,6 +21,7 @@
@import "adinplay";
@import "changelog_skins";
@import "states/wegame_splash";
@import "states/preload";
@import "states/main_menu";
@import "states/ingame";

View File

@ -565,6 +565,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;

View 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);
}
}
}

View File

@ -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");

View File

@ -1,4 +1,15 @@
export const CHANGELOG = [
{
version: "1.4.3",
date: "unreleased",
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",

View File

@ -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();
}
}

View File

@ -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) {
return false;
}
if (this.inputSlots.has(sourceSlot)) {
return false;
}
this.inputSlots.push({ item, sourceSlot });
this.inputSlots.set(sourceSlot, item);
this.inputCount++;
return true;
}
}

View File

@ -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

View File

@ -80,6 +80,15 @@ export class GameLogic {
}
// Perform additional placement checks
if (this.root.gameMode.getIsEditor()) {
const toolbar = this.root.hud.parts.buildingsToolbar;
const id = entity.components.StaticMapEntity.getMetaBuilding().getId();
if (toolbar.buildingHandles[id].puzzleLocked) {
return false;
}
}
if (this.root.signals.prePlacementCheck.dispatch(entity, offset) === STOP_PROPAGATION) {
return false;
}

View File

@ -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);
}
}
/**

View File

@ -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),
});

View File

@ -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 = {

View File

@ -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);

View File

@ -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" : ""} ">
@ -341,6 +351,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 +690,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;

View 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

View File

@ -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 na 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 nimporte quelle forme, pas seulement la forme actuelle!
- Le centre accepte nimporte 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 lempilement 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.

View File

@ -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

File diff suppressed because it is too large Load Diff