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

Merge remote-tracking branch 'tobspr/master'

This commit is contained in:
Sense101 2021-06-14 13:33:06 +01:00
commit 1297089498
228 changed files with 21418 additions and 8753 deletions

1
.gitignore vendored
View File

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

View File

@ -5,11 +5,11 @@
This is the source code for shapez.io, an open source base building game inspired by Factorio. This is the source code for shapez.io, an open source base building game inspired by Factorio.
Your goal is to produce shapes by cutting, rotating, merging and painting parts of shapes. Your goal is to produce shapes by cutting, rotating, merging and painting parts of shapes.
- [Trello Board & Roadmap](https://trello.com/b/ISQncpJP/shapezio)
- [Free web version](https://shapez.io)
- [itch.io Page](https://tobspr.itch.io/shapezio)
- [Steam Page](https://steam.shapez.io) - [Steam Page](https://steam.shapez.io)
- [Official Discord](https://discord.com/invite/HN7EVzV) <- _Highly recommended to join!_ - [Official Discord](https://discord.com/invite/HN7EVzV) <- _Highly recommended to join!_
- [Trello Board & Roadmap](https://trello.com/b/ISQncpJP/shapezio)
- [itch.io Page](https://tobspr.itch.io/shapezio)
- [Free web version](https://shapez.io)
## Reporting issues, suggestions, feedback, bugs ## Reporting issues, suggestions, feedback, bugs
@ -35,9 +35,9 @@ Your goal is to produce shapes by cutting, rotating, merging and painting parts
You can use [Gitpod](https://www.gitpod.io/) (an Online Open Source VS Code-like IDE which is free for Open Source) for working on issues and making PRs to this project. With a single click it will start a workspace and automatically: You can use [Gitpod](https://www.gitpod.io/) (an Online Open Source VS Code-like IDE which is free for Open Source) for working on issues and making PRs to this project. With a single click it will start a workspace and automatically:
- clone the `shapez.io` repo. - clone the `shapez.io` repo.
- install all of the dependencies. - install all of the dependencies.
- start `gulp` in `gulp/` directory. - start `gulp` in `gulp/` directory.
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/from-referrer/) [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/from-referrer/)

View File

@ -74,20 +74,8 @@ function createWindow() {
win.on("closed", () => { win.on("closed", () => {
console.log("Window closed"); console.log("Window closed");
win = null; win = null;
app.quit();
}); });
function handleWindowBeforeunload(event) {
const confirmed = dialog.showMessageBox(remote.getCurrentWindow(), options) === 1;
if (confirmed) {
remote.getCurrentWindow().close();
} else {
event.returnValue = false;
}
}
win.on("", handleWindowBeforeunload);
if (isDev) { if (isDev) {
menu = new Menu(); menu = new Menu();
@ -286,7 +274,10 @@ async function performFsJob(job) {
} }
} }
ipcMain.handle("fs-job", (event, arg) => performFsJob(arg)); ipcMain.on("fs-job", async (event, arg) => {
const result = await performFsJob(arg);
event.reply("fs-response", { id: arg.id, result });
});
steam.init(isDev); steam.init(isDev);
steam.listen(); steam.listen();

View File

@ -10,10 +10,10 @@
"start": "electron --disable-direct-composition --in-process-gpu ." "start": "electron --disable-direct-composition --in-process-gpu ."
}, },
"devDependencies": { "devDependencies": {
"electron": "10.4.0" "electron": "10.4.3"
}, },
"optionalDependencies": { "optionalDependencies": {
"shapez.io-private-artifacts": "github:tobspr/shapez.io-private-artifacts#abi-v85" "shapez.io-private-artifacts": "github:tobspr/shapez.io-private-artifacts#abi-v82"
}, },
"dependencies": { "dependencies": {
"async-lock": "^1.2.8" "async-lock": "^1.2.8"

View File

@ -1,5 +1,5 @@
const fs = require('fs'); const fs = require("fs");
const path = require('path'); const path = require("path");
const { ipcMain } = require("electron"); const { ipcMain } = require("electron");
let greenworks = null; let greenworks = null;
@ -11,10 +11,10 @@ try {
appId = parseInt(fs.readFileSync(path.join(__dirname, "steam_appid.txt"), "utf8")); appId = parseInt(fs.readFileSync(path.join(__dirname, "steam_appid.txt"), "utf8"));
} catch (err) { } catch (err) {
// greenworks is not installed // greenworks is not installed
// throw err; console.warn("Failed to load steam api:", err);
} }
function init (isDev) { function init(isDev) {
if (!greenworks) { if (!greenworks) {
return; return;
} }
@ -34,16 +34,49 @@ function init (isDev) {
initialized = true; initialized = true;
} }
function listen () { function listen() {
ipcMain.handle("steam:is-initialized", isInitialized); ipcMain.handle("steam:is-initialized", isInitialized);
if (!greenworks || !initialized) { if (!initialized) {
console.log("Ignoring Steam IPC events"); console.warn("Steam not initialized, won't be able to listen");
return; return;
} }
if (!greenworks) {
console.warn("Greenworks not loaded, won't be able to listen");
return;
}
console.log("Adding listeners");
ipcMain.handle("steam:get-achievement-names", getAchievementNames); ipcMain.handle("steam:get-achievement-names", getAchievementNames);
ipcMain.handle("steam:activate-achievement", activateAchievement); ipcMain.handle("steam:activate-achievement", activateAchievement);
function bufferToHex(buffer) {
return Array.from(new Uint8Array(buffer))
.map(b => b.toString(16).padStart(2, "0"))
.join("");
}
ipcMain.handle("steam:get-ticket", (event, arg) => {
console.log("Requested steam ticket ...");
return new Promise((resolve, reject) => {
greenworks.getAuthSessionTicket(
success => {
const ticketHex = bufferToHex(success.ticket);
resolve(ticketHex);
},
error => {
console.error("Failed to get steam ticket:", error);
reject(error);
}
);
});
});
ipcMain.handle("steam:check-app-ownership", (event, appId) => {
return Promise.resolve(greenworks.isSubscribedApp(appId));
});
} }
function isInitialized(event) { function isInitialized(event) {
@ -53,7 +86,7 @@ function isInitialized(event) {
function getAchievementNames(event) { function getAchievementNames(event) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
try { try {
const achievements = greenworks.getAchievementNames() const achievements = greenworks.getAchievementNames();
resolve(achievements); resolve(achievements);
} catch (err) { } catch (err) {
reject(err); reject(err);
@ -63,11 +96,15 @@ function getAchievementNames(event) {
function activateAchievement(event, id) { function activateAchievement(event, id) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
greenworks.activateAchievement(id, () => resolve(), err => reject(err)) greenworks.activateAchievement(
id,
() => resolve(),
err => reject(err)
);
}); });
} }
module.exports = { module.exports = {
init, init,
listen listen,
}; };

View File

@ -146,10 +146,10 @@ duplexer3@^0.1.4:
resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=
electron@10.4.0: electron@10.4.3:
version "10.4.0" version "10.4.3"
resolved "https://registry.yarnpkg.com/electron/-/electron-10.4.0.tgz#018385914474b56110a5a43087a53c114b67c08d" resolved "https://registry.yarnpkg.com/electron/-/electron-10.4.3.tgz#8d1c0f5e562d1b78dcec8074c0d59e58137fd508"
integrity sha512-qK8OOCWuNvEFWThmjkukkqDwIpBqULlDuMXVC9MC/2P4UaWJEjIYvBmBuTyxtFcKoE3kWvcWyeRDUuvzVxxXjA== integrity sha512-qL8XZBII9KQHr1+YmVMj1AqyTR2I8/lxozvKEWoKKSkF8Hl6GzzxrLXRfISP7aDAvsJEyyhc6b2/42ME8hG5JA==
dependencies: dependencies:
"@electron/get" "^1.0.1" "@electron/get" "^1.0.1"
"@types/node" "^12.0.12" "@types/node" "^12.0.12"
@ -503,9 +503,9 @@ serialize-error@^7.0.1:
dependencies: dependencies:
type-fest "^0.13.1" type-fest "^0.13.1"
"shapez.io-private-artifacts@github:tobspr/shapez.io-private-artifacts#abi-v85": "shapez.io-private-artifacts@github:tobspr/shapez.io-private-artifacts#abi-v82":
version "0.1.0" version "0.1.0"
resolved "git+ssh://git@github.com/tobspr/shapez.io-private-artifacts.git#63adf7e0ea4b90c2a29053ce1f0ec9d573b3ac0a" resolved "git+ssh://git@github.com/tobspr/shapez.io-private-artifacts.git#8aa3bfd3b569eb5695fc8a585a3f2ee3ed2db290"
sprintf-js@^1.1.2: sprintf-js@^1.1.2:
version "1.1.2" version "1.1.2"

1
electron_wegame/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
wegame_sdk

View File

@ -0,0 +1,13 @@
{
"folders": [
{
"path": "."
}
],
"settings": {
"files.exclude": {
"**/node_modules": true,
"**/typedefs_gen": true
}
}
}

Binary file not shown.

BIN
electron_wegame/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

BIN
electron_wegame/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

288
electron_wegame/index.js Normal file
View File

@ -0,0 +1,288 @@
/* eslint-disable quotes,no-undef */
const { app, BrowserWindow, Menu, MenuItem, ipcMain, shell } = require("electron");
app.commandLine.appendSwitch("in-process-gpu");
const path = require("path");
const url = require("url");
const fs = require("fs");
const wegame = require("./wegame");
const asyncLock = require("async-lock");
const isDev = process.argv.indexOf("--dev") >= 0;
const isLocal = process.argv.indexOf("--local") >= 0;
const roamingFolder =
process.env.APPDATA ||
(process.platform == "darwin"
? process.env.HOME + "/Library/Preferences"
: process.env.HOME + "/.local/share");
let storePath = path.join(roamingFolder, "shapez.io", "saves");
if (!fs.existsSync(storePath)) {
// No try-catch by design
fs.mkdirSync(storePath, { recursive: true });
}
/** @type {BrowserWindow} */
let win = null;
let menu = null;
function createWindow() {
let faviconExtension = ".png";
if (process.platform === "win32") {
faviconExtension = ".ico";
}
win = new BrowserWindow({
width: 1280,
height: 800,
show: false,
backgroundColor: "#222428",
useContentSize: true,
minWidth: 800,
minHeight: 600,
title: "shapez.io Standalone",
transparent: false,
icon: path.join(__dirname, "favicon" + faviconExtension),
// fullscreen: true,
autoHideMenuBar: true,
webPreferences: {
nodeIntegration: true,
webSecurity: false,
},
// allowRunningInsecureContent: false,
});
if (isLocal) {
win.loadURL("http://localhost:3005");
} else {
win.loadURL(
url.format({
pathname: path.join(__dirname, "index.html"),
protocol: "file:",
slashes: true,
})
);
}
win.webContents.session.clearCache(() => null);
win.webContents.session.clearStorageData();
win.webContents.on("new-window", (event, pth) => {
event.preventDefault();
shell.openExternal(pth);
});
win.on("closed", () => {
console.log("Window closed");
win = null;
});
if (isDev) {
menu = new Menu();
const mainItem = new MenuItem({
label: "Toggle Dev Tools",
click: () => win.webContents.toggleDevTools(),
accelerator: "F12",
});
menu.append(mainItem);
const reloadItem = new MenuItem({
label: "Restart",
click: () => win.reload(),
accelerator: "F5",
});
menu.append(reloadItem);
const fullscreenItem = new MenuItem({
label: "Fullscreen",
click: () => win.setFullScreen(!win.isFullScreen()),
accelerator: "F11",
});
menu.append(fullscreenItem);
Menu.setApplicationMenu(menu);
} else {
Menu.setApplicationMenu(null);
}
win.once("ready-to-show", () => {
win.show();
win.focus();
});
}
if (!app.requestSingleInstanceLock()) {
app.exit(0);
} else {
app.on("second-instance", (event, commandLine, workingDirectory) => {
// Someone tried to run a second instance, we should focus
if (win) {
if (win.isMinimized()) {
win.restore();
}
win.focus();
}
});
}
app.on("ready", createWindow);
app.on("window-all-closed", () => {
console.log("All windows closed");
app.quit();
});
ipcMain.on("set-fullscreen", (event, flag) => {
win.setFullScreen(flag);
});
ipcMain.on("exit-app", (event, flag) => {
win.close();
app.quit();
});
let renameCounter = 1;
const fileLock = new asyncLock({
timeout: 30000,
maxPending: 1000,
});
function niceFileName(filename) {
return filename.replace(storePath, "@");
}
async function writeFileSafe(filename, contents) {
++renameCounter;
const prefix = "[ " + renameCounter + ":" + niceFileName(filename) + " ] ";
const transactionId = String(new Date().getTime()) + "." + renameCounter;
if (fileLock.isBusy()) {
console.warn(prefix, "Concurrent write process on", filename);
}
await fileLock.acquire(filename, async () => {
console.log(prefix, "Starting write on", niceFileName(filename), "in transaction", transactionId);
if (!fs.existsSync(filename)) {
// this one is easy
console.log(prefix, "Writing file instantly because it does not exist:", niceFileName(filename));
fs.writeFileSync(filename, contents, { encoding: "utf8" });
return;
}
// first, write a temporary file (.tmp-XXX)
const tempName = filename + ".tmp-" + transactionId;
console.log(prefix, "Writing temporary file", niceFileName(tempName));
fs.writeFileSync(tempName, contents, { encoding: "utf8" });
// now, rename the original file to (.backup-XXX)
const oldTemporaryName = filename + ".backup-" + transactionId;
console.log(
prefix,
"Renaming old file",
niceFileName(filename),
"to",
niceFileName(oldTemporaryName)
);
fs.renameSync(filename, oldTemporaryName);
// now, rename the temporary file (.tmp-XXX) to the target
console.log(
prefix,
"Renaming the temporary file",
niceFileName(tempName),
"to the original",
niceFileName(filename)
);
fs.renameSync(tempName, filename);
// we are done now, try to create a backup, but don't fail if the backup fails
try {
// check if there is an old backup file
const backupFileName = filename + ".backup";
if (fs.existsSync(backupFileName)) {
console.log(prefix, "Deleting old backup file", niceFileName(backupFileName));
// delete the old backup
fs.unlinkSync(backupFileName);
}
// rename the old file to the new backup file
console.log(prefix, "Moving", niceFileName(oldTemporaryName), "to the backup file location");
fs.renameSync(oldTemporaryName, backupFileName);
} catch (ex) {
console.error(prefix, "Failed to switch backup files:", ex);
}
});
}
async function performFsJob(job) {
const fname = path.join(storePath, job.filename);
switch (job.type) {
case "read": {
if (!fs.existsSync(fname)) {
return {
// Special FILE_NOT_FOUND error code
error: "file_not_found",
};
}
try {
const data = fs.readFileSync(fname, { encoding: "utf8" });
return {
success: true,
data,
};
} catch (ex) {
console.error(ex);
return {
error: ex,
};
}
}
case "write": {
try {
writeFileSafe(fname, job.contents);
return {
success: true,
data: job.contents,
};
} catch (ex) {
console.error(ex);
return {
error: ex,
};
}
}
case "delete": {
try {
fs.unlinkSync(fname);
} catch (ex) {
console.error(ex);
return {
error: ex,
};
}
return {
success: true,
data: null,
};
}
default:
throw new Error("Unkown fs job: " + job.type);
}
}
ipcMain.on("fs-job", async (event, arg) => {
const result = await performFsJob(arg);
event.sender.send("fs-response", { id: arg.id, result });
});
wegame.init(isDev);
wegame.listen();

View File

@ -0,0 +1,18 @@
{
"name": "electron",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"private": true,
"scripts": {
"startDev": "electron --disable-direct-composition --in-process-gpu . --dev --local",
"startDevGpu": "electron --enable-gpu-rasterization --enable-accelerated-2d-canvas --num-raster-threads=8 --enable-zero-copy . --dev --local",
"start": "electron --disable-direct-composition --in-process-gpu ."
},
"devDependencies": {
"electron": "3.1.13"
},
"dependencies": {
"async-lock": "^1.2.8"
}
}

52
electron_wegame/wegame.js Normal file
View File

@ -0,0 +1,52 @@
const railsdk = require("./wegame_sdk/railsdk.js");
const { dialog } = require("electron");
function init(isDev) {
console.log("Step 1: wegame: init");
try {
console.log("Step 2: Calling need restart app");
const need_restart = railsdk.RailNeedRestartAppForCheckingEnvironment(
2001639,
[`--rail_render_pid=${process.pid}`] //,"--rail_debug_mode",
);
console.log("Step 3: Needs restart =", need_restart);
if (need_restart) {
console.error("Step 4: Need restart");
dialog.showErrorBox("加载RailSDK失败", "请先运行WeGame开发者版本");
return;
}
} catch (err) {
console.error("Rail SDK error:", err);
dialog.showErrorBox("加载RailSDK失败", err);
return;
}
console.log("Step 5: starting rail sdk");
if (railsdk.RailInitialize() === false) {
console.error("RailInitialize() = false");
dialog.showErrorBox("RailInitialize调用失败", "请先运行WeGame开发者版本");
return;
}
console.log("Initialize RailSDK success!");
railsdk.RailRegisterEvent(railsdk.RailEventID.kRailEventSystemStateChanged, event => {
console.log(event);
if (event.result === railsdk.RailResult.kSuccess) {
if (
event.state === railsdk.RailSystemState.kSystemStatePlatformOffline ||
event.state === railsdk.RailSystemState.kSystemStatePlatformExit ||
event.state === railsdk.RailSystemState.kSystemStateGameExitByAntiAddiction
) {
remote.app.exit();
}
}
});
}
function listen() {
console.log("wegame: listen");
}
module.exports = { init, listen };

982
electron_wegame/yarn.lock Normal file
View File

@ -0,0 +1,982 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@types/node@^10.1.4":
version "10.17.60"
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b"
integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==
ajv@^6.12.3:
version "6.12.6"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
dependencies:
fast-deep-equal "^3.1.1"
fast-json-stable-stringify "^2.0.0"
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
ansi-regex@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
array-find-index@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=
asn1@~0.2.3:
version "0.2.4"
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
dependencies:
safer-buffer "~2.1.0"
assert-plus@1.0.0, assert-plus@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
async-lock@^1.2.8:
version "1.2.8"
resolved "https://registry.yarnpkg.com/async-lock/-/async-lock-1.2.8.tgz#7b02bdfa2de603c0713acecd11184cf97bbc7c4c"
integrity sha512-G+26B2jc0Gw0EG/WN2M6IczuGepBsfR1+DtqLnyFSH4p2C668qkOCtEkGNVEaaNAVlYwEMazy1+/jnLxltBkIQ==
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
aws-sign2@~0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
aws4@^1.8.0:
version "1.11.0"
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
bcrypt-pbkdf@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
dependencies:
tweetnacl "^0.14.3"
buffer-crc32@~0.2.3:
version "0.2.13"
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
buffer-from@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
camelcase-keys@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7"
integrity sha1-MIvur/3ygRkFHvodkyITyRuPkuc=
dependencies:
camelcase "^2.0.0"
map-obj "^1.0.0"
camelcase@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=
caseless@~0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
code-point-at@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
combined-stream@^1.0.6, combined-stream@~1.0.6:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
dependencies:
delayed-stream "~1.0.0"
concat-stream@^1.6.2:
version "1.6.2"
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
dependencies:
buffer-from "^1.0.0"
inherits "^2.0.3"
readable-stream "^2.2.2"
typedarray "^0.0.6"
core-util-is@1.0.2, core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
currently-unhandled@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
integrity sha1-mI3zP+qxke95mmE2nddsF635V+o=
dependencies:
array-find-index "^1.0.1"
dashdash@^1.12.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=
dependencies:
assert-plus "^1.0.0"
debug@^2.1.3, debug@^2.2.0, debug@^2.6.9:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
dependencies:
ms "2.0.0"
debug@^3.0.0:
version "3.2.7"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
dependencies:
ms "^2.1.1"
decamelize@^1.1.2:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
deep-extend@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
ecc-jsbn@~0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=
dependencies:
jsbn "~0.1.0"
safer-buffer "^2.1.0"
electron-download@^4.1.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/electron-download/-/electron-download-4.1.1.tgz#02e69556705cc456e520f9e035556ed5a015ebe8"
integrity sha512-FjEWG9Jb/ppK/2zToP+U5dds114fM1ZOJqMAR4aXXL5CvyPE9fiqBK/9YcwC9poIFQTEJk/EM/zyRwziziRZrg==
dependencies:
debug "^3.0.0"
env-paths "^1.0.0"
fs-extra "^4.0.1"
minimist "^1.2.0"
nugget "^2.0.1"
path-exists "^3.0.0"
rc "^1.2.1"
semver "^5.4.1"
sumchecker "^2.0.2"
electron@3.1.13:
version "3.1.13"
resolved "https://registry.yarnpkg.com/electron/-/electron-3.1.13.tgz#aeb276f4cf5e3785078b6495e982ee46d553a5d2"
integrity sha512-aRNywoUSO1Va/lpU4nz3K6GDyFqYtlOnHGLcERAAHfhB+IJrJ34cUJW4FVBpm43AwvUdAeuCkVKRLtOmrgx5CA==
dependencies:
"@types/node" "^10.1.4"
electron-download "^4.1.0"
extract-zip "^1.0.3"
env-paths@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-1.0.0.tgz#4168133b42bb05c38a35b1ae4397c8298ab369e0"
integrity sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA=
error-ex@^1.2.0:
version "1.3.2"
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
dependencies:
is-arrayish "^0.2.1"
extend@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
extract-zip@^1.0.3:
version "1.7.0"
resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.7.0.tgz#556cc3ae9df7f452c493a0cfb51cc30277940927"
integrity sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==
dependencies:
concat-stream "^1.6.2"
debug "^2.6.9"
mkdirp "^0.5.4"
yauzl "^2.10.0"
extsprintf@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=
extsprintf@^1.2.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
fast-deep-equal@^3.1.1:
version "3.1.3"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
fast-json-stable-stringify@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
fd-slicer@~1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=
dependencies:
pend "~1.2.0"
find-up@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=
dependencies:
path-exists "^2.0.0"
pinkie-promise "^2.0.0"
forever-agent@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
form-data@~2.3.2:
version "2.3.3"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.6"
mime-types "^2.1.12"
fs-extra@^4.0.1:
version "4.0.3"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94"
integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==
dependencies:
graceful-fs "^4.1.2"
jsonfile "^4.0.0"
universalify "^0.1.0"
function-bind@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
get-stdin@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=
getpass@^0.1.1:
version "0.1.7"
resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=
dependencies:
assert-plus "^1.0.0"
graceful-fs@^4.1.2, graceful-fs@^4.1.6:
version "4.2.6"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee"
integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==
har-schema@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
har-validator@~5.1.3:
version "5.1.5"
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd"
integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==
dependencies:
ajv "^6.12.3"
har-schema "^2.0.0"
has@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
dependencies:
function-bind "^1.1.1"
hosted-git-info@^2.1.4:
version "2.8.9"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
http-signature@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=
dependencies:
assert-plus "^1.0.0"
jsprim "^1.2.2"
sshpk "^1.7.0"
indent-string@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80"
integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=
dependencies:
repeating "^2.0.0"
inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
ini@~1.3.0:
version "1.3.8"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
is-arrayish@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
is-core-module@^2.2.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.4.0.tgz#8e9fc8e15027b011418026e98f0e6f4d86305cc1"
integrity sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==
dependencies:
has "^1.0.3"
is-finite@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3"
integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==
is-fullwidth-code-point@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs=
dependencies:
number-is-nan "^1.0.0"
is-typedarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
is-utf8@^0.2.0:
version "0.2.1"
resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=
isarray@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
isarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
isstream@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
jsbn@~0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
json-schema-traverse@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
json-schema@0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
json-stringify-safe@~5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
jsonfile@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=
optionalDependencies:
graceful-fs "^4.1.6"
jsprim@^1.2.2:
version "1.4.1"
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=
dependencies:
assert-plus "1.0.0"
extsprintf "1.3.0"
json-schema "0.2.3"
verror "1.10.0"
load-json-file@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=
dependencies:
graceful-fs "^4.1.2"
parse-json "^2.2.0"
pify "^2.0.0"
pinkie-promise "^2.0.0"
strip-bom "^2.0.0"
loud-rejection@^1.0.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f"
integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=
dependencies:
currently-unhandled "^0.4.1"
signal-exit "^3.0.0"
map-obj@^1.0.0, map-obj@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=
meow@^3.1.0:
version "3.7.0"
resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=
dependencies:
camelcase-keys "^2.0.0"
decamelize "^1.1.2"
loud-rejection "^1.0.0"
map-obj "^1.0.1"
minimist "^1.1.3"
normalize-package-data "^2.3.4"
object-assign "^4.0.1"
read-pkg-up "^1.0.1"
redent "^1.0.0"
trim-newlines "^1.0.0"
mime-db@1.47.0:
version "1.47.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.47.0.tgz#8cb313e59965d3c05cfbf898915a267af46a335c"
integrity sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==
mime-types@^2.1.12, mime-types@~2.1.19:
version "2.1.30"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.30.tgz#6e7be8b4c479825f85ed6326695db73f9305d62d"
integrity sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==
dependencies:
mime-db "1.47.0"
minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
mkdirp@^0.5.4:
version "0.5.5"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
dependencies:
minimist "^1.2.5"
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
ms@^2.1.1:
version "2.1.3"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
version "2.5.0"
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==
dependencies:
hosted-git-info "^2.1.4"
resolve "^1.10.0"
semver "2 || 3 || 4 || 5"
validate-npm-package-license "^3.0.1"
nugget@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/nugget/-/nugget-2.0.1.tgz#201095a487e1ad36081b3432fa3cada4f8d071b0"
integrity sha1-IBCVpIfhrTYIGzQy+jytpPjQcbA=
dependencies:
debug "^2.1.3"
minimist "^1.1.0"
pretty-bytes "^1.0.2"
progress-stream "^1.1.0"
request "^2.45.0"
single-line-log "^1.1.2"
throttleit "0.0.2"
number-is-nan@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
oauth-sign@~0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
object-assign@^4.0.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
object-keys@~0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336"
integrity sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=
parse-json@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=
dependencies:
error-ex "^1.2.0"
path-exists@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=
dependencies:
pinkie-promise "^2.0.0"
path-exists@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=
path-parse@^1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
path-type@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=
dependencies:
graceful-fs "^4.1.2"
pify "^2.0.0"
pinkie-promise "^2.0.0"
pend@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA=
performance-now@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
pify@^2.0.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
pinkie-promise@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o=
dependencies:
pinkie "^2.0.0"
pinkie@^2.0.0:
version "2.0.4"
resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
pretty-bytes@^1.0.2:
version "1.0.4"
resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-1.0.4.tgz#0a22e8210609ad35542f8c8d5d2159aff0751c84"
integrity sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=
dependencies:
get-stdin "^4.0.1"
meow "^3.1.0"
process-nextick-args@~2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
progress-stream@^1.1.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/progress-stream/-/progress-stream-1.2.0.tgz#2cd3cfea33ba3a89c9c121ec3347abe9ab125f77"
integrity sha1-LNPP6jO6OonJwSHsM0er6asSX3c=
dependencies:
speedometer "~0.1.2"
through2 "~0.2.3"
psl@^1.1.28:
version "1.8.0"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==
punycode@^2.1.0, punycode@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
qs@~6.5.2:
version "6.5.2"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
rc@^1.2.1:
version "1.2.8"
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
dependencies:
deep-extend "^0.6.0"
ini "~1.3.0"
minimist "^1.2.0"
strip-json-comments "~2.0.1"
read-pkg-up@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=
dependencies:
find-up "^1.0.0"
read-pkg "^1.0.0"
read-pkg@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=
dependencies:
load-json-file "^1.0.0"
normalize-package-data "^2.3.2"
path-type "^1.0.0"
readable-stream@^2.2.2:
version "2.3.7"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.3"
isarray "~1.0.0"
process-nextick-args "~2.0.0"
safe-buffer "~5.1.1"
string_decoder "~1.1.1"
util-deprecate "~1.0.1"
readable-stream@~1.1.9:
version "1.1.14"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk=
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.1"
isarray "0.0.1"
string_decoder "~0.10.x"
redent@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
integrity sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=
dependencies:
indent-string "^2.1.0"
strip-indent "^1.0.1"
repeating@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=
dependencies:
is-finite "^1.0.0"
request@^2.45.0:
version "2.88.2"
resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
dependencies:
aws-sign2 "~0.7.0"
aws4 "^1.8.0"
caseless "~0.12.0"
combined-stream "~1.0.6"
extend "~3.0.2"
forever-agent "~0.6.1"
form-data "~2.3.2"
har-validator "~5.1.3"
http-signature "~1.2.0"
is-typedarray "~1.0.0"
isstream "~0.1.2"
json-stringify-safe "~5.0.1"
mime-types "~2.1.19"
oauth-sign "~0.9.0"
performance-now "^2.1.0"
qs "~6.5.2"
safe-buffer "^5.1.2"
tough-cookie "~2.5.0"
tunnel-agent "^0.6.0"
uuid "^3.3.2"
resolve@^1.10.0:
version "1.20.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
dependencies:
is-core-module "^2.2.0"
path-parse "^1.0.6"
safe-buffer@^5.0.1, safe-buffer@^5.1.2:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
"semver@2 || 3 || 4 || 5", semver@^5.4.1:
version "5.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
signal-exit@^3.0.0:
version "3.0.3"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
single-line-log@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/single-line-log/-/single-line-log-1.1.2.tgz#c2f83f273a3e1a16edb0995661da0ed5ef033364"
integrity sha1-wvg/Jzo+GhbtsJlWYdoO1e8DM2Q=
dependencies:
string-width "^1.0.1"
spdx-correct@^3.0.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9"
integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==
dependencies:
spdx-expression-parse "^3.0.0"
spdx-license-ids "^3.0.0"
spdx-exceptions@^2.1.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d"
integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==
spdx-expression-parse@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679"
integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==
dependencies:
spdx-exceptions "^2.1.0"
spdx-license-ids "^3.0.0"
spdx-license-ids@^3.0.0:
version "3.0.9"
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz#8a595135def9592bda69709474f1cbeea7c2467f"
integrity sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==
speedometer@~0.1.2:
version "0.1.4"
resolved "https://registry.yarnpkg.com/speedometer/-/speedometer-0.1.4.tgz#9876dbd2a169d3115402d48e6ea6329c8816a50d"
integrity sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=
sshpk@^1.7.0:
version "1.16.1"
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==
dependencies:
asn1 "~0.2.3"
assert-plus "^1.0.0"
bcrypt-pbkdf "^1.0.0"
dashdash "^1.12.0"
ecc-jsbn "~0.1.1"
getpass "^0.1.1"
jsbn "~0.1.0"
safer-buffer "^2.0.2"
tweetnacl "~0.14.0"
string-width@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=
dependencies:
code-point-at "^1.0.0"
is-fullwidth-code-point "^1.0.0"
strip-ansi "^3.0.0"
string_decoder@~0.10.x:
version "0.10.31"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
string_decoder@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
dependencies:
safe-buffer "~5.1.0"
strip-ansi@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=
dependencies:
ansi-regex "^2.0.0"
strip-bom@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=
dependencies:
is-utf8 "^0.2.0"
strip-indent@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2"
integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=
dependencies:
get-stdin "^4.0.1"
strip-json-comments@~2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
sumchecker@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-2.0.2.tgz#0f42c10e5d05da5d42eea3e56c3399a37d6c5b3e"
integrity sha1-D0LBDl0F2l1C7qPlbDOZo31sWz4=
dependencies:
debug "^2.2.0"
throttleit@0.0.2:
version "0.0.2"
resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-0.0.2.tgz#cfedf88e60c00dd9697b61fdd2a8343a9b680eaf"
integrity sha1-z+34jmDADdlpe2H90qg0OptoDq8=
through2@~0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/through2/-/through2-0.2.3.tgz#eb3284da4ea311b6cc8ace3653748a52abf25a3f"
integrity sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=
dependencies:
readable-stream "~1.1.9"
xtend "~2.1.1"
tough-cookie@~2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
dependencies:
psl "^1.1.28"
punycode "^2.1.1"
trim-newlines@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
integrity sha1-WIeWa7WCpFA6QetST301ARgVphM=
tunnel-agent@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=
dependencies:
safe-buffer "^5.0.1"
tweetnacl@^0.14.3, tweetnacl@~0.14.0:
version "0.14.5"
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
typedarray@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
universalify@^0.1.0:
version "0.1.2"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
uri-js@^4.2.2:
version "4.4.1"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
dependencies:
punycode "^2.1.0"
util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
uuid@^3.3.2:
version "3.4.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
validate-npm-package-license@^3.0.1:
version "3.0.4"
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==
dependencies:
spdx-correct "^3.0.0"
spdx-expression-parse "^3.0.0"
verror@1.10.0:
version "1.10.0"
resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=
dependencies:
assert-plus "^1.0.0"
core-util-is "1.0.2"
extsprintf "^1.2.0"
xtend@~2.1.1:
version "2.1.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b"
integrity sha1-bv7MKk2tjmlixJAbM3znuoe10os=
dependencies:
object-keys "~0.4.0"
yauzl@^2.10.0:
version "2.10.0"
resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=
dependencies:
buffer-crc32 "~0.2.3"
fd-slicer "~1.1.0"

View File

@ -54,8 +54,11 @@
document.documentElement.appendChild(element); document.documentElement.appendChild(element);
} }
window.addEventListener("error", errorHandler);
window.addEventListener("unhandledrejection", errorHandler); if (window.location.host.indexOf("localhost") < 0) {
window.addEventListener("error", errorHandler);
window.addEventListener("unhandledrejection", errorHandler);
}
function makeJsTag(src, integrity) { function makeJsTag(src, integrity) {
var script = document.createElement("script"); var script = document.createElement("script");

View File

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

View File

@ -59,6 +59,36 @@ function gulptasksJS($, gulp, buildFolder, browserSync) {
.pipe(gulp.dest(buildFolder)); .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 //// STAGING
gulp.task("js.staging.transpiled", () => { gulp.task("js.staging.transpiled", () => {
@ -208,6 +238,23 @@ function gulptasksJS($, gulp, buildFolder, browserSync) {
) )
.pipe(gulp.dest(buildFolder)); .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: false,
standalone: true,
wegameVersion: true,
})
)
)
.pipe(gulp.dest(buildFolder));
});
} }
module.exports = { module.exports = {

View File

@ -9,21 +9,31 @@ const buildutils = require("./buildutils");
const execSync = require("child_process").execSync; const execSync = require("child_process").execSync;
function gulptasksStandalone($, gulp) { function gulptasksStandalone($, gulp) {
const electronBaseDir = path.join(__dirname, "..", "electron");
const targets = [ const targets = [
{ {
tempDestDir: path.join(__dirname, "..", "tmp_standalone_files"), tempDestDir: path.join(__dirname, "..", "tmp_standalone_files"),
suffix: "", suffix: "",
taskPrefix: "", taskPrefix: "",
electronBaseDir: path.join(__dirname, "..", "electron"),
steam: true,
}, },
{ {
tempDestDir: path.join(__dirname, "..", "tmp_standalone_files_china"), tempDestDir: path.join(__dirname, "..", "tmp_standalone_files_china"),
suffix: "china", suffix: "china",
taskPrefix: "china.", taskPrefix: "china.",
electronBaseDir: path.join(__dirname, "..", "electron"),
steam: true,
},
{
tempDestDir: path.join(__dirname, "..", "tmp_standalone_files_wegame"),
suffix: "wegame",
taskPrefix: "wegame.",
electronBaseDir: path.join(__dirname, "..", "electron_wegame"),
steam: false,
}, },
]; ];
for (const { tempDestDir, suffix, taskPrefix } of targets) { for (const { tempDestDir, suffix, taskPrefix, electronBaseDir, steam } of targets) {
const tempDestBuildDir = path.join(tempDestDir, "built"); const tempDestBuildDir = path.join(tempDestDir, "built");
gulp.task(taskPrefix + "standalone.prepare.cleanup", () => { gulp.task(taskPrefix + "standalone.prepare.cleanup", () => {
@ -34,13 +44,17 @@ function gulptasksStandalone($, gulp) {
const requiredFiles = [ const requiredFiles = [
path.join(electronBaseDir, "node_modules", "**", "*.*"), path.join(electronBaseDir, "node_modules", "**", "*.*"),
path.join(electronBaseDir, "node_modules", "**", ".*"), path.join(electronBaseDir, "node_modules", "**", ".*"),
path.join(electronBaseDir, "steam_appid.txt"), path.join(electronBaseDir, "wegame_sdk", "**", "*.*"),
path.join(electronBaseDir, "wegame_sdk", "**", ".*"),
path.join(electronBaseDir, "favicon*"), path.join(electronBaseDir, "favicon*"),
// fails on platforms which support symlinks // fails on platforms which support symlinks
// https://github.com/gulpjs/gulp/issues/1427 // https://github.com/gulpjs/gulp/issues/1427
// path.join(electronBaseDir, "node_modules", "**", "*"), // path.join(electronBaseDir, "node_modules", "**", "*"),
]; ];
if (steam) {
requiredFiles.push(path.join(electronBaseDir, "steam_appid.txt"));
}
return gulp.src(requiredFiles, { base: electronBaseDir }).pipe(gulp.dest(tempDestBuildDir)); return gulp.src(requiredFiles, { base: electronBaseDir }).pipe(gulp.dest(tempDestBuildDir));
}); });
@ -64,6 +78,11 @@ function gulptasksStandalone($, gulp) {
}); });
gulp.task(taskPrefix + "standalone.prepareVDF", cb => { gulp.task(taskPrefix + "standalone.prepareVDF", cb => {
if (!steam) {
cb();
return;
}
const hash = buildutils.getRevision(); const hash = buildutils.getRevision();
const steampipeDir = path.join(__dirname, "steampipe", "scripts"); const steampipeDir = path.join(__dirname, "steampipe", "scripts");
@ -116,11 +135,10 @@ function gulptasksStandalone($, gulp) {
const tomlFile = fs.readFileSync(path.join(__dirname, ".itch.toml")); const tomlFile = fs.readFileSync(path.join(__dirname, ".itch.toml"));
const privateArtifactsPath = "node_modules/shapez.io-private-artifacts"; const privateArtifactsPath = "node_modules/shapez.io-private-artifacts";
let asar; let asar = steam;
if (fs.existsSync(path.join(tempDestBuildDir, privateArtifactsPath))) { if (steam && fs.existsSync(path.join(tempDestBuildDir, privateArtifactsPath))) {
// @ts-expect-error
asar = { unpackDir: privateArtifactsPath }; asar = { unpackDir: privateArtifactsPath };
} else {
asar = true;
} }
packager({ packager({
@ -147,24 +165,26 @@ function gulptasksStandalone($, gulp) {
return; return;
} }
fs.writeFileSync( if (steam) {
path.join(appPath, "LICENSE"),
fs.readFileSync(path.join(__dirname, "..", "LICENSE"))
);
fse.copySync(
path.join(tempDestBuildDir, "steam_appid.txt"),
path.join(appPath, "steam_appid.txt")
);
fs.writeFileSync(path.join(appPath, ".itch.toml"), tomlFile);
if (platform === "linux") {
fs.writeFileSync( fs.writeFileSync(
path.join(appPath, "play.sh"), path.join(appPath, "LICENSE"),
'#!/usr/bin/env bash\n./shapezio --no-sandbox "$@"\n' fs.readFileSync(path.join(__dirname, "..", "LICENSE"))
); );
fs.chmodSync(path.join(appPath, "play.sh"), 0o775);
fse.copySync(
path.join(tempDestBuildDir, "steam_appid.txt"),
path.join(appPath, "steam_appid.txt")
);
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);
}
} }
}); });

View File

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

View File

@ -1,7 +1,7 @@
"DepotBuildConfig" "DepotBuildConfig"
{ {
"DepotID" "1318695" "DepotID" "1318695"
"contentroot" "C:\work\shapez.io\tmp_standalone_files_china\shapez.io-standalonechina-linux-x64" "contentroot" "C:\work\shapez\shapez.io\tmp_standalone_files_china\shapez.io-standalonechina-linux-x64"
"FileMapping" "FileMapping"
{ {
"LocalPath" "*" "LocalPath" "*"

View File

@ -1,7 +1,7 @@
"DepotBuildConfig" "DepotBuildConfig"
{ {
"DepotID" "1318694" "DepotID" "1318694"
"contentroot" "C:\work\shapez.io\tmp_standalone_files_china\shapez.io-standalonechina-win32-x64" "contentroot" "C:\work\shapez\shapez.io\tmp_standalone_files_china\shapez.io-standalonechina-win32-x64"
"FileMapping" "FileMapping"
{ {
"LocalPath" "*" "LocalPath" "*"

View File

@ -1,7 +1,7 @@
"DepotBuildConfig" "DepotBuildConfig"
{ {
"DepotID" "1318692" "DepotID" "1318692"
"contentroot" "C:\work\shapez.io\tmp_standalone_files\shapez.io-standalone-linux-x64" "contentroot" "C:\work\shapez\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.io\tmp_standalone_files\shapez.io-standalone-win32-x64" "contentroot" "C:\work\shapez\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, chineseVersion = false }) => { module.exports = ({ watch = false, standalone = false, chineseVersion = false, wegameVersion = false }) => {
return { return {
mode: "development", mode: "development",
devtool: "cheap-source-map", devtool: "cheap-source-map",
@ -35,6 +35,7 @@ module.exports = ({ watch = false, standalone = false, chineseVersion = false })
lzString.compressToEncodedURIComponent("http://localhost:10005/v1") lzString.compressToEncodedURIComponent("http://localhost:10005/v1")
), ),
G_CHINA_VERSION: JSON.stringify(chineseVersion), G_CHINA_VERSION: JSON.stringify(chineseVersion),
G_WEGAME_VERSION: JSON.stringify(wegameVersion),
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

@ -17,6 +17,7 @@ module.exports = ({
isBrowser = true, isBrowser = true,
mobileApp = false, mobileApp = false,
chineseVersion = false, chineseVersion = false,
wegameVersion = false,
}) => { }) => {
const globalDefs = { const globalDefs = {
assert: enableAssert ? "window.assert" : "false && window.assert", assert: enableAssert ? "window.assert" : "false && window.assert",
@ -25,6 +26,7 @@ module.exports = ({
G_IS_DEV: "false", G_IS_DEV: "false",
G_CHINA_VERSION: JSON.stringify(chineseVersion), G_CHINA_VERSION: JSON.stringify(chineseVersion),
G_WEGAME_VERSION: JSON.stringify(wegameVersion),
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",
@ -40,7 +42,7 @@ module.exports = ({
G_ALL_UI_IMAGES: JSON.stringify(getAllResourceImages()), G_ALL_UI_IMAGES: JSON.stringify(getAllResourceImages()),
}; };
const minifyNames = environment === "prod"; const minifyNames = false;
return { return {
mode: "production", mode: "production",

BIN
res/logo_wegame.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
res/puzzle_dlc_logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 680 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

42
res/ui/languages/he.svg Normal file
View File

@ -0,0 +1,42 @@
<?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="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">
<rect style="fill:#41479B;" width="512" height="512"/>
<rect y="93.86" style="fill:#F5F5F5;" width="512" height="324.28"/>
<path style="fill:#41479B;" d="M317.474,256l30.734-53.234h-61.469L256,149.523l-30.739,53.243h-61.469L194.526,256l-30.734,53.234
h61.469L256,362.477l30.739-53.243h61.469L317.474,256z M318.054,220.176l-10.632,18.415l-10.632-18.415H318.054z M297.371,256
l-20.683,35.824h-41.376L214.629,256l20.683-35.824h41.376L297.371,256z M256,184.344l10.636,18.422h-21.272L256,184.344z
M193.946,220.176h21.264l-10.632,18.415L193.946,220.176z M193.946,291.824l10.632-18.415l10.632,18.415H193.946z M256,327.656
l-10.636-18.422h21.272L256,327.656z M307.423,273.409l10.632,18.415h-21.264L307.423,273.409z"/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
res/ui/puzzle_dlc_logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -85,6 +85,8 @@ def generate_blueprint_sprite(infilename, outfilename):
buildings = listdir("buildings") buildings = listdir("buildings")
for buildingId in buildings: for buildingId in buildings:
if not ".png" in buildingId:
continue
if "hub" in buildingId: if "hub" in buildingId:
continue continue
if "wire-" in buildingId: if "wire-" in buildingId:

View File

@ -1,6 +1,6 @@
#ingame_HUD_BetaOverlay { #ingame_HUD_BetaOverlay {
position: fixed; position: fixed;
@include S(top, 10px); @include S(top, 70px);
left: 50%; left: 50%;
transform: translateX(-50%); transform: translateX(-50%);
color: $colorRedBright; color: $colorRedBright;

View File

@ -37,7 +37,7 @@
.building { .building {
@include S(width, 30px); @include S(width, 30px);
@include S(height, 22px); @include S(height, 30px);
background-size: 45%; background-size: 45%;
&:not(.unlocked) { &:not(.unlocked) {
@ -49,65 +49,98 @@
} }
.building { .building {
color: $accentColorDark;
display: flex; display: flex;
flex-direction: column; @include S(width, 40px);
position: relative; position: relative;
align-items: center;
justify-content: center;
@include S(padding, 5px);
@include S(padding-bottom, 1px);
@include S(width, 35px);
@include S(height, 40px); @include S(height, 40px);
.icon {
color: $accentColorDark;
display: flex;
flex-direction: column-reverse;
position: relative;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
padding: 0;
margin: 0;
@include S(border-radius, $globalBorderRadius);
background: center center / 70% no-repeat; background: center center / 70% no-repeat;
}
&:not(.unlocked) { &:not(.unlocked) {
@include S(width, 20px); @include S(width, 25px);
opacity: 0.15; .icon {
background-image: none !important; opacity: 0.15;
}
&::before { &.editor {
content: " "; .icon {
pointer-events: all;
position: absolute; cursor: pointer;
top: 0; &:hover {
right: 0; background-color: rgba(22, 30, 68, 0.1);
bottom: 0; }
left: 0; }
z-index: 4; }
& { &:not(.editor) {
/* @load-async */ .icon {
background: uiResource("locked_building.png") center center / #{D(20px)} #{D(20px)} background-image: uiResource("locked_building.png") !important;
no-repeat;
} }
} }
} }
@include S(border-radius, $globalBorderRadius);
&.unlocked { &.unlocked {
pointer-events: all; .icon {
transition: all 50ms ease-in-out; pointer-events: all;
transition-property: background-color, transform; transition: all 50ms ease-in-out;
transition-property: background-color, transform;
cursor: pointer;
cursor: pointer; &:hover {
&:hover { background-color: rgba(30, 40, 90, 0.1);
background-color: rgba(30, 40, 90, 0.1); }
&.pressed {
transform: scale(0.9) !important;
}
} }
&.pressed {
transform: scale(0.9) !important;
}
&.selected { &.selected {
// transform: scale(1.05); // transform: scale(1.05);
background-color: rgba(lighten($colorBlueBright, 9), 0.4); background-color: rgba(lighten($colorBlueBright, 9), 0.4);
@include S(border-radius, 2px);
.keybinding { .keybinding {
color: #111; color: #111;
} }
} }
.puzzle-lock {
& {
/* @load-async */
background: uiResource("locked_building.png") center center / 90% no-repeat;
}
display: grid;
grid-auto-flow: column;
position: absolute;
@include S(top, -15px);
left: 50%;
transform: translateX(-50%) !important;
transition: all 0.12s ease-in-out;
transition-property: opacity, transform;
cursor: pointer;
pointer-events: all;
@include S(width, 12px);
@include S(height, 12px);
&:hover {
opacity: 0.5;
}
}
} }
} }
} }

View File

@ -67,6 +67,14 @@
* { * {
color: #fff; color: #fff;
} }
display: flex;
flex-direction: column;
.text {
text-transform: uppercase;
@include S(margin-bottom, 10px);
}
} }
> .dialogInner { > .dialogInner {
@ -168,6 +176,11 @@
&.errored { &.errored {
background-color: rgb(250, 206, 206); background-color: rgb(250, 206, 206);
&::placeholder {
color: #fff;
opacity: 0.8;
}
} }
} }

View File

@ -0,0 +1,41 @@
#ingame_HUD_PuzzleBackToMenu {
position: absolute;
@include S(top, 10px);
@include S(left, 0px);
display: flex;
flex-direction: column;
align-items: flex-start;
backdrop-filter: blur(D(1px));
padding: D(3px);
> .button {
@include PlainText;
pointer-events: all;
cursor: pointer;
position: relative;
color: #333438;
transition: all 0.12s ease-in-out;
transition-property: opacity, transform;
text-transform: uppercase;
@include PlainText;
@include S(width, 30px);
@include S(height, 30px);
@include DarkThemeInvert;
opacity: 1;
&:hover {
opacity: 0.9 !important;
}
&.pressed {
transform: scale(0.95) !important;
}
& {
/* @load-async */
background: uiResource("icons/state_back_button.png") center center / D(15px) no-repeat;
}
}
}

View File

@ -0,0 +1,171 @@
#ingame_HUD_PuzzleCompleteNotification {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: auto;
pointer-events: all;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
& {
/* @load-async */
background: rgba(#333538, 0.95) uiResource("dialog_bg_pattern.png") top left / #{D(10px)} repeat;
}
@include InlineAnimation(0.1s ease-in-out) {
0% {
opacity: 0;
}
}
> .dialog {
// background: rgba(#222428, 0.5);
@include S(border-radius, $globalBorderRadius);
@include S(padding, 30px);
@include InlineAnimation(0.5s ease-in-out) {
0% {
opacity: 0;
}
}
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
color: #fff;
text-align: center;
> .title {
@include SuperHeading;
text-transform: uppercase;
@include S(font-size, 30px);
@include S(margin-bottom, 40px);
color: $colorGreenBright !important;
@include InlineAnimation(0.5s ease-in-out) {
0% {
transform: translateY(-50vh);
}
50% {
transform: translateY(5vh);
}
75% {
transform: translateY(-2vh);
}
}
}
> .contents {
@include InlineAnimation(0.5s ease-in-out) {
0% {
transform: translateX(-100vw);
}
50% {
transform: translateX(5vw);
}
75% {
transform: translateX(-2vw);
}
}
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
> .stepLike {
display: flex;
flex-direction: column;
@include S(margin-bottom, 10px);
@include SuperSmallText;
> .buttons {
display: flex;
align-items: center;
justify-content: center;
@include S(margin, 10px, 0);
> button {
@include S(width, 60px);
@include S(height, 60px);
@include S(margin, 0, 10px);
box-sizing: border-box;
border-radius: 50%;
transition: opacity 0.12s ease-in-out, background-color 0.12s ease-in-out;
@include IncreasedClickArea(0px);
&.liked-yes {
/* @load-async */
background: uiResource("icons/puzzle_action_liked_yes.png") center 55% / 60%
no-repeat;
}
&:hover:not(.active) {
opacity: 0.5 !important;
}
&.active {
background-color: $colorRedBright !important;
@include InlineAnimation(0.3s ease-in-out) {
0% {
transform: scale(0);
}
50% {
transform: scale(1.2);
}
100% {
transform: scale(1);
}
}
}
&:not(.active) {
opacity: 0.4;
}
}
}
}
> .buttonBar {
display: flex;
@include S(margin-top, 20px);
button.continue {
background: #555;
@include S(margin-right, 10px);
}
button.menu {
background-color: $colorGreenBright;
}
> button {
@include S(min-width, 100px);
@include S(padding, 10px, 20px);
@include IncreasedClickArea(0px);
}
}
> .actions {
position: absolute;
@include S(bottom, 40px);
display: grid;
@include S(grid-gap, 15px);
grid-auto-flow: column;
button {
@include SuperSmallText;
}
.report {
background-color: $accentColorDark;
}
}
}
}
}

View File

@ -0,0 +1,24 @@
#ingame_HUD_PuzzleDLCLogo {
position: absolute;
@include S(width, 120px);
@include S(height, 40px);
@include S(left, 40px);
@include S(top, 7px);
& {
/* @load-async */
background: uiResource("puzzle_dlc_logo.png") center center / contain no-repeat;
}
@include DarkThemeOverride {
& {
/* @load-async */
background: uiResource("puzzle_dlc_logo_inverse.png") center center / contain no-repeat;
}
}
&.china {
/* @load-async */
background: uiResource("puzzle_dlc_logo_china.png") center center / contain no-repeat !important;
}
}

View File

@ -0,0 +1,36 @@
#ingame_HUD_PuzzleEditorControls {
position: absolute;
@include S(top, 70px);
@include S(left, 10px);
display: flex;
flex-direction: column;
@include SuperDuperSmallText;
@include S(width, 200px);
> span {
@include S(margin-bottom, 10px);
strong {
font-weight: bold;
}
}
@include DarkThemeInvert;
}
#ingame_HUD_PuzzleEditorTitle {
position: absolute;
@include S(top, 18px);
left: 50%;
transform: translateX(-50%);
text-transform: uppercase;
@include Heading;
text-align: center;
@include DarkThemeOverride {
color: #eee;
}
}

View File

@ -0,0 +1,50 @@
#ingame_HUD_PuzzleEditorReview {
position: absolute;
@include S(top, 17px);
@include S(right, 10px);
display: flex;
flex-direction: column;
align-items: flex-end;
backdrop-filter: blur(D(1px));
padding: D(3px);
> .button {
@include ButtonText;
@include IncreasedClickArea(0px);
pointer-events: all;
cursor: pointer;
position: relative;
color: #333438;
transition: all 0.12s ease-in-out;
text-transform: uppercase;
transition-property: opacity, transform;
@include PlainText;
@include S(padding-right, 25px);
opacity: 1;
@include DarkThemeInvert;
&:hover {
opacity: 0.9 !important;
}
&.pressed {
transform: scale(0.95) !important;
}
& {
/* @load-async */
background: uiResource("icons/state_next_button.png") right center / D(15px) no-repeat;
}
}
> .content {
@include SuperDuperSmallText;
@include S(width, 180px);
@include S(padding-right, 25px);
text-align: right;
text-transform: uppercase;
color: $accentColorDark;
}
}

View File

@ -0,0 +1,62 @@
#ingame_HUD_PuzzleEditorSettings {
position: absolute;
background: $ingameHudBg;
@include S(padding, 10px);
@include S(bottom, 60px);
@include S(left, 10px);
@include SuperSmallText;
color: #eee;
display: flex;
flex-direction: column;
@include S(border-radius, $globalBorderRadius);
> .section {
> label {
text-transform: uppercase;
}
.plusMinus {
@include S(margin-top, 5px);
display: grid;
grid-template-columns: 1fr auto auto auto;
align-items: center;
@include S(grid-gap, 5px);
label {
@include S(margin-right, 10px);
}
button {
@include PlainText;
@include S(padding, 0);
display: flex;
align-items: center;
justify-content: center;
@include S(width, 15px);
@include S(height, 15px);
@include IncreasedClickArea(0px);
}
.value {
text-align: center;
@include S(min-width, 15px);
}
}
> .buttons {
> .buttonBar {
display: flex;
align-items: center;
@include S(margin-top, 10px);
> button {
@include S(margin-right, 4px);
@include SuperSmallText;
&:last-child {
margin-right: 0;
}
}
}
}
}
}

View File

@ -0,0 +1,129 @@
#ingame_HUD_PuzzlePlayMetadata {
position: absolute;
@include S(top, 70px);
@include S(left, 10px);
display: flex;
flex-direction: column;
@include S(width, 200px);
> .info {
display: flex;
flex-direction: column;
@include SuperSmallText;
@include S(margin-bottom, 5px);
> label {
text-transform: uppercase;
@include SuperDuperSmallText;
color: $accentColorDark;
}
> span {
display: flex;
color: darken($accentColorDark, 25);
@include SuperSmallText;
@include DarkThemeOverride {
color: lighten($accentColorDark, 15);
}
}
}
> .plays {
display: flex;
align-items: center;
justify-self: end;
align-self: end;
flex-direction: row;
@include S(margin-bottom, 10px);
opacity: 0.8;
@include DarkThemeInvert;
@include DarkThemeOverride {
opacity: 0.8;
}
> .downloads {
@include SuperSmallText;
color: #000;
align-self: start;
justify-self: start;
font-weight: bold;
@include S(margin-right, 10px);
@include S(padding-left, 14px);
opacity: 0.7;
display: inline-flex;
align-items: center;
justify-content: center;
& {
/* @load-async */
background: uiResource("icons/puzzle_plays.png") #{D(2px)} center / #{D(8px)} #{D(8px)} no-repeat;
}
}
> .likes {
@include SuperSmallText;
align-items: center;
justify-content: center;
color: #000;
align-self: start;
justify-self: start;
font-weight: bold;
@include S(padding-left, 14px);
opacity: 0.7;
& {
/* @load-async */
background: uiResource("icons/puzzle_upvotes.png") #{D(2px)} center / #{D(8px)} #{D(8px)} no-repeat;
}
}
}
> .key {
button {
@include S(margin-top, 2px);
}
}
button {
@include SuperSmallText;
align-self: start;
@include S(min-width, 50px);
&.report {
background-color: $accentColorDark;
@include SuperDuperSmallText;
}
}
> .buttons {
display: flex;
flex-direction: column;
> button {
@include S(margin-bottom, 4px);
}
}
}
#ingame_HUD_PuzzlePlayTitle {
position: absolute;
@include S(top, 18px);
left: 50%;
transform: translateX(-50%);
text-transform: uppercase;
@include Heading;
text-align: center;
display: flex;
flex-direction: column;
> .name {
@include PlainText;
opacity: 0.5;
}
@include DarkThemeOverride {
color: #eee;
}
}

View File

@ -0,0 +1,23 @@
#ingame_HUD_PuzzlePlaySettings {
position: absolute;
background: $ingameHudBg;
@include S(padding, 10px);
@include S(bottom, 60px);
@include S(left, 10px);
@include SuperSmallText;
color: #eee;
display: flex;
flex-direction: column;
@include S(border-radius, $globalBorderRadius);
> .section {
display: grid;
@include S(grid-gap, 10px);
grid-auto-flow: row;
> button {
@include SuperSmallText;
}
}
}

View File

@ -29,6 +29,7 @@
@import "states/about"; @import "states/about";
@import "states/mobile_warning"; @import "states/mobile_warning";
@import "states/changelog"; @import "states/changelog";
@import "states/puzzle_menu";
@import "ingame_hud/buildings_toolbar"; @import "ingame_hud/buildings_toolbar";
@import "ingame_hud/building_placer"; @import "ingame_hud/building_placer";
@ -55,12 +56,21 @@
@import "ingame_hud/sandbox_controller"; @import "ingame_hud/sandbox_controller";
@import "ingame_hud/standalone_advantages"; @import "ingame_hud/standalone_advantages";
@import "ingame_hud/cat_memes"; @import "ingame_hud/cat_memes";
@import "ingame_hud/puzzle_back_to_menu";
@import "ingame_hud/puzzle_editor_review";
@import "ingame_hud/puzzle_dlc_logo";
@import "ingame_hud/puzzle_editor_controls";
@import "ingame_hud/puzzle_editor_settings";
@import "ingame_hud/puzzle_play_settings";
@import "ingame_hud/puzzle_play_metadata";
@import "ingame_hud/puzzle_complete_notification";
// prettier-ignore // prettier-ignore
$elements: $elements:
// Base // Base
ingame_Canvas, ingame_Canvas,
ingame_VignetteOverlay, ingame_VignetteOverlay,
ingame_HUD_PuzzleDLCLogo,
// Ingame overlays // Ingame overlays
ingame_HUD_Waypoints, ingame_HUD_Waypoints,
@ -71,6 +81,14 @@ ingame_HUD_PlacerVariants,
ingame_HUD_PinnedShapes, ingame_HUD_PinnedShapes,
ingame_HUD_GameMenu, ingame_HUD_GameMenu,
ingame_HUD_KeybindingOverlay, ingame_HUD_KeybindingOverlay,
ingame_HUD_PuzzleBackToMenu,
ingame_HUD_PuzzleEditorReview,
ingame_HUD_PuzzleEditorControls,
ingame_HUD_PuzzleEditorTitle,
ingame_HUD_PuzzleEditorSettings,
ingame_HUD_PuzzlePlaySettings,
ingame_HUD_PuzzlePlayMetadata,
ingame_HUD_PuzzlePlayTitle,
ingame_HUD_Notifications, ingame_HUD_Notifications,
ingame_HUD_DebugInfo, ingame_HUD_DebugInfo,
ingame_HUD_EntityDebugger, ingame_HUD_EntityDebugger,
@ -94,6 +112,7 @@ ingame_HUD_Statistics,
ingame_HUD_ShapeViewer, ingame_HUD_ShapeViewer,
ingame_HUD_StandaloneAdvantages, ingame_HUD_StandaloneAdvantages,
ingame_HUD_UnlockNotification, ingame_HUD_UnlockNotification,
ingame_HUD_PuzzleCompleteNotification,
ingame_HUD_SettingsMenu, ingame_HUD_SettingsMenu,
ingame_HUD_ModalDialogs, ingame_HUD_ModalDialogs,
ingame_HUD_CatMemes; ingame_HUD_CatMemes;
@ -113,6 +132,8 @@ body.uiHidden {
#ingame_HUD_PlacementHints, #ingame_HUD_PlacementHints,
#ingame_HUD_GameMenu, #ingame_HUD_GameMenu,
#ingame_HUD_PinnedShapes, #ingame_HUD_PinnedShapes,
#ingame_HUD_PuzzleBackToMenu,
#ingame_HUD_PuzzleEditorReview,
#ingame_HUD_Notifications, #ingame_HUD_Notifications,
#ingame_HUD_TutorialHints, #ingame_HUD_TutorialHints,
#ingame_HUD_Waypoints, #ingame_HUD_Waypoints,

View File

@ -1,11 +1,13 @@
$buildings: belt, cutter, miner, mixer, painter, rotater, balancer, stacker, trash, underground_belt, wire, $buildings: belt, cutter, miner, mixer, painter, rotater, balancer, stacker, trash, underground_belt, wire,
constant_signal, logic_gate, lever, filter, wire_tunnel, display, virtual_processor, reader, storage, constant_signal, logic_gate, lever, filter, wire_tunnel, display, virtual_processor, reader, storage,
transistor, analyzer, comparator, item_producer; transistor, analyzer, comparator, item_producer, constant_producer, goal_acceptor, block;
@each $building in $buildings { @each $building in $buildings {
[data-icon="building_icons/#{$building}.png"] { [data-icon="building_icons/#{$building}.png"] {
/* @load-async */ /* @load-async */
background-image: uiResource("res/ui/building_icons/#{$building}.png") !important; .icon {
background-image: uiResource("res/ui/building_icons/#{$building}.png") !important;
}
} }
} }
@ -13,7 +15,8 @@ $buildingsAndVariants: belt, balancer, underground_belt, underground_belt-tier2,
cutter, cutter-quad, rotater, rotater-ccw, stacker, mixer, painter-double, painter-quad, trash, storage, cutter, cutter-quad, rotater, rotater-ccw, stacker, mixer, painter-double, painter-quad, trash, storage,
reader, rotater-rotate180, display, constant_signal, wire, wire_tunnel, logic_gate-or, logic_gate-not, reader, rotater-rotate180, display, constant_signal, wire, wire_tunnel, logic_gate-or, logic_gate-not,
logic_gate-xor, analyzer, virtual_processor-rotater, virtual_processor-unstacker, item_producer, logic_gate-xor, analyzer, virtual_processor-rotater, virtual_processor-unstacker, item_producer,
virtual_processor-stacker, virtual_processor-painter, wire-second, painter, painter-mirrored, comparator; constant_producer, virtual_processor-stacker, virtual_processor-painter, wire-second, painter,
painter-mirrored, comparator, goal_acceptor, block;
@each $building in $buildingsAndVariants { @each $building in $buildingsAndVariants {
[data-icon="building_tutorials/#{$building}.png"] { [data-icon="building_tutorials/#{$building}.png"] {
/* @load-async */ /* @load-async */
@ -67,7 +70,7 @@ $icons: notification_saved, notification_success, notification_upgrade;
} }
$languages: en, de, cs, da, et, es-419, fr, it, pt-BR, sv, tr, el, ru, uk, zh-TW, zh-CN, nb, mt-MT, ar, nl, vi, $languages: en, de, cs, da, et, es-419, fr, it, pt-BR, sv, tr, el, ru, uk, zh-TW, zh-CN, nb, mt-MT, ar, nl, vi,
th, hu, pl, ja, kor, no, pt-PT, fi, ro; th, hu, pl, ja, kor, no, pt-PT, fi, ro, he;
@each $language in $languages { @each $language in $languages {
[data-languageicon="#{$language}"] { [data-languageicon="#{$language}"] {

View File

@ -88,9 +88,11 @@
@include S(grid-column-gap, 10px); @include S(grid-column-gap, 10px);
display: grid; display: grid;
grid-template-columns: 1fr;
&.demo { &[data-columns="1"] {
grid-template-columns: 1fr;
}
&[data-columns="2"] {
grid-template-columns: 1fr 1fr; grid-template-columns: 1fr 1fr;
} }
@ -183,7 +185,7 @@
.updateLabel { .updateLabel {
position: absolute; position: absolute;
transform: translateX(50%) rotate(-5deg); transform: translateX(50%) rotate(-5deg);
color: #3291e9; color: #ff590b;
@include Heading; @include Heading;
font-weight: bold; font-weight: bold;
@include S(right, 40px); @include S(right, 40px);
@ -223,9 +225,48 @@
} }
} }
.puzzleContainer {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
background: #4cc98a;
grid-row: 1 / 2;
grid-column: 2 / 3;
@include S(padding, 20px);
@include S(border-radius, $globalBorderRadius);
> .dlcLogo {
@include S(width, 190px);
}
> button {
@include S(margin-top, 20px);
@include Heading;
@include S(padding, 10px, 30px);
background-color: #333;
color: #fff;
}
&.notOwned {
p {
@include PlainText;
color: #333;
@include S(margin-top, 10px);
@include S(width, 190px);
}
> button {
box-sizing: border-box;
@include S(margin-top, 10px);
@include S(width, 190px);
@include S(padding, 10px, 20px);
}
}
}
.mainContainer { .mainContainer {
display: flex; display: flex;
align-items: center; align-items: center;
grid-row: 1 / 2;
justify-content: center; justify-content: center;
flex-direction: column; flex-direction: column;
background: #fafafa; background: #fafafa;
@ -242,6 +283,16 @@
align-items: center; align-items: center;
} }
.modeButtons {
display: grid;
grid-template-columns: repeat(2, 1fr);
@include S(grid-column-gap, 10px);
align-items: start;
height: 100%;
width: 100%;
box-sizing: border-box;
}
.browserWarning { .browserWarning {
@include S(margin-bottom, 10px); @include S(margin-bottom, 10px);
background-color: $colorRedBright; background-color: $colorRedBright;
@ -285,6 +336,18 @@
@include S(margin-left, 15px); @include S(margin-left, 15px);
} }
.playModeButton {
@include IncreasedClickArea(0px);
@include S(margin-top, 15px);
@include S(margin-left, 15px);
}
.editModeButton {
@include IncreasedClickArea(0px);
@include S(margin-top, 15px);
@include S(margin-left, 15px);
}
.savegames { .savegames {
@include S(max-height, 105px); @include S(max-height, 105px);
overflow-y: auto; overflow-y: auto;
@ -439,6 +502,27 @@
} }
} }
.bottomContainer {
display: flex;
align-items: center;
justify-content: center;
flex-direction: row;
@include S(padding-top, 10px);
height: 100%;
width: 100%;
box-sizing: border-box;
.buttons {
display: grid;
grid-template-columns: repeat(2, 1fr);
@include S(grid-column-gap, 10px);
align-items: start;
height: 100%;
width: 100%;
box-sizing: border-box;
}
}
.footer { .footer {
display: grid; display: grid;
flex-grow: 1; flex-grow: 1;

View File

@ -17,7 +17,7 @@
@include S(border-radius, 3px); @include S(border-radius, 3px);
@include DarkThemeOverride { @include DarkThemeOverride {
background: #424242; background: #33343c;
} }
.version { .version {

View File

@ -0,0 +1,277 @@
#state_PuzzleMenuState {
> .headerBar {
display: grid;
grid-template-columns: 1fr auto;
align-items: center;
> h1 {
justify-self: start;
}
.createPuzzle {
background-color: $colorGreenBright;
@include S(margin-left, 5px);
}
}
> .container {
> .mainContent {
overflow: hidden;
> .categoryChooser {
display: grid;
grid-auto-columns: 1fr;
grid-auto-flow: column;
@include S(grid-gap, 2px);
@include S(padding-right, 10px);
> .category {
background: $accentColorBright;
border-radius: 0;
color: $accentColorDark;
transition: all 0.12s ease-in-out;
transition-property: opacity, background-color, color;
&:first-child {
@include S(border-top-left-radius, $globalBorderRadius);
@include S(border-bottom-left-radius, $globalBorderRadius);
}
&:last-child {
border-top-right-radius: $globalBorderRadius;
border-bottom-right-radius: $globalBorderRadius;
}
&.active {
background: $colorBlueBright;
opacity: 1 !important;
color: #fff;
cursor: default;
}
@include DarkThemeOverride {
background: $accentColorDark;
color: #bbbbc4;
&.active {
background: $colorBlueBright;
color: #fff;
}
}
}
}
> .puzzles {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(D(180px), 1fr));
@include S(grid-auto-rows, 65px);
@include S(grid-gap, 7px);
@include S(margin-top, 10px);
@include S(padding-right, 4px);
@include S(height, 360px);
overflow-y: scroll;
pointer-events: all;
position: relative;
> .puzzle {
width: 100%;
@include S(height, 65px);
background: #f3f3f8;
@include S(border-radius, $globalBorderRadius);
display: grid;
grid-template-columns: auto 1fr;
grid-template-rows: D(15px) D(15px) 1fr;
@include S(padding, 5px);
@include S(grid-column-gap, 5px);
box-sizing: border-box;
pointer-events: all;
cursor: pointer;
position: relative;
@include S(padding-left, 10px);
@include DarkThemeOverride {
background: rgba(0, 0, 10, 0.2);
}
@include InlineAnimation(0.12s ease-in-out) {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
&:hover {
background: #f0f0f8;
}
> .title {
grid-column: 2 / 3;
grid-row: 1 / 2;
@include PlainText;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
align-self: center;
justify-self: start;
width: 100%;
box-sizing: border-box;
@include S(padding, 2px, 5px);
@include S(height, 17px);
}
> .author {
grid-column: 2 / 2;
grid-row: 2 / 3;
@include SuperSmallText;
color: $accentColorDark;
align-self: center;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
@include S(padding, 2px, 5px);
}
> .icon {
grid-column: 1 / 2;
grid-row: 1 / 4;
align-self: center;
justify-self: center;
@include S(width, 45px);
@include S(height, 45px);
canvas {
width: 100%;
height: 100%;
}
}
> .stats {
grid-column: 2 / 3;
grid-row: 3 / 4;
display: flex;
align-items: center;
justify-self: end;
justify-content: center;
align-self: end;
@include S(height, 14px);
> .downloads {
@include SuperSmallText;
color: #000;
font-weight: bold;
@include S(margin-right, 5px);
@include S(padding-left, 12px);
opacity: 0.7;
display: inline-flex;
align-items: center;
justify-content: center;
@include DarkThemeInvert;
& {
/* @load-async */
background: uiResource("icons/puzzle_plays.png") #{D(2px)} #{D(2.5px)} / #{D(
8px
)} #{D(8px)} no-repeat;
}
}
> .likes {
@include SuperSmallText;
align-items: center;
justify-content: center;
color: #000;
font-weight: bold;
@include S(padding-left, 14px);
opacity: 0.7;
@include DarkThemeInvert;
& {
/* @load-async */
background: uiResource("icons/puzzle_upvotes.png") #{D(2px)} #{D(2.4px)} / #{D(
9px
)} #{D(9px)} no-repeat;
}
}
> .difficulty {
@include SuperSmallText;
align-items: center;
justify-content: center;
color: #000;
font-weight: bold;
@include S(margin-right, 3px);
opacity: 0.7;
&.stage--easy {
color: $colorGreenBright;
}
&.stage--normal {
color: #000;
@include DarkThemeInvert;
}
&.stage--medium {
color: $colorOrangeBright;
}
&.stage--hard {
color: $colorRedBright;
}
}
}
&.completed {
> .icon,
> .stats,
> .author,
> .title {
opacity: 0.3;
}
background: #fafafa;
@include DarkThemeOverride {
background: rgba(0, 0, 0, 0.05);
}
&::after {
content: "";
position: absolute;
@include S(top, 10px);
@include S(right, 10px);
@include S(width, 30px);
@include S(height, 30px);
opacity: 0.1;
& {
/* @load-async */
background: uiResource("icons/puzzle_complete_indicator.png") center center /
contain no-repeat;
}
}
@include DarkThemeOverride {
&::after {
/* @load-async */
background: uiResource("icons/puzzle_complete_indicator_inverse.png") center
center / contain no-repeat;
}
}
}
}
> .loader,
> .empty {
display: flex;
align-items: center;
color: $accentColorDark;
justify-content: center;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
}
}
}
}

View File

@ -18,8 +18,10 @@ $textLineHeight: 21px;
$plainTextFontSize: 13px; $plainTextFontSize: 13px;
$plainTextLineHeight: 17px; $plainTextLineHeight: 17px;
$supersmallTextFontSize: 10px; $superDuperSmallTextFontSize: 8px;
$supersmallTextLineHeight: 13px; $superDuperSmallTextLineHeight: 9px;
$superSmallTextFontSize: 10px;
$superSmallTextLineHeight: 13px;
$buttonFontSize: 14px; $buttonFontSize: 14px;
$buttonLineHeight: 18px; $buttonLineHeight: 18px;
@ -33,6 +35,7 @@ $accentColorDark: #7d808a;
$colorGreenBright: #66bb6a; $colorGreenBright: #66bb6a;
$colorBlueBright: rgb(74, 151, 223); $colorBlueBright: rgb(74, 151, 223);
$colorRedBright: #ef5072; $colorRedBright: #ef5072;
$colorOrangeBright: #ef9d50;
$themeColor: #393747; $themeColor: #393747;
$ingameHudBg: rgba(#333438, 0.9); $ingameHudBg: rgba(#333438, 0.9);
@ -76,8 +79,16 @@ $mainFontScale: 1;
// } // }
} }
@mixin SuperDuperSmallText {
@include ScaleFont($superDuperSmallTextFontSize, $superDuperSmallTextLineHeight);
font-weight: $mainFontWeight;
font-family: $mainFont;
letter-spacing: $mainFontSpacing;
@include DebugText(green);
}
@mixin SuperSmallText { @mixin SuperSmallText {
@include ScaleFont($supersmallTextFontSize, $supersmallTextLineHeight); @include ScaleFont($superSmallTextFontSize, $superSmallTextLineHeight);
font-weight: $mainFontWeight; font-weight: $mainFontWeight;
font-family: $mainFont; font-family: $mainFont;
letter-spacing: $mainFontSpacing; letter-spacing: $mainFontSpacing;

View File

@ -31,6 +31,9 @@ import { PreloadState } from "./states/preload";
import { SettingsState } from "./states/settings"; import { SettingsState } from "./states/settings";
import { ShapezGameAnalytics } from "./platform/browser/game_analytics"; import { ShapezGameAnalytics } from "./platform/browser/game_analytics";
import { RestrictionManager } from "./core/restriction_manager"; import { RestrictionManager } from "./core/restriction_manager";
import { PuzzleMenuState } from "./states/puzzle_menu";
import { ClientAPI } from "./platform/api";
import { LoginState } from "./states/login";
/** /**
* @typedef {import("./platform/achievement_provider").AchievementProviderInterface} AchievementProviderInterface * @typedef {import("./platform/achievement_provider").AchievementProviderInterface} AchievementProviderInterface
@ -72,6 +75,7 @@ export class Application {
this.savegameMgr = new SavegameManager(this); this.savegameMgr = new SavegameManager(this);
this.inputMgr = new InputDistributor(this); this.inputMgr = new InputDistributor(this);
this.backgroundResourceLoader = new BackgroundResourcesLoader(this); this.backgroundResourceLoader = new BackgroundResourcesLoader(this);
this.clientApi = new ClientAPI(this);
// Restrictions (Like demo etc) // Restrictions (Like demo etc)
this.restrictionMgr = new RestrictionManager(this); this.restrictionMgr = new RestrictionManager(this);
@ -159,6 +163,8 @@ export class Application {
KeybindingsState, KeybindingsState,
AboutState, AboutState,
ChangelogState, ChangelogState,
PuzzleMenuState,
LoginState,
]; ];
for (let i = 0; i < states.length; ++i) { for (let i = 0; i < states.length; ++i) {

View File

@ -1,12 +1,32 @@
export const CHANGELOG = [ export const CHANGELOG = [
{ {
version: "1.3.1", version: "1.4.0",
date: "beta", date: "04.06.2021",
entries: [ entries: [
"Fixed savegames getting corrupt in rare conditions", "Belts in blueprints should now always paste correctly",
"Fixed game crashing sometimes since the achievements update", "You can now clear belts by selecting them and then pressing 'B'",
"Preparations for the <a href='https://store.steampowered.com/app/1625400/shapezio__Puzzle_DLC/' target='_blank'>Puzzle DLC</a>, coming June 22nd!",
], ],
}, },
{
version: "1.3.1",
date: "16.04.2021",
entries: G_CHINA_VERSION
? [
"第13关的交付目标更改为中国古代指南针。感谢玩家凯风入心 创作并提供",
"第17关的交付目标更改为永乐通宝。感谢玩家金天赐 创作并提供",
"第22关的交付目标更改为凤凰。感谢玩家我没得眼镜 创作并提供",
"第23关的交付目标更改为古代车轮。感谢玩家我没得眼镜 创作并提供",
"第24关的交付目标更改为大熊猫。感谢玩家窝囸倪现任 创作并提供",
"修复了一些特定情况下偶尔会发生的存档损坏问题",
"修复了成就更新后有时候游戏崩溃的问题",
]
: [
"Fixed savegames getting corrupt in rare conditions",
"Fixed game crashing sometimes since the achievements update",
],
},
{ {
version: "1.3.0", version: "1.3.0",
date: "12.03.2020", date: "12.03.2020",

View File

@ -51,9 +51,12 @@ export class AnimationFrame {
dt = resetDtMs; dt = resetDtMs;
} }
this.frameEmitted.dispatch(dt); try {
this.frameEmitted.dispatch(dt);
} catch (ex) {
console.error(ex);
}
this.lastTime = time; this.lastTime = time;
window.requestAnimationFrame(this.boundMethod); window.requestAnimationFrame(this.boundMethod);
} }
} }

View File

@ -12,8 +12,13 @@ import { cachebust } from "./cachebust";
const logger = createLogger("background_loader"); 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 = [ const essentialMainMenuSprites = [
G_CHINA_VERSION ? "logo_cn.png" : "logo.png", getLogoSprite(),
...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 = [

View File

@ -18,6 +18,7 @@ export const THIRDPARTY_URLS = {
shapeViewer: "https://viewer.shapez.io", shapeViewer: "https://viewer.shapez.io",
standaloneStorePage: "https://store.steampowered.com/app/1318690/shapezio/", standaloneStorePage: "https://store.steampowered.com/app/1318690/shapezio/",
puzzleDlcStorePage: "https://store.steampowered.com/app/1625400/shapezio__Puzzle_DLC",
levelTutorialVideos: { levelTutorialVideos: {
21: "https://www.youtube.com/watch?v=0nUfRLMCcgo&", 21: "https://www.youtube.com/watch?v=0nUfRLMCcgo&",
@ -71,6 +72,13 @@ export const globalConfig = {
readerAnalyzeIntervalSeconds: 10, readerAnalyzeIntervalSeconds: 10,
goalAcceptorMinimumDurationSeconds: 5,
goalAcceptorsPerProducer: 4.5,
puzzleModeSpeed: 3,
puzzleMinBoundsSize: 2,
puzzleMaxBoundsSize: 20,
puzzleValidationDurationSeconds: 30,
buildingSpeeds: { buildingSpeeds: {
cutter: 1 / 4, cutter: 1 / 4,
cutterQuad: 1 / 4, cutterQuad: 1 / 4,
@ -93,7 +101,7 @@ export const globalConfig = {
gameSpeed: 1, gameSpeed: 1,
warmupTimeSecondsFast: 0.5, warmupTimeSecondsFast: 0.5,
warmupTimeSecondsRegular: 3, warmupTimeSecondsRegular: 1.5,
smoothing: { smoothing: {
smoothMainCanvas: smoothCanvas && true, smoothMainCanvas: smoothCanvas && true,

View File

@ -62,6 +62,9 @@ export default {
// Allows unlocked achievements to be logged to console in the local build // Allows unlocked achievements to be logged to console in the local build
// testAchievements: true, // testAchievements: true,
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// Enables use of (some) existing flags within the puzzle mode context
// testPuzzleMode: true,
// -----------------------------------------------------------------------------------
// Disables the automatic switch to an overview when zooming out // Disables the automatic switch to an overview when zooming out
// disableMapOverview: true, // disableMapOverview: true,
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------

View File

@ -123,4 +123,6 @@ function catchErrors(message, source, lineno, colno, error) {
return true; return true;
} }
window.onerror = catchErrors; if (!G_IS_DEV) {
window.onerror = catchErrors;
}

View File

@ -5,6 +5,7 @@ import { Factory } from "./factory";
* @typedef {import("../game/time/base_game_speed").BaseGameSpeed} BaseGameSpeed * @typedef {import("../game/time/base_game_speed").BaseGameSpeed} BaseGameSpeed
* @typedef {import("../game/component").Component} Component * @typedef {import("../game/component").Component} Component
* @typedef {import("../game/base_item").BaseItem} BaseItem * @typedef {import("../game/base_item").BaseItem} BaseItem
* @typedef {import("../game/game_mode").GameMode} GameMode
* @typedef {import("../game/meta_building").MetaBuilding} MetaBuilding * @typedef {import("../game/meta_building").MetaBuilding} MetaBuilding
@ -19,6 +20,9 @@ export let gBuildingsByCategory = null;
/** @type {FactoryTemplate<Component>} */ /** @type {FactoryTemplate<Component>} */
export let gComponentRegistry = new Factory("component"); export let gComponentRegistry = new Factory("component");
/** @type {FactoryTemplate<GameMode>} */
export let gGameModeRegistry = new Factory("gameMode");
/** @type {FactoryTemplate<BaseGameSpeed>} */ /** @type {FactoryTemplate<BaseGameSpeed>} */
export let gGameSpeedRegistry = new Factory("gamespeed"); export let gGameSpeedRegistry = new Factory("gamespeed");

View File

@ -267,7 +267,7 @@ export class Dialog {
* Dialog which simply shows a loading spinner * Dialog which simply shows a loading spinner
*/ */
export class DialogLoading extends Dialog { export class DialogLoading extends Dialog {
constructor(app) { constructor(app, text = "") {
super({ super({
app, app,
title: "", title: "",
@ -279,6 +279,8 @@ export class DialogLoading extends Dialog {
// Loading dialog can not get closed with back button // Loading dialog can not get closed with back button
this.inputReciever.backButton.removeAll(); this.inputReciever.backButton.removeAll();
this.inputReciever.context = "dialog-loading"; this.inputReciever.context = "dialog-loading";
this.text = text;
} }
createElement() { createElement() {
@ -287,6 +289,13 @@ export class DialogLoading extends Dialog {
elem.classList.add("loadingDialog"); elem.classList.add("loadingDialog");
this.element = elem; this.element = elem;
if (this.text) {
const text = document.createElement("div");
text.classList.add("text");
text.innerText = this.text;
elem.appendChild(text);
}
const loader = document.createElement("div"); const loader = document.createElement("div");
loader.classList.add("prefab_LoadingTextWithAnim"); loader.classList.add("prefab_LoadingTextWithAnim");
loader.classList.add("loadingIndicator"); loader.classList.add("loadingIndicator");
@ -444,7 +453,7 @@ export class DialogWithForm extends Dialog {
for (let i = 0; i < this.formElements.length; ++i) { for (let i = 0; i < this.formElements.length; ++i) {
const elem = this.formElements[i]; const elem = this.formElements[i];
elem.bindEvents(div, this.clickDetectors); elem.bindEvents(div, this.clickDetectors);
elem.valueChosen.add(this.closeRequested.dispatch, this.closeRequested); // elem.valueChosen.add(this.closeRequested.dispatch, this.closeRequested);
elem.valueChosen.add(this.valueChosen.dispatch, this.valueChosen); elem.valueChosen.add(this.valueChosen.dispatch, this.valueChosen);
} }

View File

@ -117,6 +117,11 @@ export class FormElementInput extends FormElement {
return this.element.value; return this.element.value;
} }
setValue(value) {
this.element.value = value;
this.updateErrorState();
}
focus() { focus() {
this.element.focus(); this.element.focus();
} }

View File

@ -44,6 +44,15 @@ export class Rectangle {
return new Rectangle(left, top, right - left, bottom - top); return new Rectangle(left, top, right - left, bottom - top);
} }
/**
*
* @param {number} width
* @param {number} height
*/
static centered(width, height) {
return new Rectangle(-Math.ceil(width / 2), -Math.ceil(height / 2), width, height);
}
/** /**
* Returns if a intersects b * Returns if a intersects b
* @param {Rectangle} a * @param {Rectangle} a
@ -72,7 +81,7 @@ export class Rectangle {
/** /**
* Returns if this rectangle is equal to the other while taking an epsilon into account * Returns if this rectangle is equal to the other while taking an epsilon into account
* @param {Rectangle} other * @param {Rectangle} other
* @param {number} epsilon * @param {number} [epsilon]
*/ */
equalsEpsilon(other, epsilon) { equalsEpsilon(other, epsilon) {
return ( return (
@ -287,6 +296,15 @@ export class Rectangle {
return Rectangle.fromTRBL(top, right, bottom, left); return Rectangle.fromTRBL(top, right, bottom, left);
} }
/**
* Returns whether the rectangle fully intersects the given rectangle
* @param {Rectangle} rect
*/
intersectsFully(rect) {
const intersection = this.getIntersection(rect);
return intersection && Math.abs(intersection.w * intersection.h - rect.w * rect.h) < 0.001;
}
/** /**
* Returns the union of this rectangle with another * Returns the union of this rectangle with another
* @param {Rectangle} rect * @param {Rectangle} rect

View File

@ -17,6 +17,17 @@ export class Signal {
++this.modifyCount; ++this.modifyCount;
} }
/**
* Adds a new signal listener
* @param {function} receiver
* @param {object} scope
*/
addToTop(receiver, scope = null) {
assert(receiver, "receiver is null");
this.receivers.unshift({ receiver, scope });
++this.modifyCount;
}
/** /**
* Dispatches the signal * Dispatches the signal
* @param {...any} payload * @param {...any} payload

View File

@ -90,9 +90,9 @@ export class StateManager {
dialogParent.classList.add("modalDialogParent"); dialogParent.classList.add("modalDialogParent");
document.body.appendChild(dialogParent); document.body.appendChild(dialogParent);
this.currentState.internalEnterCallback(payload);
this.app.sound.playThemeMusic(this.currentState.getThemeMusic()); this.app.sound.playThemeMusic(this.currentState.getThemeMusic());
this.currentState.internalEnterCallback(payload);
this.currentState.onResized(this.app.screenWidth, this.app.screenHeight); this.currentState.onResized(this.app.screenWidth, this.app.screenHeight);
this.app.analytics.trackStateEnter(key); this.app.analytics.trackStateEnter(key);

View File

@ -573,12 +573,14 @@ export function round1DigitLocalized(speed, separator = T.global.decimalSeparato
* @param {string=} separator The decimal separator for numbers like 50.1 (separator='.') * @param {string=} separator The decimal separator for numbers like 50.1 (separator='.')
*/ */
export function formatItemsPerSecond(speed, double = false, separator = T.global.decimalSeparator) { export function formatItemsPerSecond(speed, double = false, separator = T.global.decimalSeparator) {
return speed === 1.0 return (
? T.ingame.buildingPlacement.infoTexts.oneItemPerSecond (speed === 1.0
: T.ingame.buildingPlacement.infoTexts.itemsPerSecond.replace( ? T.ingame.buildingPlacement.infoTexts.oneItemPerSecond
"<x>", : T.ingame.buildingPlacement.infoTexts.itemsPerSecond.replace(
round2Digits(speed).toString().replace(".", separator) "<x>",
) + (double ? " " + T.ingame.buildingPlacement.infoTexts.itemsPerSecondDouble : ""); round2Digits(speed).toString().replace(".", separator)
)) + (double ? " " + T.ingame.buildingPlacement.infoTexts.itemsPerSecondDouble : "")
);
} }
/** /**

View File

@ -32,6 +32,12 @@ export class AchievementProxy {
} }
onLoad() { onLoad() {
if (!this.root.gameMode.hasAchievements()) {
logger.log("Disabling achievements because game mode does not have achievements");
this.disabled = true;
return;
}
this.provider this.provider
.onLoad(this.root) .onLoad(this.root)
.then(() => { .then(() => {

View File

@ -11,6 +11,7 @@ export const itemTypes = ["shape", "color", "boolean"];
export class BaseItem extends BasicSerializableObject { export class BaseItem extends BasicSerializableObject {
constructor() { constructor() {
super(); super();
this._type = this.getItemType();
} }
static getId() { static getId() {

View File

@ -13,8 +13,6 @@ import { GameRoot } from "./root";
const logger = createLogger("belt_path"); const logger = createLogger("belt_path");
// Helpers for more semantic access into interleaved arrays // Helpers for more semantic access into interleaved arrays
const _nextDistance = 0;
const _item = 1;
const DEBUG = G_IS_DEV && false; const DEBUG = G_IS_DEV && false;
@ -110,6 +108,15 @@ export class BeltPath extends BasicSerializableObject {
} }
} }
/**
* Clears all items
*/
clearAllItems() {
this.items = [];
this.spacingToFirstItem = this.totalLength;
this.numCompressedItemsAfterFirstItem = 0;
}
/** /**
* Returns whether this path can accept a new item * Returns whether this path can accept a new item
* @returns {boolean} * @returns {boolean}
@ -174,7 +181,7 @@ export class BeltPath extends BasicSerializableObject {
* Recomputes cache variables once the path was changed * Recomputes cache variables once the path was changed
*/ */
onPathChanged() { onPathChanged() {
this.acceptorTarget = this.computeAcceptingEntityAndSlot(); this.boundAcceptor = this.computeAcceptingEntityAndSlot();
/** /**
* How many items past the first item are compressed * How many items past the first item are compressed
@ -192,7 +199,7 @@ export class BeltPath extends BasicSerializableObject {
/** /**
* Finds the entity which accepts our items * Finds the entity which accepts our items
* @param {boolean=} debug_Silent Whether debug output should be silent * @param {boolean=} debug_Silent Whether debug output should be silent
* @return {{ entity: Entity, slot: number, direction?: enumDirection }} * @return { (BaseItem, number?) => boolean }
*/ */
computeAcceptingEntityAndSlot(debug_Silent = false) { computeAcceptingEntityAndSlot(debug_Silent = false) {
DEBUG && !debug_Silent && logger.log("Recomputing acceptor target"); DEBUG && !debug_Silent && logger.log("Recomputing acceptor target");
@ -214,55 +221,142 @@ export class BeltPath extends BasicSerializableObject {
"regular" "regular"
); );
if (targetEntity) { if (!targetEntity) {
DEBUG && !debug_Silent && logger.log(" Found target entity", targetEntity.uid); return;
const targetStaticComp = targetEntity.components.StaticMapEntity; }
const targetBeltComp = targetEntity.components.Belt;
// Check for belts (special case) const noSimplifiedBelts = !this.root.app.settings.getAllSettings().simplifiedBelts;
if (targetBeltComp) {
const beltAcceptingDirection = targetStaticComp.localDirectionToWorld(enumDirection.top); DEBUG && !debug_Silent && logger.log(" Found target entity", targetEntity.uid);
DEBUG && const targetStaticComp = targetEntity.components.StaticMapEntity;
!debug_Silent && const targetBeltComp = targetEntity.components.Belt;
logger.log(
" Entity is accepting items from", // Check for belts (special case)
ejectSlotWsDirection, if (targetBeltComp) {
"vs", const beltAcceptingDirection = targetStaticComp.localDirectionToWorld(enumDirection.top);
beltAcceptingDirection, DEBUG &&
"Rotation:", !debug_Silent &&
targetStaticComp.rotation logger.log(
" Entity is accepting items from",
ejectSlotWsDirection,
"vs",
beltAcceptingDirection,
"Rotation:",
targetStaticComp.rotation
);
if (ejectSlotWsDirection === beltAcceptingDirection) {
return item => {
const path = targetBeltComp.assignedPath;
assert(path, "belt has no path");
return path.tryAcceptItem(item);
};
}
}
// Check for item acceptors
const targetAcceptorComp = targetEntity.components.ItemAcceptor;
if (!targetAcceptorComp) {
// Entity doesn't accept items
return;
}
const ejectingDirection = targetStaticComp.worldDirectionToLocal(ejectSlotWsDirection);
const matchingSlot = targetAcceptorComp.findMatchingSlot(
targetStaticComp.worldToLocalTile(ejectSlotTargetWsTile),
ejectingDirection
);
if (!matchingSlot) {
// No matching slot found
return;
}
const matchingSlotIndex = matchingSlot.index;
const passOver = this.computePassOverFunctionWithoutBelts(targetEntity, matchingSlotIndex);
if (!passOver) {
return;
}
const matchingDirection = enumInvertedDirections[ejectingDirection];
const filter = matchingSlot.slot.filter;
return function (item, remainingProgress = 0.0) {
// Check if the acceptor has a filter
if (filter && item._type !== filter) {
return false;
}
// Try to pass over
if (passOver(item, matchingSlotIndex)) {
// Trigger animation on the acceptor comp
if (noSimplifiedBelts) {
targetAcceptorComp.onItemAccepted(
matchingSlotIndex,
matchingDirection,
item,
remainingProgress
); );
if (ejectSlotWsDirection === beltAcceptingDirection) {
return {
entity: targetEntity,
direction: null,
slot: 0,
};
} }
return true;
} }
return false;
};
}
// Check for item acceptors /**
const targetAcceptorComp = targetEntity.components.ItemAcceptor; * Computes a method to pass over the item to the entity
if (!targetAcceptorComp) { * @param {Entity} entity
// Entity doesn't accept items * @param {number} matchingSlotIndex
return; * @returns {(item: BaseItem, slotIndex: number) => boolean | void}
} */
computePassOverFunctionWithoutBelts(entity, matchingSlotIndex) {
const systems = this.root.systemMgr.systems;
const hubGoals = this.root.hubGoals;
const ejectingDirection = targetStaticComp.worldDirectionToLocal(ejectSlotWsDirection); // NOTICE: THIS IS COPIED FROM THE ITEM EJECTOR SYSTEM FOR PEROFMANCE REASONS
const matchingSlot = targetAcceptorComp.findMatchingSlot(
targetStaticComp.worldToLocalTile(ejectSlotTargetWsTile),
ejectingDirection
);
if (!matchingSlot) { const itemProcessorComp = entity.components.ItemProcessor;
// No matching slot found if (itemProcessorComp) {
return; // Its an item processor ..
} return function (item) {
// Check for potential filters
if (!systems.itemProcessor.checkRequirements(entity, item, matchingSlotIndex)) {
return;
}
return itemProcessorComp.tryTakeItem(item, matchingSlotIndex);
};
}
return { const undergroundBeltComp = entity.components.UndergroundBelt;
entity: targetEntity, if (undergroundBeltComp) {
slot: matchingSlot.index, // Its an underground belt. yay.
direction: enumInvertedDirections[ejectingDirection], return function (item) {
return undergroundBeltComp.tryAcceptExternalItem(
item,
hubGoals.getUndergroundBeltBaseSpeed()
);
};
}
const storageComp = entity.components.Storage;
if (storageComp) {
// It's a storage
return function (item) {
if (storageComp.canAcceptItem(item)) {
storageComp.takeItem(item);
return true;
}
};
}
const filterComp = entity.components.Filter;
if (filterComp) {
// It's a filter! Unfortunately the filter has to know a lot about it's
// surrounding state and components, so it can't be within the component itself.
return function (item) {
if (systems.filter.tryAcceptItem(entity, matchingSlotIndex, item)) {
return true;
}
}; };
} }
} }
@ -365,17 +459,17 @@ export class BeltPath extends BasicSerializableObject {
for (let i = 0; i < this.items.length; ++i) { for (let i = 0; i < this.items.length; ++i) {
const item = this.items[i]; const item = this.items[i];
if (item[_nextDistance] < 0 || item[_nextDistance] > this.totalLength + 0.02) { if (item[0 /* nextDistance */] < 0 || item[0 /* nextDistance */] > this.totalLength + 0.02) {
return fail( return fail(
"Item has invalid offset to next item: ", "Item has invalid offset to next item: ",
item[_nextDistance], item[0 /* nextDistance */],
"(total length:", "(total length:",
this.totalLength, this.totalLength,
")" ")"
); );
} }
currentPos += item[_nextDistance]; currentPos += item[0 /* nextDistance */];
} }
// Check the total sum matches // Check the total sum matches
@ -387,7 +481,7 @@ export class BeltPath extends BasicSerializableObject {
this.spacingToFirstItem, this.spacingToFirstItem,
") and items does not match total length (", ") and items does not match total length (",
this.totalLength, this.totalLength,
") -> items: " + this.items.map(i => i[_nextDistance]).join("|") ") -> items: " + this.items.map(i => i[0 /* nextDistance */]).join("|")
); );
} }
@ -399,43 +493,14 @@ export class BeltPath extends BasicSerializableObject {
// Check acceptor // Check acceptor
const acceptor = this.computeAcceptingEntityAndSlot(true); const acceptor = this.computeAcceptingEntityAndSlot(true);
if (!!acceptor !== !!this.acceptorTarget) { if (!!acceptor !== !!this.boundAcceptor) {
return fail("Acceptor target mismatch, acceptor", !!acceptor, "vs stored", !!this.acceptorTarget); return fail("Acceptor target mismatch, acceptor", !!acceptor, "vs stored", !!this.boundAcceptor);
}
if (acceptor) {
if (this.acceptorTarget.entity !== acceptor.entity) {
return fail(
"Mismatching entity on acceptor target:",
acceptor.entity.uid,
"vs",
this.acceptorTarget.entity.uid
);
}
if (this.acceptorTarget.slot !== acceptor.slot) {
return fail(
"Mismatching entity on acceptor target:",
acceptor.slot,
"vs stored",
this.acceptorTarget.slot
);
}
if (this.acceptorTarget.direction !== acceptor.direction) {
return fail(
"Mismatching direction on acceptor target:",
acceptor.direction,
"vs stored",
this.acceptorTarget.direction
);
}
} }
// Check first nonzero offset // Check first nonzero offset
let firstNonzero = 0; let firstNonzero = 0;
for (let i = this.items.length - 2; i >= 0; --i) { for (let i = this.items.length - 2; i >= 0; --i) {
if (this.items[i][_nextDistance] < globalConfig.itemSpacingOnBelts + 1e-5) { if (this.items[i][0 /* nextDistance */] < globalConfig.itemSpacingOnBelts + 1e-5) {
++firstNonzero; ++firstNonzero;
} else { } else {
break; break;
@ -483,11 +548,11 @@ export class BeltPath extends BasicSerializableObject {
DEBUG && DEBUG &&
logger.log( logger.log(
" Extended spacing of last item from", " Extended spacing of last item from",
lastItem[_nextDistance], lastItem[0 /* nextDistance */],
"to", "to",
lastItem[_nextDistance] + additionalLength lastItem[0 /* nextDistance */] + additionalLength
); );
lastItem[_nextDistance] += additionalLength; lastItem[0 /* nextDistance */] += additionalLength;
} }
// Assign reference // Assign reference
@ -618,7 +683,7 @@ export class BeltPath extends BasicSerializableObject {
DEBUG && DEBUG &&
logger.log( logger.log(
"Old items are", "Old items are",
this.items.map(i => i[_nextDistance]) this.items.map(i => i[0 /* nextDistance */])
); );
// Create second path // Create second path
@ -628,7 +693,7 @@ export class BeltPath extends BasicSerializableObject {
let itemPos = this.spacingToFirstItem; let itemPos = this.spacingToFirstItem;
for (let i = 0; i < this.items.length; ++i) { for (let i = 0; i < this.items.length; ++i) {
const item = this.items[i]; const item = this.items[i];
const distanceToNext = item[_nextDistance]; const distanceToNext = item[0 /* nextDistance */];
DEBUG && logger.log(" Checking item at", itemPos, "with distance of", distanceToNext, "to next"); DEBUG && logger.log(" Checking item at", itemPos, "with distance of", distanceToNext, "to next");
@ -643,7 +708,7 @@ export class BeltPath extends BasicSerializableObject {
// Check if its on the second path (otherwise its on the removed belt and simply lost) // Check if its on the second path (otherwise its on the removed belt and simply lost)
if (itemPos >= secondPathStart) { if (itemPos >= secondPathStart) {
// Put item on second path // Put item on second path
secondPath.items.push([distanceToNext, item[_item]]); secondPath.items.push([distanceToNext, item[1 /* item */]]);
DEBUG && DEBUG &&
logger.log( logger.log(
" Put item to second path @", " Put item to second path @",
@ -672,7 +737,7 @@ export class BeltPath extends BasicSerializableObject {
"to", "to",
clampedDistanceToNext clampedDistanceToNext
); );
item[_nextDistance] = clampedDistanceToNext; item[0 /* nextDistance */] = clampedDistanceToNext;
} }
} }
@ -683,13 +748,13 @@ export class BeltPath extends BasicSerializableObject {
DEBUG && DEBUG &&
logger.log( logger.log(
"New items are", "New items are",
this.items.map(i => i[_nextDistance]) this.items.map(i => i[0 /* nextDistance */])
); );
DEBUG && DEBUG &&
logger.log( logger.log(
"And second path items are", "And second path items are",
secondPath.items.map(i => i[_nextDistance]) secondPath.items.map(i => i[0 /* nextDistance */])
); );
// Adjust our total length // Adjust our total length
@ -776,9 +841,17 @@ export class BeltPath extends BasicSerializableObject {
continue; continue;
} }
DEBUG && logger.log("Item", i, "is at", itemOffset, "with next offset", item[_nextDistance]); DEBUG &&
logger.log(
"Item",
i,
"is at",
itemOffset,
"with next offset",
item[0 /* nextDistance */]
);
lastItemOffset = itemOffset; lastItemOffset = itemOffset;
itemOffset += item[_nextDistance]; itemOffset += item[0 /* nextDistance */];
} }
// If we still have an item, make sure the last item matches // If we still have an item, make sure the last item matches
@ -805,7 +878,7 @@ export class BeltPath extends BasicSerializableObject {
this.totalLength, this.totalLength,
")" ")"
); );
this.items[this.items.length - 1][_nextDistance] = lastDistance; this.items[this.items.length - 1][0 /* nextDistance */] = lastDistance;
} else { } else {
DEBUG && logger.log(" Removed all items so we'll update spacing to total length"); DEBUG && logger.log(" Removed all items so we'll update spacing to total length");
@ -893,7 +966,7 @@ export class BeltPath extends BasicSerializableObject {
DEBUG && DEBUG &&
logger.log( logger.log(
" Items:", " Items:",
this.items.map(i => i[_nextDistance]) this.items.map(i => i[0 /* nextDistance */])
); );
// Find offset to first item // Find offset to first item
@ -912,7 +985,7 @@ export class BeltPath extends BasicSerializableObject {
// This item must be dropped // This item must be dropped
this.items.splice(i, 1); this.items.splice(i, 1);
i -= 1; i -= 1;
itemOffset += item[_nextDistance]; itemOffset += item[0 /* nextDistance */];
continue; continue;
} else { } else {
// This item can be kept, thus its the first we know // This item can be kept, thus its the first we know
@ -990,9 +1063,13 @@ export class BeltPath extends BasicSerializableObject {
// Now, update the distance of our last item // Now, update the distance of our last item
if (this.items.length !== 0) { if (this.items.length !== 0) {
const lastItem = this.items[this.items.length - 1]; const lastItem = this.items[this.items.length - 1];
lastItem[_nextDistance] += otherPath.spacingToFirstItem; lastItem[0 /* nextDistance */] += otherPath.spacingToFirstItem;
DEBUG && DEBUG &&
logger.log(" Add distance to last item, effectively being", lastItem[_nextDistance], "now"); logger.log(
" Add distance to last item, effectively being",
lastItem[0 /* nextDistance */],
"now"
);
} else { } else {
// Seems we have no items, update our first item distance // Seems we have no items, update our first item distance
this.spacingToFirstItem = oldLength + otherPath.spacingToFirstItem; this.spacingToFirstItem = oldLength + otherPath.spacingToFirstItem;
@ -1012,7 +1089,7 @@ export class BeltPath extends BasicSerializableObject {
// Aaand push the other paths items // Aaand push the other paths items
for (let i = 0; i < otherPath.items.length; ++i) { for (let i = 0; i < otherPath.items.length; ++i) {
const item = otherPath.items[i]; const item = otherPath.items[i];
this.items.push([item[_nextDistance], item[_item]]); this.items.push([item[0 /* nextDistance */], item[1 /* item */]]);
} }
// Update bounds // Update bounds
@ -1046,6 +1123,11 @@ export class BeltPath extends BasicSerializableObject {
this.debug_checkIntegrity("pre-update"); this.debug_checkIntegrity("pre-update");
} }
// Skip empty belts
if (this.items.length === 0) {
return;
}
// Divide by item spacing on belts since we use throughput and not speed // Divide by item spacing on belts since we use throughput and not speed
let beltSpeed = let beltSpeed =
this.root.hubGoals.getBeltBaseSpeed() * this.root.hubGoals.getBeltBaseSpeed() *
@ -1074,30 +1156,40 @@ export class BeltPath extends BasicSerializableObject {
lastItemProcessed === this.items.length - 1 ? 0 : globalConfig.itemSpacingOnBelts; lastItemProcessed === this.items.length - 1 ? 0 : globalConfig.itemSpacingOnBelts;
// Compute how much we can advance // Compute how much we can advance
const clampedProgress = Math.max( let clampedProgress = nextDistanceAndItem[0 /* nextDistance */] - minimumSpacing;
0,
Math.min(remainingVelocity, nextDistanceAndItem[_nextDistance] - minimumSpacing) // Make sure we don't advance more than the remaining velocity has stored
); if (remainingVelocity < clampedProgress) {
clampedProgress = remainingVelocity;
}
// Make sure we don't advance back
if (clampedProgress < 0) {
clampedProgress = 0;
}
// Reduce our velocity by the amount we consumed // Reduce our velocity by the amount we consumed
remainingVelocity -= clampedProgress; remainingVelocity -= clampedProgress;
// Reduce the spacing // Reduce the spacing
nextDistanceAndItem[_nextDistance] -= clampedProgress; nextDistanceAndItem[0 /* nextDistance */] -= clampedProgress;
// Advance all items behind by the progress we made // Advance all items behind by the progress we made
this.spacingToFirstItem += clampedProgress; this.spacingToFirstItem += clampedProgress;
// If the last item can be ejected, eject it and reduce the spacing, because otherwise // If the last item can be ejected, eject it and reduce the spacing, because otherwise
// we lose velocity // we lose velocity
if (isFirstItemProcessed && nextDistanceAndItem[_nextDistance] < 1e-7) { if (isFirstItemProcessed && nextDistanceAndItem[0 /* nextDistance */] < 1e-7) {
// Store how much velocity we "lost" because we bumped the item to the end of the // Store how much velocity we "lost" because we bumped the item to the end of the
// belt but couldn't move it any farther. We need this to tell the item acceptor // belt but couldn't move it any farther. We need this to tell the item acceptor
// animation to start a tad later, so everything matches up. Yes I'm a perfectionist. // animation to start a tad later, so everything matches up. Yes I'm a perfectionist.
const excessVelocity = beltSpeed - clampedProgress; const excessVelocity = beltSpeed - clampedProgress;
// Try to directly get rid of the item // Try to directly get rid of the item
if (this.tryHandOverItem(nextDistanceAndItem[_item], excessVelocity)) { if (
this.boundAcceptor &&
this.boundAcceptor(nextDistanceAndItem[1 /* item */], excessVelocity)
) {
this.items.pop(); this.items.pop();
const itemBehind = this.items[lastItemProcessed - 1]; const itemBehind = this.items[lastItemProcessed - 1];
@ -1108,11 +1200,11 @@ export class BeltPath extends BasicSerializableObject {
// Also see #999 // Also see #999
const fixupProgress = Math.max( const fixupProgress = Math.max(
0, 0,
Math.min(remainingVelocity, itemBehind[_nextDistance]) Math.min(remainingVelocity, itemBehind[0 /* nextDistance */])
); );
// See above // See above
itemBehind[_nextDistance] -= fixupProgress; itemBehind[0 /* nextDistance */] -= fixupProgress;
remainingVelocity -= fixupProgress; remainingVelocity -= fixupProgress;
this.spacingToFirstItem += fixupProgress; this.spacingToFirstItem += fixupProgress;
} }
@ -1145,8 +1237,8 @@ export class BeltPath extends BasicSerializableObject {
// Check if we have an item which is ready to be emitted // Check if we have an item which is ready to be emitted
const lastItem = this.items[this.items.length - 1]; const lastItem = this.items[this.items.length - 1];
if (lastItem && lastItem[_nextDistance] === 0 && this.acceptorTarget) { if (lastItem && lastItem[0 /* nextDistance */] === 0) {
if (this.tryHandOverItem(lastItem[_item])) { if (this.boundAcceptor && this.boundAcceptor(lastItem[1 /* item */])) {
this.items.pop(); this.items.pop();
this.numCompressedItemsAfterFirstItem = Math.max( this.numCompressedItemsAfterFirstItem = Math.max(
0, 0,
@ -1160,50 +1252,6 @@ export class BeltPath extends BasicSerializableObject {
} }
} }
/**
* Tries to hand over the item to the end entity
* @param {BaseItem} item
*/
tryHandOverItem(item, remainingProgress = 0.0) {
if (!this.acceptorTarget) {
return;
}
const targetAcceptorComp = this.acceptorTarget.entity.components.ItemAcceptor;
// Check if the acceptor has a filter for example
if (targetAcceptorComp && !targetAcceptorComp.canAcceptItem(this.acceptorTarget.slot, item)) {
// Well, this item is not accepted
return false;
}
// Try to pass over
if (
this.root.systemMgr.systems.itemEjector.tryPassOverItem(
item,
this.acceptorTarget.entity,
this.acceptorTarget.slot
)
) {
// Trigger animation on the acceptor comp
const targetAcceptorComp = this.acceptorTarget.entity.components.ItemAcceptor;
if (targetAcceptorComp) {
if (!this.root.app.settings.getAllSettings().simplifiedBelts) {
targetAcceptorComp.onItemAccepted(
this.acceptorTarget.slot,
this.acceptorTarget.direction,
item,
remainingProgress
);
}
}
return true;
}
return false;
}
/** /**
* Computes a world space position from the given progress * Computes a world space position from the given progress
* @param {number} progress * @param {number} progress
@ -1270,11 +1318,11 @@ export class BeltPath extends BasicSerializableObject {
parameters.context.font = "6px GameFont"; parameters.context.font = "6px GameFont";
parameters.context.fillStyle = "#111"; parameters.context.fillStyle = "#111";
parameters.context.fillText( parameters.context.fillText(
"" + round4Digits(nextDistanceAndItem[_nextDistance]), "" + round4Digits(nextDistanceAndItem[0 /* nextDistance */]),
worldPos.x + 5, worldPos.x + 5,
worldPos.y + 2 worldPos.y + 2
); );
progress += nextDistanceAndItem[_nextDistance]; progress += nextDistanceAndItem[0 /* nextDistance */];
if (this.items.length - 1 - this.numCompressedItemsAfterFirstItem === i) { if (this.items.length - 1 - this.numCompressedItemsAfterFirstItem === i) {
parameters.context.fillStyle = "red"; parameters.context.fillStyle = "red";
@ -1370,7 +1418,7 @@ export class BeltPath extends BasicSerializableObject {
const centerPos = staticComp.localTileToWorld(centerPosLocal).toWorldSpaceCenterOfTile(); const centerPos = staticComp.localTileToWorld(centerPosLocal).toWorldSpaceCenterOfTile();
parameters.context.globalAlpha = 0.5; parameters.context.globalAlpha = 0.5;
firstItem[_item].drawItemCenteredClipped(centerPos.x, centerPos.y, parameters); firstItem[1 /* item */].drawItemCenteredClipped(centerPos.x, centerPos.y, parameters);
parameters.context.globalAlpha = 1; parameters.context.globalAlpha = 1;
} }
@ -1402,7 +1450,7 @@ export class BeltPath extends BasicSerializableObject {
const distanceAndItem = this.items[currentItemIndex]; const distanceAndItem = this.items[currentItemIndex];
distanceAndItem[_item].drawItemCenteredClipped( distanceAndItem[1 /* item */].drawItemCenteredClipped(
worldPos.x, worldPos.x,
worldPos.y, worldPos.y,
parameters, parameters,
@ -1410,7 +1458,7 @@ export class BeltPath extends BasicSerializableObject {
); );
// Check for the next item // Check for the next item
currentItemPos += distanceAndItem[_nextDistance]; currentItemPos += distanceAndItem[0 /* nextDistance */];
++currentItemIndex; ++currentItemIndex;
if (currentItemIndex >= this.items.length) { if (currentItemIndex >= this.items.length) {

View File

@ -149,29 +149,31 @@ export class Blueprint {
*/ */
tryPlace(root, tile) { tryPlace(root, tile) {
return root.logic.performBulkOperation(() => { return root.logic.performBulkOperation(() => {
let count = 0; return root.logic.performImmutableOperation(() => {
for (let i = 0; i < this.entities.length; ++i) { let count = 0;
const entity = this.entities[i]; for (let i = 0; i < this.entities.length; ++i) {
if (!root.logic.checkCanPlaceEntity(entity, tile)) { const entity = this.entities[i];
continue; if (!root.logic.checkCanPlaceEntity(entity, tile)) {
continue;
}
const clone = entity.clone();
clone.components.StaticMapEntity.origin.addInplace(tile);
root.logic.freeEntityAreaBeforeBuild(clone);
root.map.placeStaticEntity(clone);
root.entityMgr.registerEntity(clone);
count++;
} }
const clone = entity.clone(); root.signals.bulkAchievementCheck.dispatch(
clone.components.StaticMapEntity.origin.addInplace(tile); ACHIEVEMENTS.placeBlueprint,
root.logic.freeEntityAreaBeforeBuild(clone); count,
root.map.placeStaticEntity(clone); ACHIEVEMENTS.placeBp1000,
root.entityMgr.registerEntity(clone); count
count++; );
}
root.signals.bulkAchievementCheck.dispatch( return count !== 0;
ACHIEVEMENTS.placeBlueprint, });
count,
ACHIEVEMENTS.placeBp1000,
count
);
return count !== 0;
}); });
} }
} }

View File

@ -66,6 +66,10 @@ export class MetaBalancerBuilding extends MetaBuilding {
* @returns {Array<[string, string]>} * @returns {Array<[string, string]>}
*/ */
getAdditionalStatistics(root, variant) { getAdditionalStatistics(root, variant) {
if (root.gameMode.throughputDoesNotMatter()) {
return [];
}
let speedMultiplier = 2; let speedMultiplier = 2;
switch (variant) { switch (variant) {
case enumBalancerVariants.merger: case enumBalancerVariants.merger:
@ -88,9 +92,11 @@ export class MetaBalancerBuilding extends MetaBuilding {
* @param {GameRoot} root * @param {GameRoot} root
*/ */
getAvailableVariants(root) { getAvailableVariants(root) {
let available = [defaultBuildingVariant]; const deterministic = root.gameMode.getIsDeterministic();
if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_merger)) { let available = deterministic ? [] : [defaultBuildingVariant];
if (!deterministic && root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_merger)) {
available.push(enumBalancerVariants.merger, enumBalancerVariants.mergerInverse); available.push(enumBalancerVariants.merger, enumBalancerVariants.mergerInverse);
} }

View File

@ -55,6 +55,9 @@ export class MetaBeltBuilding extends MetaBuilding {
* @returns {Array<[string, string]>} * @returns {Array<[string, string]>}
*/ */
getAdditionalStatistics(root, variant) { getAdditionalStatistics(root, variant) {
if (root.gameMode.throughputDoesNotMatter()) {
return [];
}
const beltSpeed = root.hubGoals.getBeltBaseSpeed(); const beltSpeed = root.hubGoals.getBeltBaseSpeed();
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(beltSpeed)]]; return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(beltSpeed)]];
} }

View File

@ -0,0 +1,30 @@
/* typehints:start */
import { Entity } from "../entity";
/* typehints:end */
import { MetaBuilding } from "../meta_building";
export class MetaBlockBuilding extends MetaBuilding {
constructor() {
super("block");
}
getSilhouetteColor() {
return "#333";
}
/**
*
* @param {import("../../savegame/savegame_serializer").GameRoot} root
* @returns
*/
getIsRemovable(root) {
return root.gameMode.getIsEditor();
}
/**
* Creates the entity at the given location
* @param {Entity} entity
*/
setupEntityComponents(entity) {}
}

View File

@ -0,0 +1,42 @@
/* typehints:start */
import { Entity } from "../entity";
/* typehints:end */
import { enumDirection, Vector } from "../../core/vector";
import { ConstantSignalComponent } from "../components/constant_signal";
import { ItemEjectorComponent } from "../components/item_ejector";
import { ItemProducerComponent } from "../components/item_producer";
import { MetaBuilding } from "../meta_building";
export class MetaConstantProducerBuilding extends MetaBuilding {
constructor() {
super("constant_producer");
}
getSilhouetteColor() {
return "#bfd630";
}
/**
*
* @param {import("../../savegame/savegame_serializer").GameRoot} root
* @returns
*/
getIsRemovable(root) {
return root.gameMode.getIsEditor();
}
/**
* Creates the entity at the given location
* @param {Entity} entity
*/
setupEntityComponents(entity) {
entity.addComponent(
new ItemEjectorComponent({
slots: [{ pos: new Vector(0, 0), direction: enumDirection.top }],
})
);
entity.addComponent(new ItemProducerComponent({}));
entity.addComponent(new ConstantSignalComponent({}));
}
}

View File

@ -38,6 +38,9 @@ export class MetaCutterBuilding extends MetaBuilding {
* @returns {Array<[string, string]>} * @returns {Array<[string, string]>}
*/ */
getAdditionalStatistics(root, variant) { getAdditionalStatistics(root, variant) {
if (root.gameMode.throughputDoesNotMatter()) {
return [];
}
const speed = root.hubGoals.getProcessorBaseSpeed( const speed = root.hubGoals.getProcessorBaseSpeed(
variant === enumCutterVariants.quad variant === enumCutterVariants.quad
? enumItemProcessorTypes.cutterQuad ? enumItemProcessorTypes.cutterQuad

View File

@ -40,6 +40,9 @@ export class MetaFilterBuilding extends MetaBuilding {
* @returns {Array<[string, string]>} * @returns {Array<[string, string]>}
*/ */
getAdditionalStatistics(root, variant) { getAdditionalStatistics(root, variant) {
if (root.gameMode.throughputDoesNotMatter()) {
return [];
}
const beltSpeed = root.hubGoals.getBeltBaseSpeed(); const beltSpeed = root.hubGoals.getBeltBaseSpeed();
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(beltSpeed)]]; return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(beltSpeed)]];
} }

View File

@ -0,0 +1,54 @@
/* typehints:start */
import { Entity } from "../entity";
/* typehints:end */
import { enumDirection, Vector } from "../../core/vector";
import { GoalAcceptorComponent } from "../components/goal_acceptor";
import { ItemAcceptorComponent } from "../components/item_acceptor";
import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor";
import { MetaBuilding } from "../meta_building";
export class MetaGoalAcceptorBuilding extends MetaBuilding {
constructor() {
super("goal_acceptor");
}
getSilhouetteColor() {
return "#ce418a";
}
/**
*
* @param {import("../../savegame/savegame_serializer").GameRoot} root
* @returns
*/
getIsRemovable(root) {
return root.gameMode.getIsEditor();
}
/**
* Creates the entity at the given location
* @param {Entity} entity
*/
setupEntityComponents(entity) {
entity.addComponent(
new ItemAcceptorComponent({
slots: [
{
pos: new Vector(0, 0),
directions: [enumDirection.bottom],
filter: "shape",
},
],
})
);
entity.addComponent(
new ItemProcessorComponent({
processorType: enumItemProcessorTypes.goal,
})
);
entity.addComponent(new GoalAcceptorComponent({}));
}
}

View File

@ -39,6 +39,6 @@ export class MetaItemProducerBuilding extends MetaBuilding {
], ],
}) })
); );
entity.addComponent(new ItemProducerComponent()); entity.addComponent(new ItemProducerComponent({}));
} }
} }

View File

@ -31,6 +31,9 @@ export class MetaMinerBuilding extends MetaBuilding {
* @returns {Array<[string, string]>} * @returns {Array<[string, string]>}
*/ */
getAdditionalStatistics(root, variant) { getAdditionalStatistics(root, variant) {
if (root.gameMode.throughputDoesNotMatter()) {
return [];
}
const speed = root.hubGoals.getMinerBaseSpeed(); const speed = root.hubGoals.getMinerBaseSpeed();
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]];
} }

Some files were not shown because too many files have changed in this diff Show More