1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2025-06-13 13:04:03 +00:00

Merge branch 'master' into feature/steam-achievements

This commit is contained in:
Greg Considine 2021-03-09 19:48:57 -05:00
commit 27cdbbd668
28 changed files with 780 additions and 475 deletions

1
.gitignore vendored
View File

@ -46,6 +46,7 @@ res_built
gulp/runnable-texturepacker.jar gulp/runnable-texturepacker.jar
tmp_standalone_files tmp_standalone_files
tmp_standalone_files_china
# Local config # Local config
config.local.js config.local.js

View File

@ -21,7 +21,6 @@ function gulptasksCSS($, gulp, buildFolder, browserSync) {
const plugins = [postcssAssetsPlugin(cachebust)]; const plugins = [postcssAssetsPlugin(cachebust)];
if (prod) { if (prod) {
plugins.unshift( plugins.unshift(
// $.postcssUnprefix(),
$.postcssPresetEnv({ $.postcssPresetEnv({
browsers: ["> 0.1%"], browsers: ["> 0.1%"],
}) })

View File

@ -139,7 +139,7 @@ gulp.task("main.webserver", () => {
); );
}); });
function serve({ standalone }) { function serve({ standalone, chineseVersion = false }) {
browserSync.init({ browserSync.init({
server: buildFolder, server: buildFolder,
port: 3005, port: 3005,
@ -203,7 +203,11 @@ function serve({ standalone }) {
if (standalone) { if (standalone) {
gulp.series("js.standalone-dev.watch")(() => true); gulp.series("js.standalone-dev.watch")(() => true);
} else { } else {
gulp.series("js.dev.watch")(() => true); if (chineseVersion) {
gulp.series("china.js.dev.watch")(() => true);
} else {
gulp.series("js.dev.watch")(() => true);
}
} }
} }
@ -289,30 +293,28 @@ gulp.task(
); );
// Builds everything (standalone-prod) // Builds everything (standalone-prod)
gulp.task(
"step.standalone-prod.code",
gulp.series("sounds.fullbuildHQ", "translations.fullBuild", "js.standalone-prod")
);
gulp.task("step.standalone-prod.mainbuild", gulp.parallel("step.baseResources", "step.standalone-prod.code"));
gulp.task(
"step.standalone-prod.all",
gulp.series("step.standalone-prod.mainbuild", "css.prod-standalone", "html.standalone-prod")
);
gulp.task(
"build.standalone-prod",
gulp.series("utils.cleanup", "step.standalone-prod.all", "step.postbuild")
);
// OS X build and release upload for (const prefix of ["", "china."]) {
gulp.task( gulp.task(
"build.darwin64-prod", prefix + "step.standalone-prod.code",
gulp.series( gulp.series("sounds.fullbuildHQ", "translations.fullBuild", prefix + "js.standalone-prod")
"build.standalone-prod", );
"standalone.prepare",
"standalone.package.prod.darwin64", gulp.task(
"standalone.uploadRelease.darwin64" prefix + "step.standalone-prod.mainbuild",
) gulp.parallel("step.baseResources", prefix + "step.standalone-prod.code")
); );
gulp.task(
prefix + "step.standalone-prod.all",
gulp.series(prefix + "step.standalone-prod.mainbuild", "css.prod-standalone", "html.standalone-prod")
);
gulp.task(
prefix + "build.standalone-prod",
gulp.series("utils.cleanup", prefix + "step.standalone-prod.all", "step.postbuild")
);
}
// Deploying! // Deploying!
gulp.task( gulp.task(
@ -325,7 +327,12 @@ gulp.task(
); );
gulp.task("main.deploy.prod", gulp.series("utils.requireCleanWorkingTree", "build.prod", "ftp.upload.prod")); gulp.task("main.deploy.prod", gulp.series("utils.requireCleanWorkingTree", "build.prod", "ftp.upload.prod"));
gulp.task("main.deploy.all", gulp.series("main.deploy.staging", "main.deploy.prod")); gulp.task("main.deploy.all", gulp.series("main.deploy.staging", "main.deploy.prod"));
gulp.task("main.standalone", gulp.series("build.standalone-prod", "standalone.package.prod")); gulp.task("regular.main.standalone", gulp.series("build.standalone-prod", "standalone.package.prod"));
gulp.task(
"china.main.standalone",
gulp.series("china.build.standalone-prod", "china.standalone.package.prod")
);
gulp.task("standalone.all", gulp.series("regular.main.standalone", "china.main.standalone"));
// Live-development // Live-development
gulp.task( gulp.task(
@ -336,5 +343,9 @@ gulp.task(
"main.serveStandalone", "main.serveStandalone",
gulp.series("build.standalone.dev", () => serve({ standalone: true })) gulp.series("build.standalone.dev", () => serve({ standalone: true }))
); );
gulp.task(
"china.main.serveDev",
gulp.series("build.dev", () => serve({ standalone: false, chineseVersion: true }))
);
gulp.task("default", gulp.series("main.serveDev")); gulp.task("default", gulp.series("main.serveDev"));

View File

@ -6,7 +6,6 @@ function requireUncached(module) {
} }
function gulptasksJS($, gulp, buildFolder, browserSync) { function gulptasksJS($, gulp, buildFolder, browserSync) {
//// DEV //// DEV
gulp.task("js.dev.watch", () => { gulp.task("js.dev.watch", () => {
@ -30,6 +29,36 @@ function gulptasksJS($, gulp, buildFolder, browserSync) {
.pipe(gulp.dest(buildFolder)); .pipe(gulp.dest(buildFolder));
}); });
//// DEV CHINA
gulp.task("china.js.dev.watch", () => {
return gulp
.src("../src/js/main.js")
.pipe(
$.webpackStream(
requireUncached("./webpack.config.js")({
watch: true,
chineseVersion: true,
})
)
)
.pipe(gulp.dest(buildFolder))
.pipe(browserSync.stream());
});
gulp.task("china.js.dev", () => {
return gulp
.src("../src/js/main.js")
.pipe(
$.webpackStream(
requireUncached("./webpack.config.js")({
chineseVersion: true,
})
)
)
.pipe(gulp.dest(buildFolder));
});
//// STAGING //// STAGING
gulp.task("js.staging.transpiled", () => { gulp.task("js.staging.transpiled", () => {
@ -162,6 +191,23 @@ function gulptasksJS($, gulp, buildFolder, browserSync) {
) )
.pipe(gulp.dest(buildFolder)); .pipe(gulp.dest(buildFolder));
}); });
gulp.task("china.js.standalone-prod", () => {
return gulp
.src("../src/js/main.js")
.pipe(
$.webpackStream(
requireUncached("./webpack.production.config.js")({
enableAssert: false,
environment: "prod",
es6: true,
standalone: true,
chineseVersion: true,
})
)
)
.pipe(gulp.dest(buildFolder));
});
} }
module.exports = { module.exports = {

View File

@ -34,6 +34,7 @@
"fastdom": "^1.0.9", "fastdom": "^1.0.9",
"flatted": "^2.0.1", "flatted": "^2.0.1",
"fs-extra": "^8.1.0", "fs-extra": "^8.1.0",
"gifsicle": "^5.2.0",
"gulp-audiosprite": "^1.1.0", "gulp-audiosprite": "^1.1.0",
"howler": "^2.1.2", "howler": "^2.1.2",
"html-loader": "^0.5.5", "html-loader": "^0.5.5",

View File

@ -11,6 +11,7 @@ const execSync = require("child_process").execSync;
function gulptasksStandalone($, gulp) { function gulptasksStandalone($, gulp) {
const electronBaseDir = path.join(__dirname, "..", "electron"); const electronBaseDir = path.join(__dirname, "..", "electron");
<<<<<<< HEAD
const tempDestDir = path.join(__dirname, "..", "tmp_standalone_files"); const tempDestDir = path.join(__dirname, "..", "tmp_standalone_files");
const tempDestBuildDir = path.join(tempDestDir, "built"); const tempDestBuildDir = path.join(tempDestDir, "built");
@ -172,73 +173,170 @@ function gulptasksStandalone($, gulp) {
"For more information, see " + "For more information, see " +
"https://github.com/electron/electron-packager/issues/71".underline "https://github.com/electron/electron-packager/issues/71".underline
); );
=======
for (const { tempDestDir, suffix, taskPrefix } of [
{ tempDestDir: path.join(__dirname, "..", "tmp_standalone_files"), suffix: "", taskPrefix: "" },
{
tempDestDir: path.join(__dirname, "..", "tmp_standalone_files_china"),
suffix: "china",
taskPrefix: "china.",
},
]) {
const tempDestBuildDir = path.join(tempDestDir, "built");
// Clear up framework folders gulp.task(taskPrefix + "standalone.prepare.cleanup", () => {
fs.writeFileSync( return gulp.src(tempDestDir, { read: false, allowEmpty: true }).pipe($.clean({ force: true }));
path.join(appPath, "play.sh"), });
'#!/usr/bin/env bash\n./shapez.io-standalone.app/Contents/MacOS/shapezio --no-sandbox "$@"\n'
);
fs.chmodSync(path.join(appPath, "play.sh"), 0o775);
fs.chmodSync(
path.join(appPath, "shapez.io-standalone.app", "Contents", "MacOS", "shapezio"),
0o775
);
const finalPath = path.join(appPath, "shapez.io-standalone.app"); gulp.task(taskPrefix + "standalone.prepare.copyPrefab", () => {
// const requiredFiles = $.glob.sync("../electron/");
const requiredFiles = [
path.join(electronBaseDir, "lib", "**", "*.node"),
path.join(electronBaseDir, "node_modules", "**", "*.*"),
path.join(electronBaseDir, "node_modules", "**", ".*"),
path.join(electronBaseDir, "favicon*"),
const frameworksDir = path.join(finalPath, "Contents", "Frameworks"); // fails on platforms which support symlinks
const frameworkFolders = fs // https://github.com/gulpjs/gulp/issues/1427
.readdirSync(frameworksDir) // path.join(electronBaseDir, "node_modules", "**", "*"),
.filter(fname => fname.endsWith(".framework")); ];
return gulp.src(requiredFiles, { base: electronBaseDir }).pipe(gulp.dest(tempDestBuildDir));
});
for (let i = 0; i < frameworkFolders.length; ++i) { gulp.task(taskPrefix + "standalone.prepare.writePackageJson", cb => {
const folderName = frameworkFolders[i]; fs.writeFileSync(
const frameworkFolder = path.join(frameworksDir, folderName); path.join(tempDestBuildDir, "package.json"),
console.log(" -> ", frameworkFolder); JSON.stringify(
{
devDependencies: {
electron: "6.1.12",
},
},
null,
4
)
);
cb();
});
const filesToDelete = fs gulp.task(taskPrefix + "standalone.prepareVDF", cb => {
.readdirSync(frameworkFolder) const hash = buildutils.getRevision();
.filter(fname => fname.toLowerCase() !== "versions");
filesToDelete.forEach(fname => {
console.log(" -> Deleting", fname);
fs.unlinkSync(path.join(frameworkFolder, fname));
});
const frameworkSourceDir = path.join(frameworkFolder, "Versions", "A"); const steampipeDir = path.join(__dirname, "steampipe", "scripts");
fse.copySync(frameworkSourceDir, frameworkFolder); const templateContents = fs
} .readFileSync(path.join(steampipeDir, "app.vdf.template"), { encoding: "utf-8" })
} .toString();
});
cb(); const convertedContents = templateContents.replace("$DESC$", "Commit " + hash);
}, fs.writeFileSync(path.join(steampipeDir, "app.vdf"), convertedContents);
err => {
console.error("Packaging error:", err); cb();
cb(); });
gulp.task(taskPrefix + "standalone.prepare.minifyCode", () => {
return gulp.src(path.join(electronBaseDir, "*.js")).pipe(gulp.dest(tempDestBuildDir));
});
gulp.task(taskPrefix + "standalone.prepare.copyGamefiles", () => {
return gulp.src("../build/**/*.*", { base: "../build" }).pipe(gulp.dest(tempDestBuildDir));
});
gulp.task(taskPrefix + "standalone.killRunningInstances", cb => {
try {
execSync("taskkill /F /IM shapezio.exe");
} catch (ex) {
console.warn("Failed to kill running instances, maybe none are up.");
} }
cb();
});
gulp.task(
taskPrefix + "standalone.prepare",
gulp.series(
taskPrefix + "standalone.killRunningInstances",
taskPrefix + "standalone.prepare.cleanup",
taskPrefix + "standalone.prepare.copyPrefab",
taskPrefix + "standalone.prepare.writePackageJson",
taskPrefix + "standalone.prepare.minifyCode",
taskPrefix + "standalone.prepare.copyGamefiles"
)
);
/**
*
* @param {'win32'|'linux'} platform
* @param {'x64'|'ia32'} arch
* @param {function():void} cb
*/
function packageStandalone(platform, arch, cb) {
const tomlFile = fs.readFileSync(path.join(__dirname, ".itch.toml"));
packager({
dir: tempDestBuildDir,
appCopyright: "Tobias Springer",
appVersion: getVersion(),
buildVersion: "1.0.0",
arch,
platform,
asar: true,
executableName: "shapezio",
icon: path.join(electronBaseDir, "favicon"),
name: "shapez.io-standalone" + suffix,
out: tempDestDir,
overwrite: true,
appBundleId: "io.shapez.standalone",
appCategoryType: "public.app-category.games",
}).then(
appPaths => {
console.log("Packages created:", appPaths);
appPaths.forEach(appPath => {
if (!fs.existsSync(appPath)) {
console.error("Bad app path gotten:", appPath);
return;
}
>>>>>>> master
fs.writeFileSync(
path.join(appPath, "LICENSE"),
fs.readFileSync(path.join(__dirname, "..", "LICENSE"))
);
fs.writeFileSync(path.join(appPath, ".itch.toml"), tomlFile);
if (platform === "linux") {
fs.writeFileSync(
path.join(appPath, "play.sh"),
'#!/usr/bin/env bash\n./shapezio --no-sandbox "$@"\n'
);
fs.chmodSync(path.join(appPath, "play.sh"), 0o775);
}
});
cb();
},
err => {
console.error("Packaging error:", err);
cb();
}
);
}
gulp.task(taskPrefix + "standalone.package.prod.win64", cb => packageStandalone("win32", "x64", cb));
gulp.task(taskPrefix + "standalone.package.prod.linux64", cb =>
packageStandalone("linux", "x64", cb)
);
gulp.task(
taskPrefix + "standalone.package.prod",
gulp.series(
taskPrefix + "standalone.prepare",
gulp.parallel(
taskPrefix + "standalone.package.prod.win64",
taskPrefix + "standalone.package.prod.linux64"
)
)
); );
} }
gulp.task("standalone.package.prod.win64", cb => packageStandalone("win32", "x64", cb));
gulp.task("standalone.package.prod.win32", cb => packageStandalone("win32", "ia32", cb));
gulp.task("standalone.package.prod.linux64", cb => packageStandalone("linux", "x64", cb));
gulp.task("standalone.package.prod.linux32", cb => packageStandalone("linux", "ia32", cb));
gulp.task("standalone.package.prod.darwin64", cb => packageStandalone("darwin", "x64", cb));
gulp.task("standalone.package.prod.darwin64.unsigned", cb =>
packageStandalone("darwin", "x64", cb, false)
);
gulp.task(
"standalone.package.prod",
gulp.series(
"standalone.prepare",
gulp.parallel(
"standalone.package.prod.win64",
"standalone.package.prod.linux64",
"standalone.package.prod.darwin64"
)
)
);
} }
module.exports = { gulptasksStandalone }; module.exports = { gulptasksStandalone };

