mirror of
				https://github.com/tobspr/shapez.io.git
				synced 2025-06-13 13:04:03 +00:00 
			
		
		
		
	Merge branch 'master' of git://github.com/tobspr/shapez.io into feature/ore-q-ing
This commit is contained in:
		
						commit
						f43a266fad
					
				
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 14 KiB  | 
@ -1,3 +1,3 @@
 | 
			
		||||
version https://git-lfs.github.com/spec/v1
 | 
			
		||||
oid sha256:746c6cf3f0284798a78c08f77d7e9d0c28b02323081fda42b5fa876a7ade29a0
 | 
			
		||||
size 205925
 | 
			
		||||
oid sha256:40d458f800344d819ad4d3f38943f53f399258369ee5c20f6583d1b49847465f
 | 
			
		||||
size 188255
 | 
			
		||||
 | 
			
		||||
@ -36,7 +36,6 @@ module.exports = ({ watch = false, standalone = false }) => {
 | 
			
		||||
                    lzString.compressToEncodedURIComponent("http://localhost:10005/v1")
 | 
			
		||||
                ),
 | 
			
		||||
                G_IS_DEV: "true",
 | 
			
		||||
                G_IS_PROD: "false",
 | 
			
		||||
                G_IS_RELEASE: "false",
 | 
			
		||||
                G_IS_MOBILE_APP: "false",
 | 
			
		||||
                G_IS_BROWSER: "true",
 | 
			
		||||
 | 
			
		||||
