Wegame version & DLC Translation in Chinese

pull/1177/head
tobspr 3 years ago
parent 65721e0837
commit b3d1204d9c

1
.gitignore vendored

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

@ -139,7 +139,12 @@ gulp.task("main.webserver", () => {
);
});
function serve({ standalone, chineseVersion = false }) {
/**
*
* @param {object} param0
* @param {"web"|"standalone"|"china"|"wegame"} param0.version
*/
function serve({ version = "web" }) {
browserSync.init({
server: buildFolder,
port: 3005,
@ -163,7 +168,7 @@ function serve({ standalone, chineseVersion = false }) {
gulp.watch(["../src/**/*.scss"], gulp.series("css.dev"));
// Watch .html files, those trigger a html rebuild
gulp.watch("../src/**/*.html", gulp.series(standalone ? "html.standalone-dev" : "html.dev"));
gulp.watch("../src/**/*.html", gulp.series(version === "web" ? "html.dev" : "html.standalone-dev"));
// Watch sound files
// gulp.watch(["../res_raw/sounds/**/*.mp3", "../res_raw/sounds/**/*.wav"], gulp.series("sounds.dev"));
@ -199,14 +204,25 @@ function serve({ standalone, chineseVersion = false }) {
return gulp.src(path).pipe(browserSync.reload({ stream: true }));
});
// Start the webpack watching server (Will never return)
if (standalone) {
gulp.series("js.standalone-dev.watch")(() => true);
} else {
if (chineseVersion) {
gulp.series("china.js.dev.watch")(() => true);
} else {
switch (version) {
case "web": {
gulp.series("js.dev.watch")(() => true);
break;
}
case "standalone": {
gulp.series("js.standalone-dev.watch")(() => true);
break;
}
case "china": {
gulp.series("china.js.dev.watch")(() => true);
break;
}
case "wegame": {
gulp.series("wegame.js.dev.watch")(() => true);
break;
}
default: {
throw new Error("Unknown version " + version);
}
}
}
@ -294,7 +310,7 @@ gulp.task(
// Builds everything (standalone-prod)
for (const prefix of ["", "china."]) {
for (const prefix of ["", "china.", "wegame."]) {
gulp.task(
prefix + "step.standalone-prod.code",
gulp.series("sounds.fullbuildHQ", "translations.fullBuild", prefix + "js.standalone-prod")
@ -327,25 +343,41 @@ gulp.task(
);
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"));
// steam
gulp.task("regular.main.standalone", gulp.series("build.standalone-prod", "standalone.package.prod"));
// china
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"));
// wegame
gulp.task(
"wegame.main.standalone",
gulp.series("wegame.build.standalone-prod", "wegame.standalone.package.prod")
);
// all (except wegame)
gulp.task("standalone.all", gulp.series("regular.main.standalone", "wegame.main.standalone"));
// Live-development
gulp.task(
"main.serveDev",
gulp.series("build.dev", () => serve({ standalone: false }))
gulp.series("build.dev", () => serve({ version: "web" }))
);
gulp.task(
"main.serveStandalone",
gulp.series("build.standalone.dev", () => serve({ standalone: true }))
gulp.series("build.standalone.dev", () => serve({ version: "standalone" }))
);
gulp.task(
"china.main.serveDev",
gulp.series("build.dev", () => serve({ standalone: false, chineseVersion: true }))
gulp.series("build.dev", () => serve({ version: "china" }))
);
gulp.task(
"wegame.main.serveDev",
gulp.series("build.dev", () => serve({ version: "wegame" }))
);
gulp.task("default", gulp.series("main.serveDev"));

@ -59,6 +59,36 @@ function gulptasksJS($, gulp, buildFolder, browserSync) {
.pipe(gulp.dest(buildFolder));
});
//// DEV WEGAME
gulp.task("wegame.js.dev.watch", () => {
return gulp
.src("../src/js/main.js")
.pipe(
$.webpackStream(
requireUncached("./webpack.config.js")({
watch: true,
wegameVersion: true,
})
)
)
.pipe(gulp.dest(buildFolder))
.pipe(browserSync.stream());
});
gulp.task("wegame.js.dev", () => {
return gulp
.src("../src/js/main.js")
.pipe(
$.webpackStream(
requireUncached("./webpack.config.js")({
wegameVersion: true,
})
)
)
.pipe(gulp.dest(buildFolder));
});
//// STAGING
gulp.task("js.staging.transpiled", () => {
@ -208,6 +238,23 @@ function gulptasksJS($, gulp, buildFolder, browserSync) {
)
.pipe(gulp.dest(buildFolder));
});
gulp.task("wegame.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,
wegameVersion: true,
})
)
)
.pipe(gulp.dest(buildFolder));
});
}
module.exports = {

@ -21,6 +21,11 @@ function gulptasksStandalone($, gulp) {
suffix: "china",
taskPrefix: "china.",
},
{
tempDestDir: path.join(__dirname, "..", "tmp_standalone_files_wegame"),
suffix: "wegame",
taskPrefix: "wegame.",
},
];
for (const { tempDestDir, suffix, taskPrefix } of targets) {

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

@ -17,6 +17,7 @@ module.exports = ({
isBrowser = true,
mobileApp = false,
chineseVersion = false,
wegameVersion = false,
}) => {
const globalDefs = {
assert: enableAssert ? "window.assert" : "false && window.assert",
@ -25,6 +26,7 @@ module.exports = ({
G_IS_DEV: "false",
G_CHINA_VERSION: JSON.stringify(chineseVersion),
G_WEGAME_VERSION: JSON.stringify(wegameVersion),
G_IS_RELEASE: environment === "prod" ? "true" : "false",
G_IS_STANDALONE: standalone ? "true" : "false",
G_IS_BROWSER: isBrowser ? "true" : "false",

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

@ -12,8 +12,13 @@ import { cachebust } from "./cachebust";
const logger = createLogger("background_loader");
export function getLogoSprite() {
// @todo: ugh, in a hurry
return G_WEGAME_VERSION ? "logo_wegame.png" : G_CHINA_VERSION ? "logo_cn.png" : "logo.png";
}
const essentialMainMenuSprites = [
G_CHINA_VERSION ? "logo_cn.png" : "logo.png",
getLogoSprite(),
...G_ALL_UI_IMAGES.filter(src => src.startsWith("ui/") && src.indexOf(".gif") < 0),
];
const essentialMainMenuSounds = [

@ -66,6 +66,8 @@ const preparementShape = "CpRpCp--:SwSwSwSw";
// Tiers need % of the previous tier as requirement too
const tierGrowth = 2.5;
const chinaShapes = G_WEGAME_VERSION || G_CHINA_VERSION;
/**
* Generates all upgrades
* @returns {Object<string, UpgradeTiers>} */
@ -144,7 +146,7 @@ function generateUpgrades(limitedVersion = false) {
{
required: [
{
shape: G_CHINA_VERSION
shape: chinaShapes
? "CyCyCyCy:CyCyCyCy:RyRyRyRy:RuRuRuRu"
: "CbRbRbCb:CwCwCwCw:WbWbWbWb",
amount: 50000,
@ -205,7 +207,7 @@ function generateUpgrades(limitedVersion = false) {
{
required: [
{
shape: G_CHINA_VERSION ? "CuCuCuCu:CwCwCwCw:Sb--Sr--" : "RpRpRpRp:CwCwCwCw",
shape: chinaShapes ? "CuCuCuCu:CwCwCwCw:Sb--Sr--" : "RpRpRpRp:CwCwCwCw",
amount: 6500,
},
],
@ -382,7 +384,7 @@ export function generateLevelDefinitions(limitedVersion = false) {
// 13
// Tunnel Tier 2
{
shape: G_CHINA_VERSION ? "CuCuCuCu:CwCwCwCw:Sb--Sr--" : "RpRpRpRp:CwCwCwCw", // painting t3
shape: chinaShapes ? "CuCuCuCu:CwCwCwCw:Sb--Sr--" : "RpRpRpRp:CwCwCwCw", // painting t3
required: 3800,
reward: enumHubGoalRewards.reward_underground_belt_tier_2,
},
@ -391,7 +393,7 @@ export function generateLevelDefinitions(limitedVersion = false) {
...(limitedVersion
? [
{
shape: G_CHINA_VERSION ? "CuCuCuCu:CwCwCwCw:Sb--Sr--" : "RpRpRpRp:CwCwCwCw",
shape: chinaShapes ? "CuCuCuCu:CwCwCwCw:Sb--Sr--" : "RpRpRpRp:CwCwCwCw",
required: 0,
reward: enumHubGoalRewards.reward_demo_end,
},
@ -425,7 +427,7 @@ export function generateLevelDefinitions(limitedVersion = false) {
// 17
// Double painter
{
shape: G_CHINA_VERSION
shape: chinaShapes
? "CyCyCyCy:CyCyCyCy:RyRyRyRy:RuRuRuRu"
: "CbRbRbCb:CwCwCwCw:WbWbWbWb", // miner t4 (two variants)
required: 20000,
@ -467,7 +469,7 @@ export function generateLevelDefinitions(limitedVersion = false) {
// 22
// Constant signal
{
shape: G_CHINA_VERSION
shape: chinaShapes
? "RrSySrSy:RyCrCwCr:CyCyRyCy"
: "Cg----Cr:Cw----Cw:Sy------:Cy----Cy",
required: 25000,
@ -477,7 +479,7 @@ export function generateLevelDefinitions(limitedVersion = false) {
// 23
// Display
{
shape: G_CHINA_VERSION
shape: chinaShapes
? "CrCrCrCr:CwCwCwCw:WwWwWwWw:CrCrCrCr"
: "CcSyCcSy:SyCcSyCc:CcSyCcSy",
required: 25000,
@ -486,7 +488,7 @@ export function generateLevelDefinitions(limitedVersion = false) {
// 24 Logic gates
{
shape: G_CHINA_VERSION
shape: chinaShapes
? "Su----Su:RwRwRwRw:Cu----Cu:CwCwCwCw"
: "CcRcCcRc:RwCwRwCw:Sr--Sw--:CyCyCyCy",
required: 25000,

@ -20,6 +20,7 @@ declare const G_ALL_UI_IMAGES: Array<string>;
declare const G_IS_RELEASE: boolean;
declare const G_CHINA_VERSION: boolean;
declare const G_WEGAME_VERSION: boolean;
// Polyfills
declare interface String {

@ -101,7 +101,10 @@ export class ClientAPI {
*/
apiTryLogin() {
if (!G_IS_STANDALONE) {
return Promise.reject("Not possible outside of standalone.");
const token = window.prompt(
"Please enter the auth token for the puzzle DLC (If you have none, you can't login):"
);
return Promise.resolve({ token });
}
const renderer = getIPCRenderer();

@ -53,6 +53,10 @@ export class ShapezGameAnalytics extends GameAnalyticsInterface {
initialize() {
this.syncKey = null;
if (G_WEGAME_VERSION) {
return;
}
setInterval(() => this.sendTimePoints(), 60 * 1000);
// Retrieve sync key from player
@ -136,6 +140,10 @@ export class ShapezGameAnalytics extends GameAnalyticsInterface {
* @param {string} value
*/
sendGameEvent(category, value) {
if (G_WEGAME_VERSION) {
return;
}
if (!this.syncKey) {
logger.warn("Can not send event due to missing sync key");
return;

@ -2,6 +2,7 @@ import { TextualGameState } from "../core/textual_game_state";
import { T } from "../translations";
import { THIRDPARTY_URLS } from "../core/config";
import { cachebust } from "../core/cachebust";
import { getLogoSprite } from "../core/background_resources_loader";
export class AboutState extends TextualGameState {
constructor() {
@ -15,9 +16,7 @@ export class AboutState extends TextualGameState {
getMainContentHTML() {
return `
<div class="head">
<img src="${cachebust(
G_CHINA_VERSION ? "res/logo_cn.png" : "res/logo.png"
)}" alt="shapez.io Logo">
<img src="${cachebust("res/" + getLogoSprite())}" alt="shapez.io Logo">
</div>
<div class="text">
${T.about.body

@ -1,3 +1,4 @@
import { getLogoSprite } from "../core/background_resources_loader";
import { cachebust } from "../core/cachebust";
import { A_B_TESTING_LINK_TYPE, globalConfig, THIRDPARTY_URLS } from "../core/config";
import { GameState } from "../core/game_state";
@ -49,7 +50,7 @@ export class MainMenuState extends GameState {
return `
<div class="topButtons">
${
G_CHINA_VERSION
G_CHINA_VERSION || G_WEGAME_VERSION
? ""
: `<button class="languageChoose" data-languageicon="${this.app.settings.getLanguage()}"></button>`
}
@ -69,10 +70,12 @@ export class MainMenuState extends GameState {
</video>
<div class="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} - Puzzle DLC!</span>
<img src="${cachebust("res/" + getLogoSprite())}" alt="shapez.io Logo">
${
G_WEGAME_VERSION
? ""
: `<span class="updateLabel">v${G_BUILD_VERSION} - Puzzle DLC!</span>`
}
</div>
<div class="mainWrapper ${showDemoBadges ? "demo" : "noDemo"}" data-columns="${
@ -92,7 +95,7 @@ export class MainMenuState extends GameState {
</div>
${
(G_IS_STANDALONE && puzzleDlc) || G_IS_DEV
!G_WEGAME_VERSION && ((G_IS_STANDALONE && puzzleDlc) || G_IS_DEV)
? `
<div class="puzzleContainer">
<img class="dlcLogo" src="${cachebust(
@ -104,7 +107,7 @@ export class MainMenuState extends GameState {
}
${
G_IS_STANDALONE && !puzzleDlc
!G_WEGAME_VERSION && G_IS_STANDALONE && !puzzleDlc
? `
<div class="puzzleContainer notOwned">
<img class="dlcLogo" src="${cachebust(
@ -119,7 +122,11 @@ export class MainMenuState extends GameState {
}
</div>
<div class="footer ${G_CHINA_VERSION ? "china" : ""}">
${
G_WEGAME_VERSION
? "<div class='footer wegame'></div>"
: `
<div class="footer ${G_CHINA_VERSION ? "china" : ""} ">
${
G_CHINA_VERSION
@ -150,6 +157,8 @@ export class MainMenuState extends GameState {
'<a class="producerLink" target="_blank">Tobias Springer</a>'
)}</div>
</div>
`
}
`;
}
@ -263,7 +272,7 @@ export class MainMenuState extends GameState {
this.trackClicks(qs(".settingsButton"), this.onSettingsButtonClicked);
if (!G_CHINA_VERSION) {
if (!G_CHINA_VERSION && !G_WEGAME_VERSION) {
this.trackClicks(qs(".languageChoose"), this.onLanguageChooseClicked);
this.trackClicks(qs(".redditLink"), this.onRedditClicked);
this.trackClicks(qs(".changelog"), this.onChangelogClicked);
@ -283,14 +292,16 @@ export class MainMenuState extends GameState {
}
const discordLink = this.htmlElement.querySelector(".discordLink");
this.trackClicks(
discordLink,
() => {
this.app.analytics.trackUiClick("main_menu_link_discord");
this.app.platformWrapper.openExternalLink(THIRDPARTY_URLS.discord);
},
{ preventClick: true }
);
if (discordLink) {
this.trackClicks(
discordLink,
() => {
this.app.analytics.trackUiClick("main_menu_link_discord");
this.app.platformWrapper.openExternalLink(THIRDPARTY_URLS.discord);
},
{ preventClick: true }
);
}
const githubLink = this.htmlElement.querySelector(".githubLink");
if (githubLink) {
@ -305,9 +316,15 @@ export class MainMenuState extends GameState {
}
const producerLink = this.htmlElement.querySelector(".producerLink");
this.trackClicks(producerLink, () => this.app.platformWrapper.openExternalLink("https://tobspr.io"), {
preventClick: true,
});
if (producerLink) {
this.trackClicks(
producerLink,
() => this.app.platformWrapper.openExternalLink("https://tobspr.io"),
{
preventClick: true,
}
);
}
const puzzleModeButton = qs(".puzzleDlcPlayButton");
if (puzzleModeButton) {

@ -1,6 +1,7 @@
import { GameState } from "../core/game_state";
import { cachebust } from "../core/cachebust";
import { THIRDPARTY_URLS } from "../core/config";
import { getLogoSprite } from "../core/background_resources_loader";
export class MobileWarningState extends GameState {
constructor() {
@ -10,9 +11,7 @@ export class MobileWarningState extends GameState {
getInnerHTML() {
return `
<img class="logo" src="${cachebust(
G_CHINA_VERSION ? "res/logo_cn.png" : "res/logo.png"
)}" alt="shapez.io Logo">
<img class="logo" src="${cachebust("res/" + getLogoSprite())}" alt="shapez.io Logo">
<p>
I'm sorry, but shapez.io is not available on mobile devices yet!

@ -1,4 +1,5 @@
import { CHANGELOG } from "../changelog";
import { getLogoSprite } from "../core/background_resources_loader";
import { cachebust } from "../core/cachebust";
import { globalConfig } from "../core/config";
import { GameState } from "../core/game_state";
@ -19,7 +20,7 @@ export class PreloadState extends GameState {
return `
<div class="loadingImage"></div>
<div class="loadingStatus">
<span class="desc">${G_CHINA_VERSION ? "加载中" : "Booting"}</span>
<span class="desc">${G_CHINA_VERSION || G_WEGAME_VERSION ? "加载中" : "Booting"}</span>
</div>
</div>
<span class="prefab_GameHint"></span>
@ -112,7 +113,7 @@ export class PreloadState extends GameState {
.then(() => this.setStatus("Initializing language"))
.then(() => {
if (G_CHINA_VERSION) {
if (G_CHINA_VERSION || G_WEGAME_VERSION) {
return this.app.settings.updateLanguage("zh-CN");
}
@ -164,7 +165,7 @@ export class PreloadState extends GameState {
return;
}
if (G_CHINA_VERSION) {
if (G_CHINA_VERSION || G_WEGAME_VERSION) {
return;
}
@ -227,7 +228,7 @@ export class PreloadState extends GameState {
}
update() {
if (G_CHINA_VERSION) {
if (G_CHINA_VERSION || G_WEGAME_VERSION) {
return;
}
const now = performance.now();
@ -260,7 +261,7 @@ export class PreloadState extends GameState {
*/
setStatus(text) {
logger.log("✅ " + text);
if (G_CHINA_VERSION) {
if (G_CHINA_VERSION || G_WEGAME_VERSION) {
return Promise.resolve();
}
this.currentStatus = text;
@ -278,9 +279,7 @@ export class PreloadState extends GameState {
subElement.innerHTML = `
<div class="logo">
<img src="${cachebust(
G_CHINA_VERSION ? "res/logo_cn.png" : "res/logo.png"
)}" alt="Shapez.io Logo">
<img src="${cachebust("res/" + getLogoSprite())}" alt="Shapez.io Logo">
</div>
<div class="failureInner">
<div class="errorHeader">

@ -30,7 +30,7 @@ export class SettingsState extends TextualGameState {
<div class="other">
${
G_CHINA_VERSION
G_CHINA_VERSION || G_WEGAME_VERSION
? ""
: `
<button class="styledButton about">${T.about.title}</button>
@ -74,7 +74,7 @@ export class SettingsState extends TextualGameState {
for (let i = 0; i < allApplicationSettings.length; ++i) {
const setting = allApplicationSettings[i];
if (G_CHINA_VERSION && setting.id === "language") {
if ((G_CHINA_VERSION || G_WEGAME_VERSION) && setting.id === "language") {
continue;
}
@ -105,7 +105,7 @@ export class SettingsState extends TextualGameState {
onEnter(payload) {
this.renderBuildText();
if (!G_CHINA_VERSION) {
if (!G_CHINA_VERSION && !G_WEGAME_VERSION) {
this.trackClicks(this.htmlElement.querySelector(".about"), this.onAboutClicked, {
preventDefault: false,
});
@ -144,7 +144,7 @@ export class SettingsState extends TextualGameState {
initSettings() {
allApplicationSettings.forEach(setting => {
if (G_CHINA_VERSION && setting.id === "language") {
if ((G_CHINA_VERSION || G_WEGAME_VERSION) && setting.id === "language") {
return;
}

@ -68,11 +68,10 @@ mainMenu:
madeBy: 作者:<author-link>
subreddit: Reddit
savegameUnnamed: 存档未命名
puzzleMode: Puzzle Mode
back: Back
puzzleDlcText: Do you enjoy compacting and optimizing factories? Get the Puzzle
DLC now on Steam for even more fun!
puzzleDlcWishlist: Wishlist now!
puzzleMode: 谜题模式
back: 返回
puzzleDlcText: 持续优化追求极致效率。在限定空间内使用有限的设施来创造图形《异形工厂》Shapez.io的首个DLC“谜题挑战者”将会给大家带来更烧脑、更自由的全新挑战
puzzleDlcWishlist: 添加愿望单!
dialogs:
buttons:
ok: 确认
@ -86,9 +85,9 @@ dialogs:
viewUpdate: 查看更新
showUpgrades: 显示设施升级
showKeybindings: 显示按键设置
retry: Retry
continue: Continue
playOffline: Play Offline
retry: 重试
continue: 继续
playOffline: 离线游戏
importSavegameError:
title: 读取错误
text: 未能读取您的存档:
@ -136,13 +135,15 @@ dialogs:
desc: 您还没有解锁蓝图功能通过第12关的挑战后可解锁蓝图。
keybindingsIntroduction:
title: 实用快捷键
desc: "这个游戏有很多有用的快捷键设定。 以下是其中的一些介绍,记得在<strong>按键设置</strong>中查看其他按键设定!<br><br>
desc:
"这个游戏有很多有用的快捷键设定。 以下是其中的一些介绍,记得在<strong>按键设置</strong>中查看其他按键设定!<br><br>
<code class='keybinding'>CTRL键</code> + 拖动:选择区域以复制或删除。<br> <code
class='keybinding'>SHIFT键</code>: 按住以放置多个同一种设施。<br> <code
class='keybinding'>ALT键</code>: 反向放置传送带。<br>"
createMarker:
title: 创建地图标记
desc: 填写一个有意义的名称, 还可以同时包含一个形状的 <strong>短代码</strong> (您可以 <link>点击这里</link>
desc:
填写一个有意义的名称, 还可以同时包含一个形状的 <strong>短代码</strong> (您可以 <link>点击这里</link>
生成短代码)
titleEdit: 编辑地图标记
markerDemoLimit:
@ -170,66 +171,59 @@ dialogs:
title: 教程
desc: 这个关卡有英语版本的视频攻略! 您想查看这个视频攻略吗??
editConstantProducer:
title: Set Item
title: 设置项目
puzzleLoadFailed:
title: Puzzles failed to load
desc: "Unfortunately the puzzles could not be loaded:"
title: 谜题载入失败
desc: "很遗憾,谜题未能载入:"
submitPuzzle:
title: Submit Puzzle
descName: "Give your puzzle a name:"
descIcon: "Please enter a unique short key, which will be shown as the icon of
your puzzle (You can generate them <link>here</link>, or choose one
of the randomly suggested shapes below):"
placeholderName: Puzzle Title
title: 提交谜题
descName: "给您的谜题设定名称:"
descIcon:
"请输入唯一的短代码,它将显示为标志您的谜题的图标( <link>在此</link>生成,或者从以下随机推荐的图形中选择一个):
"
placeholderName: 谜题标题
puzzleResizeBadBuildings:
title: Resize not possible
desc: You can't make the zone any smaller, because then some buildings would be
outside the zone.
title: 无法调整大小
desc: 您无法使这块区域变得更小,否则有些设施将会超出区域范围。
puzzleLoadError:
title: Bad Puzzle
desc: "The puzzle failed to load:"
title: 谜题出错
desc: "谜题载入失败:"
offlineMode:
title: Offline Mode
desc: We couldn't reach the servers, so the game has to run in offline mode.
Please make sure you have an active internect connection.
title: 离线模式
desc: 访问服务器失败,游戏只能在离线模式下进行。请确认您的网络连接正常。
puzzleDownloadError:
title: Download Error
desc: "Failed to download the puzzle:"
title: 下载出错
desc: "无法下载谜题:"
puzzleSubmitError:
title: Submission Error
desc: "Failed to submit your puzzle:"
title: 提交出错
desc: "无法提交您的谜题:"
puzzleSubmitOk:
title: Puzzle Published
desc: Congratulations! Your puzzle has been published and can now be played by
others. You can now find it in the "My puzzles" section.
title: 谜题已发布
desc: 恭喜!您所创造的谜题已成功发布,别的玩家已经可以对您的谜题发起挑战!您可以在"我的谜题"部分找到您发布的谜题。
puzzleCreateOffline:
title: Offline Mode
desc: Since you are offline, you will not be able to save and/or publish your
puzzle. Would you still like to continue?
title: 离线模式
desc: 由于您现在没有连接互联网,所以您将无法保存或发布您的谜题。是否仍要继续?
puzzlePlayRegularRecommendation:
title: Recommendation
desc: I <strong>strongly</strong> recommend playing the normal game to level 12
before attempting the puzzle DLC, otherwise you may encounter
mechanics not yet introduced. Do you still want to continue?
title: 游戏建议
desc: <strong>强烈</strong>建议您在至少完成本体第12关后再尝试体验“谜题挑战者”DLC否则您可能在游戏过程中遇到困难您是否仍要继续
puzzleShare:
title: Short Key Copied
desc: The short key of the puzzle (<key>) has been copied to your clipboard! It
can be entered in the puzzle menu to access the puzzle.
title: 短代码已复制
desc: 此谜题的短代码(<key>)已经复制到了您的剪贴板!您可以在谜题菜单中输入短代码以快速访问对应谜题。
puzzleReport:
title: Report Puzzle
title: 上报谜题
options:
profane: Profane
unsolvable: Not solvable
profane: 污言秽语
unsolvable: 无法完成
trolling: Trolling
puzzleReportComplete:
title: Thank you for your feedback!
desc: The puzzle has been flagged.
title: 感谢您的反馈!
desc: 此谜题已标记!
puzzleReportError:
title: Failed to report
desc: "Your report could not get processed:"
title: 上报失败
desc: "无法处理您的上报:"
puzzleLoadShortKey:
title: Enter short key
desc: Enter the short key of the puzzle to load it.
title: 输入短代码
desc: 输入此谜题的短代码以载入。
ingame:
keybindingsOverlay:
moveMap: 移动地图
@ -251,7 +245,7 @@ ingame:
clearSelection: 取消选择
pipette: 吸取器
switchLayers: 切换层
clearBelts: Clear belts
clearBelts: 清除传送带
buildingPlacement:
cycleBuildingVariants: 按 <key> 键以选择设施的变型体。
hotkeyLabel: "快捷键: <key>"
@ -315,15 +309,18 @@ ingame:
hints:
1_1_extractor: 在<strong>圆形</strong>上放置一个<strong>开采器</strong>来获取圆形!<br><br>提示:<strong>按下鼠标左键</strong>选中<strong>开采器</strong>
1_2_conveyor: 用<strong>传送带</strong>将您的开采器连接到中心基地上!<br><br>提示:选中<strong>传送带</strong>后<strong>按下鼠标左键可拖动</strong>布置传送带!
1_3_expand: 您可以放置更多的<strong>开采器</strong>和<strong>传送带</strong>来更有效率地完成关卡目标。<br><br>
1_3_expand:
您可以放置更多的<strong>开采器</strong>和<strong>传送带</strong>来更有效率地完成关卡目标。<br><br>
提示:按住 <strong>SHIFT</strong>
键可放置多个<strong>开采器</strong>,注意用<strong>R</strong>
键可旋转<strong>开采器</strong>的出口方向,确保开采的图形可以顺利传送。
2_1_place_cutter: 现在放置一个<strong>切割器</strong>,这个设施可把<strong>圆形</strong>切成两半!<br><br>注意:无论如何放置,切割机总是<strong>从上到下</strong>切割。
2_2_place_trash: 使用切割机后产生的废弃图形会导致<strong>堵塞</strong>。<br><br>注意使用<strong>垃圾桶</strong>清除当前
2_2_place_trash:
使用切割机后产生的废弃图形会导致<strong>堵塞</strong>。<br><br>注意使用<strong>垃圾桶</strong>清除当前
(!) 不需要的废物。
2_3_more_cutters: 干的好!现在放置<strong>2个以上的切割机</strong>来加快当前缓慢的过程!<br><br>提示:用<strong>快捷键0-9</strong>可以快速选择各项设施!
3_1_rectangles: 现在让我们开采一些矩形!找到<strong>矩形地带</strong>并<strong>放置4个开采器</strong>并将它们用<strong>传送带</strong>连接到中心基地。<br><br>
3_1_rectangles:
现在让我们开采一些矩形!找到<strong>矩形地带</strong>并<strong>放置4个开采器</strong>并将它们用<strong>传送带</strong>连接到中心基地。<br><br>
提示:选中<strong>传送带</strong>后按住<strong>SHIFT键</strong>可快速准确地规划<strong>传送带路线!</strong>
21_1_place_quad_painter: 放置<strong>四口上色器</strong>并且获取一些<strong>圆形</strong><strong>白色</strong>和<strong>红色</strong>
21_2_switch_to_wires: 按 <strong>E</strong> 键选择<strong>电线层</strong><br><br>
@ -381,43 +378,35 @@ ingame:
title: 成就
desc: 挑战全成就解锁!
puzzleEditorSettings:
zoneTitle: Zone
zoneWidth: Width
zoneHeight: Height
trimZone: Trim
clearItems: Clear Items
share: Share
report: Report
zoneTitle: 区域
zoneWidth: 宽度
zoneHeight: 高度
trimZone: 整理
clearItems: 清除项目
share: 共享
report: 上报
puzzleEditorControls:
title: Puzzle Creator
title: 谜题编辑器
instructions:
- 1. Place <strong>Constant Producers</strong> to provide shapes and
colors to the player
- 2. Build one or more shapes you want the player to build later and
deliver it to one or more <strong>Goal Acceptors</strong>
- 3. Once a Goal Acceptor receives a shape for a certain amount of
time, it <strong>saves it as a goal</strong> that the player must
produce later (Indicated by the <strong>green badge</strong>).
- 4. Click the <strong>lock button</strong> on a building to disable
it.
- 5. Once you click review, your puzzle will be validated and you
can publish it.
- 6. Upon release, <strong>all buildings will be removed</strong>
except for the Producers and Goal Acceptors - That's the part that
the player is supposed to figure out for themselves, after all :)
- 1.放置<strong>常量生成器</strong>,为玩家提供此谜题的初始图形和颜色。
- 2.建造您希望玩家稍后建造的一个或多个图形,并将其交付给一个或多个<strong>目标接收器</strong>。
- 3.当一个目标接收器接收到一个图形一段时间后,会<strong>将其保存为此玩家稍后必须建造的目标</strong>(由<strong>绿色充能条</strong>表示)。
- 4.单击设施上的<strong>锁定按钮</strong>即可将其禁用。
- 5.单击审阅后,您的谜题将通过验证,您可以正式发布它。
- 6.谜题发布后,<strong>所有设施都将被拆除</strong>,除了<strong>常量生成器</strong>和<strong>目标接收器</strong>。然后,等着其他玩家对您创造的谜题发起挑战吧!
puzzleCompletion:
title: Puzzle Completed!
titleLike: "Click the heart if you liked the puzzle:"
titleRating: How difficult did you find the puzzle?
titleRatingDesc: Your rating will help me to make you better suggestions in the future
continueBtn: Keep Playing
menuBtn: Menu
title: 谜题挑战成功!
titleLike: "喜欢此谜题的话,请为它点赞:"
titleRating: 您觉得此谜题难度如何?
titleRatingDesc: 您的评分将帮助作者在未来创作出更好的谜题!
continueBtn: 继续游戏
menuBtn: 菜单
puzzleMetadata:
author: Author
shortKey: Short Key
rating: Difficulty score
averageDuration: Avg. Duration
completionRate: Completion rate
author: 作者
shortKey: 短代码
rating: 难度评分
averageDuration: 平均挑战时间
completionRate: 挑战完成率
shopUpgrades:
belt:
name: 传送、分发、隧道
@ -495,7 +484,7 @@ buildings:
hub:
deliver: 交付
toUnlock: 解锁
levelShortcut: LVL
levelShortcut: 关卡
endOfDemo: 试玩版结束
wire:
default:
@ -601,16 +590,16 @@ buildings:
description: 仅在沙盒模式下可用,在常规层上输出<strong>电线层</strong>给定的<strong>信号</strong>。
constant_producer:
default:
name: Constant Producer
description: Constantly outputs a specified shape or color.
name: 常量生成器
description: 不断输出指定的图形或颜色。
goal_acceptor:
default:
name: Goal Acceptor
description: Deliver shapes to the goal acceptor to set them as a goal.
name: 目标接收器
description: 将图状传递给目标接收器,以将它们设置为谜题挑战目标。
block:
default:
name: Block
description: Allows you to block a tile.
name: 方块
description: 放置了方块的格子将无法再进行其他放置。
storyRewards:
reward_cutter_and_trash:
title: 切割图形
@ -622,7 +611,8 @@ storyRewards:
desc: 恭喜!您解锁了<strong>旋转机</strong>。它会顺时针将输入的<strong>图形旋转90度</strong>。
reward_painter:
title: 上色
desc: 恭喜!您解锁了<strong>上色器</strong>。开采一些颜色 (就像您开采图形一样),将其在上色器中与图形结合来将图形上色!
desc:
恭喜!您解锁了<strong>上色器</strong>。开采一些颜色 (就像您开采图形一样),将其在上色器中与图形结合来将图形上色!
<br>注意:如果您不幸患有色盲,可以在设置中启用<strong>色盲模式</strong>
reward_mixer:
title: 混合颜色
@ -639,11 +629,13 @@ storyRewards:
desc: 恭喜!您解锁了<strong>隧道</strong>。它可放置在<strong>传送带</strong>或<strong>设施</strong>下方以运送物品。
reward_rotater_ccw:
title: 逆时针旋转
desc: 恭喜!您解锁了<strong>旋转机</strong>的<strong>逆时针</strong>变体。它可以逆时针旋转<strong>图形</strong>。
desc:
恭喜!您解锁了<strong>旋转机</strong>的<strong>逆时针</strong>变体。它可以逆时针旋转<strong>图形</strong>。
<br>选择<strong>旋转机</strong>然后按"T"键来选取这个变体。
reward_miner_chainable:
title: 链式开采器
desc: 您已经解锁了<strong>链式开采器</strong>!它能<strong>转发资源</strong>给其他的开采器,这样您就能更有效率的开采各类资源了!<br><br>
desc:
您已经解锁了<strong>链式开采器</strong>!它能<strong>转发资源</strong>给其他的开采器,这样您就能更有效率的开采各类资源了!<br><br>
注意:新的开采器已替换了工具栏里旧的开采器!
reward_underground_belt_tier_2:
title: 二级隧道
@ -660,12 +652,14 @@ storyRewards:
<br>它<strong>优先从左边</strong>输出,这样您就可以用它做一个<strong>溢流门</strong>了!
reward_freeplay:
title: 自由模式
desc: 成功了!您解锁了<strong>自由模式</strong>!挑战升级!这意味着现在将<strong>随机</strong>生成图形!
desc:
成功了!您解锁了<strong>自由模式</strong>!挑战升级!这意味着现在将<strong>随机</strong>生成图形!
从现在起,中心基地最为需要的是<strong>产量</strong>,我强烈建议您去制造一台能够自动交付所需图形的机器!<br><br>
基地会在<strong>电线层</strong>输出需要的图形,您需要去分析图形并在此基础上自动配置您的工厂。
reward_blueprints:
title: 蓝图
desc: 您现在可以<strong>复制粘贴</strong>您的工厂的一部分了!按住 CTRL键并拖动鼠标来选择一块区域然后按C键复制。
desc:
您现在可以<strong>复制粘贴</strong>您的工厂的一部分了!按住 CTRL键并拖动鼠标来选择一块区域然后按C键复制。
<br><br>粘贴并<strong>不是免费的</strong>,您需要制造<strong>蓝图图形</strong>来负担。蓝图图形是您刚刚交付的图形。
no_reward:
title: 下一关
@ -693,7 +687,8 @@ storyRewards:
<br>注意:您注意到<strong>传送读取器</strong>和<strong>存储器</strong>输出的他们最后读取的物品了吗?试着在显示屏上展示一下!"
reward_constant_signal:
title: 恒定信号
desc: 恭喜!您解锁了生成于电线层之上的<strong>恒定信号</strong>,把它连接到<strong>过滤器</strong>时非常有用。
desc:
恭喜!您解锁了生成于电线层之上的<strong>恒定信号</strong>,把它连接到<strong>过滤器</strong>时非常有用。
<br>比如它能发出图形、颜色、开关值1 / 0的固定信号。
reward_logic_gates:
title: 逻辑门
@ -712,7 +707,8 @@ storyRewards:
<strong>提示</strong>:可在设置中打开电线层教程!"
reward_filter:
title: 物品过滤器
desc: 恭喜!您解锁了<strong>物品过滤器</strong>!它会根据在电线层上输入的信号决定是从上面还是右边输出物品。<br><br>
desc:
恭喜!您解锁了<strong>物品过滤器</strong>!它会根据在电线层上输入的信号决定是从上面还是右边输出物品。<br><br>
您也可以输入开关值1 / 0信号来激活或者禁用它。
reward_demo_end:
title: 试玩结束
@ -927,10 +923,10 @@ keybindings:
rotateToDown: 向下旋转
rotateToRight: 向右旋转
rotateToLeft: 向左旋转
constant_producer: Constant Producer
goal_acceptor: Goal Acceptor
block: Block
massSelectClear: Clear belts
constant_producer: 常量生成器
goal_acceptor: 目标接收器
block: 方块
massSelectClear: 清除传送带
about:
title: 关于游戏
body: >-
@ -1010,58 +1006,51 @@ tips:
- 按F4显示FPS。
- 按两次F4显示您鼠标和镜头所在的块。
- 您可以点击被固定在屏幕左侧的图形来解除固定。
- You can click a pinned shape on the left side to unpin it.
- 您可以单击左侧的固定形状将其取消固定。
puzzleMenu:
play: Play
edit: Edit
title: Puzzle Mode
createPuzzle: Create Puzzle
loadPuzzle: Load
reviewPuzzle: Review & Publish
validatingPuzzle: Validating Puzzle
submittingPuzzle: Submitting Puzzle
noPuzzles: There are currently no puzzles in this section.
play: 游戏
edit: 编辑
title: 谜题模式
createPuzzle: 创建谜题
loadPuzzle: 载入
reviewPuzzle: 审阅 & 发布
validatingPuzzle: 验证谜题
submittingPuzzle: 提交谜题
noPuzzles: 暂无满足此部分条件的谜题。
categories:
levels: Levels
new: New
top-rated: Top Rated
mine: My Puzzles
short: Short
easy: Easy
hard: Hard
completed: Completed
levels: 关卡
new: 最新
top-rated: 最受好评
mine: 我的谜题
short: 速通
easy: 简单
hard: 困难
completed: 完成
validation:
title: Invalid Puzzle
noProducers: Please place a Constant Producer!
noGoalAcceptors: Please place a Goal Acceptor!
goalAcceptorNoItem: One or more Goal Acceptors have not yet assigned an item.
Deliver a shape to them to set a goal.
goalAcceptorRateNotMet: One or more Goal Acceptors are not getting enough items.
Make sure that the indicators are green for all acceptors.
buildingOutOfBounds: One or more buildings are outside of the buildable area.
Either increase the area or remove them.
autoComplete: Your puzzle autocompletes itself! Please make sure your constant
producers are not directly delivering to your goal acceptors.
title: 无效谜题
noProducers: 请放置<strong>常量生成器</strong>
noGoalAcceptors: 请放置<strong>目标接收器</strong>
goalAcceptorNoItem: 一个或多个目标接收器尚未被分配图形目标。请向它们传递图形以设置目标。
goalAcceptorRateNotMet: 一个或多个目标接收器没有获得足够数量的图形。请确保所有接收器的充能条指示器均为绿色。
buildingOutOfBounds: 一个或多个设施位于可建造区域之外。请增加区域面积,或将超出区域的设施移除。
autoComplete: 请确保您的常量生成器不会直接向目标接收器传递目标图形。否则您的谜题会自动完成。
backendErrors:
ratelimit: You are performing your actions too frequent. Please wait a bit.
invalid-api-key: Failed to communicate with the backend, please try to
update/restart the game (Invalid Api Key).
unauthorized: Failed to communicate with the backend, please try to
update/restart the game (Unauthorized).
bad-token: Failed to communicate with the backend, please try to update/restart
the game (Bad Token).
bad-id: Invalid puzzle identifier.
not-found: The given puzzle could not be found.
bad-category: The given category could not be found.
bad-short-key: The given short key is invalid.
profane-title: Your puzzle title contains profane words.
bad-title-too-many-spaces: Your puzzle title is too short.
bad-shape-key-in-emitter: A constant producer has an invalid item.
bad-shape-key-in-goal: A goal acceptor has an invalid item.
no-emitters: Your puzzle does not contain any constant producers.
no-goals: Your puzzle does not contain any goal acceptors.
short-key-already-taken: This short key is already taken, please use another one.
can-not-report-your-own-puzzle: You can not report your own puzzle.
bad-payload: The request contains invalid data.
bad-building-placement: Your puzzle contains invalid placed buildings.
timeout: The request timed out.
ratelimit: 你的操作太频繁了。请稍等。
invalid-api-key: 与后台通信失败,请尝试更新或重新启动游戏(无效的Api密钥)。
unauthorized: 与后台通信失败,请尝试更新或重新启动游戏(未经授权)。
bad-token: 与后台通信失败,请尝试更新或重新启动游戏(令牌错误)。
bad-id: 谜题标识符无效。
not-found: 找不到给定的谜题。
bad-category: 找不到给定的类别。
bad-short-key: 给定的短代码错误。
profane-title: 您的谜题标题包含污言秽语。
bad-title-too-many-spaces: 您的谜题标题过短。
bad-shape-key-in-emitter: 常量生成器包含无效项目。
bad-shape-key-in-goal: 目标接收器包含无效项目。
no-emitters: 您的谜题没有任何常量生成器。
no-goals: 您的谜题没有任何目标接收器。
short-key-already-taken: 此短代码已被使用,请使用其他短代码。
can-not-report-your-own-puzzle: 您无法上报您自己的谜题问题。
bad-payload: 此请求包含无效数据。
bad-building-placement: 您的谜题包含放置错误的设施。
timeout: 请求超时。

Loading…
Cancel
Save