View File

@ -2,14 +2,16 @@
{ {
"appid" "1318690" "appid" "1318690"
"desc" "$DESC$" "desc" "$DESC$"
"buildoutput" "C:\work\shapez\shapez.io\gulp\steampipe\steamtemp" "buildoutput" "C:\work\shapez.io\gulp\steampipe\steamtemp"
"contentroot" "" "contentroot" ""
"setlive" "" "setlive" ""
"preview" "0" "preview" "0"
"local" "" "local" ""
"depots" "depots"
{ {
"1318691" "C:\work\shapez\shapez.io\gulp\steampipe\scripts\windows.vdf" "1318691" "C:\work\shapez.io\gulp\steampipe\scripts\windows.vdf"
"1318692" "C:\work\shapez\shapez.io\gulp\steampipe\scripts\linux.vdf" "1318694" "C:\work\shapez.io\gulp\steampipe\scripts\china-windows.vdf"
"1318692" "C:\work\shapez.io\gulp\steampipe\scripts\linux.vdf"
"1318695" "C:\work\shapez.io\gulp\steampipe\scripts\china-linux.vdf"
} }
} }

View File

@ -0,0 +1,12 @@
"DepotBuildConfig"
{
"DepotID" "1318695"
"contentroot" "C:\work\shapez.io\tmp_standalone_files_china\shapez.io-standalonechina-linux-x64"
"FileMapping"
{
"LocalPath" "*"
"DepotPath" "."
"recursive" "1"
}
"FileExclusion" "*.pdb"
}