@ -24,7 +24,6 @@ module.exports = ({
 | 
			
		||||
        assertAlways: "window.assert",
 | 
			
		||||
        abstract: "window.assert(false, 'abstract method called');",
 | 
			
		||||
        G_IS_DEV: "false",
 | 
			
		||||
        G_IS_PROD: "true",
 | 
			
		||||
        G_IS_RELEASE: environment === "prod" ? "true" : "false",
 | 
			
		||||
        G_IS_STANDALONE: standalone ? "true" : "false",
 | 
			
		||||
        G_IS_BROWSER: isBrowser ? "true" : "false",
 | 
			
		||||
 | 
			
		||||
@ -1,25 +1,78 @@
 | 
			
		||||
<?xml version="1.0" encoding="iso-8859-1"?>
 | 
			
		||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
 | 
			
		||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
 | 
			
		||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
 | 
			
		||||
	 viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
 | 
			
		||||
<g transform="translate(-1)">
 | 
			
		||||
	<path style="fill:#46B29D;" d="M328.61,98.163h0.088c1.971-0.012,3.923,0.379,5.738,1.148l71.683,29.484
 | 
			
		||||
		c4.07,1.723,7.249,5.049,8.787,9.193c1.537,4.144,1.297,8.739-0.665,12.699l-11.652,24.099
 | 
			
		||||
		c-5.942,12.252-10.388,25.174-13.242,38.488l-12.624,58.086c-1.107,5.424-5.003,9.857-10.24,11.652l-11.653,3.972
 | 
			
		||||
		c-5.094,1.809-8.94,6.053-10.241,11.299l-6.885,28.513c-0.25,1.103-0.635,2.17-1.148,3.178l-5.473,11.211
 | 
			
		||||
		c-2.003,4.139-5.709,7.201-10.152,8.386l-18.715,4.855c-7.018,1.83-11.893,8.196-11.829,15.448v11.211
 | 
			
		||||
		c-0.023,3.42-1.102,6.75-3.09,9.534l-19.51,26.748c-3.683,5.056-5.967,10.993-6.621,17.214l-6.091,56.585
 | 
			
		||||
		c-0.638,5.71-3.3,11.002-7.503,14.919c-4.172,3.812-9.621,5.922-15.272,5.914c-10.207-0.042-19.147-6.854-21.896-16.684
 | 
			
		||||
		L187.45,416.75c-0.269-0.922-0.447-1.868-0.53-2.825l-17.656-163.84c-0.585-5.323-3.801-9.997-8.563-12.447l-21.629-11.211
 | 
			
		||||
		c-5.391-2.781-9.662-7.331-12.094-12.888l-26.661-61.793c-4.326-9.941-2.235-21.509,5.297-29.308l10.064-10.417
 | 
			
		||||
		c3.583-3.658,5.192-8.813,4.326-13.859l-4.414-27.63c-2.316-13.91,2.107-28.094,11.918-38.223l18.715-19.244
 | 
			
		||||
		C154.266,4.72,165.356,0.003,176.945,0h29.662c11.59,0.003,22.679,4.72,30.721,13.065l16.244,16.684L328.61,98.163z"/>
 | 
			
		||||
	<path style="fill:#BDC3C7;" d="M283.478,97.103h35.31V220.69c0,9.751-7.904,17.655-17.655,17.655l0,0
 | 
			
		||||
		c-9.751,0-17.655-7.904-17.655-17.655V97.103z"/>
 | 
			
		||||
	<circle style="fill:#CC4B4C;" cx="301.133" cy="52.966" r="52.966"/>
 | 
			
		||||
	<path style="fill:#FB7B76;" d="M283.478,61.793c-4.875,0-8.828-3.952-8.828-8.828c0.016-14.619,11.863-26.467,26.483-26.483
 | 
			
		||||
		c4.875,0,8.828,3.952,8.828,8.828s-3.952,8.828-8.828,8.828c-4.873,0.006-8.821,3.955-8.828,8.828
 | 
			
		||||
		C292.305,57.841,288.353,61.793,283.478,61.793z"/>
 | 
			
		||||
<rect x="1.985" style="fill:#C8414B;" width="508.03" height="512"/>
 | 
			
		||||
<rect x="1.985" y="107.79" style="fill:#FFD250;" width="508.03" height="296.42"/>
 | 
			
		||||
<path style="fill:#C8414B;" d="M223.347,256.409l8.191-33.404c0.754-3.076-1.829-5.994-5.306-5.994h-5.77
 | 
			
		||||
	c-3.477,0-6.061,2.918-5.306,5.994L223.347,256.409z"/>
 | 
			
		||||
<rect x="213.681" y="238.89" style="fill:#F5F5F5;" width="19.322" height="74.42"/>
 | 
			
		||||
<rect x="208.861" y="230.14" style="fill:#FAB446;" width="28.984" height="8.756"/>
 | 
			
		||||
<g>
 | 
			
		||||
	<rect x="189.531" y="256.41" style="fill:#C8414B;" width="48.3" height="8.756"/>
 | 
			
		||||
	<polygon style="fill:#C8414B;" points="237.839,291.429 208.856,282.674 208.856,273.919 237.839,282.674 	"/>
 | 
			
		||||
	<path style="fill:#C8414B;" d="M78.435,256.409l8.191-33.404c0.754-3.076-1.829-5.994-5.306-5.994h-5.77
 | 
			
		||||
		c-3.477,0-6.061,2.918-5.306,5.994L78.435,256.409z"/>
 | 
			
		||||
</g>
 | 
			
		||||
<path style="fill:#F5F5F5;" d="M112.248,230.143c-5.335,0-9.661,3.919-9.661,8.756v56.908c0,10.638,10.955,30.643,48.305,30.643
 | 
			
		||||
	s48.305-20.006,48.305-30.643v-56.908c0-4.835-4.325-8.756-9.661-8.756H112.248L112.248,230.143z"/>
 | 
			
		||||
<g>
 | 
			
		||||
	<path style="fill:#C8414B;" d="M150.891,273.919h-48.305V239.34c0-5.079,4.118-9.197,9.197-9.197h39.107v43.776H150.891z"/>
 | 
			
		||||
	<path style="fill:#C8414B;" d="M150.891,273.919h48.305v20.784c0,12.698-10.294,22.992-22.992,22.992h-2.32
 | 
			
		||||
		c-12.698,0-22.992-10.294-22.992-22.992L150.891,273.919L150.891,273.919z"/>
 | 
			
		||||
</g>
 | 
			
		||||
<path style="fill:#FAB446;" d="M102.587,273.919h48.305v20.784c0,12.698-10.294,22.992-22.992,22.992h-2.32
 | 
			
		||||
	c-12.698,0-22.992-10.294-22.992-22.992C102.587,294.703,102.587,273.919,102.587,273.919z"/>
 | 
			
		||||
<g>
 | 
			
		||||
	<path style="fill:#C8414B;" d="M141.231,313.218v-39.299h-9.661v43.334C135.162,316.592,138.41,315.15,141.231,313.218z"/>
 | 
			
		||||
	<path style="fill:#C8414B;" d="M121.909,317.253v-43.334h-9.661v39.299C115.069,315.15,118.316,316.592,121.909,317.253z"/>
 | 
			
		||||
</g>
 | 
			
		||||
<rect x="112.241" y="256.41" style="fill:#FFB441;" width="28.984" height="8.756"/>
 | 
			
		||||
<g>
 | 
			
		||||
	<rect x="112.241" y="238.89" style="fill:#FAB446;" width="28.984" height="8.756"/>
 | 
			
		||||
	<rect x="117.081" y="244.1" style="fill:#FAB446;" width="19.322" height="15.861"/>
 | 
			
		||||
</g>
 | 
			
		||||
<rect x="68.774" y="238.89" style="fill:#F5F5F5;" width="19.322" height="74.42"/>
 | 
			
		||||
<g>
 | 
			
		||||
	<rect x="63.941" y="308.94" style="fill:#FAB446;" width="28.984" height="8.756"/>
 | 
			
		||||
	<rect x="63.941" y="230.14" style="fill:#FAB446;" width="28.984" height="8.756"/>
 | 
			
		||||
</g>
 | 
			
		||||
<rect x="59.111" y="317.7" style="fill:#5064AA;" width="38.643" height="8.756"/>
 | 
			
		||||
<rect x="213.681" y="308.94" style="fill:#FAB446;" width="28.984" height="8.756"/>
 | 
			
		||||
<rect x="204.031" y="317.7" style="fill:#5064AA;" width="38.643" height="8.756"/>
 | 
			
		||||
<rect x="121.911" y="221.39" style="fill:#FAB446;" width="57.967" height="8.756"/>
 | 
			
		||||
<rect x="146.061" y="195.13" style="fill:#FFB441;" width="9.661" height="26.27"/>
 | 
			
		||||
<g>
 | 
			
		||||
	<path style="fill:#F5F5F5;" d="M141.231,208.255c-7.991,0-14.491-5.891-14.491-13.132s6.5-13.132,14.491-13.132
 | 
			
		||||
		s14.491,5.891,14.491,13.132C155.721,202.364,149.221,208.255,141.231,208.255z M141.231,190.745c-2.665,0-4.83,1.963-4.83,4.378
 | 
			
		||||
		c0,2.415,2.165,4.378,4.83,4.378c2.665,0,4.83-1.963,4.83-4.378C146.061,192.707,143.896,190.745,141.231,190.745z"/>
 | 
			
		||||
	<path style="fill:#F5F5F5;" d="M160.552,208.255c-7.991,0-14.491-5.891-14.491-13.132s6.5-13.132,14.491-13.132
 | 
			
		||||
		s14.491,5.891,14.491,13.132C175.042,202.364,168.543,208.255,160.552,208.255z M160.552,190.745c-2.665,0-4.83,1.963-4.83,4.378
 | 
			
		||||
		c0,2.415,2.165,4.378,4.83,4.378c2.665,0,4.83-1.963,4.83-4.378C165.382,192.707,163.217,190.745,160.552,190.745z"/>
 | 
			
		||||
	<path style="fill:#F5F5F5;" d="M179.874,217.011c-7.991,0-14.491-5.891-14.491-13.132s6.5-13.132,14.491-13.132
 | 
			
		||||
		s14.491,5.891,14.491,13.132S187.864,217.011,179.874,217.011z M179.874,199.5c-2.665,0-4.83,1.963-4.83,4.378
 | 
			
		||||
		c0,2.415,2.165,4.378,4.83,4.378c2.665,0,4.83-1.963,4.83-4.378C184.704,201.462,182.539,199.5,179.874,199.5z"/>
 | 
			
		||||
	<path style="fill:#F5F5F5;" d="M121.909,217.011c-7.991,0-14.491-5.891-14.491-13.132s6.5-13.132,14.491-13.132
 | 
			
		||||
		s14.491,5.891,14.491,13.132C136.399,211.12,129.899,217.011,121.909,217.011z M121.909,199.5c-2.665,0-4.83,1.963-4.83,4.378
 | 
			
		||||
		c0,2.415,2.165,4.378,4.83,4.378s4.83-1.963,4.83-4.378C126.739,201.462,124.574,199.5,121.909,199.5z"/>
 | 
			
		||||
</g>
 | 
			
		||||
<path style="fill:#FAB446;" d="M179.874,291.429v4.378c0,2.414-2.167,4.378-4.83,4.378s-4.83-1.964-4.83-4.378v-4.378H179.874
 | 
			
		||||
	 M189.534,282.674h-28.983v13.132c0,7.241,6.501,13.132,14.491,13.132c7.991,0,14.491-5.891,14.491-13.132L189.534,282.674
 | 
			
		||||
	L189.534,282.674z"/>
 | 
			
		||||
<path style="fill:#FFA0D2;" d="M175.507,265.163h-0.928c-5.079,0-9.197-4.118-9.197-9.197v-7.872c0-5.079,4.118-9.197,9.197-9.197
 | 
			
		||||
	h0.928c5.079,0,9.197,4.118,9.197,9.197v7.872C184.704,261.047,180.586,265.163,175.507,265.163z"/>
 | 
			
		||||
<ellipse style="fill:#5064AA;" cx="150.891" cy="273.92" rx="14.491" ry="13.13"/>
 | 
			
		||||
<rect x="146.061" y="177.61" style="fill:#FAB446;" width="9.661" height="26.27"/>
 | 
			
		||||
<path style="fill:#C8414B;" d="M121.909,221.388l-9.661-8.756l5.659-5.129c8.748-7.928,20.613-12.381,32.984-12.381l0,0
 | 
			
		||||
	c12.371,0,24.237,4.454,32.984,12.381l5.659,5.129l-9.661,8.756H121.909z"/>
 | 
			
		||||
<g>
 | 
			
		||||
	<ellipse style="fill:#FFD250;" cx="150.891" cy="212.63" rx="4.83" ry="4.378"/>
 | 
			
		||||
	<ellipse style="fill:#FFD250;" cx="131.571" cy="212.63" rx="4.83" ry="4.378"/>
 | 
			
		||||
	<ellipse style="fill:#FFD250;" cx="170.211" cy="212.63" rx="4.83" ry="4.378"/>
 | 
			
		||||
</g>
 | 
			
		||||
<g>
 | 
			
		||||
	<rect x="63.941" y="256.41" style="fill:#C8414B;" width="48.3" height="8.756"/>
 | 
			
		||||
	<polygon style="fill:#C8414B;" points="63.943,291.429 92.926,282.674 92.926,273.919 63.943,282.674 	"/>
 | 
			
		||||
</g>
 | 
			
		||||
<g>
 | 
			
		||||
</g>
 | 
			
		||||
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 5.8 KiB  | 
@ -33,6 +33,7 @@ import { MainMenuState } from "./states/main_menu";
 | 
			
		||||
import { MobileWarningState } from "./states/mobile_warning";
 | 
			
		||||
import { PreloadState } from "./states/preload";
 | 
			
		||||
import { SettingsState } from "./states/settings";
 | 
			
		||||
import { ShapezGameAnalytics } from "./platform/browser/game_analytics";
 | 
			
		||||
 | 
			
		||||
const logger = createLogger("application");
 | 
			
		||||
 | 
			
		||||
@ -130,8 +131,7 @@ export class Application {
 | 
			
		||||
        this.adProvider = new NoAdProvider(this);
 | 
			
		||||
        this.sound = new SoundImplBrowser(this);
 | 
			
		||||
        this.analytics = new GoogleAnalyticsImpl(this);
 | 
			
		||||
        // this.gameAnalytics = new ShapezGameAnalytics(this);
 | 
			
		||||
        this.gameAnalytics = new NoGameAnalytics(this);
 | 
			
		||||
        this.gameAnalytics = new ShapezGameAnalytics(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,14 @@
 | 
			
		||||
export const CHANGELOG = [
 | 
			
		||||
    {
 | 
			
		||||
        version: "1.1.18",
 | 
			
		||||
        date: "24.06.2020",
 | 
			
		||||
        entries: [
 | 
			
		||||
            "Preparations for the wires update",
 | 
			
		||||
            "Add setting (on by default) to store the last used rotation per building instead of globally storing it (by Magos)",
 | 
			
		||||
            "Added chinese (traditional) translation",
 | 
			
		||||
            "Updated translations",
 | 
			
		||||
        ],
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        version: "1.1.17",
 | 
			
		||||
        date: "22.06.2020",
 | 
			
		||||
 | 
			
		||||
@ -9,7 +9,7 @@ export const IS_DEBUG =
 | 
			
		||||
 | 
			
		||||
export const IS_DEMO = queryParamOptions.fullVersion
 | 
			
		||||
    ? false
 | 
			
		||||
    : (G_IS_PROD && !G_IS_STANDALONE) ||
 | 
			
		||||
    : (!G_IS_DEV && !G_IS_STANDALONE) ||
 | 
			
		||||
      (typeof window !== "undefined" && window.location.search.indexOf("demo") >= 0);
 | 
			
		||||
 | 
			
		||||
export const SUPPORT_TOUCH = false;
 | 
			
		||||
 | 
			
		||||
@ -769,7 +769,7 @@ export function quantizeFloat(value) {
 | 
			
		||||
 * @param {number} tickRate Interval of the timer
 | 
			
		||||
 */
 | 
			
		||||
export function checkTimerExpired(now, lastTick, tickRate) {
 | 
			
		||||
    if (!G_IS_PROD) {
 | 
			
		||||
    if (G_IS_DEV) {
 | 
			
		||||
        if (quantizeFloat(now) !== now) {
 | 
			
		||||
            console.error("Got non-quantizied time:" + now + " vs " + quantizeFloat(now));
 | 
			
		||||
            now = quantizeFloat(now);
 | 
			
		||||
 | 
			
		||||
@ -3,13 +3,16 @@ import { BaseItem } from "../base_item";
 | 
			
		||||
import { Component } from "../component";
 | 
			
		||||
import { types } from "../../savegame/serialization";
 | 
			
		||||
import { gItemRegistry } from "../../core/global_registries";
 | 
			
		||||
import { Entity } from "../entity";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @typedef {{
 | 
			
		||||
 *    pos: Vector,
 | 
			
		||||
 *    direction: enumDirection,
 | 
			
		||||
 *    item: BaseItem,
 | 
			
		||||
 *    progress: number?
 | 
			
		||||
 *    progress: number?,
 | 
			
		||||
 *    cachedDestSlot?: import("./item_acceptor").ItemAcceptorLocatedSlot,
 | 
			
		||||
 *    cachedTargetEntity?: Entity
 | 
			
		||||
 * }} ItemEjectorSlot
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@ -19,6 +22,8 @@ export class ItemEjectorComponent extends Component {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static getSchema() {
 | 
			
		||||
        // The cachedDestSlot, cachedTargetEntity, and cachedConnectedSlots fields
 | 
			
		||||
        // are not serialized.
 | 
			
		||||
        return {
 | 
			
		||||
            instantEject: types.bool,
 | 
			
		||||
            slots: types.array(
 | 
			
		||||
@ -61,6 +66,9 @@ export class ItemEjectorComponent extends Component {
 | 
			
		||||
        this.instantEject = instantEject;
 | 
			
		||||
 | 
			
		||||
        this.setSlots(slots);
 | 
			
		||||
 | 
			
		||||
        /** @type {ItemEjectorSlot[]} */
 | 
			
		||||
        this.cachedConnectedSlots = null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -76,6 +84,8 @@ export class ItemEjectorComponent extends Component {
 | 
			
		||||
                direction: slot.direction,
 | 
			
		||||
                item: null,
 | 
			
		||||
                progress: 0,
 | 
			
		||||
                cachedDestSlot: null,
 | 
			
		||||
                cachedTargetEntity: null,
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -46,7 +46,13 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart {
 | 
			
		||||
         * The current rotation
 | 
			
		||||
         * @type {number}
 | 
			
		||||
         */
 | 
			
		||||
        this.currentBaseRotation = 0;
 | 
			
		||||
        this.currentBaseRotationGeneral = 0;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * The current rotation preference for each building.
 | 
			
		||||
         * @type{Object.<string,number>}
 | 
			
		||||
         */
 | 
			
		||||
        this.preferredBaseRotations = {};
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Whether we are currently dragging
 | 
			
		||||
@ -115,6 +121,39 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart {
 | 
			
		||||
        this.root.camera.upPostHandler.add(this.onMouseUp, this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the current base rotation for the current meta-building.
 | 
			
		||||
     * @returns {number}
 | 
			
		||||
     */
 | 
			
		||||
    get currentBaseRotation() {
 | 
			
		||||
        if (!this.root.app.settings.getAllSettings().rotationByBuilding) {
 | 
			
		||||
            return this.currentBaseRotationGeneral;
 | 
			
		||||
        }
 | 
			
		||||
        const metaBuilding = this.currentMetaBuilding.get();
 | 
			
		||||
        if (metaBuilding && this.preferredBaseRotations.hasOwnProperty(metaBuilding.getId())) {
 | 
			
		||||
            return this.preferredBaseRotations[metaBuilding.getId()];
 | 
			
		||||
        } else {
 | 
			
		||||
            return this.currentBaseRotationGeneral;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the base rotation for the current meta-building.
 | 
			
		||||
     * @param {number} rotation The new rotation/angle.
 | 
			
		||||
     */
 | 
			
		||||
    set currentBaseRotation(rotation) {
 | 
			
		||||
        if (!this.root.app.settings.getAllSettings().rotationByBuilding) {
 | 
			
		||||
            this.currentBaseRotationGeneral = rotation;
 | 
			
		||||
        } else {
 | 
			
		||||
            const metaBuilding = this.currentMetaBuilding.get();
 | 
			
		||||
            if (metaBuilding) {
 | 
			
		||||
                this.preferredBaseRotations[metaBuilding.getId()] = rotation;
 | 
			
		||||
            } else {
 | 
			
		||||
                this.currentBaseRotationGeneral = rotation;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns if the direction lock is currently active
 | 
			
		||||
     * @returns {boolean}
 | 
			
		||||
 | 
			
		||||
@ -7,6 +7,7 @@ import { Entity } from "../entity";
 | 
			
		||||
import { GameSystemWithFilter } from "../game_system_with_filter";
 | 
			
		||||
import { Math_min } from "../../core/builtins";
 | 
			
		||||
import { createLogger } from "../../core/logging";
 | 
			
		||||
import { Rectangle } from "../../core/rectangle";
 | 
			
		||||
 | 
			
		||||
const logger = createLogger("systems/ejector");
 | 
			
		||||
 | 
			
		||||
@ -14,23 +15,34 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
 | 
			
		||||
    constructor(root) {
 | 
			
		||||
        super(root, [ItemEjectorComponent]);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * @type {Array<{
 | 
			
		||||
         *  targetEntity: Entity,
 | 
			
		||||
         *  sourceSlot: import("../components/item_ejector").ItemEjectorSlot,
 | 
			
		||||
         *  destSlot: import("../components/item_acceptor").ItemAcceptorLocatedSlot
 | 
			
		||||
         * }>}
 | 
			
		||||
         */
 | 
			
		||||
        this.cache = [];
 | 
			
		||||
 | 
			
		||||
        this.cacheNeedsUpdate = true;
 | 
			
		||||
 | 
			
		||||
        this.root.signals.entityAdded.add(this.invalidateCache, this);
 | 
			
		||||
        this.root.signals.entityDestroyed.add(this.invalidateCache, this);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * @type {Rectangle[]}
 | 
			
		||||
         */
 | 
			
		||||
        this.smallCacheAreas = [];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    invalidateCache() {
 | 
			
		||||
    /**
 | 
			
		||||
     *
 | 
			
		||||
     * @param {Entity} entity
 | 
			
		||||
     */
 | 
			
		||||
    invalidateCache(entity) {
 | 
			
		||||
        if (!entity.components.StaticMapEntity) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.cacheNeedsUpdate = true;
 | 
			
		||||
 | 
			
		||||
        // Optimize for the common case: adding or removing one building at a time. Clicking
 | 
			
		||||
        // and dragging can cause up to 4 add/remove signals.
 | 
			
		||||
        const staticComp = entity.components.StaticMapEntity;
 | 
			
		||||
        const bounds = staticComp.getTileSpaceBounds();
 | 
			
		||||
        const expandedBounds = bounds.expandedInAllDirections(2);
 | 
			
		||||
        this.smallCacheAreas.push(expandedBounds);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -39,59 +51,102 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
 | 
			
		||||
    recomputeCache() {
 | 
			
		||||
        logger.log("Recomputing cache");
 | 
			
		||||
 | 
			
		||||
        const cache = [];
 | 
			
		||||
 | 
			
		||||
        // Try to find acceptors for every ejector
 | 
			
		||||
        for (let i = 0; i < this.allEntities.length; ++i) {
 | 
			
		||||
            const entity = this.allEntities[i];
 | 
			
		||||
            const ejectorComp = entity.components.ItemEjector;
 | 
			
		||||
            const staticComp = entity.components.StaticMapEntity;
 | 
			
		||||
 | 
			
		||||
            // For every ejector slot, try to find an acceptor
 | 
			
		||||
            for (let ejectorSlotIndex = 0; ejectorSlotIndex < ejectorComp.slots.length; ++ejectorSlotIndex) {
 | 
			
		||||
                const ejectorSlot = ejectorComp.slots[ejectorSlotIndex];
 | 
			
		||||
 | 
			
		||||
                // Figure out where and into which direction we eject items
 | 
			
		||||
                const ejectSlotWsTile = staticComp.localTileToWorld(ejectorSlot.pos);
 | 
			
		||||
                const ejectSlotWsDirection = staticComp.localDirectionToWorld(ejectorSlot.direction);
 | 
			
		||||
                const ejectSlotWsDirectionVector = enumDirectionToVector[ejectSlotWsDirection];
 | 
			
		||||
                const ejectSlotTargetWsTile = ejectSlotWsTile.add(ejectSlotWsDirectionVector);
 | 
			
		||||
 | 
			
		||||
                // Try to find the given acceptor component to take the item
 | 
			
		||||
                const targetEntity = this.root.map.getTileContent(ejectSlotTargetWsTile);
 | 
			
		||||
                if (!targetEntity) {
 | 
			
		||||
                    // No consumer for item
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                const targetAcceptorComp = targetEntity.components.ItemAcceptor;
 | 
			
		||||
                const targetStaticComp = targetEntity.components.StaticMapEntity;
 | 
			
		||||
                if (!targetAcceptorComp) {
 | 
			
		||||
                    // Entity doesn't accept items
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                const matchingSlot = targetAcceptorComp.findMatchingSlot(
 | 
			
		||||
                    targetStaticComp.worldToLocalTile(ejectSlotTargetWsTile),
 | 
			
		||||
                    targetStaticComp.worldDirectionToLocal(ejectSlotWsDirection)
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
                if (!matchingSlot) {
 | 
			
		||||
                    // No matching slot found
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Ok we found a connection
 | 
			
		||||
                cache.push({
 | 
			
		||||
                    targetEntity,
 | 
			
		||||
                    sourceSlot: ejectorSlot,
 | 
			
		||||
                    destSlot: matchingSlot,
 | 
			
		||||
                });
 | 
			
		||||
        let entryCount = 0;
 | 
			
		||||
        if (this.smallCacheAreas.length <= 4) {
 | 
			
		||||
            // Only recompute caches of entities inside the rectangles.
 | 
			
		||||
            for (let i = 0; i < this.smallCacheAreas.length; i++) {
 | 
			
		||||
                entryCount += this.recomputeAreaCaches(this.smallCacheAreas[i]);
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            // Try to find acceptors for every ejector
 | 
			
		||||
            for (let i = 0; i < this.allEntities.length; ++i) {
 | 
			
		||||
                const entity = this.allEntities[i];
 | 
			
		||||
                entryCount += this.recomputeSingleEntityCache(entity);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        logger.log("Found", entryCount, "entries to update");
 | 
			
		||||
 | 
			
		||||
        this.cache = cache;
 | 
			
		||||
        logger.log("Found", cache.length, "entries to update");
 | 
			
		||||
        this.smallCacheAreas = [];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     *
 | 
			
		||||
     * @param {Rectangle} area
 | 
			
		||||
     */
 | 
			
		||||
    recomputeAreaCaches(area) {
 | 
			
		||||
        let entryCount = 0;
 | 
			
		||||
        for (let x = area.x; x < area.right(); ++x) {
 | 
			
		||||
            for (let y = area.y; y < area.bottom(); ++y) {
 | 
			
		||||
                const entity = this.root.map.getTileContentXY(x, y);
 | 
			
		||||
                if (entity && entity.components.ItemEjector) {
 | 
			
		||||
                    entryCount += this.recomputeSingleEntityCache(entity);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return entryCount;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     *
 | 
			
		||||
     * @param {Entity} entity
 | 
			
		||||
     */
 | 
			
		||||
    recomputeSingleEntityCache(entity) {
 | 
			
		||||
        const ejectorComp = entity.components.ItemEjector;
 | 
			
		||||
        const staticComp = entity.components.StaticMapEntity;
 | 
			
		||||
 | 
			
		||||
        // Clear the old cache.
 | 
			
		||||
        ejectorComp.cachedConnectedSlots = null;
 | 
			
		||||
 | 
			
		||||
        // For every ejector slot, try to find an acceptor
 | 
			
		||||
        let entryCount = 0;
 | 
			
		||||
        for (let ejectorSlotIndex = 0; ejectorSlotIndex < ejectorComp.slots.length; ++ejectorSlotIndex) {
 | 
			
		||||
            const ejectorSlot = ejectorComp.slots[ejectorSlotIndex];
 | 
			
		||||
 | 
			
		||||
            // Clear the old cache.
 | 
			
		||||
            ejectorSlot.cachedDestSlot = null;
 | 
			
		||||
            ejectorSlot.cachedTargetEntity = null;
 | 
			
		||||
 | 
			
		||||
            // Figure out where and into which direction we eject items
 | 
			
		||||
            const ejectSlotWsTile = staticComp.localTileToWorld(ejectorSlot.pos);
 | 
			
		||||
            const ejectSlotWsDirection = staticComp.localDirectionToWorld(ejectorSlot.direction);
 | 
			
		||||
            const ejectSlotWsDirectionVector = enumDirectionToVector[ejectSlotWsDirection];
 | 
			
		||||
            const ejectSlotTargetWsTile = ejectSlotWsTile.add(ejectSlotWsDirectionVector);
 | 
			
		||||
 | 
			
		||||
            // Try to find the given acceptor component to take the item
 | 
			
		||||
            const targetEntity = this.root.map.getTileContent(ejectSlotTargetWsTile);
 | 
			
		||||
            if (!targetEntity) {
 | 
			
		||||
                // No consumer for item
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const targetAcceptorComp = targetEntity.components.ItemAcceptor;
 | 
			
		||||
            const targetStaticComp = targetEntity.components.StaticMapEntity;
 | 
			
		||||
            if (!targetAcceptorComp) {
 | 
			
		||||
                // Entity doesn't accept items
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const matchingSlot = targetAcceptorComp.findMatchingSlot(
 | 
			
		||||
                targetStaticComp.worldToLocalTile(ejectSlotTargetWsTile),
 | 
			
		||||
                targetStaticComp.worldDirectionToLocal(ejectSlotWsDirection)
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            if (!matchingSlot) {
 | 
			
		||||
                // No matching slot found
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Ok we found a connection
 | 
			
		||||
            if (ejectorComp.cachedConnectedSlots) {
 | 
			
		||||
                ejectorComp.cachedConnectedSlots.push(ejectorSlot);
 | 
			
		||||
            } else {
 | 
			
		||||
                ejectorComp.cachedConnectedSlots = [ejectorSlot];
 | 
			
		||||
            }
 | 
			
		||||
            ejectorSlot.cachedTargetEntity = targetEntity;
 | 
			
		||||
            ejectorSlot.cachedDestSlot = matchingSlot;
 | 
			
		||||
            entryCount += 1;
 | 
			
		||||
        }
 | 
			
		||||
        return entryCount;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    update() {
 | 
			
		||||
@ -109,35 +164,45 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Go over all cache entries
 | 
			
		||||
        for (let i = 0; i < this.cache.length; ++i) {
 | 
			
		||||
            const { sourceSlot, destSlot, targetEntity } = this.cache[i];
 | 
			
		||||
            const item = sourceSlot.item;
 | 
			
		||||
 | 
			
		||||
            if (!item) {
 | 
			
		||||
                // No item available to be ejected
 | 
			
		||||
        for (let i = 0; i < this.allEntities.length; ++i) {
 | 
			
		||||
            const sourceEntity = this.allEntities[i];
 | 
			
		||||
            const sourceEjectorComp = sourceEntity.components.ItemEjector;
 | 
			
		||||
            if (!sourceEjectorComp.cachedConnectedSlots) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            for (let j = 0; j < sourceEjectorComp.cachedConnectedSlots.length; j++) {
 | 
			
		||||
                const sourceSlot = sourceEjectorComp.cachedConnectedSlots[j];
 | 
			
		||||
                const destSlot = sourceSlot.cachedDestSlot;
 | 
			
		||||
                const targetEntity = sourceSlot.cachedTargetEntity;
 | 
			
		||||
 | 
			
		||||
            // Advance items on the slot
 | 
			
		||||
            sourceSlot.progress = Math_min(1, sourceSlot.progress + progressGrowth);
 | 
			
		||||
                const item = sourceSlot.item;
 | 
			
		||||
 | 
			
		||||
            // Check if we are still in the process of ejecting, can't proceed then
 | 
			
		||||
            if (sourceSlot.progress < 1.0) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
                if (!item) {
 | 
			
		||||
                    // No item available to be ejected
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            // Check if the target acceptor can actually accept this item
 | 
			
		||||
            const targetAcceptorComp = targetEntity.components.ItemAcceptor;
 | 
			
		||||
            if (!targetAcceptorComp.canAcceptItem(destSlot.index, item)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
                // Advance items on the slot
 | 
			
		||||
                sourceSlot.progress = Math_min(1, sourceSlot.progress + progressGrowth);
 | 
			
		||||
 | 
			
		||||
            // Try to hand over the item
 | 
			
		||||
            if (this.tryPassOverItem(item, targetEntity, destSlot.index)) {
 | 
			
		||||
                // Handover successful, clear slot
 | 
			
		||||
                targetAcceptorComp.onItemAccepted(destSlot.index, destSlot.acceptedDirection, item);
 | 
			
		||||
                sourceSlot.item = null;
 | 
			
		||||
                continue;
 | 
			
		||||
                // Check if we are still in the process of ejecting, can't proceed then
 | 
			
		||||
                if (sourceSlot.progress < 1.0) {
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Check if the target acceptor can actually accept this item
 | 
			
		||||
                const targetAcceptorComp = targetEntity.components.ItemAcceptor;
 | 
			
		||||
                if (!targetAcceptorComp.canAcceptItem(destSlot.index, item)) {
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Try to hand over the item
 | 
			
		||||
                if (this.tryPassOverItem(item, targetEntity, destSlot.index)) {
 | 
			
		||||
                    // Handover successful, clear slot
 | 
			
		||||
                    targetAcceptorComp.onItemAccepted(destSlot.index, destSlot.acceptedDirection, item);
 | 
			
		||||
                    sourceSlot.item = null;
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1
									
								
								src/js/globals.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								src/js/globals.d.ts
									
									
									
									
										vendored
									
									
								
							@ -1,7 +1,6 @@
 | 
			
		||||
// Globals defined by webpack
 | 
			
		||||
 | 
			
		||||
declare const G_IS_DEV: boolean;
 | 
			
		||||
declare const G_IS_PROD: boolean;
 | 
			
		||||
declare function assert(condition: boolean | object | string, ...errorMessage: string[]): void;
 | 
			
		||||
declare function assertAlways(condition: boolean | object | string, ...errorMessage: string[]): void;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -51,10 +51,10 @@ export const LANGUAGES = {
 | 
			
		||||
        region: "",
 | 
			
		||||
    },
 | 
			
		||||
    "es-419": {
 | 
			
		||||
        name: "Español (Latinoamérica)",
 | 
			
		||||
        name: "Español",
 | 
			
		||||
        data: require("./built-temp/base-es.json"),
 | 
			
		||||
        code: "es",
 | 
			
		||||
        region: "419",
 | 
			
		||||
        region: "",
 | 
			
		||||
    },
 | 
			
		||||
    "pl": {
 | 
			
		||||
        name: "Polski",
 | 
			
		||||
@ -80,12 +80,23 @@ export const LANGUAGES = {
 | 
			
		||||
        code: "no",
 | 
			
		||||
        region: "",
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    "zh-CN": {
 | 
			
		||||
        name: "简体中文",
 | 
			
		||||
        // simplified
 | 
			
		||||
        name: "中文简体",
 | 
			
		||||
        data: require("./built-temp/base-zh-CN.json"),
 | 
			
		||||
        code: "zh",
 | 
			
		||||
        region: "CN",
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    "zh-TW": {
 | 
			
		||||
        // traditional
 | 
			
		||||
        name: "中文繁體",
 | 
			
		||||
        data: require("./built-temp/base-zh-TW.json"),
 | 
			
		||||
        code: "zh",
 | 
			
		||||
        region: "TW",
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    "sv": {
 | 
			
		||||
        name: "Svenska",
 | 
			
		||||
        data: require("./built-temp/base-sv.json"),
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
import { GameAnalyticsInterface } from "../game_analytics";
 | 
			
		||||
import { createLogger } from "../../core/logging";
 | 
			
		||||
import { ShapeDefinition } from "../../game/shape_definition";
 | 
			
		||||
import { Savegame } from "../../savegame/savegame";
 | 
			
		||||
import { FILE_NOT_FOUND } from "../storage";
 | 
			
		||||
import { globalConfig } from "../../core/config";
 | 
			
		||||
import { InGameState } from "../../states/ingame";
 | 
			
		||||
import { createLogger } from "../../core/logging";
 | 
			
		||||
import { GameRoot } from "../../game/root";
 | 
			
		||||
import { InGameState } from "../../states/ingame";
 | 
			
		||||
import { GameAnalyticsInterface } from "../game_analytics";
 | 
			
		||||
import { FILE_NOT_FOUND } from "../storage";
 | 
			
		||||
import { blueprintShape, UPGRADES } from "../../game/upgrades";
 | 
			
		||||
import { tutorialGoals } from "../../game/tutorial_goals";
 | 
			
		||||
import { BeltComponent } from "../../game/components/belt";
 | 
			
		||||
import { StaticMapEntityComponent } from "../../game/components/static_map_entity";
 | 
			
		||||
 | 
			
		||||
const logger = createLogger("game_analytics");
 | 
			
		||||
@ -14,16 +15,32 @@ const analyticsUrl = G_IS_DEV ? "http://localhost:8001" : "https://analytics.sha
 | 
			
		||||
 | 
			
		||||
// Be sure to increment the ID whenever it changes to make sure all
 | 
			
		||||
// users are tracked
 | 
			
		||||
const analyticsLocalFile = "analytics_token.3.bin";
 | 
			
		||||
const analyticsLocalFile = "shapez_token_123.bin";
 | 
			
		||||
 | 
			
		||||
export class ShapezGameAnalytics extends GameAnalyticsInterface {
 | 
			
		||||
    get environment() {
 | 
			
		||||
        if (G_IS_DEV) {
 | 
			
		||||
            return "dev";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (G_IS_STANDALONE) {
 | 
			
		||||
            return "steam";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (G_IS_RELEASE) {
 | 
			
		||||
            return "prod";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return "beta";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @returns {Promise<void>}
 | 
			
		||||
     */
 | 
			
		||||
    initialize() {
 | 
			
		||||
        this.syncKey = null;
 | 
			
		||||
 | 
			
		||||
        setInterval(() => this.sendTimePoints(), 120 * 1000);
 | 
			
		||||
        setInterval(() => this.sendTimePoints(), 60 * 1000);
 | 
			
		||||
 | 
			
		||||
        // Retrieve sync key from player
 | 
			
		||||
        return this.app.storage.readFileAsync(analyticsLocalFile).then(
 | 
			
		||||
@ -38,7 +55,7 @@ export class ShapezGameAnalytics extends GameAnalyticsInterface {
 | 
			
		||||
 | 
			
		||||
                    // Perform call to get a new key from the API
 | 
			
		||||
                    this.sendToApi("/v1/register", {
 | 
			
		||||
                        environment: G_APP_ENVIRONMENT,
 | 
			
		||||
                        environment: this.environment,
 | 
			
		||||
                    })
 | 
			
		||||
                        .then(res => {
 | 
			
		||||
                            // Try to read and parse the key from the api
 | 
			
		||||
@ -135,10 +152,12 @@ export class ShapezGameAnalytics extends GameAnalyticsInterface {
 | 
			
		||||
            playerKey: this.syncKey,
 | 
			
		||||
            gameKey: savegameId,
 | 
			
		||||
            ingameTime: root.time.now(),
 | 
			
		||||
            environment: this.environment,
 | 
			
		||||
            category,
 | 
			
		||||
            value,
 | 
			
		||||
            version: G_BUILD_VERSION,
 | 
			
		||||
            gameDump: this.generateGameDump(root, category === "sync"),
 | 
			
		||||
            level: root.hubGoals.level,
 | 
			
		||||
            gameDump: this.generateGameDump(root),
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -151,52 +170,58 @@ export class ShapezGameAnalytics extends GameAnalyticsInterface {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Generates a game dump
 | 
			
		||||
     * @param {GameRoot} root
 | 
			
		||||
     * @param {boolean=} metaOnly
 | 
			
		||||
     * Returns true if the shape is interesting
 | 
			
		||||
     * @param {string} key
 | 
			
		||||
     */
 | 
			
		||||
    generateGameDump(root, metaOnly = false) {
 | 
			
		||||
        let staticEntities = [];
 | 
			
		||||
    isInterestingShape(key) {
 | 
			
		||||
        if (key === blueprintShape) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const entities = root.entityMgr.getAllWithComponent(StaticMapEntityComponent);
 | 
			
		||||
 | 
			
		||||
        // Limit the entities
 | 
			
		||||
        if (!metaOnly && entities.length < 500) {
 | 
			
		||||
            for (let i = 0; i < entities.length; ++i) {
 | 
			
		||||
                const entity = entities[i];
 | 
			
		||||
                const staticComp = entity.components.StaticMapEntity;
 | 
			
		||||
                const payload = {};
 | 
			
		||||
                payload.origin = staticComp.origin;
 | 
			
		||||
                payload.tileSize = staticComp.tileSize;
 | 
			
		||||
                payload.rotation = staticComp.rotation;
 | 
			
		||||
 | 
			
		||||
                if (entity.components.Belt) {
 | 
			
		||||
                    payload.type = "belt";
 | 
			
		||||
                } else if (entity.components.UndergroundBelt) {
 | 
			
		||||
                    payload.type = "tunnel";
 | 
			
		||||
                } else if (entity.components.ItemProcessor) {
 | 
			
		||||
                    payload.type = entity.components.ItemProcessor.type;
 | 
			
		||||
                } else if (entity.components.Miner) {
 | 
			
		||||
                    payload.type = "extractor";
 | 
			
		||||
                } else {
 | 
			
		||||
                    logger.warn("Unkown entity type", entity);
 | 
			
		||||
                }
 | 
			
		||||
                staticEntities.push(payload);
 | 
			
		||||
        // Check if its a story goal
 | 
			
		||||
        for (let i = 0; i < tutorialGoals.length; ++i) {
 | 
			
		||||
            if (key === tutorialGoals[i].shape) {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return {
 | 
			
		||||
            storedShapes: root.hubGoals.storedShapes,
 | 
			
		||||
            gainedRewards: root.hubGoals.gainedRewards,
 | 
			
		||||
            upgradeLevels: root.hubGoals.upgradeLevels,
 | 
			
		||||
            staticEntities,
 | 
			
		||||
        };
 | 
			
		||||
        // Check if its required to unlock an upgrade
 | 
			
		||||
        for (const upgradeKey in UPGRADES) {
 | 
			
		||||
            const handle = UPGRADES[upgradeKey];
 | 
			
		||||
            const tiers = handle.tiers;
 | 
			
		||||
            for (let i = 0; i < tiers.length; ++i) {
 | 
			
		||||
                const tier = tiers[i];
 | 
			
		||||
                const required = tier.required;
 | 
			
		||||
                for (let k = 0; k < required.length; ++k) {
 | 
			
		||||
                    if (required[k].shape === key) {
 | 
			
		||||
                        return true;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param {ShapeDefinition} definition
 | 
			
		||||
     * Generates a game dump
 | 
			
		||||
     * @param {GameRoot} root
 | 
			
		||||
     */
 | 
			
		||||
    handleShapeDelivered(definition) {}
 | 
			
		||||
    generateGameDump(root) {
 | 
			
		||||
        const shapeIds = Object.keys(root.hubGoals.storedShapes).filter(this.isInterestingShape.bind(this));
 | 
			
		||||
        let shapes = {};
 | 
			
		||||
        for (let i = 0; i < shapeIds.length; ++i) {
 | 
			
		||||
            shapes[shapeIds[i]] = root.hubGoals.storedShapes[shapeIds[i]];
 | 
			
		||||
        }
 | 
			
		||||
        return {
 | 
			
		||||
            shapes,
 | 
			
		||||
            upgrades: root.hubGoals.upgradeLevels,
 | 
			
		||||
            belts: root.entityMgr.getAllWithComponent(BeltComponent).length,
 | 
			
		||||
            buildings:
 | 
			
		||||
                root.entityMgr.getAllWithComponent(StaticMapEntityComponent).length -
 | 
			
		||||
                root.entityMgr.getAllWithComponent(BeltComponent).length,
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     */
 | 
			
		||||
@ -204,6 +229,12 @@ export class ShapezGameAnalytics extends GameAnalyticsInterface {
 | 
			
		||||
        this.sendGameEvent("game_start", "");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     */
 | 
			
		||||
    handleGameResumed() {
 | 
			
		||||
        this.sendTimePoints();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handles the given level completed
 | 
			
		||||
     * @param {number} level
 | 
			
		||||
 | 
			
		||||
@ -25,9 +25,9 @@ export class GameAnalyticsInterface {
 | 
			
		||||
    handleGameStarted() {}
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param {ShapeDefinition} definition
 | 
			
		||||
     * Handles a resumed game
 | 
			
		||||
     */
 | 
			
		||||
    handleShapeDelivered(definition) {}
 | 
			
		||||
    handleGameResumed() {}
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handles the given level completed
 | 
			
		||||
 | 
			
		||||
@ -251,6 +251,7 @@ export const allApplicationSettings = [
 | 
			
		||||
    new BoolSetting("vignette", categoryGame, (app, value) => {}),
 | 
			
		||||
    new BoolSetting("compactBuildingInfo", categoryGame, (app, value) => {}),
 | 
			
		||||
    new BoolSetting("disableCutDeleteWarnings", categoryGame, (app, value) => {}),
 | 
			
		||||
    new BoolSetting("rotationByBuilding", categoryGame, (app, value) => {}),
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
export function getApplicationSettingById(id) {
 | 
			
		||||
@ -277,6 +278,7 @@ class SettingsStorage {
 | 
			
		||||
        this.vignette = true;
 | 
			
		||||
        this.compactBuildingInfo = false;
 | 
			
		||||
        this.disableCutDeleteWarnings = false;
 | 
			
		||||
        this.rotationByBuilding = true;
 | 
			
		||||
 | 
			
		||||
        this.enableColorBlindHelper = false;
 | 
			
		||||
 | 
			
		||||
@ -479,7 +481,7 @@ export class ApplicationSettings extends ReadWriteProxy {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getCurrentVersion() {
 | 
			
		||||
        return 17;
 | 
			
		||||
        return 18;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** @param {{settings: SettingsStorage, version: number}} data */
 | 
			
		||||
@ -552,6 +554,11 @@ export class ApplicationSettings extends ReadWriteProxy {
 | 
			
		||||
            data.version = 17;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (data.version < 18) {
 | 
			
		||||
            data.settings.rotationByBuilding = true;
 | 
			
		||||
            data.version = 18;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return ExplainedResult.good();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -217,7 +217,6 @@ export class InGameState extends GameState {
 | 
			
		||||
            this.core.initializeRoot(this, this.savegame);
 | 
			
		||||
 | 
			
		||||
            if (this.savegame.hasGameDump()) {
 | 
			
		||||
                this.app.gameAnalytics.handleGameStarted();
 | 
			
		||||
                this.stage4bResumeGame();
 | 
			
		||||
            } else {
 | 
			
		||||
                this.app.gameAnalytics.handleGameStarted();
 | 
			
		||||
@ -245,6 +244,7 @@ export class InGameState extends GameState {
 | 
			
		||||
                this.onInitializationFailure("Savegame is corrupt and can not be restored.");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            this.app.gameAnalytics.handleGameResumed();
 | 
			
		||||
            this.stage5FirstUpdate();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -21,7 +21,7 @@ const placeholderRegexp = /<([a-zA-Z_0-9]+)>/gi;
 | 
			
		||||
 | 
			
		||||
function match(originalObj, translatedObj, path = "/") {
 | 
			
		||||
    for (const key in originalObj) {
 | 
			
		||||
        if (!translatedObj[key]) {
 | 
			
		||||
        if (!translatedObj.hasOwnProperty(key)) {
 | 
			
		||||
            console.warn(" | Missing key", path + key);
 | 
			
		||||
            translatedObj[key] = originalObj[key];
 | 
			
		||||
            continue;
 | 
			
		||||
@ -60,7 +60,7 @@ function match(originalObj, translatedObj, path = "/") {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (const key in translatedObj) {
 | 
			
		||||
        if (!originalObj[key]) {
 | 
			
		||||
        if (!originalObj.hasOwnProperty(key)) {
 | 
			
		||||
            console.warn(" | Obsolete key", path + key);
 | 
			
		||||
            delete translatedObj[key];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -531,7 +531,7 @@ storyRewards:
 | 
			
		||||
    reward_painter:
 | 
			
		||||
        title: Painting
 | 
			
		||||
        desc: >-
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, I'm working on a solution already!
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, there is a <strong>color blind mode</strong> in the settings!
 | 
			
		||||
 | 
			
		||||
    reward_mixer:
 | 
			
		||||
        title: Color Mixing
 | 
			
		||||
@ -728,6 +728,12 @@ settings:
 | 
			
		||||
        enableColorBlindHelper:
 | 
			
		||||
            title: Color Blind Mode
 | 
			
		||||
            description: Enables various tools which allow to play the game if you are color blind.
 | 
			
		||||
        rotationByBuilding:
 | 
			
		||||
          title: Rotation by building type
 | 
			
		||||
          description: >-
 | 
			
		||||
            Each building type remembers the rotation you last set it to individually.
 | 
			
		||||
            This may be more comfortable if you frequently switch between placing
 | 
			
		||||
            different building types.
 | 
			
		||||
 | 
			
		||||
keybindings:
 | 
			
		||||
    title: Keybindings
 | 
			
		||||
 | 
			
		||||
@ -512,7 +512,7 @@ storyRewards:
 | 
			
		||||
    reward_painter:
 | 
			
		||||
        title: Barvení
 | 
			
		||||
        desc: >-
 | 
			
		||||
            <strong>Barvič</strong> byl právě odemčen - vytěžte nějakou barvu (stejně jako těžíte tvary) a skombinujte ji v barviči s tvarem pro obarvení!<br><br>PS: Pokud jste barvoslepí, nebojte, již pracuju na řešení.!
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, there is a <strong>color blind mode</strong> in the settings!
 | 
			
		||||
 | 
			
		||||
    reward_mixer:
 | 
			
		||||
        title: Míchání barev
 | 
			
		||||
@ -708,6 +708,12 @@ settings:
 | 
			
		||||
        enableColorBlindHelper:
 | 
			
		||||
            title: Režim pro barvoslepé
 | 
			
		||||
            description: Zapné různé nástroje, které vám umožní hrát hru i pokud jste barvoslepí.
 | 
			
		||||
        rotationByBuilding:
 | 
			
		||||
          title: Rotation by building type
 | 
			
		||||
          description: >-
 | 
			
		||||
            Each building type remembers the rotation you last set it to individually.
 | 
			
		||||
            This may be more comfortable if you frequently switch between placing
 | 
			
		||||
            different building types.
 | 
			
		||||
 | 
			
		||||
keybindings:
 | 
			
		||||
    title: Klávesové zkratky
 | 
			
		||||
 | 
			
		||||
@ -532,7 +532,7 @@ storyRewards:
 | 
			
		||||
    reward_painter:
 | 
			
		||||
        title: Färben
 | 
			
		||||
        desc: >-
 | 
			
		||||
            Der <strong>Färber</strong> wurde freigeschaltet! Extrahiere ein paar Farben (genauso wie die Formen) und lasse sie vom Färber bemalen!<br><br>PS: Falls du farbenblind bist: Ich arbeite bereits an einer Lösung!
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, there is a <strong>color blind mode</strong> in the settings!
 | 
			
		||||
 | 
			
		||||
    reward_mixer:
 | 
			
		||||
        title: Farben mischen
 | 
			
		||||
@ -728,6 +728,12 @@ settings:
 | 
			
		||||
        enableColorBlindHelper:
 | 
			
		||||
            title: Modus für Farbenblinde
 | 
			
		||||
            description: Aktiviert verschiedene Werkzeuge, die dir das Spielen trotz Farbenblindheit ermöglichen.
 | 
			
		||||
        rotationByBuilding:
 | 
			
		||||
          title: Rotation by building type
 | 
			
		||||
          description: >-
 | 
			
		||||
            Each building type remembers the rotation you last set it to individually.
 | 
			
		||||
            This may be more comfortable if you frequently switch between placing
 | 
			
		||||
            different building types.
 | 
			
		||||
 | 
			
		||||
keybindings:
 | 
			
		||||
    title: Tastenbelegung
 | 
			
		||||
 | 
			
		||||
@ -531,7 +531,7 @@ storyRewards:
 | 
			
		||||
    reward_painter:
 | 
			
		||||
        title: Painting
 | 
			
		||||
        desc: >-
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, I'm working on a solution already!
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, there is a <strong>color blind mode</strong> in the settings!
 | 
			
		||||
 | 
			
		||||
    reward_mixer:
 | 
			
		||||
        title: Color Mixing
 | 
			
		||||
@ -729,6 +729,12 @@ settings:
 | 
			
		||||
        enableColorBlindHelper:
 | 
			
		||||
            title: Color Blind Mode
 | 
			
		||||
            description: Enables various tools which allow to play the game if you are color blind.
 | 
			
		||||
        rotationByBuilding:
 | 
			
		||||
          title: Rotation by building type
 | 
			
		||||
          description: >-
 | 
			
		||||
            Each building type remembers the rotation you last set it to individually.
 | 
			
		||||
            This may be more comfortable if you frequently switch between placing
 | 
			
		||||
            different building types.
 | 
			
		||||
 | 
			
		||||
keybindings:
 | 
			
		||||
    title: Keybindings
 | 
			
		||||
 | 
			
		||||
@ -534,7 +534,7 @@ storyRewards:
 | 
			
		||||
    reward_painter:
 | 
			
		||||
        title: Painting
 | 
			
		||||
        desc: >-
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, I'm working on a solution already!
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, there is a <strong>color blind mode</strong> in the settings!
 | 
			
		||||
 | 
			
		||||
    reward_mixer:
 | 
			
		||||
        title: Color Mixing
 | 
			
		||||
@ -721,6 +721,11 @@ settings:
 | 
			
		||||
            title: Vignette
 | 
			
		||||
            description: >-
 | 
			
		||||
                Enables the vignette which darkens the screen corners and makes text easier to read.
 | 
			
		||||
        
 | 
			
		||||
        rotationByBuilding: 
 | 
			
		||||
            title: Rotation by building type
 | 
			
		||||
            description: >-
 | 
			
		||||
                Each building type remembers the rotation you last set it to individually. This may be more comfortable if you frequently switch between placing different building types.
 | 
			
		||||
 | 
			
		||||
        compactBuildingInfo:
 | 
			
		||||
            title: Compact Building Infos
 | 
			
		||||
 | 
			
		||||
@ -528,7 +528,8 @@ storyRewards:
 | 
			
		||||
    reward_painter:
 | 
			
		||||
        title: Pintor
 | 
			
		||||
        desc: >-
 | 
			
		||||
            El <strong> pintor</strong> ha sido desbloqueado - ¡Extrae color de las betas (al igual que haces con las figuras) y combínalo con una figura para pintarla de ese color!<br><br> PS: Si eres daltónico, estoy trabajando en una solución!
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, there is a <strong>color blind mode</strong> in the settings!
 | 
			
		||||
 | 
			
		||||
    reward_mixer:
 | 
			
		||||
        title: Mezclador de Color
 | 
			
		||||
        desc: El <strong>mezclador</strong> ha sido desbloqueado - ¡Combina dos colores usando <strong>mezcla aditiva</strong> con este edificio!
 | 
			
		||||
@ -716,6 +717,12 @@ settings:
 | 
			
		||||
        enableColorBlindHelper:
 | 
			
		||||
            title: Modo para Daltonicos
 | 
			
		||||
            description: Activa varias herramientas que permiten jugar si eres daltonico.
 | 
			
		||||
        rotationByBuilding:
 | 
			
		||||
          title: Rotation by building type
 | 
			
		||||
          description: >-
 | 
			
		||||
            Each building type remembers the rotation you last set it to individually.
 | 
			
		||||
            This may be more comfortable if you frequently switch between placing
 | 
			
		||||
            different building types.
 | 
			
		||||
 | 
			
		||||
keybindings:
 | 
			
		||||
    title: Atajos de Teclado
 | 
			
		||||
 | 
			
		||||
@ -533,7 +533,7 @@ storyRewards:
 | 
			
		||||
    reward_painter:
 | 
			
		||||
        title: Peintre
 | 
			
		||||
        desc: >-
 | 
			
		||||
            Le <strong>peintre</strong> a été débloqué - Extrayez des pigments de couleur (comme vous le faites avec les formes) et combinez les avec une forme dans un peintre pour les colorier !<br><br>PS: Si vous êtes daltonien, je travaille déjà à une solution !
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, there is a <strong>color blind mode</strong> in the settings!
 | 
			
		||||
 | 
			
		||||
    reward_mixer:
 | 
			
		||||
        title: Mélangeur de couleurs
 | 
			
		||||
@ -727,6 +727,12 @@ settings:
 | 
			
		||||
        enableColorBlindHelper:
 | 
			
		||||
            title: Mode Daltonien
 | 
			
		||||
            description: Active divers outils qui permettent de jouer à ce jeu si vous êtes daltonien.
 | 
			
		||||
        rotationByBuilding:
 | 
			
		||||
          title: Rotation by building type
 | 
			
		||||
          description: >-
 | 
			
		||||
            Each building type remembers the rotation you last set it to individually.
 | 
			
		||||
            This may be more comfortable if you frequently switch between placing
 | 
			
		||||
            different building types.
 | 
			
		||||
 | 
			
		||||
keybindings:
 | 
			
		||||
    title: Contrôles
 | 
			
		||||
 | 
			
		||||
@ -531,7 +531,7 @@ storyRewards:
 | 
			
		||||
    reward_painter:
 | 
			
		||||
        title: Painting
 | 
			
		||||
        desc: >-
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, I'm working on a solution already!
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, there is a <strong>color blind mode</strong> in the settings!
 | 
			
		||||
 | 
			
		||||
    reward_mixer:
 | 
			
		||||
        title: Color Mixing
 | 
			
		||||
@ -727,6 +727,12 @@ settings:
 | 
			
		||||
        enableColorBlindHelper:
 | 
			
		||||
            title: Color Blind Mode
 | 
			
		||||
            description: Enables various tools which allow to play the game if you are color blind.
 | 
			
		||||
        rotationByBuilding:
 | 
			
		||||
          title: Rotation by building type
 | 
			
		||||
          description: >-
 | 
			
		||||
            Each building type remembers the rotation you last set it to individually.
 | 
			
		||||
            This may be more comfortable if you frequently switch between placing
 | 
			
		||||
            different building types.
 | 
			
		||||
 | 
			
		||||
keybindings:
 | 
			
		||||
    title: Keybindings
 | 
			
		||||
 | 
			
		||||
@ -530,7 +530,7 @@ storyRewards:
 | 
			
		||||
    reward_painter:
 | 
			
		||||
        title: Painting
 | 
			
		||||
        desc: >-
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, I'm working on a solution already!
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, there is a <strong>color blind mode</strong> in the settings!
 | 
			
		||||
 | 
			
		||||
    reward_mixer:
 | 
			
		||||
        title: Color Mixing
 | 
			
		||||
@ -726,6 +726,12 @@ settings:
 | 
			
		||||
        enableColorBlindHelper:
 | 
			
		||||
            title: Color Blind Mode
 | 
			
		||||
            description: Enables various tools which allow to play the game if you are color blind.
 | 
			
		||||
        rotationByBuilding:
 | 
			
		||||
          title: Rotation by building type
 | 
			
		||||
          description: >-
 | 
			
		||||
            Each building type remembers the rotation you last set it to individually.
 | 
			
		||||
            This may be more comfortable if you frequently switch between placing
 | 
			
		||||
            different building types.
 | 
			
		||||
 | 
			
		||||
keybindings:
 | 
			
		||||
    title: Keybindings
 | 
			
		||||
 | 
			
		||||
@ -531,7 +531,7 @@ storyRewards:
 | 
			
		||||
    reward_painter:
 | 
			
		||||
        title: Painting
 | 
			
		||||
        desc: >-
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, I'm working on a solution already!
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, there is a <strong>color blind mode</strong> in the settings!
 | 
			
		||||
 | 
			
		||||
    reward_mixer:
 | 
			
		||||
        title: Color Mixing
 | 
			
		||||
@ -727,6 +727,12 @@ settings:
 | 
			
		||||
        enableColorBlindHelper:
 | 
			
		||||
            title: Color Blind Mode
 | 
			
		||||
            description: Enables various tools which allow to play the game if you are color blind.
 | 
			
		||||
        rotationByBuilding:
 | 
			
		||||
          title: Rotation by building type
 | 
			
		||||
          description: >-
 | 
			
		||||
            Each building type remembers the rotation you last set it to individually.
 | 
			
		||||
            This may be more comfortable if you frequently switch between placing
 | 
			
		||||
            different building types.
 | 
			
		||||
 | 
			
		||||
keybindings:
 | 
			
		||||
    title: Keybindings
 | 
			
		||||
 | 
			
		||||
@ -530,7 +530,7 @@ storyRewards:
 | 
			
		||||
    reward_painter:
 | 
			
		||||
        title: 着色
 | 
			
		||||
        desc: >-
 | 
			
		||||
            <strong>着色機</strong>が利用可能になりました。 - 色の鉱脈から形の手順と同様に色を抽出し、着色機で形と組み合わせることで着色できます。<br><br>PS:もしあなたが色の認識に問題があっても安心してください。我々はすでにその解決に着手しています!
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, there is a <strong>color blind mode</strong> in the settings!
 | 
			
		||||
 | 
			
		||||
    reward_mixer:
 | 
			
		||||
        title: 色の混合
 | 
			
		||||
@ -722,6 +722,12 @@ settings:
 | 
			
		||||
        enableColorBlindHelper:
 | 
			
		||||
            title: 色覚モード
 | 
			
		||||
            description: 色覚異常を持っていてもゲームがプレイできるようにするための各種ツールを有効化します。
 | 
			
		||||
        rotationByBuilding:
 | 
			
		||||
          title: Rotation by building type
 | 
			
		||||
          description: >-
 | 
			
		||||
            Each building type remembers the rotation you last set it to individually.
 | 
			
		||||
            This may be more comfortable if you frequently switch between placing
 | 
			
		||||
            different building types.
 | 
			
		||||
 | 
			
		||||
keybindings:
 | 
			
		||||
    title: キー設定
 | 
			
		||||
 | 
			
		||||
@ -531,7 +531,7 @@ storyRewards:
 | 
			
		||||
    reward_painter:
 | 
			
		||||
        title: 색칠기
 | 
			
		||||
        desc: >-
 | 
			
		||||
            <strong>색칠기</strong>가 잠금 해제 되었습니다! 색소 광물을 추출해서 이 기계로 도형을 색칠하세요. <br><br>PS: 당신이 색맹이라면, 해결책을 찾고 있으니 잠시만 기다려주세요!
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, there is a <strong>color blind mode</strong> in the settings!
 | 
			
		||||
 | 
			
		||||
    reward_mixer:
 | 
			
		||||
        title: 혼합기
 | 
			
		||||
@ -728,6 +728,12 @@ settings:
 | 
			
		||||
        enableColorBlindHelper:
 | 
			
		||||
            title: Color Blind Mode
 | 
			
		||||
            description: Enables various tools which allow to play the game if you are color blind.
 | 
			
		||||
        rotationByBuilding:
 | 
			
		||||
          title: Rotation by building type
 | 
			
		||||
          description: >-
 | 
			
		||||
            Each building type remembers the rotation you last set it to individually.
 | 
			
		||||
            This may be more comfortable if you frequently switch between placing
 | 
			
		||||
            different building types.
 | 
			
		||||
 | 
			
		||||
keybindings:
 | 
			
		||||
    title: 키바인딩
 | 
			
		||||
 | 
			
		||||
@ -531,7 +531,7 @@ storyRewards:
 | 
			
		||||
    reward_painter:
 | 
			
		||||
        title: Painting
 | 
			
		||||
        desc: >-
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, I'm working on a solution already!
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, there is a <strong>color blind mode</strong> in the settings!
 | 
			
		||||
 | 
			
		||||
    reward_mixer:
 | 
			
		||||
        title: Color Mixing
 | 
			
		||||
@ -726,6 +726,12 @@ settings:
 | 
			
		||||
        enableColorBlindHelper:
 | 
			
		||||
            title: Color Blind Mode
 | 
			
		||||
            description: Enables various tools which allow to play the game if you are color blind.
 | 
			
		||||
        rotationByBuilding:
 | 
			
		||||
          title: Rotation by building type
 | 
			
		||||
          description: >-
 | 
			
		||||
            Each building type remembers the rotation you last set it to individually.
 | 
			
		||||
            This may be more comfortable if you frequently switch between placing
 | 
			
		||||
            different building types.
 | 
			
		||||
 | 
			
		||||
keybindings:
 | 
			
		||||
    title: Keybindings
 | 
			
		||||
 | 
			
		||||
@ -529,7 +529,7 @@ storyRewards:
 | 
			
		||||
    reward_painter:
 | 
			
		||||
        title: Verven
 | 
			
		||||
        desc: >-
 | 
			
		||||
            De <strong>verver</strong> is ontgrendeld - Onttrek wat kleurstoffen (net als met vormen) en combineer deze met een vorm in de verver om de vorm een kleur te geven!<br><br>PS: Ik werk aan een oplossing voor kleurenblinden!
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, there is a <strong>color blind mode</strong> in the settings!
 | 
			
		||||
 | 
			
		||||
    reward_mixer:
 | 
			
		||||
        title: Kleuren mengen
 | 
			
		||||
@ -701,9 +701,9 @@ settings:
 | 
			
		||||
        autosaveInterval:
 | 
			
		||||
            title: Autosave Interval
 | 
			
		||||
            description: >-
 | 
			
		||||
                Bepaalt hoe vaak het spel automatisch opslaat. Je kan het hier ook volledig 
 | 
			
		||||
                Bepaalt hoe vaak het spel automatisch opslaat. Je kan het hier ook volledig
 | 
			
		||||
                mee uitschakelen.
 | 
			
		||||
         
 | 
			
		||||
 | 
			
		||||
            intervals:
 | 
			
		||||
                one_minute: 1 Minuut
 | 
			
		||||
                two_minutes: 2 Minuten
 | 
			
		||||
@ -715,7 +715,7 @@ settings:
 | 
			
		||||
            title: Combacte gebouwinformatie
 | 
			
		||||
            description: >-
 | 
			
		||||
                Informatie weergeven bij gebouwen wordt beperkt tot alleen hun 'ratios'. Anders
 | 
			
		||||
                zie je een beschrijving en een afbeelding. 
 | 
			
		||||
                zie je een beschrijving en een afbeelding.
 | 
			
		||||
        disableCutDeleteWarnings:
 | 
			
		||||
            title: Schakel knip/delete waarschuwingen uit.
 | 
			
		||||
            description: >-
 | 
			
		||||
@ -724,6 +724,12 @@ settings:
 | 
			
		||||
        enableColorBlindHelper:
 | 
			
		||||
            title: Kleurenblindmodus
 | 
			
		||||
            description: Schakelt verschillende hulpmiddelen in zodat je het spel alsnog kunt spelen wanneer je kleurenblind bent.
 | 
			
		||||
        rotationByBuilding:
 | 
			
		||||
          title: Rotation by building type
 | 
			
		||||
          description: >-
 | 
			
		||||
            Each building type remembers the rotation you last set it to individually.
 | 
			
		||||
            This may be more comfortable if you frequently switch between placing
 | 
			
		||||
            different building types.
 | 
			
		||||
 | 
			
		||||
keybindings:
 | 
			
		||||
    title: Sneltoetsen
 | 
			
		||||
 | 
			
		||||
@ -529,7 +529,7 @@ storyRewards:
 | 
			
		||||
    reward_painter:
 | 
			
		||||
        title: Maling
 | 
			
		||||
        desc: >-
 | 
			
		||||
            <strong>Maleren</strong> har blitt tilgjengelig - Hent ut fargeressurser (på samme måte som du gjør med objekter) og kombiner det med et objekt i maleren for å male de!<br><br>PS: Hvis du er fargeblind, så jobber jeg med en løsning alt!
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, there is a <strong>color blind mode</strong> in the settings!
 | 
			
		||||
 | 
			
		||||
    reward_mixer:
 | 
			
		||||
        title: Fargemikser
 | 
			
		||||
@ -726,6 +726,12 @@ settings:
 | 
			
		||||
        enableColorBlindHelper:
 | 
			
		||||
            title: Fargeblind Modus
 | 
			
		||||
            description: Aktiverer forskjellige verktøy som lar deg spille spillet om du er fargeblind.
 | 
			
		||||
        rotationByBuilding:
 | 
			
		||||
          title: Rotation by building type
 | 
			
		||||
          description: >-
 | 
			
		||||
            Each building type remembers the rotation you last set it to individually.
 | 
			
		||||
            This may be more comfortable if you frequently switch between placing
 | 
			
		||||
            different building types.
 | 
			
		||||
 | 
			
		||||
keybindings:
 | 
			
		||||
    title: Hurtigtaster
 | 
			
		||||
 | 
			
		||||
@ -546,7 +546,7 @@ storyRewards:
 | 
			
		||||
    reward_painter:
 | 
			
		||||
        title: Malowanie
 | 
			
		||||
        desc: >-
 | 
			
		||||
            Odblokowano nową maszynę: <strong>Malarz</strong> - Wydobądź barwniki (tak jak w przypadku kształtów) i połącz z kształtem, by go pomalować!<br><br>PS: Jeśli cierpisz na ślepotę barw, pracuję nad tym!
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, there is a <strong>color blind mode</strong> in the settings!
 | 
			
		||||
 | 
			
		||||
    reward_mixer:
 | 
			
		||||
        title: Mieszanie
 | 
			
		||||
@ -752,6 +752,12 @@ settings:
 | 
			
		||||
        enableColorBlindHelper:
 | 
			
		||||
            title: Color Blind Mode
 | 
			
		||||
            description: Enables various tools which allow to play the game if you are color blind.
 | 
			
		||||
        rotationByBuilding:
 | 
			
		||||
          title: Rotation by building type
 | 
			
		||||
          description: >-
 | 
			
		||||
            Each building type remembers the rotation you last set it to individually.
 | 
			
		||||
            This may be more comfortable if you frequently switch between placing
 | 
			
		||||
            different building types.
 | 
			
		||||
 | 
			
		||||
keybindings:
 | 
			
		||||
    title: Klawiszologia
 | 
			
		||||
 | 
			
		||||
@ -532,7 +532,7 @@ storyRewards:
 | 
			
		||||
    reward_painter:
 | 
			
		||||
        title: Pintura
 | 
			
		||||
        desc: >-
 | 
			
		||||
            O <strong> pintor </strong> foi desbloqueado - Extraia algumas fontes coloridas (como você faz com formas) e combine-as com uma forma no pintor para colorí-las! <br> <br> PS: Se você é daltônico, já estou trabalhando em uma solução!
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, there is a <strong>color blind mode</strong> in the settings!
 | 
			
		||||
 | 
			
		||||
    reward_mixer:
 | 
			
		||||
        title: Misturando cores
 | 
			
		||||
@ -727,6 +727,12 @@ settings:
 | 
			
		||||
        enableColorBlindHelper:
 | 
			
		||||
            title: Color Blind Mode
 | 
			
		||||
            description: Enables various tools which allow to play the game if you are color blind.
 | 
			
		||||
        rotationByBuilding:
 | 
			
		||||
          title: Rotation by building type
 | 
			
		||||
          description: >-
 | 
			
		||||
            Each building type remembers the rotation you last set it to individually.
 | 
			
		||||
            This may be more comfortable if you frequently switch between placing
 | 
			
		||||
            different building types.
 | 
			
		||||
 | 
			
		||||
keybindings:
 | 
			
		||||
    title: Controles
 | 
			
		||||
 | 
			
		||||
@ -287,10 +287,10 @@ ingame:
 | 
			
		||||
        pasteLastBlueprint: Colar o último blueprint
 | 
			
		||||
        lockBeltDirection: Ativa o planeamento de tapetes
 | 
			
		||||
        plannerSwitchSide: Lado de rotação do planeamento
 | 
			
		||||
        cutSelection: Cut
 | 
			
		||||
        copySelection: Copy
 | 
			
		||||
        clearSelection: Clear Selection
 | 
			
		||||
        pipette: Pipette
 | 
			
		||||
        cutSelection: Cortar
 | 
			
		||||
        copySelection: Copiar
 | 
			
		||||
        clearSelection: Cancelar
 | 
			
		||||
        pipette: Pipeta
 | 
			
		||||
 | 
			
		||||
    # Everything related to placing buildings (I.e. as soon as you selected a building
 | 
			
		||||
    # from the toolbar)
 | 
			
		||||
@ -398,17 +398,17 @@ ingame:
 | 
			
		||||
                Isto <strong>NÃO</strong> é um jogo idle! Constrói mais extratores e tapetes para atingir o objetivo mais rapidamente.<br><br>Dica: Pressiona <strong>SHIFT</strong> para colocar vários extratores, e usa <strong>R</strong> para os rodar.
 | 
			
		||||
 | 
			
		||||
    colors:
 | 
			
		||||
        red: Red
 | 
			
		||||
        green: Green
 | 
			
		||||
        blue: Blue
 | 
			
		||||
        yellow: Yellow
 | 
			
		||||
        purple: Purple
 | 
			
		||||
        cyan: Cyan
 | 
			
		||||
        white: White
 | 
			
		||||
        uncolored: No color
 | 
			
		||||
        red: Vermelho
 | 
			
		||||
        green: Verde
 | 
			
		||||
        blue: Azul
 | 
			
		||||
        yellow: Amarelo
 | 
			
		||||
        purple: Roxo
 | 
			
		||||
        cyan: Azul-bebé
 | 
			
		||||
        white: Branco
 | 
			
		||||
        uncolored: Sem cor
 | 
			
		||||
    shapeViewer:
 | 
			
		||||
        title: Layers
 | 
			
		||||
        empty: Empty
 | 
			
		||||
        title: Camadas
 | 
			
		||||
        empty: Vazio
 | 
			
		||||
 | 
			
		||||
# All shop upgrades
 | 
			
		||||
shopUpgrades:
 | 
			
		||||
@ -529,7 +529,7 @@ storyRewards:
 | 
			
		||||
    reward_painter:
 | 
			
		||||
        title: Pintura
 | 
			
		||||
        desc: >-
 | 
			
		||||
            O <strong>Pintor</strong> foi desbloqueado - Extrai alguns pigmentos coloridos (tal como fazes com as formas) e combina-os com uma forma no pintor para a colorir!<br><br>PS: Se fores daltónico, já estou a trabalhar para encontrar uma solução!
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, there is a <strong>color blind mode</strong> in the settings!
 | 
			
		||||
 | 
			
		||||
    reward_mixer:
 | 
			
		||||
        title: Mistura de Cores
 | 
			
		||||
@ -679,14 +679,14 @@ settings:
 | 
			
		||||
                Se ativado, dá dicas e tutoriais de apoio ao jogo. Adicionalmente, esconde certos elementos da interface do utilizador até ao nível em que são desbloqueados de forma a simplificar o início do jogo.
 | 
			
		||||
 | 
			
		||||
        movementSpeed:
 | 
			
		||||
            title: Velociade de movimentação
 | 
			
		||||
            title: Velocidade de movimentação
 | 
			
		||||
            description: Define quão rápida é a movimentação usando o teclado.
 | 
			
		||||
            speeds:
 | 
			
		||||
                super_slow: Muito lenta
 | 
			
		||||
                slow: Lenta
 | 
			
		||||
                regular: Média
 | 
			
		||||
                fast: Rápiada
 | 
			
		||||
                super_fast: Muito rádida
 | 
			
		||||
                fast: Rápida
 | 
			
		||||
                super_fast: Muito rápida
 | 
			
		||||
                extremely_fast: Extremamente rápida
 | 
			
		||||
        enableTunnelSmartplace:
 | 
			
		||||
            title: Túneis inteligentes
 | 
			
		||||
@ -700,31 +700,37 @@ settings:
 | 
			
		||||
                mais fácil.
 | 
			
		||||
 | 
			
		||||
        autosaveInterval:
 | 
			
		||||
            title: Autosave Interval
 | 
			
		||||
            title: Intervalo de gravação automática
 | 
			
		||||
            description: >-
 | 
			
		||||
                Controls how often the game saves automatically. You can also disable it
 | 
			
		||||
                entirely here.
 | 
			
		||||
                Define o quão frequentemente o jogo grava automaticamente. Também podes desativar
 | 
			
		||||
                aqui.
 | 
			
		||||
            intervals:
 | 
			
		||||
                one_minute: 1 Minute
 | 
			
		||||
                two_minutes: 2 Minutes
 | 
			
		||||
                five_minutes: 5 Minutes
 | 
			
		||||
                ten_minutes: 10 Minutes
 | 
			
		||||
                twenty_minutes: 20 Minutes
 | 
			
		||||
                disabled: Disabled
 | 
			
		||||
                one_minute: 1 Minuto
 | 
			
		||||
                two_minutes: 2 Minutos
 | 
			
		||||
                five_minutes: 5 Minutos
 | 
			
		||||
                ten_minutes: 10 Minutos
 | 
			
		||||
                twenty_minutes: 20 Minutos
 | 
			
		||||
                disabled: Desligado
 | 
			
		||||
        compactBuildingInfo:
 | 
			
		||||
            title: Compact Building Infos
 | 
			
		||||
            title: Informações de construções compactas
 | 
			
		||||
            description: >-
 | 
			
		||||
                Shortens info boxes for buildings by only showing their ratios. Otherwise a
 | 
			
		||||
                description and image is shown.
 | 
			
		||||
                Encurta caixas de informação mostrando apenas os respetivos rácios. Caso contrário
 | 
			
		||||
                é mostrada a descrição e a imagem.
 | 
			
		||||
        disableCutDeleteWarnings:
 | 
			
		||||
            title: Disable Cut/Delete Warnings
 | 
			
		||||
            title: Desativar Avisos de Corte/Eliminação
 | 
			
		||||
            description: >-
 | 
			
		||||
                Disable the warning dialogs brought up when cutting/deleting more than 100
 | 
			
		||||
                entities.
 | 
			
		||||
                Desativa os avisos mostrados quando é feito o corte ou a eliminação de mais de 100
 | 
			
		||||
                entidades.
 | 
			
		||||
 | 
			
		||||
        enableColorBlindHelper:
 | 
			
		||||
            title: Color Blind Mode
 | 
			
		||||
            description: Enables various tools which allow to play the game if you are color blind.
 | 
			
		||||
            title: Modo Daltónico
 | 
			
		||||
            description: Ativa várias ferramentas para daltónicos.
 | 
			
		||||
        rotationByBuilding:
 | 
			
		||||
          title: Rotation by building type
 | 
			
		||||
          description: >-
 | 
			
		||||
            Each building type remembers the rotation you last set it to individually.
 | 
			
		||||
            This may be more comfortable if you frequently switch between placing
 | 
			
		||||
            different building types.
 | 
			
		||||
 | 
			
		||||
keybindings:
 | 
			
		||||
    title: Atalhos
 | 
			
		||||
@ -791,7 +797,7 @@ keybindings:
 | 
			
		||||
        mapMoveFaster: Mover rapidamente
 | 
			
		||||
        lockBeltDirection: Ativa o planeamento de tapetes
 | 
			
		||||
        switchDirectionLockSide: "Planeador: Troca o lado"
 | 
			
		||||
        pipette: Pipette
 | 
			
		||||
        pipette: Pipeta
 | 
			
		||||
about:
 | 
			
		||||
    title: Sobre o jogo
 | 
			
		||||
    body: >-
 | 
			
		||||
 | 
			
		||||
@ -530,7 +530,7 @@ storyRewards:
 | 
			
		||||
    reward_painter:
 | 
			
		||||
        title: Painting
 | 
			
		||||
        desc: >-
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, I'm working on a solution already!
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, there is a <strong>color blind mode</strong> in the settings!
 | 
			
		||||
 | 
			
		||||
    reward_mixer:
 | 
			
		||||
        title: Color Mixing
 | 
			
		||||
@ -726,6 +726,12 @@ settings:
 | 
			
		||||
        enableColorBlindHelper:
 | 
			
		||||
            title: Color Blind Mode
 | 
			
		||||
            description: Enables various tools which allow to play the game if you are color blind.
 | 
			
		||||
        rotationByBuilding:
 | 
			
		||||
          title: Rotation by building type
 | 
			
		||||
          description: >-
 | 
			
		||||
            Each building type remembers the rotation you last set it to individually.
 | 
			
		||||
            This may be more comfortable if you frequently switch between placing
 | 
			
		||||
            different building types.
 | 
			
		||||
 | 
			
		||||
keybindings:
 | 
			
		||||
    title: Keybindings
 | 
			
		||||
 | 
			
		||||
@ -532,7 +532,7 @@ storyRewards:
 | 
			
		||||
    reward_painter:
 | 
			
		||||
        title: Покраска
 | 
			
		||||
        desc: >-
 | 
			
		||||
            Разблокирован <strong>покрасчик</strong>! Добудьте краситель из жилы (так же как и фигуры) и объедините его с фигурой в покрасчике, чтобы раскрасить ее!<br><br>PS: Если вы дальтоник, я уже работаю над решением!
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, there is a <strong>color blind mode</strong> in the settings!
 | 
			
		||||
 | 
			
		||||
    reward_mixer:
 | 
			
		||||
        title: Смешивание Цветов
 | 
			
		||||
@ -727,6 +727,12 @@ settings:
 | 
			
		||||
        enableColorBlindHelper:
 | 
			
		||||
            title: Режим Дальтоника
 | 
			
		||||
            description: Включает различные инструменты, которые позволяют играть в игру дальтоникам.
 | 
			
		||||
        rotationByBuilding:
 | 
			
		||||
          title: Rotation by building type
 | 
			
		||||
          description: >-
 | 
			
		||||
            Each building type remembers the rotation you last set it to individually.
 | 
			
		||||
            This may be more comfortable if you frequently switch between placing
 | 
			
		||||
            different building types.
 | 
			
		||||
 | 
			
		||||
keybindings:
 | 
			
		||||
    title: Настройки управления
 | 
			
		||||
 | 
			
		||||
@ -530,7 +530,7 @@ storyRewards:
 | 
			
		||||
    reward_painter:
 | 
			
		||||
        title: Måleri
 | 
			
		||||
        desc: >-
 | 
			
		||||
            <strong>Färgläggaren</strong> har blivit upplåst - Extrahera färg (precis som du gör med former) och kombinera dem med former för att färglägga dem!<br><br>PS: Om du är färgblind, jag jobbar redan på en lösning!
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, there is a <strong>color blind mode</strong> in the settings!
 | 
			
		||||
 | 
			
		||||
    reward_mixer:
 | 
			
		||||
        title: Färgblandning
 | 
			
		||||
@ -726,6 +726,12 @@ settings:
 | 
			
		||||
        enableColorBlindHelper:
 | 
			
		||||
            title: Färgblint läge
 | 
			
		||||
            description: Aktiverar olika verktyg som låter dig spela spelet om du är färbling.
 | 
			
		||||
        rotationByBuilding:
 | 
			
		||||
          title: Rotation by building type
 | 
			
		||||
          description: >-
 | 
			
		||||
            Each building type remembers the rotation you last set it to individually.
 | 
			
		||||
            This may be more comfortable if you frequently switch between placing
 | 
			
		||||
            different building types.
 | 
			
		||||
 | 
			
		||||
keybindings:
 | 
			
		||||
    title: Tangentbindningar
 | 
			
		||||
 | 
			
		||||
@ -531,7 +531,7 @@ storyRewards:
 | 
			
		||||
    reward_painter:
 | 
			
		||||
        title: Painting
 | 
			
		||||
        desc: >-
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, I'm working on a solution already!
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, there is a <strong>color blind mode</strong> in the settings!
 | 
			
		||||
 | 
			
		||||
    reward_mixer:
 | 
			
		||||
        title: Color Mixing
 | 
			
		||||
@ -727,6 +727,12 @@ settings:
 | 
			
		||||
        enableColorBlindHelper:
 | 
			
		||||
            title: Color Blind Mode
 | 
			
		||||
            description: Enables various tools which allow to play the game if you are color blind.
 | 
			
		||||
        rotationByBuilding:
 | 
			
		||||
          title: Rotation by building type
 | 
			
		||||
          description: >-
 | 
			
		||||
            Each building type remembers the rotation you last set it to individually.
 | 
			
		||||
            This may be more comfortable if you frequently switch between placing
 | 
			
		||||
            different building types.
 | 
			
		||||
 | 
			
		||||
keybindings:
 | 
			
		||||
    title: Keybindings
 | 
			
		||||
 | 
			
		||||
@ -319,10 +319,10 @@ ingame:
 | 
			
		||||
        pasteLastBlueprint: 粘贴上一个蓝图
 | 
			
		||||
        lockBeltDirection: 启用传送带规划
 | 
			
		||||
        plannerSwitchSide: 规划器换边
 | 
			
		||||
        cutSelection: Cut
 | 
			
		||||
        copySelection: Copy
 | 
			
		||||
        clearSelection: Clear Selection
 | 
			
		||||
        pipette: Pipette
 | 
			
		||||
        cutSelection: 剪切
 | 
			
		||||
        copySelection: 复制
 | 
			
		||||
        clearSelection: 取消选择
 | 
			
		||||
        pipette: 选取器
 | 
			
		||||
 | 
			
		||||
    # Everything related to placing buildings (I.e. as soon as you selected a building
 | 
			
		||||
    # from the toolbar)
 | 
			
		||||
@ -377,14 +377,14 @@ ingame:
 | 
			
		||||
        title: 统计信息
 | 
			
		||||
        dataSources:
 | 
			
		||||
            stored:
 | 
			
		||||
                title: 储存
 | 
			
		||||
                description: 显示基地中每种图形储存的数量。
 | 
			
		||||
                title: 已交付
 | 
			
		||||
                description: 显示基地中每种图形已交付且未使用的数量。
 | 
			
		||||
            produced:
 | 
			
		||||
                title: 生产
 | 
			
		||||
                description: 显示所有正在被生产的图形数量,包括中间产物。
 | 
			
		||||
            delivered:
 | 
			
		||||
                title: 送达
 | 
			
		||||
                description: 显示图形送达基地的速度。
 | 
			
		||||
                description: 显示图形送达基地并交付的速度。
 | 
			
		||||
        noShapesProduced: 你还没有生产任何图形。
 | 
			
		||||
 | 
			
		||||
        # Displays the shapes per minute, e.g. '523 / m'
 | 
			
		||||
@ -416,7 +416,7 @@ ingame:
 | 
			
		||||
    waypoints:
 | 
			
		||||
        waypoints: 地图标记
 | 
			
		||||
        hub: 基地
 | 
			
		||||
        description: Left-click a marker to jump to it, right-click to delete it.<br><br>Press <keybinding> to create a marker from the current view, or <strong>right-click</strong> to create a marker at the selected location.
 | 
			
		||||
        description: 左键跳转到地图标记,右键删除地图标记。<br><br>按<keybinding>在当前地点创建地图标记,或者在选定位置上<strong>右键</strong>创建地图标记.
 | 
			
		||||
        creationSuccessNotification: 成功创建地图标记。
 | 
			
		||||
 | 
			
		||||
    # Interactive tutorial
 | 
			
		||||
@ -432,17 +432,17 @@ ingame:
 | 
			
		||||
                提示:按住<strong>SHIFT</strong>键来放置多个开采机,用<strong>R</strong>键旋转它们。
 | 
			
		||||
 | 
			
		||||
    colors:
 | 
			
		||||
        red: Red
 | 
			
		||||
        green: Green
 | 
			
		||||
        blue: Blue
 | 
			
		||||
        yellow: Yellow
 | 
			
		||||
        purple: Purple
 | 
			
		||||
        cyan: Cyan
 | 
			
		||||
        white: White
 | 
			
		||||
        uncolored: No color
 | 
			
		||||
        red: 红色
 | 
			
		||||
        green: 绿色
 | 
			
		||||
        blue: 蓝色
 | 
			
		||||
        yellow: 黄色
 | 
			
		||||
        purple: 紫色
 | 
			
		||||
        cyan: 青色
 | 
			
		||||
        white: 白色
 | 
			
		||||
        uncolored: 无色
 | 
			
		||||
    shapeViewer:
 | 
			
		||||
        title: Layers
 | 
			
		||||
        empty: Empty
 | 
			
		||||
        title: 层 # TODO: find better translation
 | 
			
		||||
        empty: 空
 | 
			
		||||
 | 
			
		||||
# All shop upgrades
 | 
			
		||||
shopUpgrades:
 | 
			
		||||
@ -502,7 +502,7 @@ buildings:
 | 
			
		||||
            name: &cutter 切割机
 | 
			
		||||
            description: 将图形从上到下切开并输出。 <strong>如果你只需要其中一半,记得把另一半销毁掉,否则切割机会停止工作!</strong>
 | 
			
		||||
        quad:
 | 
			
		||||
            name: 切割机(四分)
 | 
			
		||||
            name: 切割机(四向)
 | 
			
		||||
            description: 将输入的图形切成四块。 <strong>如果你只需要其中一块,记得把其他的销毁掉,否则切割机会停止工作!</strong>
 | 
			
		||||
 | 
			
		||||
    rotater:
 | 
			
		||||
@ -554,16 +554,16 @@ storyRewards:
 | 
			
		||||
    # Those are the rewards gained from completing the store
 | 
			
		||||
    reward_cutter_and_trash:
 | 
			
		||||
        title: 切割图形
 | 
			
		||||
        desc: <strong>切割机</strong>已解锁。不论切割机的方向,它都会把图形<strong>从上到下</strong>切成两半。<br><br>记得把不需要的部分处理掉,否则这个这个建筑会停止工作。为此我给你准备了<strong>垃圾桶</strong>,它会把所有放进去的物品销毁掉。
 | 
			
		||||
        desc: 恭喜!你解锁了<strong>切割机</strong>。切割机会把图形<strong>从上到下</strong>切成两半。注意切割的方向和切割机的朝向无关。<br><br>记得把不需要的部分处理掉,否则这个这个建筑会停止工作。为此我给你准备了<strong>垃圾桶</strong>,它会把所有放进去的物品销毁掉。
 | 
			
		||||
 | 
			
		||||
    reward_rotater:
 | 
			
		||||
        title: 顺时针旋转
 | 
			
		||||
        desc: <strong>旋转机</strong>已解锁。它会顺时针旋转输入的图形90度。
 | 
			
		||||
        desc: 恭喜!你解锁了<strong>旋转机</strong>。它会顺时针旋转输入的图形90度。
 | 
			
		||||
 | 
			
		||||
    reward_painter:
 | 
			
		||||
        title: 上色
 | 
			
		||||
        desc: >-
 | 
			
		||||
            <strong>上色机</strong>已解锁。和图形一样,从颜色矿脉中开采颜色,然后将在上色机中将颜色涂在图形上。<br><br>PS:我们正在开发色盲模式!
 | 
			
		||||
            The <strong>painter</strong> has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!<br><br>PS: If you are colorblind, there is a <strong>color blind mode</strong> in the settings!
 | 
			
		||||
 | 
			
		||||
    reward_mixer:
 | 
			
		||||
        title: 混合颜色
 | 
			
		||||
@ -571,56 +571,55 @@ storyRewards:
 | 
			
		||||
 | 
			
		||||
    reward_stacker:
 | 
			
		||||
        title: 堆叠
 | 
			
		||||
        desc: <strong>堆叠机</strong>已解锁。堆叠机会尝试把两个输入的图形<strong>拼贴</strong>在一起。如果有重叠的部分,右边的输入会被<strong>堆叠</strong>在左边的输入上方!
 | 
			
		||||
        desc: 恭喜!你解锁了<strong>堆叠机</strong>。堆叠机会尝试把两个输入的图形<strong>拼贴</strong>在一起。如果有重叠的部分,右边的输入会被<strong>堆叠</strong>在左边的输入上方!
 | 
			
		||||
 | 
			
		||||
    reward_splitter:
 | 
			
		||||
        title: 分离与合并
 | 
			
		||||
        desc: <strong>平衡机</strong>已解锁。在大型工厂中,平衡机负责<strong>合并或分离</strong>多个传送带上的物品。<br><br>
 | 
			
		||||
        desc: 恭喜!你解锁了<strong>平衡机</strong>。在大型工厂中,平衡机负责<strong>合并或分离</strong>多个传送带上的物品。<br><br>
 | 
			
		||||
 | 
			
		||||
    reward_tunnel:
 | 
			
		||||
        title: 隧道
 | 
			
		||||
        desc: <strong>隧道</strong>已解锁。你现在可以从其他传送带或建筑底下运送物品了!
 | 
			
		||||
        desc: 恭喜!你解锁了<strong>隧道</strong>。你现在可以从其他传送带或建筑底下运送物品了!
 | 
			
		||||
 | 
			
		||||
    reward_rotater_ccw:
 | 
			
		||||
        title: 逆时针旋转
 | 
			
		||||
        desc: You have unlocked a variant of the <strong>rotater</strong> - It allows to rotate counter clockwise! To build it, select the rotater and <strong>press 'T' to cycle its variants</strong>!
 | 
			
		||||
        desc: 恭喜!你解锁了<strong>旋转机</strong>的<strong>逆时针</strong>变体。这个变体可以逆时针旋转图形。选择旋转机然后按“T”键来选取这个变体。
 | 
			
		||||
 | 
			
		||||
    reward_miner_chainable:
 | 
			
		||||
        title: 链式开采机
 | 
			
		||||
        desc: <strong>链式开采机</strong>变体已解锁。它是开采机的一个变体。它可以将开采出来的资源<strong>传递</strong>给其他的开采机,使得资源提取更加高效!
 | 
			
		||||
        desc: You have unlocked the <strong>chaining extractor</strong>! It can <strong>forward its resources</strong> to other extractors so you can more efficiently extract resources!
 | 
			
		||||
 | 
			
		||||
    reward_underground_belt_tier_2:
 | 
			
		||||
        title: 二级隧道
 | 
			
		||||
        desc: <strong>二级隧道</strong>变体已解锁。这个隧道有<strong>更长的传输距离</strong>。你还可以混用不同的隧道变体!
 | 
			
		||||
        desc: 恭喜!你解锁了<strong>二级隧道</strong>。这是隧道的一个变体。二级隧道有<strong>更长的传输距离</strong>。你还可以混用不同的隧道变体!
 | 
			
		||||
 | 
			
		||||
    reward_splitter_compact:
 | 
			
		||||
        title: 小型合流机
 | 
			
		||||
        desc: >-
 | 
			
		||||
            <strong>小型合流机</strong>变体已解锁。它可以把两个输入合并到一个输出上。
 | 
			
		||||
        desc: You have unlocked a compact variant of the <strong>balancer</strong> - It accepts two inputs and merges them into one!
 | 
			
		||||
 | 
			
		||||
    reward_cutter_quad:
 | 
			
		||||
        title: 四分切割机
 | 
			
		||||
        desc: You have unlocked a variant of the <strong>cutter</strong> - It allows you to cut shapes in <strong>four parts</strong> instead of just two!
 | 
			
		||||
        title: 四向切割机
 | 
			
		||||
        desc: 恭喜!你解锁了<strong>切割机</strong>的<strong>四向</strong>变体。它可以将输入的图形切成四块而不只是左右两块!
 | 
			
		||||
 | 
			
		||||
    reward_painter_double:
 | 
			
		||||
        title: 双倍上色机
 | 
			
		||||
        desc: You have unlocked a variant of the <strong>painter</strong> - It works as the regular painter but processes <strong>two shapes at once</strong> consuming just one color instead of two!
 | 
			
		||||
        desc: 恭喜!你解锁了<strong>上色机</strong>的<strong>双倍</strong>变体。它可以同时为两个图形上色,每次只消耗一份颜色!
 | 
			
		||||
 | 
			
		||||
    reward_painter_quad:
 | 
			
		||||
        title: 四向上色机
 | 
			
		||||
        desc: <strong>上色机</strong>四向变体已解锁。它可以在一个图形的四个角上涂不同的颜色!
 | 
			
		||||
        desc: 恭喜!你解锁了<strong>上色机</strong>四向变体。它可以在一个图形的四个角上涂不同的颜色!
 | 
			
		||||
 | 
			
		||||
    reward_storage:
 | 
			
		||||
        title: 仓库
 | 
			
		||||
        desc: <strong>仓库</strong>变体已解锁。它可以暂时储存一些材料,有容量上限。
 | 
			
		||||
        desc: You have unlocked a variant of the <strong>trash</strong> - It allows to store items up to a given capacity!
 | 
			
		||||
 | 
			
		||||
    reward_freeplay:
 | 
			
		||||
        title: 自由模式
 | 
			
		||||
        desc: 恭喜你!你解锁了<strong>自由模式</strong>!现在图形将会是随机生成的!(不用担心,我计划在独立版本中加入更多内容!)
 | 
			
		||||
        desc: 恭喜你!你解锁了<strong>自由模式</strong>。现在图形将会是随机生成的!(不用担心,我计划在独立版本中加入更多内容!)
 | 
			
		||||
 | 
			
		||||
    reward_blueprints:
 | 
			
		||||
        title: 蓝图
 | 
			
		||||
        desc: You can now <strong>copy and paste</strong> parts of your factory! Select an area (Hold CTRL, then drag with your mouse), and press 'C' to copy it.<br><br>Pasting it is <strong>not free</strong>, you need to produce <strong>blueprint shapes</strong> to afford it! (Those you just delivered).
 | 
			
		||||
        desc: 你现在可以<strong>复制粘贴</strong>你的工厂的一部分了!按住CTRL键并拖动鼠标来选择一块区域,然后按C键复制。<br><br>粘贴并<strong>不是免费的</strong>,你需要使用<strong>蓝图图形</strong>来粘贴你的蓝图。蓝图图形是你刚刚交付的图形。
 | 
			
		||||
 | 
			
		||||
    # Special reward, which is shown when there is no reward actually
 | 
			
		||||
    no_reward:
 | 
			
		||||
@ -740,31 +739,34 @@ settings:
 | 
			
		||||
                启用晕映,将屏幕角落里的颜色变深,更容易阅读文本。
 | 
			
		||||
 | 
			
		||||
        autosaveInterval:
 | 
			
		||||
            title: Autosave Interval
 | 
			
		||||
            title: 自动保存间隔
 | 
			
		||||
            description: >-
 | 
			
		||||
                Controls how often the game saves automatically. You can also disable it
 | 
			
		||||
                entirely here.
 | 
			
		||||
                在这里控制你的游戏多长时间保存一次,或者完全关闭这个功能。
 | 
			
		||||
            intervals:
 | 
			
		||||
                one_minute: 1 Minute
 | 
			
		||||
                two_minutes: 2 Minutes
 | 
			
		||||
                five_minutes: 5 Minutes
 | 
			
		||||
                ten_minutes: 10 Minutes
 | 
			
		||||
                twenty_minutes: 20 Minutes
 | 
			
		||||
                disabled: Disabled
 | 
			
		||||
                one_minute: 1分钟
 | 
			
		||||
                two_minutes: 2分钟
 | 
			
		||||
                five_minutes: 5分钟
 | 
			
		||||
                ten_minutes: 10分钟
 | 
			
		||||
                twenty_minutes: 20分钟
 | 
			
		||||
                disabled: 关闭
 | 
			
		||||
        compactBuildingInfo:
 | 
			
		||||
            title: Compact Building Infos
 | 
			
		||||
            title: 精简建筑信息
 | 
			
		||||
            description: >-
 | 
			
		||||
                Shortens info boxes for buildings by only showing their ratios. Otherwise a
 | 
			
		||||
                description and image is shown.
 | 
			
		||||
                缩小建筑信息展示框。如果打开,放置建筑时建筑将不再显示建筑说明和图片,只显示建筑速度或其他数据。
 | 
			
		||||
        disableCutDeleteWarnings:
 | 
			
		||||
            title: Disable Cut/Delete Warnings
 | 
			
		||||
            title: 关闭剪切/删除警告
 | 
			
		||||
            description: >-
 | 
			
		||||
                Disable the warning dialogs brought up when cutting/deleting more than 100
 | 
			
		||||
                entities.
 | 
			
		||||
                如果打开,将不再在剪切或者删除100+建筑时显示警告信息。
 | 
			
		||||
 | 
			
		||||
        enableColorBlindHelper:
 | 
			
		||||
            title: Color Blind Mode
 | 
			
		||||
            description: Enables various tools which allow to play the game if you are color blind.
 | 
			
		||||
            title: 色盲模式
 | 
			
		||||
            description: 提供一些分辨颜色的工具。目前当鼠标移至颜色资源上方时,屏幕上方会显示颜色名称。
 | 
			
		||||
        rotationByBuilding:
 | 
			
		||||
            title: Rotation by building type
 | 
			
		||||
            description: >-
 | 
			
		||||
                Each building type remembers the rotation you last set it to individually.
 | 
			
		||||
                This may be more comfortable if you frequently switch between placing
 | 
			
		||||
                different building types.
 | 
			
		||||
 | 
			
		||||
keybindings:
 | 
			
		||||
    title: 按键设置
 | 
			
		||||
@ -840,7 +842,7 @@ keybindings:
 | 
			
		||||
 | 
			
		||||
        lockBeltDirection: 启用传送带规划
 | 
			
		||||
        switchDirectionLockSide: "规划器:换边"
 | 
			
		||||
        pipette: Pipette
 | 
			
		||||
        pipette: 选取器
 | 
			
		||||
 | 
			
		||||
about:
 | 
			
		||||
    title: 关于游戏
 | 
			
		||||
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Loading…
	
		Reference in New Issue
	
	Block a user