View File

@ -0,0 +1,12 @@
"DepotBuildConfig"
{
"DepotID" "1318694"
"contentroot" "C:\work\shapez.io\tmp_standalone_files_china\shapez.io-standalonechina-win32-x64"
"FileMapping"
{
"LocalPath" "*"
"DepotPath" "."
"recursive" "1"
}
"FileExclusion" "*.pdb"
}

View File

@ -1,7 +1,7 @@
"DepotBuildConfig" "DepotBuildConfig"
{ {
"DepotID" "1318692" "DepotID" "1318692"
"contentroot" "C:\work\shapez\shapez.io\tmp_standalone_files\shapez.io-standalone-linux-x64" "contentroot" "C:\work\shapez.io\tmp_standalone_files\shapez.io-standalone-linux-x64"
"FileMapping" "FileMapping"
{ {
"LocalPath" "*" "LocalPath" "*"

View File

@ -1,7 +1,7 @@
"DepotBuildConfig" "DepotBuildConfig"
{ {
"DepotID" "1318691" "DepotID" "1318691"
"contentroot" "C:\work\shapez\shapez.io\tmp_standalone_files\shapez.io-standalone-win32-x64" "contentroot" "C:\work\shapez.io\tmp_standalone_files\shapez.io-standalone-win32-x64"
"FileMapping" "FileMapping"
{ {
"LocalPath" "*" "LocalPath" "*"

View File

@ -6,7 +6,7 @@ const { getRevision, getVersion, getAllResourceImages } = require("./buildutils"
const lzString = require("lz-string"); const lzString = require("lz-string");
const CircularDependencyPlugin = require("circular-dependency-plugin"); const CircularDependencyPlugin = require("circular-dependency-plugin");
module.exports = ({ watch = false, standalone = false }) => { module.exports = ({ watch = false, standalone = false, chineseVersion = false }) => {
return { return {
mode: "development", mode: "development",
devtool: "cheap-source-map", devtool: "cheap-source-map",
@ -34,6 +34,7 @@ module.exports = ({ watch = false, standalone = false }) => {
G_TRACKING_ENDPOINT: JSON.stringify( G_TRACKING_ENDPOINT: JSON.stringify(
lzString.compressToEncodedURIComponent("http://localhost:10005/v1") lzString.compressToEncodedURIComponent("http://localhost:10005/v1")
), ),
G_CHINA_VERSION: JSON.stringify(chineseVersion),
G_IS_DEV: "true", G_IS_DEV: "true",
G_IS_RELEASE: "false", G_IS_RELEASE: "false",
G_IS_MOBILE_APP: "false", G_IS_MOBILE_APP: "false",

View File

@ -16,12 +16,15 @@ module.exports = ({
standalone = false, standalone = false,
isBrowser = true, isBrowser = true,
mobileApp = false, mobileApp = false,
chineseVersion = false,
}) => { }) => {
const globalDefs = { const globalDefs = {
assert: enableAssert ? "window.assert" : "false && window.assert", assert: enableAssert ? "window.assert" : "false && window.assert",
assertAlways: "window.assert", assertAlways: "window.assert",
abstract: "window.assert(false, 'abstract method called');", abstract: "window.assert(false, 'abstract method called');",
G_IS_DEV: "false", G_IS_DEV: "false",
G_CHINA_VERSION: JSON.stringify(chineseVersion),
G_IS_RELEASE: environment === "prod" ? "true" : "false", G_IS_RELEASE: environment === "prod" ? "true" : "false",
G_IS_STANDALONE: standalone ? "true" : "false", G_IS_STANDALONE: standalone ? "true" : "false",
G_IS_BROWSER: isBrowser ? "true" : "false", G_IS_BROWSER: isBrowser ? "true" : "false",

View File

@ -3402,7 +3402,7 @@ cross-spawn@^5.0.1:
shebang-command "^1.2.0" shebang-command "^1.2.0"
which "^1.2.9" which "^1.2.9"
cross-spawn@^7.0.0: cross-spawn@^7.0.0, cross-spawn@^7.0.3:
version "7.0.3" version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
@ -4746,6 +4746,21 @@ execa@^4.0.0:
signal-exit "^3.0.2" signal-exit "^3.0.2"
strip-final-newline "^2.0.0" strip-final-newline "^2.0.0"
execa@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/execa/-/execa-5.0.0.tgz#4029b0007998a841fbd1032e5f4de86a3c1e3376"
integrity sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==
dependencies:
cross-spawn "^7.0.3"
get-stream "^6.0.0"
human-signals "^2.1.0"
is-stream "^2.0.0"
merge-stream "^2.0.0"
npm-run-path "^4.0.1"
onetime "^5.1.2"
signal-exit "^3.0.3"
strip-final-newline "^2.0.0"
executable@^4.1.0: executable@^4.1.0:
version "4.1.1" version "4.1.1"
resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c" resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c"
@ -5517,6 +5532,11 @@ get-stream@^5.0.0, get-stream@^5.1.0:
dependencies: dependencies:
pump "^3.0.0" pump "^3.0.0"
get-stream@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.0.tgz#3e0012cb6827319da2706e601a1583e8629a6718"
integrity sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==
get-value@^2.0.3, get-value@^2.0.6: get-value@^2.0.3, get-value@^2.0.6:
version "2.0.6" version "2.0.6"
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
@ -5539,6 +5559,16 @@ gifsicle@^5.0.0:
execa "^4.0.0" execa "^4.0.0"
logalot "^2.0.0" logalot "^2.0.0"
gifsicle@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/gifsicle/-/gifsicle-5.2.0.tgz#b06b25ed7530f033f6ed2c545d6f9b546cc182fb"
integrity sha512-vOIS3j0XoTCxq9pkGj43gEix82RkI5FveNgaFZutjbaui/HH+4fR8Y56dwXDuxYo8hR4xOo6/j2h1WHoQW6XLw==
dependencies:
bin-build "^3.0.0"
bin-wrapper "^4.0.0"
execa "^5.0.0"
logalot "^2.0.0"
glob-all@^3.1.0: glob-all@^3.1.0:
version "3.1.0" version "3.1.0"
resolved "https://registry.yarnpkg.com/glob-all/-/glob-all-3.1.0.tgz#8913ddfb5ee1ac7812656241b03d5217c64b02ab" resolved "https://registry.yarnpkg.com/glob-all/-/glob-all-3.1.0.tgz#8913ddfb5ee1ac7812656241b03d5217c64b02ab"
@ -6520,6 +6550,11 @@ human-signals@^1.1.1:
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==
human-signals@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4: iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4:
version "0.4.24" version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
@ -8772,7 +8807,7 @@ npm-run-path@^2.0.0:
dependencies: dependencies:
path-key "^2.0.0" path-key "^2.0.0"
npm-run-path@^4.0.0: npm-run-path@^4.0.0, npm-run-path@^4.0.1:
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==
@ -8985,6 +9020,13 @@ onetime@^5.1.0:
dependencies: dependencies:
mimic-fn "^2.1.0" mimic-fn "^2.1.0"
onetime@^5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
dependencies:
mimic-fn "^2.1.0"
open@^0.0.5: open@^0.0.5:
version "0.0.5" version "0.0.5"
resolved "https://registry.yarnpkg.com/open/-/open-0.0.5.tgz#42c3e18ec95466b6bf0dc42f3a2945c3f0cad8fc" resolved "https://registry.yarnpkg.com/open/-/open-0.0.5.tgz#42c3e18ec95466b6bf0dc42f3a2945c3f0cad8fc"
@ -11469,6 +11511,11 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
signal-exit@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
simple-swizzle@^0.2.2: simple-swizzle@^0.2.2:
version "0.2.2" version "0.2.2"
resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a"

BIN
res/logo_cn.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

@ -451,6 +451,10 @@
box-sizing: border-box; box-sizing: border-box;
@include S(grid-gap, 4px); @include S(grid-gap, 4px);
&.china {
grid-template-columns: auto auto 1fr;
}
.author { .author {
flex-grow: 1; flex-grow: 1;
text-align: right; text-align: right;

View File

@ -13,7 +13,7 @@ import { cachebust } from "./cachebust";
const logger = createLogger("background_loader"); const logger = createLogger("background_loader");
const essentialMainMenuSprites = [ const essentialMainMenuSprites = [
"logo.png", G_CHINA_VERSION ? "logo_cn.png" : "logo.png",
...G_ALL_UI_IMAGES.filter(src => src.startsWith("ui/") && src.indexOf(".gif") < 0), ...G_ALL_UI_IMAGES.filter(src => src.startsWith("ui/") && src.indexOf(".gif") < 0),
]; ];
const essentialMainMenuSounds = [ const essentialMainMenuSounds = [

2
src/js/globals.d.ts vendored
View File

@ -19,6 +19,8 @@ declare const G_BUILD_VERSION: string;
declare const G_ALL_UI_IMAGES: Array<string>; declare const G_ALL_UI_IMAGES: Array<string>;
declare const G_IS_RELEASE: boolean; declare const G_IS_RELEASE: boolean;
declare const G_CHINA_VERSION : boolean;
// Polyfills // Polyfills
declare interface String { declare interface String {
replaceAll(search: string, replacement: string): string; replaceAll(search: string, replacement: string): string;

View File

@ -15,7 +15,9 @@ export class AboutState extends TextualGameState {
getMainContentHTML() { getMainContentHTML() {
return ` return `
<div class="head"> <div class="head">
<img src="${cachebust("res/logo.png")}" alt="shapez.io Logo"> <img src="${cachebust(
G_CHINA_VERSION ? "res/logo_cn.png" : "res/logo.png"
)}" alt="shapez.io Logo">
</div> </div>
<div class="text"> <div class="text">
${T.about.body ${T.about.body

View File

@ -42,7 +42,12 @@ export class MainMenuState extends GameState {
return ` return `
<div class="topButtons"> <div class="topButtons">
<button class="languageChoose" data-languageicon="${this.app.settings.getLanguage()}"></button> ${
G_CHINA_VERSION
? ""
: `<button class="languageChoose" data-languageicon="${this.app.settings.getLanguage()}"></button>`
}
<button class="settingsButton"></button> <button class="settingsButton"></button>
${ ${
G_IS_STANDALONE || G_IS_DEV G_IS_STANDALONE || G_IS_DEV
@ -58,7 +63,9 @@ export class MainMenuState extends GameState {
</video> </video>
<div class="logo"> <div class="logo">
<img src="${cachebust("res/logo.png")}" alt="shapez.io Logo"> <img src="${cachebust(
G_CHINA_VERSION ? "res/logo_cn.png" : "res/logo.png"
)}" alt="shapez.io Logo">
<span class="updateLabel">v${G_BUILD_VERSION}</span> <span class="updateLabel">v${G_BUILD_VERSION}</span>
</div> </div>
@ -77,11 +84,17 @@ export class MainMenuState extends GameState {
</div> </div>
</div> </div>
<div class="footer"> <div class="footer ${G_CHINA_VERSION ? "china" : ""}">
${
G_CHINA_VERSION
? ""
: `
<a class="githubLink boxLink" target="_blank"> <a class="githubLink boxLink" target="_blank">
${T.mainMenu.openSourceHint} ${T.mainMenu.openSourceHint}
<span class="thirdpartyLogo githubLogo"></span> <span class="thirdpartyLogo githubLogo"></span>
</a> </a>`
}
<a class="discordLink boxLink" target="_blank"> <a class="discordLink boxLink" target="_blank">
${T.mainMenu.discordLink} ${T.mainMenu.discordLink}
@ -89,11 +102,11 @@ export class MainMenuState extends GameState {
</a> </a>
<div class="sidelinks"> <div class="sidelinks">
<a class="redditLink">${T.mainMenu.subreddit}</a> ${G_CHINA_VERSION ? "" : `<a class="redditLink">${T.mainMenu.subreddit}</a>`}
<a class="changelog">${T.changelog.title}</a> ${G_CHINA_VERSION ? "" : `<a class="changelog">${T.changelog.title}</a>`}
<a class="helpTranslate">${T.mainMenu.helpTranslate}</a> ${G_CHINA_VERSION ? "" : `<a class="helpTranslate">${T.mainMenu.helpTranslate}</a>`}
</div> </div>
<div class="author">${T.mainMenu.madeBy.replace( <div class="author">${T.mainMenu.madeBy.replace(
@ -208,10 +221,13 @@ export class MainMenuState extends GameState {
}); });
this.trackClicks(qs(".settingsButton"), this.onSettingsButtonClicked); this.trackClicks(qs(".settingsButton"), this.onSettingsButtonClicked);
this.trackClicks(qs(".changelog"), this.onChangelogClicked);
this.trackClicks(qs(".redditLink"), this.onRedditClicked); if (!G_CHINA_VERSION) {
this.trackClicks(qs(".languageChoose"), this.onLanguageChooseClicked); this.trackClicks(qs(".languageChoose"), this.onLanguageChooseClicked);
this.trackClicks(qs(".helpTranslate"), this.onTranslationHelpLinkClicked); this.trackClicks(qs(".redditLink"), this.onRedditClicked);
this.trackClicks(qs(".changelog"), this.onChangelogClicked);
this.trackClicks(qs(".helpTranslate"), this.onTranslationHelpLinkClicked);
}
if (G_IS_STANDALONE) { if (G_IS_STANDALONE) {
this.trackClicks(qs(".exitAppButton"), this.onExitAppButtonClicked); this.trackClicks(qs(".exitAppButton"), this.onExitAppButtonClicked);
@ -233,11 +249,13 @@ export class MainMenuState extends GameState {
); );
const githubLink = this.htmlElement.querySelector(".githubLink"); const githubLink = this.htmlElement.querySelector(".githubLink");
this.trackClicks( if (githubLink) {
githubLink, this.trackClicks(
() => this.app.platformWrapper.openExternalLink(THIRDPARTY_URLS.github), githubLink,
{ preventClick: true } () => this.app.platformWrapper.openExternalLink(THIRDPARTY_URLS.github),
); { preventClick: true }
);
}
const producerLink = this.htmlElement.querySelector(".producerLink"); const producerLink = this.htmlElement.querySelector(".producerLink");
this.trackClicks( this.trackClicks(

View File

@ -9,17 +9,19 @@ export class MobileWarningState extends GameState {
getInnerHTML() { getInnerHTML() {
return ` return `
<img class="logo" src="${cachebust("res/logo.png")}" alt="shapez.io Logo"> <img class="logo" src="${cachebust(
G_CHINA_VERSION ? "res/logo_cn.png" : "res/logo.png"
)}" alt="shapez.io Logo">
<p> <p>
I'm sorry, but shapez.io is not available on mobile devices yet! I'm sorry, but shapez.io is not available on mobile devices yet!
There is also no estimate when this will change, but feel to make a contribution! It's There is also no estimate when this will change, but feel to make a contribution! It's
&nbsp;<a href="https://github.com/tobspr/shapez.io" target="_blank">open source</a>!</p> &nbsp;<a href="https://github.com/tobspr/shapez.io" target="_blank">open source</a>!</p>
<p>If you want to play on your computer, you can also get the standalone on Steam:</p> <p>If you want to play on your computer, you can also get the standalone on Steam:</p>
<a href="${ <a href="${
THIRDPARTY_URLS.standaloneStorePage + "?ref=mobile" THIRDPARTY_URLS.standaloneStorePage + "?ref=mobile"
}" class="standaloneLink" target="_blank">Get the shapez.io standalone!</a> }" class="standaloneLink" target="_blank">Get the shapez.io standalone!</a>

View File

@ -3,7 +3,6 @@ import { cachebust } from "../core/cachebust";
import { globalConfig } from "../core/config"; import { globalConfig } from "../core/config";
import { GameState } from "../core/game_state"; import { GameState } from "../core/game_state";
import { createLogger } from "../core/logging"; import { createLogger } from "../core/logging";
import { findNiceValue } from "../core/utils";
import { getRandomHint } from "../game/hints"; import { getRandomHint } from "../game/hints";
import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs"; import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs";
import { PlatformWrapperImplBrowser } from "../platform/browser/wrapper"; import { PlatformWrapperImplBrowser } from "../platform/browser/wrapper";
@ -20,7 +19,7 @@ export class PreloadState extends GameState {
return ` return `
<div class="loadingImage"></div> <div class="loadingImage"></div>
<div class="loadingStatus"> <div class="loadingStatus">
<span class="desc">Booting</span> <span class="desc">${G_CHINA_VERSION ? "加载中" : "Booting"}</span>
</div> </div>
</div> </div>
<span class="prefab_GameHint"></span> <span class="prefab_GameHint"></span>
@ -115,6 +114,10 @@ export class PreloadState extends GameState {
.then(() => this.setStatus("Initializing language")) .then(() => this.setStatus("Initializing language"))
.then(() => { .then(() => {
if (G_CHINA_VERSION) {
return this.app.settings.updateLanguage("zh-CN");
}
if (this.app.settings.getLanguage() === "auto-detect") { if (this.app.settings.getLanguage() === "auto-detect") {
const language = autoDetectLanguageId(); const language = autoDetectLanguageId();
logger.log("Setting language to", language); logger.log("Setting language to", language);
@ -163,6 +166,10 @@ export class PreloadState extends GameState {
return; return;
} }
if (G_CHINA_VERSION) {
return;
}
return this.app.storage return this.app.storage
.readFileAsync("lastversion.bin") .readFileAsync("lastversion.bin")
.catch(err => { .catch(err => {
@ -220,6 +227,9 @@ export class PreloadState extends GameState {
} }
update() { update() {
if (G_CHINA_VERSION) {
return;
}
const now = performance.now(); const now = performance.now();
if (now - this.lastHintShown > this.nextHintDuration) { if (now - this.lastHintShown > this.nextHintDuration) {
this.lastHintShown = now; this.lastHintShown = now;
@ -250,6 +260,9 @@ export class PreloadState extends GameState {
*/ */
setStatus(text) { setStatus(text) {
logger.log("✅ " + text); logger.log("✅ " + text);
if (G_CHINA_VERSION) {
return Promise.resolve();
}
this.currentStatus = text; this.currentStatus = text;
this.statusText.innerText = text; this.statusText.innerText = text;
return Promise.resolve(); return Promise.resolve();
@ -265,7 +278,9 @@ export class PreloadState extends GameState {
subElement.innerHTML = ` subElement.innerHTML = `
<div class="logo"> <div class="logo">
<img src="${cachebust("res/logo.png")}" alt="Shapez.io Logo"> <img src="${cachebust(
G_CHINA_VERSION ? "res/logo_cn.png" : "res/logo.png"
)}" alt="Shapez.io Logo">
</div> </div>
<div class="failureInner"> <div class="failureInner">
<div class="errorHeader"> <div class="errorHeader">

View File

@ -28,8 +28,14 @@ export class SettingsState extends TextualGameState {
} }
<div class="other"> <div class="other">
<button class="styledButton about">${T.about.title}</button>
${
G_CHINA_VERSION
? ""
: `
<button class="styledButton about">${T.about.title}</button>
`
}
<div class="versionbar"> <div class="versionbar">
<div class="buildVersion">${T.global.loading} ...</div> <div class="buildVersion">${T.global.loading} ...</div>
</div> </div>
@ -68,6 +74,10 @@ export class SettingsState extends TextualGameState {
for (let i = 0; i < allApplicationSettings.length; ++i) { for (let i = 0; i < allApplicationSettings.length; ++i) {
const setting = allApplicationSettings[i]; const setting = allApplicationSettings[i];
if (G_CHINA_VERSION && setting.id === "language") {
continue;
}
categoriesHTML[setting.categoryId] += setting.getHtml(this.app); categoriesHTML[setting.categoryId] += setting.getHtml(this.app);
} }
@ -94,9 +104,12 @@ export class SettingsState extends TextualGameState {
onEnter(payload) { onEnter(payload) {
this.renderBuildText(); this.renderBuildText();
this.trackClicks(this.htmlElement.querySelector(".about"), this.onAboutClicked, {
preventDefault: false, if (!G_CHINA_VERSION) {
}); this.trackClicks(this.htmlElement.querySelector(".about"), this.onAboutClicked, {
preventDefault: false,
});
}
const keybindingsButton = this.htmlElement.querySelector(".editKeybindings"); const keybindingsButton = this.htmlElement.querySelector(".editKeybindings");
@ -131,6 +144,10 @@ export class SettingsState extends TextualGameState {
initSettings() { initSettings() {
allApplicationSettings.forEach(setting => { allApplicationSettings.forEach(setting => {
if (G_CHINA_VERSION && setting.id === "language") {
return;
}
/** @type {HTMLElement} */ /** @type {HTMLElement} */
const element = this.htmlElement.querySelector("[data-setting='" + setting.id + "']"); const element = this.htmlElement.querySelector("[data-setting='" + setting.id + "']");
setting.bind(this.app, element, this.dialogs); setting.bind(this.app, element, this.dialogs);

View File

@ -291,7 +291,7 @@ ingame:
interactiveTutorial: interactiveTutorial:
title: Tutoriál title: Tutoriál
hints: hints:
1_1_extractor: Umístěte <strong>extraktor</strong> na naleziště<strong>kruhového 1_1_extractor: Umístěte <strong>extraktor</strong> na naleziště <strong>kruhového
tvaru</strong> a vytěžte jej! tvaru</strong> a vytěžte jej!
1_2_conveyor: "Připojte extraktor pomocí <strong>dopravníkového pásu</strong> k 1_2_conveyor: "Připojte extraktor pomocí <strong>dopravníkového pásu</strong> k
vašemu HUBu!<br><br>Tip: <strong>Klikněte a táhněte</strong> vašemu HUBu!<br><br>Tip: <strong>Klikněte a táhněte</strong>
@ -404,7 +404,7 @@ buildings:
name: Extraktor name: Extraktor
description: Umístěte na naleziště tvaru nebo barvy pro zahájení těžby. description: Umístěte na naleziště tvaru nebo barvy pro zahájení těžby.
chainable: chainable:
name: Extraktor (Navazující) name: Extraktor (Řetěz)
description: Umístěte na naleziště tvaru nebo barvy pro zahájení těžby. Lze description: Umístěte na naleziště tvaru nebo barvy pro zahájení těžby. Lze
zapojit po skupinách. zapojit po skupinách.
underground_belt: underground_belt:
@ -449,10 +449,10 @@ buildings:
name: Barvič name: Barvič
description: Obarví celý tvar v levém vstupu barvou z pravého vstupu. description: Obarví celý tvar v levém vstupu barvou z pravého vstupu.
double: double:
name: Barvič (dvojnásobný) name: Barvič (2x)
description: Obarví tvary z levých vstupů barvou z horního vstupu. description: Obarví tvary z levých vstupů barvou z horního vstupu.
quad: quad:
name: Barvič (čtyřnásobný) name: Barvič (4x)
description: Umožňuje obarvit každou čtvrtinu tvaru individuálně. Jen čtvrtiny description: Umožňuje obarvit každou čtvrtinu tvaru individuálně. Jen čtvrtiny
se vstupy barev s <strong>logickým signálem</strong> na vrstvě se vstupy barev s <strong>logickým signálem</strong> na vrstvě
kabelů budou obarveny! kabelů budou obarveny!
@ -475,16 +475,16 @@ buildings:
name: Vyvažovač name: Vyvažovač
description: Multifunkční - Rovnoměrně rozděluje vstupy na výstupech. description: Multifunkční - Rovnoměrně rozděluje vstupy na výstupech.
merger: merger:
name: Spojovač (kompaktní) name: Spojovač
description: Spojí dva pásy do jednoho. description: Spojí dva pásy do jednoho.
merger-inverse: merger-inverse:
name: Spojovač (kompaktní) name: Spojovač
description: Spojí dva pásy do jednoho. description: Spojí dva pásy do jednoho.
splitter: splitter:
name: Rozdělovač (kompaktní) name: Rozdělovač
description: Rozdělí jeden pás na dva. description: Rozdělí jeden pás na dva.
splitter-inverse: splitter-inverse:
name: Rozdělovač (kompaktní) name: Rozdělovač
description: Rozdělí jeden pás na dva. description: Rozdělí jeden pás na dva.
storage: storage:
default: default:
@ -558,12 +558,12 @@ buildings:
name: Virtuální rotor name: Virtuální rotor
description: Virtuálně otáčí tvary o 90 stupňů po směru hodinových ručiček. description: Virtuálně otáčí tvary o 90 stupňů po směru hodinových ručiček.
unstacker: unstacker:
name: Virtuální extrahátor name: Virt. extrahátor
description: Virtuálně extrahuje nejvyšší vrstvu do pravého výstupu a zbývající description: Virtuálně extrahuje nejvyšší vrstvu do pravého výstupu a zbývající
do levé. do levé.
stacker: stacker:
name: Virtuální kombinátor name: Virt. kombinátor
description: Virtuálně Spojí tvary dohromady. Pokud nemohou být spojeny, pravý description: Virtuálně spojí tvary dohromady. Pokud nemohou být spojeny, pravý
tvar je položen na levý. tvar je položen na levý.
painter: painter:
name: Virtuální barvič name: Virtuální barvič
@ -615,8 +615,8 @@ storyRewards:
proti směru hodinových ručiček. Vyberte rotor a <strong>zmáčkněte proti směru hodinových ručiček. Vyberte rotor a <strong>zmáčkněte
'T' pro přepnutí mezi variantami</strong>! 'T' pro přepnutí mezi variantami</strong>!
reward_miner_chainable: reward_miner_chainable:
title: Napojovací extraktor title: Řetězový extraktor
desc: "Právě jste odemkli <strong>napojovací extraktor</strong>! Může desc: "Právě jste odemkli <strong>řetězový extraktor</strong>! Může
<strong>předat své zdroje</strong> ostatním extraktorům, čímž můžete <strong>předat své zdroje</strong> ostatním extraktorům, čímž můžete
efektivněji těžit více zdrojů!<br><br> PS: Starý extraktor bude od efektivněji těžit více zdrojů!<br><br> PS: Starý extraktor bude od
teď nahrazen ve vašem panelu nástrojů!" teď nahrazen ve vašem panelu nástrojů!"
@ -1008,7 +1008,7 @@ tips:
- Můžete proplétat různé úrovně tunelů. - Můžete proplétat různé úrovně tunelů.
- Snažte se postavit kompaktní továrny - vyplatí se to! - Snažte se postavit kompaktní továrny - vyplatí se to!
- Barvič má zrcadlově otočenou variantu, kterou můžete vybrat klávesou - Barvič má zrcadlově otočenou variantu, kterou můžete vybrat klávesou
<b>T</b> <b>T</b>.
- Užití správné kombinace vylepšení maximalizuje efektivitu. - Užití správné kombinace vylepšení maximalizuje efektivitu.
- Na maximální úrovní, 5 extraktorů zaplní jeden celý pás. - Na maximální úrovní, 5 extraktorů zaplní jeden celý pás.
- Nezapomeňte na tunely! - Nezapomeňte na tunely!

View File

@ -495,7 +495,7 @@ buildings:
description: 入力された信号をディスプレイに表示します。 形状、色、真偽値のいずれでも可能です。 description: 入力された信号をディスプレイに表示します。 形状、色、真偽値のいずれでも可能です。
reader: reader:
default: default:
name: ベルトリーダ name: ベルトリーダ
description: 平均スループットを計測できます。 アンロック後は、 最後に通過したアイテムの情報を出力します。 description: 平均スループットを計測できます。 アンロック後は、 最後に通過したアイテムの情報を出力します。
analyzer: analyzer:
default: default:
@ -577,8 +577,8 @@ storyRewards:
desc: <strong>分配機</strong>の<strong>コンパクトバージョン</strong>が利用可能になりました! - desc: <strong>分配機</strong>の<strong>コンパクトバージョン</strong>が利用可能になりました! -
1つの入力を2つの出力に分配します 1つの入力を2つの出力に分配します
reward_belt_reader: reward_belt_reader:
title: ベルトリーダ title: ベルトリーダ
desc: <strong>ベルトリーダ</strong>が利用可能になりました!ベルトのスループットを計測できます。<br><br>ワイヤーのロックが解除されれば、より便利になります! desc: <strong>ベルトリーダ</strong>が利用可能になりました!ベルトのスループットを計測できます。<br><br>ワイヤーのロックが解除されれば、より便利になります!
reward_cutter_quad: reward_cutter_quad:
title: 四分割 title: 四分割
desc: <strong>切断機</strong>のバリエーションが利用可能になりました。 - desc: <strong>切断機</strong>のバリエーションが利用可能になりました。 -
@ -846,7 +846,7 @@ keybindings:
filter: アイテムフィルタ filter: アイテムフィルタ
wire_tunnel: 交差ワイヤ wire_tunnel: 交差ワイヤ
display: ディスプレイ display: ディスプレイ
reader: ベルトリーダ reader: ベルトリーダ
virtual_processor: 仮想切断機 virtual_processor: 仮想切断機
transistor: トランジスタ transistor: トランジスタ
analyzer: 形状解析機 analyzer: 形状解析機

View File

@ -186,7 +186,7 @@ dialogs:
wersję gry dla nielimitowanych znaczników! wersję gry dla nielimitowanych znaczników!
massCutConfirm: massCutConfirm:
title: Potwierdź wycinanie title: Potwierdź wycinanie
desc: Wycinasz sporą ilość maszyn (<count> gwoli ścisłości)! Czy na pewno chcesz desc: Wycinasz sporą ilość maszyn (<count> w roli ścisłości)! Czy na pewno chcesz
kontynuować? kontynuować?
exportScreenshotWarning: exportScreenshotWarning:
title: Tworzenie zrzutu fabryki title: Tworzenie zrzutu fabryki

View File

@ -438,7 +438,7 @@ buildings:
name: Döndürücü (Saat Yönünün Tersİ) name: Döndürücü (Saat Yönünün Tersİ)
description: Şekilleri saat yönünün tersinde 90 derece döndürür. description: Şekilleri saat yönünün tersinde 90 derece döndürür.
rotate180: rotate180:
name: dürücü (180 Derece) name: ndürücü (180 Derece)
description: Şekilleri 180 derece döndürür. description: Şekilleri 180 derece döndürür.
stacker: stacker:
default: default:
@ -701,7 +701,7 @@ storyRewards:
hızını ölçmeyi sağlar.<br><br>Kabloları açana kadar bekle - o zaman hızını ölçmeyi sağlar.<br><br>Kabloları açana kadar bekle - o zaman
çok kullanışlı olacak. çok kullanışlı olacak.
reward_rotater_180: reward_rotater_180:
title: dürücü (180 derece) title: ndürücü (180 derece)
desc: 180 derece <strong>döndürücüyü</strong> açtınız! - Şekilleri 180 derece desc: 180 derece <strong>döndürücüyü</strong> açtınız! - Şekilleri 180 derece
döndürür (Süpriz! :D) döndürür (Süpriz! :D)
reward_display: reward_display:

File diff suppressed because it is too large Load Diff