Merge branch 'master' of https://github.com/tobspr/shapez.io
8
.editorconfig
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[{src, translations}/*]
|
||||||
|
end_of_line = crlf
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
charset = utf-8
|
||||||
18
.github/workflows/ci.yml
vendored
@ -35,19 +35,23 @@ jobs:
|
|||||||
cd gulp/
|
cd gulp/
|
||||||
yarn
|
yarn
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
- name: Lint
|
- name: Lint
|
||||||
run: |
|
run: |
|
||||||
yarn lint
|
yarn lint
|
||||||
|
|
||||||
- name: YAML Lint
|
|
||||||
uses: ibiqlik/action-yamllint@v1.0.0
|
|
||||||
with:
|
|
||||||
file_or_dir: translations/*.yaml
|
|
||||||
|
|
||||||
- name: TSLint
|
- name: TSLint
|
||||||
run: |
|
run: |
|
||||||
cd gulp
|
cd gulp
|
||||||
yarn gulp translations.fullBuild
|
yarn gulp translations.fullBuild
|
||||||
cd ..
|
cd ..
|
||||||
yarn tslint
|
yarn tslint
|
||||||
|
|
||||||
|
yaml-lint:
|
||||||
|
name: yaml-lint
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: YAML Lint
|
||||||
|
uses: ibiqlik/action-yamllint@v1.0.0
|
||||||
|
with:
|
||||||
|
file_or_dir: translations/*.yaml
|
||||||
|
|||||||
66
.gitignore
vendored
@ -15,34 +15,11 @@ pids
|
|||||||
*.seed
|
*.seed
|
||||||
*.pid.lock
|
*.pid.lock
|
||||||
|
|
||||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
|
||||||
lib-cov
|
|
||||||
|
|
||||||
# Coverage directory used by tools like istanbul
|
|
||||||
coverage
|
|
||||||
*.lcov
|
|
||||||
|
|
||||||
# nyc test coverage
|
|
||||||
.nyc_output
|
|
||||||
|
|
||||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
|
||||||
.grunt
|
|
||||||
|
|
||||||
# Bower dependency directory (https://bower.io/)
|
|
||||||
bower_components
|
|
||||||
|
|
||||||
# node-waf configuration
|
|
||||||
.lock-wscript
|
|
||||||
|
|
||||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
build/Release
|
build/Release
|
||||||
|
|
||||||
# Dependency directories
|
# Dependency directories
|
||||||
node_modules/
|
node_modules/
|
||||||
jspm_packages/
|
|
||||||
|
|
||||||
# TypeScript v1 declaration files
|
|
||||||
typings/
|
|
||||||
|
|
||||||
# TypeScript cache
|
# TypeScript cache
|
||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
@ -53,18 +30,9 @@ typings/
|
|||||||
# Optional eslint cache
|
# Optional eslint cache
|
||||||
.eslintcache
|
.eslintcache
|
||||||
|
|
||||||
# Microbundle cache
|
|
||||||
.rpt2_cache/
|
|
||||||
.rts2_cache_cjs/
|
|
||||||
.rts2_cache_es/
|
|
||||||
.rts2_cache_umd/
|
|
||||||
|
|
||||||
# Optional REPL history
|
# Optional REPL history
|
||||||
.node_repl_history
|
.node_repl_history
|
||||||
|
|
||||||
# Output of 'npm pack'
|
|
||||||
*.tgz
|
|
||||||
|
|
||||||
# Yarn Integrity file
|
# Yarn Integrity file
|
||||||
.yarn-integrity
|
.yarn-integrity
|
||||||
|
|
||||||
@ -72,41 +40,11 @@ typings/
|
|||||||
.env
|
.env
|
||||||
.env.test
|
.env.test
|
||||||
|
|
||||||
# parcel-bundler cache (https://parceljs.org/)
|
|
||||||
.cache
|
|
||||||
|
|
||||||
# Next.js build output
|
|
||||||
.next
|
|
||||||
|
|
||||||
# Nuxt.js build / generate output
|
|
||||||
.nuxt
|
|
||||||
dist
|
|
||||||
|
|
||||||
# Gatsby files
|
|
||||||
.cache/
|
|
||||||
# Comment in the public line in if your project uses Gatsby and *not* Next.js
|
|
||||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
|
||||||
# public
|
|
||||||
|
|
||||||
# vuepress build output
|
|
||||||
.vuepress/dist
|
|
||||||
|
|
||||||
# Serverless directories
|
|
||||||
.serverless/
|
|
||||||
|
|
||||||
# FuseBox cache
|
|
||||||
.fusebox/
|
|
||||||
|
|
||||||
# DynamoDB Local files
|
|
||||||
.dynamodb/
|
|
||||||
|
|
||||||
# TernJS port file
|
|
||||||
.tern-port
|
|
||||||
|
|
||||||
|
|
||||||
# Buildfiles
|
# Buildfiles
|
||||||
build
|
build
|
||||||
|
res_built
|
||||||
|
|
||||||
|
gulp/runnable-texturepacker.jar
|
||||||
tmp_standalone_files
|
tmp_standalone_files
|
||||||
|
|
||||||
# Local config
|
# Local config
|
||||||
|
|||||||
4
.gitpod.Dockerfile
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
FROM gitpod/workspace-full
|
||||||
|
|
||||||
|
RUN sudo apt-get update \
|
||||||
|
&& sudo apt install ffmpeg -yq
|
||||||
10
.gitpod.yml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
image:
|
||||||
|
file: .gitpod.Dockerfile
|
||||||
|
tasks:
|
||||||
|
- init: yarn && gp sync-done boot
|
||||||
|
- before: cd gulp
|
||||||
|
init: gp sync-await boot && yarn
|
||||||
|
command: yarn gulp
|
||||||
|
ports:
|
||||||
|
- port: 3005
|
||||||
|
onOpen: open-preview
|
||||||
4
.vscode/settings.json
vendored
@ -1,3 +1,5 @@
|
|||||||
{
|
{
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
|
"files.trimTrailingWhitespace": true,
|
||||||
|
"editor.formatOnSave": true
|
||||||
}
|
}
|
||||||
@ -4,3 +4,4 @@ rules:
|
|||||||
line-length:
|
line-length:
|
||||||
level: warning
|
level: warning
|
||||||
max: 200
|
max: 200
|
||||||
|
document-start: disable
|
||||||
|
|||||||
31
Dockerfile
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
FROM node:12 as base
|
||||||
|
|
||||||
|
EXPOSE 3001 3005
|
||||||
|
|
||||||
|
WORKDIR /shapez.io
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
ffmpeg default-jre \
|
||||||
|
&& apt-get clean \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
COPY package.json yarn.lock ./
|
||||||
|
RUN yarn
|
||||||
|
|
||||||
|
COPY gulp ./gulp
|
||||||
|
WORKDIR /shapez.io/gulp
|
||||||
|
RUN yarn
|
||||||
|
|
||||||
|
WORKDIR /shapez.io
|
||||||
|
COPY res ./res
|
||||||
|
COPY src/html ./src/html
|
||||||
|
COPY src/css ./src/css
|
||||||
|
COPY version ./version
|
||||||
|
COPY sync-translations.js ./
|
||||||
|
COPY translations ./translations
|
||||||
|
COPY src/js ./src/js
|
||||||
|
COPY res_raw ./res_raw
|
||||||
|
COPY .git ./.git
|
||||||
|
|
||||||
|
WORKDIR /shapez.io/gulp
|
||||||
|
ENTRYPOINT ["yarn", "gulp"]
|
||||||
15
README.md
@ -24,12 +24,23 @@ Your goal is to produce shapes by cutting, rotating, merging and painting parts
|
|||||||
|
|
||||||
- Make sure `ffmpeg` is on your path
|
- Make sure `ffmpeg` is on your path
|
||||||
- Install Node.js and Yarn
|
- Install Node.js and Yarn
|
||||||
|
- Install Java (required for textures)
|
||||||
- Run `yarn` in the root folder
|
- Run `yarn` in the root folder
|
||||||
- Cd into `gulp` folder
|
- Cd into `gulp` folder
|
||||||
- Run `yarn` and then `yarn gulp` - it should now open in your browser
|
- Run `yarn` and then `yarn gulp` - it should now open in your browser
|
||||||
|
|
||||||
**Notice**: This will produce a debug build with several debugging flags enabled. If you want to disable them, modify [`src/js/core/config.js`](src/js/core/config.js).
|
**Notice**: This will produce a debug build with several debugging flags enabled. If you want to disable them, modify [`src/js/core/config.js`](src/js/core/config.js).
|
||||||
|
|
||||||
|
## Build Online with one-click setup
|
||||||
|
|
||||||
|
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.
|
||||||
|
- install all of the dependencies.
|
||||||
|
- start `gulp` in `gulp/` directory.
|
||||||
|
|
||||||
|
[](https://gitpod.io/from-referrer/)
|
||||||
|
|
||||||
## Helping translate
|
## Helping translate
|
||||||
|
|
||||||
Please checkout the [Translations readme](translations/).
|
Please checkout the [Translations readme](translations/).
|
||||||
@ -114,8 +125,8 @@ This is a quick checklist, if a new building is added this points should be fulf
|
|||||||
|
|
||||||
### Assets
|
### Assets
|
||||||
|
|
||||||
For most assets I use Adobe Photoshop, you can find them in `assets/`.
|
For most assets I use Adobe Photoshop, you can find them <a href="//github.com/tobspr/shapez.io-artwork" target="_blank">here</a>.
|
||||||
|
|
||||||
You will need a <a href="https://www.codeandweb.com/texturepacker" target="_blank">Texture Packer</a> license in order to regenerate the atlas. If you don't have one but want to contribute assets, let me know and I might compile it for you. I'm currently switching to an open source solution but I can't give an estimate when that's done.
|
All assets will be automatically rebuilt into the atlas once changed (Thanks to dengr1065!)
|
||||||
|
|
||||||
<img src="https://i.imgur.com/W25Fkl0.png" alt="shapez.io Screenshot">
|
<img src="https://i.imgur.com/W25Fkl0.png" alt="shapez.io Screenshot">
|
||||||
|
|||||||
@ -1,3 +0,0 @@
|
|||||||
The artwork can be found here:
|
|
||||||
|
|
||||||
https://github.com/tobspr/shapez.io-artwork
|
|
||||||
@ -4,7 +4,7 @@ const { app, BrowserWindow, Menu, MenuItem, session } = require("electron");
|
|||||||
const path = require("path");
|
const path = require("path");
|
||||||
const url = require("url");
|
const url = require("url");
|
||||||
const childProcess = require("child_process");
|
const childProcess = require("child_process");
|
||||||
const { ipcMain } = require("electron");
|
const { ipcMain, shell } = require("electron");
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const isDev = process.argv.indexOf("--dev") >= 0;
|
const isDev = process.argv.indexOf("--dev") >= 0;
|
||||||
const isLocal = process.argv.indexOf("--local") >= 0;
|
const isLocal = process.argv.indexOf("--local") >= 0;
|
||||||
@ -67,11 +67,7 @@ function createWindow() {
|
|||||||
|
|
||||||
win.webContents.on("new-window", (event, pth) => {
|
win.webContents.on("new-window", (event, pth) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (process.platform == "win32") {
|
shell.openExternal(pth);
|
||||||
childProcess.execSync("start " + pth);
|
|
||||||
} else if (process.platform == "linux") {
|
|
||||||
childProcess.execSync("xdg-open " + pth);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
win.on("closed", () => {
|
win.on("closed", () => {
|
||||||
|
|||||||
127
gulp/atlas2json.js
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
const { join, resolve } = require("path");
|
||||||
|
const { readFileSync, readdirSync, writeFileSync } = require("fs");
|
||||||
|
|
||||||
|
const suffixToScale = {
|
||||||
|
lq: "0.25",
|
||||||
|
mq: "0.5",
|
||||||
|
hq: "0.75"
|
||||||
|
};
|
||||||
|
|
||||||
|
function convert(srcDir) {
|
||||||
|
const full = resolve(srcDir);
|
||||||
|
const srcFiles = readdirSync(full)
|
||||||
|
.filter(n => n.endsWith(".atlas"))
|
||||||
|
.map(n => join(full, n));
|
||||||
|
|
||||||
|
for (const atlas of srcFiles) {
|
||||||
|
console.log(`Processing: ${atlas}`);
|
||||||
|
|
||||||
|
// Read all text, split it into line array
|
||||||
|
// and filter all empty lines
|
||||||
|
const lines = readFileSync(atlas, "utf-8")
|
||||||
|
.split("\n")
|
||||||
|
.filter(n => n.trim());
|
||||||
|
|
||||||
|
// Get source image name
|
||||||
|
const image = lines.shift();
|
||||||
|
const srcMeta = {};
|
||||||
|
|
||||||
|
// Read all metadata (supports only one page)
|
||||||
|
while (true) {
|
||||||
|
const kv = lines.shift().split(":");
|
||||||
|
if (kv.length != 2) {
|
||||||
|
lines.unshift(kv[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
srcMeta[kv[0]] = kv[1].trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
const frames = {};
|
||||||
|
let current = null;
|
||||||
|
|
||||||
|
lines.push("Dummy line to make it convert last frame");
|
||||||
|
|
||||||
|
for (const line of lines) {
|
||||||
|
if (!line.startsWith(" ")) {
|
||||||
|
// New frame, convert previous if it exists
|
||||||
|
if (current != null) {
|
||||||
|
let { name, rotate, xy, size, orig, offset, index } = current;
|
||||||
|
|
||||||
|
// Convert to arrays because Node.js doesn't
|
||||||
|
// support latest JS features
|
||||||
|
xy = xy.split(",").map(v => Number(v));
|
||||||
|
size = size.split(",").map(v => Number(v));
|
||||||
|
orig = orig.split(",").map(v => Number(v));
|
||||||
|
offset = offset.split(",").map(v => Number(v));
|
||||||
|
|
||||||
|
// GDX TexturePacker removes index suffixes
|
||||||
|
const indexSuff = index != -1 ? `_${index}` : "";
|
||||||
|
const isTrimmed = size != orig;
|
||||||
|
|
||||||
|
frames[`${name}${indexSuff}.png`] = {
|
||||||
|
// Bounds on atlas
|
||||||
|
frame: {
|
||||||
|
x: xy[0],
|
||||||
|
y: xy[1],
|
||||||
|
w: size[0],
|
||||||
|
h: size[1]
|
||||||
|
},
|
||||||
|
|
||||||
|
// Whether image was rotated
|
||||||
|
rotated: rotate == "true",
|
||||||
|
trimmed: isTrimmed,
|
||||||
|
|
||||||
|
// How is the image trimmed
|
||||||
|
spriteSourceSize: {
|
||||||
|
x: offset[0],
|
||||||
|
y: (orig[1] - size[1]) - offset[1],
|
||||||
|
w: size[0],
|
||||||
|
h: size[1]
|
||||||
|
},
|
||||||
|
|
||||||
|
sourceSize: {
|
||||||
|
w: orig[0],
|
||||||
|
h: orig[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple object that will hold other metadata
|
||||||
|
current = {
|
||||||
|
name: line
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// Read and set current image metadata
|
||||||
|
const kv = line.split(":").map(v => v.trim());
|
||||||
|
current[kv[0]] = isNaN(Number(kv[1])) ? kv[1] : Number(kv[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const atlasSize = srcMeta.size.split(",").map(v => Number(v));
|
||||||
|
const atlasScale = suffixToScale[atlas.match(/_(\w+)\.atlas$/)[1]];
|
||||||
|
|
||||||
|
const result = JSON.stringify({
|
||||||
|
frames,
|
||||||
|
meta: {
|
||||||
|
image,
|
||||||
|
format: srcMeta.format,
|
||||||
|
size: {
|
||||||
|
w: atlasSize[0],
|
||||||
|
h: atlasSize[1]
|
||||||
|
},
|
||||||
|
scale: atlasScale.toString()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
writeFileSync(atlas.replace(".atlas", ".json"), result, {
|
||||||
|
encoding: "utf-8"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (require.main == module) {
|
||||||
|
convert(process.argv[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { convert };
|
||||||
@ -71,10 +71,6 @@ releaseUploader.gulptasksReleaseUploader($, gulp, buildFolder);
|
|||||||
const translations = require("./translations");
|
const translations = require("./translations");
|
||||||
translations.gulptasksTranslations($, gulp, buildFolder);
|
translations.gulptasksTranslations($, gulp, buildFolder);
|
||||||
|
|
||||||
// FIXME
|
|
||||||
// const cordova = require("./cordova");
|
|
||||||
// cordova.gulptasksCordova($, gulp, buildFolder);
|
|
||||||
|
|
||||||
///////////////////// BUILD TASKS /////////////////////
|
///////////////////// BUILD TASKS /////////////////////
|
||||||
|
|
||||||
// Cleans up everything
|
// Cleans up everything
|
||||||
@ -86,8 +82,16 @@ gulp.task("utils.cleanBuildTempFolder", () => {
|
|||||||
.src(path.join(__dirname, "..", "src", "js", "built-temp"), { read: false, allowEmpty: true })
|
.src(path.join(__dirname, "..", "src", "js", "built-temp"), { read: false, allowEmpty: true })
|
||||||
.pipe($.clean({ force: true }));
|
.pipe($.clean({ force: true }));
|
||||||
});
|
});
|
||||||
|
gulp.task("utils.cleanImageBuildFolder", () => {
|
||||||
|
return gulp
|
||||||
|
.src(path.join(__dirname, "res_built"), { read: false, allowEmpty: true })
|
||||||
|
.pipe($.clean({ force: true }));
|
||||||
|
});
|
||||||
|
|
||||||
gulp.task("utils.cleanup", gulp.series("utils.cleanBuildFolder", "utils.cleanBuildTempFolder"));
|
gulp.task(
|
||||||
|
"utils.cleanup",
|
||||||
|
gulp.series("utils.cleanBuildFolder", "utils.cleanImageBuildFolder", "utils.cleanBuildTempFolder")
|
||||||
|
);
|
||||||
|
|
||||||
// Requires no uncomitted files
|
// Requires no uncomitted files
|
||||||
gulp.task("utils.requireCleanWorkingTree", cb => {
|
gulp.task("utils.requireCleanWorkingTree", cb => {
|
||||||
@ -174,10 +178,12 @@ function serve({ standalone }) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Watch resource files and copy them on change
|
// Watch resource files and copy them on change
|
||||||
|
gulp.watch(imgres.rawImageResourcesGlobs, gulp.series("imgres.buildAtlas"));
|
||||||
gulp.watch(imgres.nonImageResourcesGlobs, gulp.series("imgres.copyNonImageResources"));
|
gulp.watch(imgres.nonImageResourcesGlobs, gulp.series("imgres.copyNonImageResources"));
|
||||||
gulp.watch(imgres.imageResourcesGlobs, gulp.series("imgres.copyImageResources"));
|
gulp.watch(imgres.imageResourcesGlobs, gulp.series("imgres.copyImageResources"));
|
||||||
|
|
||||||
// Watch .atlas files and recompile the atlas on change
|
// Watch .atlas files and recompile the atlas on change
|
||||||
|
gulp.watch("../res_built/atlas/*.atlas", gulp.series("imgres.atlasToJson"));
|
||||||
gulp.watch("../res_built/atlas/*.json", gulp.series("imgres.atlas"));
|
gulp.watch("../res_built/atlas/*.json", gulp.series("imgres.atlas"));
|
||||||
|
|
||||||
// Watch the build folder and reload when anything changed
|
// Watch the build folder and reload when anything changed
|
||||||
@ -215,6 +221,8 @@ gulp.task(
|
|||||||
gulp.series(
|
gulp.series(
|
||||||
"utils.cleanup",
|
"utils.cleanup",
|
||||||
"utils.copyAdditionalBuildFiles",
|
"utils.copyAdditionalBuildFiles",
|
||||||
|
"imgres.buildAtlas",
|
||||||
|
"imgres.atlasToJson",
|
||||||
"imgres.atlas",
|
"imgres.atlas",
|
||||||
"sounds.dev",
|
"sounds.dev",
|
||||||
"imgres.copyImageResources",
|
"imgres.copyImageResources",
|
||||||
@ -230,12 +238,13 @@ gulp.task(
|
|||||||
"build.standalone.dev",
|
"build.standalone.dev",
|
||||||
gulp.series(
|
gulp.series(
|
||||||
"utils.cleanup",
|
"utils.cleanup",
|
||||||
|
"imgres.buildAtlas",
|
||||||
|
"imgres.atlasToJson",
|
||||||
"imgres.atlas",
|
"imgres.atlas",
|
||||||
"sounds.dev",
|
"sounds.dev",
|
||||||
"imgres.copyImageResources",
|
"imgres.copyImageResources",
|
||||||
"imgres.copyNonImageResources",
|
"imgres.copyNonImageResources",
|
||||||
"translations.fullBuild",
|
"translations.fullBuild",
|
||||||
"js.standalone-dev",
|
|
||||||
"css.dev",
|
"css.dev",
|
||||||
"html.standalone-dev"
|
"html.standalone-dev"
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,5 +1,15 @@
|
|||||||
|
const { existsSync } = require("fs");
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
|
const atlasToJson = require("./atlas2json");
|
||||||
|
|
||||||
|
const execute = command =>
|
||||||
|
require("child_process").execSync(command, {
|
||||||
|
encoding: "utf-8",
|
||||||
|
});
|
||||||
|
|
||||||
|
// Globs for atlas resources
|
||||||
|
const rawImageResourcesGlobs = ["../res_raw/atlas.json", "../res_raw/**/*.png"];
|
||||||
|
|
||||||
// Globs for non-ui resources
|
// Globs for non-ui resources
|
||||||
const nonImageResourcesGlobs = ["../res/**/*.woff2", "../res/*.ico", "../res/**/*.webm"];
|
const nonImageResourcesGlobs = ["../res/**/*.woff2", "../res/*.ico", "../res/**/*.webm"];
|
||||||
@ -7,6 +17,9 @@ const nonImageResourcesGlobs = ["../res/**/*.woff2", "../res/*.ico", "../res/**/
|
|||||||
// Globs for ui resources
|
// Globs for ui resources
|
||||||
const imageResourcesGlobs = ["../res/**/*.png", "../res/**/*.svg", "../res/**/*.jpg", "../res/**/*.gif"];
|
const imageResourcesGlobs = ["../res/**/*.png", "../res/**/*.svg", "../res/**/*.jpg", "../res/**/*.gif"];
|
||||||
|
|
||||||
|
// Link to download LibGDX runnable-texturepacker.jar
|
||||||
|
const runnableTPSource = "https://libgdx.badlogicgames.com/ci/nightlies/runnables/runnable-texturepacker.jar";
|
||||||
|
|
||||||
function gulptasksImageResources($, gulp, buildFolder) {
|
function gulptasksImageResources($, gulp, buildFolder) {
|
||||||
// Lossless options
|
// Lossless options
|
||||||
const minifyImagesOptsLossless = () => [
|
const minifyImagesOptsLossless = () => [
|
||||||
@ -59,6 +72,54 @@ function gulptasksImageResources($, gulp, buildFolder) {
|
|||||||
|
|
||||||
/////////////// ATLAS /////////////////////
|
/////////////// ATLAS /////////////////////
|
||||||
|
|
||||||
|
gulp.task("imgres.buildAtlas", cb => {
|
||||||
|
const config = JSON.stringify("../res_raw/atlas.json");
|
||||||
|
const source = JSON.stringify("../res_raw");
|
||||||
|
const dest = JSON.stringify("../res_built/atlas");
|
||||||
|
|
||||||
|
try {
|
||||||
|
// First check whether Java is installed
|
||||||
|
execute("java -version");
|
||||||
|
// Now check and try downloading runnable-texturepacker.jar (22MB)
|
||||||
|
if (!existsSync("./runnable-texturepacker.jar")) {
|
||||||
|
const safeLink = JSON.stringify(runnableTPSource);
|
||||||
|
const commands = [
|
||||||
|
// linux/macos if installed
|
||||||
|
`wget -O runnable-texturepacker.jar ${safeLink}`,
|
||||||
|
// linux/macos, latest windows 10
|
||||||
|
`curl -o runnable-texturepacker.jar ${safeLink}`,
|
||||||
|
// windows 10 / updated windows 7+
|
||||||
|
"powershell.exe -Command (new-object System.Net.WebClient)" +
|
||||||
|
`.DownloadFile(${safeLink.replace(/"/g, "'")}, 'runnable-texturepacker.jar')`,
|
||||||
|
// windows 7+, vulnerability exploit
|
||||||
|
`certutil.exe -urlcache -split -f ${safeLink} runnable-texturepacker.jar`,
|
||||||
|
];
|
||||||
|
|
||||||
|
while (commands.length) {
|
||||||
|
try {
|
||||||
|
execute(commands.shift());
|
||||||
|
break;
|
||||||
|
} catch {
|
||||||
|
if (!commands.length) {
|
||||||
|
throw new Error("Failed to download runnable-texturepacker.jar!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
execute(`java -jar runnable-texturepacker.jar ${source} ${dest} atlas0 ${config}`);
|
||||||
|
} catch {
|
||||||
|
console.warn("Building atlas failed. Java not found / unsupported version?");
|
||||||
|
}
|
||||||
|
cb();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Converts .atlas LibGDX files to JSON
|
||||||
|
gulp.task("imgres.atlasToJson", cb => {
|
||||||
|
atlasToJson.convert("../res_built/atlas");
|
||||||
|
cb();
|
||||||
|
});
|
||||||
|
|
||||||
// Copies the atlas to the final destination
|
// Copies the atlas to the final destination
|
||||||
gulp.task("imgres.atlas", () => {
|
gulp.task("imgres.atlas", () => {
|
||||||
return gulp.src(["../res_built/atlas/*.png"]).pipe(gulp.dest(resourcesDestFolder));
|
return gulp.src(["../res_built/atlas/*.png"]).pipe(gulp.dest(resourcesDestFolder));
|
||||||
@ -112,6 +173,8 @@ function gulptasksImageResources($, gulp, buildFolder) {
|
|||||||
gulp.task(
|
gulp.task(
|
||||||
"imgres.allOptimized",
|
"imgres.allOptimized",
|
||||||
gulp.parallel(
|
gulp.parallel(
|
||||||
|
"imgres.buildAtlas",
|
||||||
|
"imgres.atlasToJson",
|
||||||
"imgres.atlasOptimized",
|
"imgres.atlasOptimized",
|
||||||
"imgres.copyNonImageResources",
|
"imgres.copyNonImageResources",
|
||||||
"imgres.copyImageResourcesOptimized"
|
"imgres.copyImageResourcesOptimized"
|
||||||
@ -135,6 +198,7 @@ function gulptasksImageResources($, gulp, buildFolder) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
rawImageResourcesGlobs,
|
||||||
nonImageResourcesGlobs,
|
nonImageResourcesGlobs,
|
||||||
imageResourcesGlobs,
|
imageResourcesGlobs,
|
||||||
gulptasksImageResources,
|
gulptasksImageResources,
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
"@types/node": "^12.7.5",
|
"@types/node": "^12.7.5",
|
||||||
"ajv": "^6.10.2",
|
"ajv": "^6.10.2",
|
||||||
"audiosprite": "^0.7.2",
|
"audiosprite": "^0.7.2",
|
||||||
|
"babel-core": "^6.26.3",
|
||||||
"babel-loader": "^8.1.0",
|
"babel-loader": "^8.1.0",
|
||||||
"browser-sync": "^2.26.10",
|
"browser-sync": "^2.26.10",
|
||||||
"circular-dependency-plugin": "^5.0.2",
|
"circular-dependency-plugin": "^5.0.2",
|
||||||
@ -45,6 +46,7 @@
|
|||||||
"query-string": "^6.8.1",
|
"query-string": "^6.8.1",
|
||||||
"rusha": "^0.8.13",
|
"rusha": "^0.8.13",
|
||||||
"serialize-error": "^3.0.0",
|
"serialize-error": "^3.0.0",
|
||||||
|
"stream-browserify": "^3.0.0",
|
||||||
"strictdom": "^1.0.1",
|
"strictdom": "^1.0.1",
|
||||||
"string-replace-webpack-plugin": "^0.1.3",
|
"string-replace-webpack-plugin": "^0.1.3",
|
||||||
"strip-indent": "^3.0.0",
|
"strip-indent": "^3.0.0",
|
||||||
|
|||||||
233
gulp/yarn.lock
@ -1923,6 +1923,62 @@ axios@0.19.0:
|
|||||||
follow-redirects "1.5.10"
|
follow-redirects "1.5.10"
|
||||||
is-buffer "^2.0.2"
|
is-buffer "^2.0.2"
|
||||||
|
|
||||||
|
babel-code-frame@^6.26.0:
|
||||||
|
version "6.26.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
|
||||||
|
integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=
|
||||||
|
dependencies:
|
||||||
|
chalk "^1.1.3"
|
||||||
|
esutils "^2.0.2"
|
||||||
|
js-tokens "^3.0.2"
|
||||||
|
|
||||||
|
babel-core@^6.26.0, babel-core@^6.26.3:
|
||||||
|
version "6.26.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207"
|
||||||
|
integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==
|
||||||
|
dependencies:
|
||||||
|
babel-code-frame "^6.26.0"
|
||||||
|
babel-generator "^6.26.0"
|
||||||
|
babel-helpers "^6.24.1"
|
||||||
|
babel-messages "^6.23.0"
|
||||||
|
babel-register "^6.26.0"
|
||||||
|
babel-runtime "^6.26.0"
|
||||||
|
babel-template "^6.26.0"
|
||||||
|
babel-traverse "^6.26.0"
|
||||||
|
babel-types "^6.26.0"
|
||||||
|
babylon "^6.18.0"
|
||||||
|
convert-source-map "^1.5.1"
|
||||||
|
debug "^2.6.9"
|
||||||
|
json5 "^0.5.1"
|
||||||
|
lodash "^4.17.4"
|
||||||
|
minimatch "^3.0.4"
|
||||||
|
path-is-absolute "^1.0.1"
|
||||||
|
private "^0.1.8"
|
||||||
|
slash "^1.0.0"
|
||||||
|
source-map "^0.5.7"
|
||||||
|
|
||||||
|
babel-generator@^6.26.0:
|
||||||
|
version "6.26.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90"
|
||||||
|
integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==
|
||||||
|
dependencies:
|
||||||
|
babel-messages "^6.23.0"
|
||||||
|
babel-runtime "^6.26.0"
|
||||||
|
babel-types "^6.26.0"
|
||||||
|
detect-indent "^4.0.0"
|
||||||
|
jsesc "^1.3.0"
|
||||||
|
lodash "^4.17.4"
|
||||||
|
source-map "^0.5.7"
|
||||||
|
trim-right "^1.0.1"
|
||||||
|
|
||||||
|
babel-helpers@^6.24.1:
|
||||||
|
version "6.24.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2"
|
||||||
|
integrity sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=
|
||||||
|
dependencies:
|
||||||
|
babel-runtime "^6.22.0"
|
||||||
|
babel-template "^6.24.1"
|
||||||
|
|
||||||
babel-loader@^8.1.0:
|
babel-loader@^8.1.0:
|
||||||
version "8.1.0"
|
version "8.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.1.0.tgz#c611d5112bd5209abe8b9fa84c3e4da25275f1c3"
|
resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.1.0.tgz#c611d5112bd5209abe8b9fa84c3e4da25275f1c3"
|
||||||
@ -1934,6 +1990,13 @@ babel-loader@^8.1.0:
|
|||||||
pify "^4.0.1"
|
pify "^4.0.1"
|
||||||
schema-utils "^2.6.5"
|
schema-utils "^2.6.5"
|
||||||
|
|
||||||
|
babel-messages@^6.23.0:
|
||||||
|
version "6.23.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e"
|
||||||
|
integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=
|
||||||
|
dependencies:
|
||||||
|
babel-runtime "^6.22.0"
|
||||||
|
|
||||||
babel-plugin-closure-elimination@^1.3.0:
|
babel-plugin-closure-elimination@^1.3.0:
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/babel-plugin-closure-elimination/-/babel-plugin-closure-elimination-1.3.0.tgz#3217fbf6d416dfdf14ff41a8a34e4d0a6bfc22b2"
|
resolved "https://registry.yarnpkg.com/babel-plugin-closure-elimination/-/babel-plugin-closure-elimination-1.3.0.tgz#3217fbf6d416dfdf14ff41a8a34e4d0a6bfc22b2"
|
||||||
@ -1956,6 +2019,27 @@ babel-plugin-dynamic-import-node@^2.3.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
object.assign "^4.1.0"
|
object.assign "^4.1.0"
|
||||||
|
|
||||||
|
babel-register@^6.26.0:
|
||||||
|
version "6.26.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071"
|
||||||
|
integrity sha1-btAhFz4vy0htestFxgCahW9kcHE=
|
||||||
|
dependencies:
|
||||||
|
babel-core "^6.26.0"
|
||||||
|
babel-runtime "^6.26.0"
|
||||||
|
core-js "^2.5.0"
|
||||||
|
home-or-tmp "^2.0.0"
|
||||||
|
lodash "^4.17.4"
|
||||||
|
mkdirp "^0.5.1"
|
||||||
|
source-map-support "^0.4.15"
|
||||||
|
|
||||||
|
babel-runtime@^6.22.0, babel-runtime@^6.26.0:
|
||||||
|
version "6.26.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
|
||||||
|
integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4=
|
||||||
|
dependencies:
|
||||||
|
core-js "^2.4.0"
|
||||||
|
regenerator-runtime "^0.11.0"
|
||||||
|
|
||||||
babel-runtime@^7.0.0-beta.3:
|
babel-runtime@^7.0.0-beta.3:
|
||||||
version "7.0.0-beta.3"
|
version "7.0.0-beta.3"
|
||||||
resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-7.0.0-beta.3.tgz#7c750de5514452c27612172506b49085a4a630f2"
|
resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-7.0.0-beta.3.tgz#7c750de5514452c27612172506b49085a4a630f2"
|
||||||
@ -1964,6 +2048,47 @@ babel-runtime@^7.0.0-beta.3:
|
|||||||
core-js "^2.4.0"
|
core-js "^2.4.0"
|
||||||
regenerator-runtime "^0.11.0"
|
regenerator-runtime "^0.11.0"
|
||||||
|
|
||||||
|
babel-template@^6.24.1, babel-template@^6.26.0:
|
||||||
|
version "6.26.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02"
|
||||||
|
integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=
|
||||||
|
dependencies:
|
||||||
|
babel-runtime "^6.26.0"
|
||||||
|
babel-traverse "^6.26.0"
|
||||||
|
babel-types "^6.26.0"
|
||||||
|
babylon "^6.18.0"
|
||||||
|
lodash "^4.17.4"
|
||||||
|
|
||||||
|
babel-traverse@^6.26.0:
|
||||||
|
version "6.26.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee"
|
||||||
|
integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=
|
||||||
|
dependencies:
|
||||||
|
babel-code-frame "^6.26.0"
|
||||||
|
babel-messages "^6.23.0"
|
||||||
|
babel-runtime "^6.26.0"
|
||||||
|
babel-types "^6.26.0"
|
||||||
|
babylon "^6.18.0"
|
||||||
|
debug "^2.6.8"
|
||||||
|
globals "^9.18.0"
|
||||||
|
invariant "^2.2.2"
|
||||||
|
lodash "^4.17.4"
|
||||||
|
|
||||||
|
babel-types@^6.26.0:
|
||||||
|
version "6.26.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497"
|
||||||
|
integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=
|
||||||
|
dependencies:
|
||||||
|
babel-runtime "^6.26.0"
|
||||||
|
esutils "^2.0.2"
|
||||||
|
lodash "^4.17.4"
|
||||||
|
to-fast-properties "^1.0.3"
|
||||||
|
|
||||||
|
babylon@^6.18.0:
|
||||||
|
version "6.18.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
|
||||||
|
integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==
|
||||||
|
|
||||||
bach@^1.0.0:
|
bach@^1.0.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/bach/-/bach-1.2.0.tgz#4b3ce96bf27134f79a1b414a51c14e34c3bd9880"
|
resolved "https://registry.yarnpkg.com/bach/-/bach-1.2.0.tgz#4b3ce96bf27134f79a1b414a51c14e34c3bd9880"
|
||||||
@ -2965,6 +3090,11 @@ color@^3.0.0:
|
|||||||
color-convert "^1.9.1"
|
color-convert "^1.9.1"
|
||||||
color-string "^1.5.2"
|
color-string "^1.5.2"
|
||||||
|
|
||||||
|
colorette@^1.2.1:
|
||||||
|
version "1.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b"
|
||||||
|
integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==
|
||||||
|
|
||||||
colors@1.0.x:
|
colors@1.0.x:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b"
|
resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b"
|
||||||
@ -3135,7 +3265,7 @@ content-disposition@^0.5.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
safe-buffer "5.1.2"
|
safe-buffer "5.1.2"
|
||||||
|
|
||||||
convert-source-map@^1.5.0, convert-source-map@^1.7.0:
|
convert-source-map@^1.5.0, convert-source-map@^1.5.1, convert-source-map@^1.7.0:
|
||||||
version "1.7.0"
|
version "1.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
|
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
|
||||||
integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==
|
integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==
|
||||||
@ -3190,6 +3320,11 @@ core-js@^2.4.0, core-js@^2.5.7:
|
|||||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2"
|
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2"
|
||||||
integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==
|
integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==
|
||||||
|
|
||||||
|
core-js@^2.5.0:
|
||||||
|
version "2.6.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c"
|
||||||
|
integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==
|
||||||
|
|
||||||
core-util-is@1.0.2, core-util-is@~1.0.0:
|
core-util-is@1.0.2, core-util-is@~1.0.0:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||||
@ -3581,7 +3716,7 @@ dateformat@^2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062"
|
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062"
|
||||||
integrity sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=
|
integrity sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=
|
||||||
|
|
||||||
debug@2.6.9, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8:
|
debug@2.6.9, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
|
||||||
version "2.6.9"
|
version "2.6.9"
|
||||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||||
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
|
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
|
||||||
@ -3808,6 +3943,13 @@ detect-file@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7"
|
resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7"
|
||||||
integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=
|
integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=
|
||||||
|
|
||||||
|
detect-indent@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208"
|
||||||
|
integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg=
|
||||||
|
dependencies:
|
||||||
|
repeating "^2.0.0"
|
||||||
|
|
||||||
detect-libc@^1.0.2:
|
detect-libc@^1.0.2:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
|
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
|
||||||
@ -5607,7 +5749,7 @@ globals@^11.1.0, globals@^11.7.0:
|
|||||||
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
|
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
|
||||||
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
|
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
|
||||||
|
|
||||||
globals@^9.2.0:
|
globals@^9.18.0, globals@^9.2.0:
|
||||||
version "9.18.0"
|
version "9.18.0"
|
||||||
resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
|
resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
|
||||||
integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==
|
integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==
|
||||||
@ -6265,6 +6407,14 @@ hmac-drbg@^1.0.0:
|
|||||||
minimalistic-assert "^1.0.0"
|
minimalistic-assert "^1.0.0"
|
||||||
minimalistic-crypto-utils "^1.0.1"
|
minimalistic-crypto-utils "^1.0.1"
|
||||||
|
|
||||||
|
home-or-tmp@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8"
|
||||||
|
integrity sha1-42w/LSyufXRqhX440Y1fMqeILbg=
|
||||||
|
dependencies:
|
||||||
|
os-homedir "^1.0.0"
|
||||||
|
os-tmpdir "^1.0.1"
|
||||||
|
|
||||||
homedir-polyfill@^1.0.1:
|
homedir-polyfill@^1.0.1:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8"
|
resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8"
|
||||||
@ -6602,7 +6752,7 @@ inherits@1:
|
|||||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-1.0.2.tgz#ca4309dadee6b54cc0b8d247e8d7c7a0975bdc9b"
|
resolved "https://registry.yarnpkg.com/inherits/-/inherits-1.0.2.tgz#ca4309dadee6b54cc0b8d247e8d7c7a0975bdc9b"
|
||||||
integrity sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=
|
integrity sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=
|
||||||
|
|
||||||
inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
|
inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4:
|
||||||
version "2.0.4"
|
version "2.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||||
@ -7172,6 +7322,11 @@ js-levenshtein@^1.1.3:
|
|||||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||||
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
||||||
|
|
||||||
|
js-tokens@^3.0.2:
|
||||||
|
version "3.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
|
||||||
|
integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls=
|
||||||
|
|
||||||
js-yaml@^3.13.0, js-yaml@^3.13.1, js-yaml@^3.4.6, js-yaml@^3.5.1, js-yaml@^3.5.4:
|
js-yaml@^3.13.0, js-yaml@^3.13.1, js-yaml@^3.4.6, js-yaml@^3.5.1, js-yaml@^3.5.4:
|
||||||
version "3.13.1"
|
version "3.13.1"
|
||||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
|
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
|
||||||
@ -7216,6 +7371,11 @@ jsdom@12.2.0:
|
|||||||
ws "^6.1.0"
|
ws "^6.1.0"
|
||||||
xml-name-validator "^3.0.0"
|
xml-name-validator "^3.0.0"
|
||||||
|
|
||||||
|
jsesc@^1.3.0:
|
||||||
|
version "1.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
|
||||||
|
integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s=
|
||||||
|
|
||||||
jsesc@^2.5.1:
|
jsesc@^2.5.1:
|
||||||
version "2.5.2"
|
version "2.5.2"
|
||||||
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
|
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
|
||||||
@ -7263,7 +7423,7 @@ json-stringify-safe@~5.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
|
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
|
||||||
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
|
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
|
||||||
|
|
||||||
json5@^0.5.0:
|
json5@^0.5.0, json5@^0.5.1:
|
||||||
version "0.5.1"
|
version "0.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
|
resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
|
||||||
integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=
|
integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=
|
||||||
@ -7463,6 +7623,14 @@ limiter@^1.0.5:
|
|||||||
resolved "https://registry.yarnpkg.com/limiter/-/limiter-1.1.4.tgz#87c9c3972d389fdb0ba67a45aadbc5d2f8413bc1"
|
resolved "https://registry.yarnpkg.com/limiter/-/limiter-1.1.4.tgz#87c9c3972d389fdb0ba67a45aadbc5d2f8413bc1"
|
||||||
integrity sha512-XCpr5bElgDI65vVgstP8TWjv6/QKWm9GU5UG0Pr5sLQ3QLo8NVKsioe+Jed5/3vFOe3IQuqE7DKwTvKQkjTHvg==
|
integrity sha512-XCpr5bElgDI65vVgstP8TWjv6/QKWm9GU5UG0Pr5sLQ3QLo8NVKsioe+Jed5/3vFOe3IQuqE7DKwTvKQkjTHvg==
|
||||||
|
|
||||||
|
line-column@^1.0.2:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/line-column/-/line-column-1.0.2.tgz#d25af2936b6f4849172b312e4792d1d987bc34a2"
|
||||||
|
integrity sha1-0lryk2tvSEkXKzEuR5LR2Ye8NKI=
|
||||||
|
dependencies:
|
||||||
|
isarray "^1.0.0"
|
||||||
|
isobject "^2.0.0"
|
||||||
|
|
||||||
load-bmfont@^1.3.1, load-bmfont@^1.4.0:
|
load-bmfont@^1.3.1, load-bmfont@^1.4.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/load-bmfont/-/load-bmfont-1.4.0.tgz#75f17070b14a8c785fe7f5bee2e6fd4f98093b6b"
|
resolved "https://registry.yarnpkg.com/load-bmfont/-/load-bmfont-1.4.0.tgz#75f17070b14a8c785fe7f5bee2e6fd4f98093b6b"
|
||||||
@ -7851,6 +8019,11 @@ lodash@^4.0.0, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12
|
|||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
||||||
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
||||||
|
|
||||||
|
lodash@^4.17.4:
|
||||||
|
version "4.17.20"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
|
||||||
|
integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
|
||||||
|
|
||||||
lodash@~1.0.1:
|
lodash@~1.0.1:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-1.0.2.tgz#8f57560c83b59fc270bd3d561b690043430e2551"
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-1.0.2.tgz#8f57560c83b59fc270bd3d561b690043430e2551"
|
||||||
@ -8404,6 +8577,11 @@ nan@^2.12.1, nan@^2.13.2:
|
|||||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
|
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
|
||||||
integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
|
integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
|
||||||
|
|
||||||
|
nanoid@^3.1.12:
|
||||||
|
version "3.1.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.12.tgz#6f7736c62e8d39421601e4a0c77623a97ea69654"
|
||||||
|
integrity sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==
|
||||||
|
|
||||||
nanomatch@^1.2.9:
|
nanomatch@^1.2.9:
|
||||||
version "1.2.13"
|
version "1.2.13"
|
||||||
resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
|
resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
|
||||||
@ -8982,7 +9160,7 @@ os-locale@^3.1.0:
|
|||||||
lcid "^2.0.0"
|
lcid "^2.0.0"
|
||||||
mem "^4.0.0"
|
mem "^4.0.0"
|
||||||
|
|
||||||
os-tmpdir@^1.0.0, os-tmpdir@~1.0.2:
|
os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
|
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
|
||||||
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
|
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
|
||||||
@ -9304,7 +9482,7 @@ path-exists@^4.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
|
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
|
||||||
integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
|
integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
|
||||||
|
|
||||||
path-is-absolute@^1.0.0:
|
path-is-absolute@^1.0.0, path-is-absolute@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||||
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
|
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
|
||||||
@ -10212,6 +10390,16 @@ postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2
|
|||||||
source-map "^0.6.1"
|
source-map "^0.6.1"
|
||||||
supports-color "^6.1.0"
|
supports-color "^6.1.0"
|
||||||
|
|
||||||
|
postcss@^8.1.1:
|
||||||
|
version "8.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.1.1.tgz#c3a287dd10e4f6c84cb3791052b96a5d859c9389"
|
||||||
|
integrity sha512-9DGLSsjooH3kSNjTZUOt2eIj2ZTW0VI2PZ/3My+8TC7KIbH2OKwUlISfDsf63EP4aiRUt3XkEWMWvyJHvJelEg==
|
||||||
|
dependencies:
|
||||||
|
colorette "^1.2.1"
|
||||||
|
line-column "^1.0.2"
|
||||||
|
nanoid "^3.1.12"
|
||||||
|
source-map "^0.6.1"
|
||||||
|
|
||||||
prelude-ls@~1.1.2:
|
prelude-ls@~1.1.2:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
|
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
|
||||||
@ -10242,7 +10430,7 @@ pretty-hrtime@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1"
|
resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1"
|
||||||
integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=
|
integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=
|
||||||
|
|
||||||
private@^0.1.6, private@~0.1.5:
|
private@^0.1.6, private@^0.1.8, private@~0.1.5:
|
||||||
version "0.1.8"
|
version "0.1.8"
|
||||||
resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
|
resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
|
||||||
integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==
|
integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==
|
||||||
@ -10573,7 +10761,7 @@ readable-stream@^1.0.27-1, readable-stream@~1.1.9:
|
|||||||
isarray "0.0.1"
|
isarray "0.0.1"
|
||||||
string_decoder "~0.10.x"
|
string_decoder "~0.10.x"
|
||||||
|
|
||||||
readable-stream@^3.0.2, readable-stream@^3.1.1:
|
readable-stream@^3.0.2, readable-stream@^3.1.1, readable-stream@^3.5.0:
|
||||||
version "3.6.0"
|
version "3.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
|
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
|
||||||
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
|
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
|
||||||
@ -11372,6 +11560,11 @@ simple-swizzle@^0.2.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-arrayish "^0.3.1"
|
is-arrayish "^0.3.1"
|
||||||
|
|
||||||
|
slash@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
|
||||||
|
integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=
|
||||||
|
|
||||||
slash@^3.0.0:
|
slash@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
|
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
|
||||||
@ -11533,6 +11726,13 @@ source-map-resolve@^0.5.0:
|
|||||||
source-map-url "^0.4.0"
|
source-map-url "^0.4.0"
|
||||||
urix "^0.1.0"
|
urix "^0.1.0"
|
||||||
|
|
||||||
|
source-map-support@^0.4.15:
|
||||||
|
version "0.4.18"
|
||||||
|
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f"
|
||||||
|
integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==
|
||||||
|
dependencies:
|
||||||
|
source-map "^0.5.6"
|
||||||
|
|
||||||
source-map-support@~0.5.12:
|
source-map-support@~0.5.12:
|
||||||
version "0.5.13"
|
version "0.5.13"
|
||||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932"
|
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932"
|
||||||
@ -11553,7 +11753,7 @@ source-map@^0.4.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
amdefine ">=0.0.4"
|
amdefine ">=0.0.4"
|
||||||
|
|
||||||
source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.0:
|
source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.0:
|
||||||
version "0.5.7"
|
version "0.5.7"
|
||||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
|
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
|
||||||
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
|
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
|
||||||
@ -11718,6 +11918,14 @@ stream-browserify@^2.0.1:
|
|||||||
inherits "~2.0.1"
|
inherits "~2.0.1"
|
||||||
readable-stream "^2.0.2"
|
readable-stream "^2.0.2"
|
||||||
|
|
||||||
|
stream-browserify@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-3.0.0.tgz#22b0a2850cdf6503e73085da1fc7b7d0c2122f2f"
|
||||||
|
integrity sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==
|
||||||
|
dependencies:
|
||||||
|
inherits "~2.0.4"
|
||||||
|
readable-stream "^3.5.0"
|
||||||
|
|
||||||
stream-consume@~0.1.0:
|
stream-consume@~0.1.0:
|
||||||
version "0.1.1"
|
version "0.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/stream-consume/-/stream-consume-0.1.1.tgz#d3bdb598c2bd0ae82b8cac7ac50b1107a7996c48"
|
resolved "https://registry.yarnpkg.com/stream-consume/-/stream-consume-0.1.1.tgz#d3bdb598c2bd0ae82b8cac7ac50b1107a7996c48"
|
||||||
@ -12394,6 +12602,11 @@ to-buffer@^1.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80"
|
resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80"
|
||||||
integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==
|
integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==
|
||||||
|
|
||||||
|
to-fast-properties@^1.0.3:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
|
||||||
|
integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=
|
||||||
|
|
||||||
to-fast-properties@^2.0.0:
|
to-fast-properties@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
|
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
|
||||||
|
|||||||
@ -28,6 +28,7 @@
|
|||||||
"@types/cordova": "^0.0.34",
|
"@types/cordova": "^0.0.34",
|
||||||
"@types/filesystem": "^0.0.29",
|
"@types/filesystem": "^0.0.29",
|
||||||
"ajv": "^6.10.2",
|
"ajv": "^6.10.2",
|
||||||
|
"babel-core": "^6.26.3",
|
||||||
"babel-loader": "^8.0.4",
|
"babel-loader": "^8.0.4",
|
||||||
"circular-dependency-plugin": "^5.0.2",
|
"circular-dependency-plugin": "^5.0.2",
|
||||||
"circular-json": "^0.5.9",
|
"circular-json": "^0.5.9",
|
||||||
@ -49,6 +50,7 @@
|
|||||||
"markdown-loader": "^4.0.0",
|
"markdown-loader": "^4.0.0",
|
||||||
"match-all": "^1.2.5",
|
"match-all": "^1.2.5",
|
||||||
"phonegap-plugin-mobile-accessibility": "^1.0.5",
|
"phonegap-plugin-mobile-accessibility": "^1.0.5",
|
||||||
|
"postcss": ">=5.0.0",
|
||||||
"promise-polyfill": "^8.1.0",
|
"promise-polyfill": "^8.1.0",
|
||||||
"query-string": "^6.8.1",
|
"query-string": "^6.8.1",
|
||||||
"rusha": "^0.8.13",
|
"rusha": "^0.8.13",
|
||||||
@ -71,7 +73,7 @@
|
|||||||
"yawn-yaml": "^1.5.0"
|
"yawn-yaml": "^1.5.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@octokit/rest": "^18.0.6",
|
"@octokit/rest": "^18.0.6",
|
||||||
"@typescript-eslint/eslint-plugin": "3.0.1",
|
"@typescript-eslint/eslint-plugin": "3.0.1",
|
||||||
"@typescript-eslint/parser": "3.0.1",
|
"@typescript-eslint/parser": "3.0.1",
|
||||||
"autoprefixer": "^9.4.3",
|
"autoprefixer": "^9.4.3",
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 132 KiB |
BIN
res/ui/interactive_tutorial.noinline/21_1_place_quad_painter.gif
Normal file
|
After Width: | Height: | Size: 809 KiB |
BIN
res/ui/interactive_tutorial.noinline/21_2_switch_to_wires.gif
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
res/ui/interactive_tutorial.noinline/21_3_place_button.gif
Normal file
|
After Width: | Height: | Size: 531 KiB |
BIN
res/ui/interactive_tutorial.noinline/21_4_press_button.gif
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
res/ui/interactive_tutorial.noinline/2_1_place_cutter.gif
Normal file
|
After Width: | Height: | Size: 502 KiB |
BIN
res/ui/interactive_tutorial.noinline/2_2_place_trash.gif
Normal file
|
After Width: | Height: | Size: 575 KiB |
BIN
res/ui/interactive_tutorial.noinline/2_3_more_cutters.gif
Normal file
|
After Width: | Height: | Size: 776 KiB |
BIN
res/ui/interactive_tutorial.noinline/3_1_rectangles.gif
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
@ -1,36 +1,38 @@
|
|||||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
<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"
|
||||||
<path style="fill:#FF4B55;" d="M400,0H112C50.144,0,0,50.144,0,112v288c0,61.856,50.144,112,112,112h288 c61.856,0,112-50.144,112-112V112C512,50.144,461.856,0,400,0z"/>
|
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||||
<polygon style="fill:#F5F5F5;" points="512,229.517 211.862,229.517 211.862,0 158.897,0 158.897,229.517 0,229.517 0,282.483 158.897,282.483 158.897,512 211.862,512 211.862,282.483 512,282.483 "/>
|
<rect style="fill:#FF4B55;" width="512" height="512"/>
|
||||||
<g>
|
<polygon style="fill:#F5F5F5;" points="512,229.517 211.862,229.517 211.862,0 158.897,0 158.897,229.517 0,229.517 0,282.483
|
||||||
</g>
|
158.897,282.483 158.897,512 211.862,512 211.862,282.483 512,282.483 "/>
|
||||||
<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>
|
||||||
</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>
|
<g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 858 B After Width: | Height: | Size: 786 B |
2
res_built/.gitignore
vendored
@ -1,2 +0,0 @@
|
|||||||
# Ignore built sounds
|
|
||||||
sounds
|
|
||||||
|
Before Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 286 KiB |
|
Before Width: | Height: | Size: 723 KiB |
22
res_raw/atlas.json
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"pot": true,
|
||||||
|
"paddingX": 2,
|
||||||
|
"paddingY": 2,
|
||||||
|
"edgePadding": true,
|
||||||
|
"rotation": false,
|
||||||
|
"maxWidth": 2048,
|
||||||
|
"useIndexes": false,
|
||||||
|
"alphaThreshold": 1,
|
||||||
|
"maxHeight": 2048,
|
||||||
|
"stripWhitespaceX": true,
|
||||||
|
"stripWhitespaceY": true,
|
||||||
|
"duplicatePadding": true,
|
||||||
|
"alias": true,
|
||||||
|
"fast": false,
|
||||||
|
"limitMemory": false,
|
||||||
|
"combineSubdirectories": true,
|
||||||
|
"flattenPaths": false,
|
||||||
|
"bleedIterations": 4,
|
||||||
|
"scale": [0.25, 0.5, 0.75],
|
||||||
|
"scaleSuffix": ["_lq", "_mq", "_hq"]
|
||||||
|
}
|
||||||
@ -1,625 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<data version="1.0">
|
|
||||||
<struct type="Settings">
|
|
||||||
<key>fileFormatVersion</key>
|
|
||||||
<int>4</int>
|
|
||||||
<key>texturePackerVersion</key>
|
|
||||||
<string>5.4.0</string>
|
|
||||||
<key>autoSDSettings</key>
|
|
||||||
<array>
|
|
||||||
<struct type="AutoSDSettings">
|
|
||||||
<key>scale</key>
|
|
||||||
<double>0.75</double>
|
|
||||||
<key>extension</key>
|
|
||||||
<string>_hq</string>
|
|
||||||
<key>spriteFilter</key>
|
|
||||||
<string></string>
|
|
||||||
<key>acceptFractionalValues</key>
|
|
||||||
<true/>
|
|
||||||
<key>maxTextureSize</key>
|
|
||||||
<QSize>
|
|
||||||
<key>width</key>
|
|
||||||
<int>2048</int>
|
|
||||||
<key>height</key>
|
|
||||||
<int>2048</int>
|
|
||||||
</QSize>
|
|
||||||
</struct>
|
|
||||||
<struct type="AutoSDSettings">
|
|
||||||
<key>scale</key>
|
|
||||||
<double>0.5</double>
|
|
||||||
<key>extension</key>
|
|
||||||
<string>_mq</string>
|
|
||||||
<key>spriteFilter</key>
|
|
||||||
<string></string>
|
|
||||||
<key>acceptFractionalValues</key>
|
|
||||||
<true/>
|
|
||||||
<key>maxTextureSize</key>
|
|
||||||
<QSize>
|
|
||||||
<key>width</key>
|
|
||||||
<int>2048</int>
|
|
||||||
<key>height</key>
|
|
||||||
<int>2048</int>
|
|
||||||
</QSize>
|
|
||||||
</struct>
|
|
||||||
<struct type="AutoSDSettings">
|
|
||||||
<key>scale</key>
|
|
||||||
<double>0.25</double>
|
|
||||||
<key>extension</key>
|
|
||||||
<string>_lq</string>
|
|
||||||
<key>spriteFilter</key>
|
|
||||||
<string></string>
|
|
||||||
<key>acceptFractionalValues</key>
|
|
||||||
<true/>
|
|
||||||
<key>maxTextureSize</key>
|
|
||||||
<QSize>
|
|
||||||
<key>width</key>
|
|
||||||
<int>2048</int>
|
|
||||||
<key>height</key>
|
|
||||||
<int>2048</int>
|
|
||||||
</QSize>
|
|
||||||
</struct>
|
|
||||||
</array>
|
|
||||||
<key>allowRotation</key>
|
|
||||||
<false/>
|
|
||||||
<key>shapeDebug</key>
|
|
||||||
<false/>
|
|
||||||
<key>dpi</key>
|
|
||||||
<uint>72</uint>
|
|
||||||
<key>dataFormat</key>
|
|
||||||
<string>json</string>
|
|
||||||
<key>textureFileName</key>
|
|
||||||
<filename></filename>
|
|
||||||
<key>flipPVR</key>
|
|
||||||
<false/>
|
|
||||||
<key>pvrCompressionQuality</key>
|
|
||||||
<enum type="SettingsBase::PvrCompressionQuality">PVR_QUALITY_NORMAL</enum>
|
|
||||||
<key>atfCompressData</key>
|
|
||||||
<false/>
|
|
||||||
<key>mipMapMinSize</key>
|
|
||||||
<uint>32768</uint>
|
|
||||||
<key>etc1CompressionQuality</key>
|
|
||||||
<enum type="SettingsBase::Etc1CompressionQuality">ETC1_QUALITY_LOW_PERCEPTUAL</enum>
|
|
||||||
<key>etc2CompressionQuality</key>
|
|
||||||
<enum type="SettingsBase::Etc2CompressionQuality">ETC2_QUALITY_LOW_PERCEPTUAL</enum>
|
|
||||||
<key>dxtCompressionMode</key>
|
|
||||||
<enum type="SettingsBase::DxtCompressionMode">DXT_PERCEPTUAL</enum>
|
|
||||||
<key>jxrColorFormat</key>
|
|
||||||
<enum type="SettingsBase::JpegXrColorMode">JXR_YUV444</enum>
|
|
||||||
<key>jxrTrimFlexBits</key>
|
|
||||||
<uint>0</uint>
|
|
||||||
<key>jxrCompressionLevel</key>
|
|
||||||
<uint>0</uint>
|
|
||||||
<key>ditherType</key>
|
|
||||||
<enum type="SettingsBase::DitherType">NearestNeighbour</enum>
|
|
||||||
<key>backgroundColor</key>
|
|
||||||
<uint>0</uint>
|
|
||||||
<key>libGdx</key>
|
|
||||||
<struct type="LibGDX">
|
|
||||||
<key>filtering</key>
|
|
||||||
<struct type="LibGDXFiltering">
|
|
||||||
<key>x</key>
|
|
||||||
<enum type="LibGDXFiltering::Filtering">Linear</enum>
|
|
||||||
<key>y</key>
|
|
||||||
<enum type="LibGDXFiltering::Filtering">Linear</enum>
|
|
||||||
</struct>
|
|
||||||
</struct>
|
|
||||||
<key>shapePadding</key>
|
|
||||||
<uint>2</uint>
|
|
||||||
<key>jpgQuality</key>
|
|
||||||
<uint>80</uint>
|
|
||||||
<key>pngOptimizationLevel</key>
|
|
||||||
<uint>0</uint>
|
|
||||||
<key>webpQualityLevel</key>
|
|
||||||
<uint>101</uint>
|
|
||||||
<key>textureSubPath</key>
|
|
||||||
<string></string>
|
|
||||||
<key>atfFormats</key>
|
|
||||||
<string></string>
|
|
||||||
<key>textureFormat</key>
|
|
||||||
<enum type="SettingsBase::TextureFormat">png</enum>
|
|
||||||
<key>borderPadding</key>
|
|
||||||
<uint>4</uint>
|
|
||||||
<key>maxTextureSize</key>
|
|
||||||
<QSize>
|
|
||||||
<key>width</key>
|
|
||||||
<int>2048</int>
|
|
||||||
<key>height</key>
|
|
||||||
<int>2048</int>
|
|
||||||
</QSize>
|
|
||||||
<key>fixedTextureSize</key>
|
|
||||||
<QSize>
|
|
||||||
<key>width</key>
|
|
||||||
<int>-1</int>
|
|
||||||
<key>height</key>
|
|
||||||
<int>-1</int>
|
|
||||||
</QSize>
|
|
||||||
<key>algorithmSettings</key>
|
|
||||||
<struct type="AlgorithmSettings">
|
|
||||||
<key>algorithm</key>
|
|
||||||
<enum type="AlgorithmSettings::AlgorithmId">MaxRects</enum>
|
|
||||||
<key>freeSizeMode</key>
|
|
||||||
<enum type="AlgorithmSettings::AlgorithmFreeSizeMode">Best</enum>
|
|
||||||
<key>sizeConstraints</key>
|
|
||||||
<enum type="AlgorithmSettings::SizeConstraints">POT</enum>
|
|
||||||
<key>forceSquared</key>
|
|
||||||
<false/>
|
|
||||||
<key>maxRects</key>
|
|
||||||
<struct type="AlgorithmMaxRectsSettings">
|
|
||||||
<key>heuristic</key>
|
|
||||||
<enum type="AlgorithmMaxRectsSettings::Heuristic">Best</enum>
|
|
||||||
</struct>
|
|
||||||
<key>basic</key>
|
|
||||||
<struct type="AlgorithmBasicSettings">
|
|
||||||
<key>sortBy</key>
|
|
||||||
<enum type="AlgorithmBasicSettings::SortBy">Best</enum>
|
|
||||||
<key>order</key>
|
|
||||||
<enum type="AlgorithmBasicSettings::Order">Ascending</enum>
|
|
||||||
</struct>
|
|
||||||
<key>polygon</key>
|
|
||||||
<struct type="AlgorithmPolygonSettings">
|
|
||||||
<key>alignToGrid</key>
|
|
||||||
<uint>1</uint>
|
|
||||||
</struct>
|
|
||||||
</struct>
|
|
||||||
<key>dataFileNames</key>
|
|
||||||
<map type="GFileNameMap">
|
|
||||||
<key>data</key>
|
|
||||||
<struct type="DataFile">
|
|
||||||
<key>name</key>
|
|
||||||
<filename>../res_built/atlas/atlas{n}{v}.json</filename>
|
|
||||||
</struct>
|
|
||||||
</map>
|
|
||||||
<key>multiPack</key>
|
|
||||||
<true/>
|
|
||||||
<key>forceIdenticalLayout</key>
|
|
||||||
<false/>
|
|
||||||
<key>outputFormat</key>
|
|
||||||
<enum type="SettingsBase::OutputFormat">RGBA8888</enum>
|
|
||||||
<key>alphaHandling</key>
|
|
||||||
<enum type="SettingsBase::AlphaHandling">ClearTransparentPixels</enum>
|
|
||||||
<key>contentProtection</key>
|
|
||||||
<struct type="ContentProtection">
|
|
||||||
<key>key</key>
|
|
||||||
<string></string>
|
|
||||||
</struct>
|
|
||||||
<key>autoAliasEnabled</key>
|
|
||||||
<true/>
|
|
||||||
<key>trimSpriteNames</key>
|
|
||||||
<false/>
|
|
||||||
<key>prependSmartFolderName</key>
|
|
||||||
<true/>
|
|
||||||
<key>autodetectAnimations</key>
|
|
||||||
<true/>
|
|
||||||
<key>globalSpriteSettings</key>
|
|
||||||
<struct type="SpriteSettings">
|
|
||||||
<key>scale</key>
|
|
||||||
<double>1</double>
|
|
||||||
<key>scaleMode</key>
|
|
||||||
<enum type="ScaleMode">Smooth</enum>
|
|
||||||
<key>extrude</key>
|
|
||||||
<uint>2</uint>
|
|
||||||
<key>trimThreshold</key>
|
|
||||||
<uint>2</uint>
|
|
||||||
<key>trimMargin</key>
|
|
||||||
<uint>1</uint>
|
|
||||||
<key>trimMode</key>
|
|
||||||
<enum type="SpriteSettings::TrimMode">Trim</enum>
|
|
||||||
<key>tracerTolerance</key>
|
|
||||||
<int>200</int>
|
|
||||||
<key>heuristicMask</key>
|
|
||||||
<false/>
|
|
||||||
<key>defaultPivotPoint</key>
|
|
||||||
<point_f>0.5,0.5</point_f>
|
|
||||||
<key>writePivotPoints</key>
|
|
||||||
<false/>
|
|
||||||
</struct>
|
|
||||||
<key>individualSpriteSettings</key>
|
|
||||||
<map type="IndividualSpriteSettingsMap">
|
|
||||||
<key type="filename">sprites/belt/built/forward_0.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/forward_1.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/forward_10.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/forward_11.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/forward_12.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/forward_13.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/forward_2.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/forward_3.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/forward_4.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/forward_5.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/forward_6.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/forward_7.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/forward_8.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/forward_9.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/left_0.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/left_1.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/left_10.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/left_11.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/left_12.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/left_13.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/left_2.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/left_3.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/left_4.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/left_5.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/left_6.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/left_7.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/left_8.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/left_9.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/right_0.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/right_1.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/right_10.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/right_11.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/right_12.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/right_13.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/right_2.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/right_3.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/right_4.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/right_5.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/right_6.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/right_7.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/right_8.png</key>
|
|
||||||
<key type="filename">sprites/belt/built/right_9.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/analyzer.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/balancer-merger-inverse.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/balancer-merger.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/balancer-splitter-inverse.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/balancer-splitter.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/belt_left.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/belt_right.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/belt_top.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/comparator.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/constant_signal.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/display.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/item_producer.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/lever.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/logic_gate-not.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/logic_gate-or.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/logic_gate-xor.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/logic_gate.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/miner-chainable.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/miner.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/reader.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/rotater-ccw.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/rotater-rotate180.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/rotater.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/transistor-mirrored.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/transistor.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/trash.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/underground_belt_entry-tier2.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/underground_belt_entry.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/underground_belt_exit-tier2.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/underground_belt_exit.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/virtual_processor-painter.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/virtual_processor-rotater.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/virtual_processor-stacker.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/virtual_processor-unstacker.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/virtual_processor.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/wire_tunnel.png</key>
|
|
||||||
<key type="filename">sprites/buildings/analyzer.png</key>
|
|
||||||
<key type="filename">sprites/buildings/balancer-merger-inverse.png</key>
|
|
||||||
<key type="filename">sprites/buildings/balancer-merger.png</key>
|
|
||||||
<key type="filename">sprites/buildings/balancer-splitter-inverse.png</key>
|
|
||||||
<key type="filename">sprites/buildings/balancer-splitter.png</key>
|
|
||||||
<key type="filename">sprites/buildings/comparator.png</key>
|
|
||||||
<key type="filename">sprites/buildings/constant_signal.png</key>
|
|
||||||
<key type="filename">sprites/buildings/display.png</key>
|
|
||||||
<key type="filename">sprites/buildings/item_producer.png</key>
|
|
||||||
<key type="filename">sprites/buildings/lever.png</key>
|
|
||||||
<key type="filename">sprites/buildings/logic_gate-not.png</key>
|
|
||||||
<key type="filename">sprites/buildings/logic_gate-or.png</key>
|
|
||||||
<key type="filename">sprites/buildings/logic_gate-xor.png</key>
|
|
||||||
<key type="filename">sprites/buildings/logic_gate.png</key>
|
|
||||||
<key type="filename">sprites/buildings/miner-chainable.png</key>
|
|
||||||
<key type="filename">sprites/buildings/reader.png</key>
|
|
||||||
<key type="filename">sprites/buildings/rotater-ccw.png</key>
|
|
||||||
<key type="filename">sprites/buildings/rotater-rotate180.png</key>
|
|
||||||
<key type="filename">sprites/buildings/transistor-mirrored.png</key>
|
|
||||||
<key type="filename">sprites/buildings/transistor.png</key>
|
|
||||||
<key type="filename">sprites/buildings/underground_belt_entry-tier2.png</key>
|
|
||||||
<key type="filename">sprites/buildings/underground_belt_entry.png</key>
|
|
||||||
<key type="filename">sprites/buildings/underground_belt_exit-tier2.png</key>
|
|
||||||
<key type="filename">sprites/buildings/underground_belt_exit.png</key>
|
|
||||||
<key type="filename">sprites/buildings/virtual_processor-painter.png</key>
|
|
||||||
<key type="filename">sprites/buildings/virtual_processor-rotater.png</key>
|
|
||||||
<key type="filename">sprites/buildings/virtual_processor-stacker.png</key>
|
|
||||||
<key type="filename">sprites/buildings/virtual_processor-unstacker.png</key>
|
|
||||||
<key type="filename">sprites/buildings/virtual_processor.png</key>
|
|
||||||
<key type="filename">sprites/buildings/wire_tunnel.png</key>
|
|
||||||
<key type="filename">sprites/misc/reader_overlay.png</key>
|
|
||||||
<key type="filename">sprites/wires/lever_on.png</key>
|
|
||||||
<key type="filename">sprites/wires/sets/conflict_cross.png</key>
|
|
||||||
<key type="filename">sprites/wires/sets/conflict_forward.png</key>
|
|
||||||
<key type="filename">sprites/wires/sets/conflict_split.png</key>
|
|
||||||
<key type="filename">sprites/wires/sets/conflict_turn.png</key>
|
|
||||||
<key type="filename">sprites/wires/sets/first_cross.png</key>
|
|
||||||
<key type="filename">sprites/wires/sets/first_forward.png</key>
|
|
||||||
<key type="filename">sprites/wires/sets/first_split.png</key>
|
|
||||||
<key type="filename">sprites/wires/sets/first_turn.png</key>
|
|
||||||
<key type="filename">sprites/wires/sets/second_cross.png</key>
|
|
||||||
<key type="filename">sprites/wires/sets/second_forward.png</key>
|
|
||||||
<key type="filename">sprites/wires/sets/second_split.png</key>
|
|
||||||
<key type="filename">sprites/wires/sets/second_turn.png</key>
|
|
||||||
<struct type="IndividualSpriteSettings">
|
|
||||||
<key>pivotPoint</key>
|
|
||||||
<point_f>0.5,0.5</point_f>
|
|
||||||
<key>spriteScale</key>
|
|
||||||
<double>1</double>
|
|
||||||
<key>scale9Enabled</key>
|
|
||||||
<false/>
|
|
||||||
<key>scale9Borders</key>
|
|
||||||
<rect>48,48,96,96</rect>
|
|
||||||
<key>scale9Paddings</key>
|
|
||||||
<rect>48,48,96,96</rect>
|
|
||||||
<key>scale9FromFile</key>
|
|
||||||
<false/>
|
|
||||||
</struct>
|
|
||||||
<key type="filename">sprites/blueprints/balancer.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/cutter.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/filter.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/mixer.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/painter-mirrored.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/painter.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/stacker.png</key>
|
|
||||||
<key type="filename">sprites/buildings/balancer.png</key>
|
|
||||||
<key type="filename">sprites/buildings/filter.png</key>
|
|
||||||
<key type="filename">sprites/buildings/painter-mirrored.png</key>
|
|
||||||
<struct type="IndividualSpriteSettings">
|
|
||||||
<key>pivotPoint</key>
|
|
||||||
<point_f>0.5,0.5</point_f>
|
|
||||||
<key>spriteScale</key>
|
|
||||||
<double>1</double>
|
|
||||||
<key>scale9Enabled</key>
|
|
||||||
<false/>
|
|
||||||
<key>scale9Borders</key>
|
|
||||||
<rect>96,48,192,96</rect>
|
|
||||||
<key>scale9Paddings</key>
|
|
||||||
<rect>96,48,192,96</rect>
|
|
||||||
<key>scale9FromFile</key>
|
|
||||||
<false/>
|
|
||||||
</struct>
|
|
||||||
<key type="filename">sprites/blueprints/cutter-quad.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/painter-quad.png</key>
|
|
||||||
<key type="filename">sprites/buildings/cutter-quad.png</key>
|
|
||||||
<key type="filename">sprites/buildings/painter-quad.png</key>
|
|
||||||
<struct type="IndividualSpriteSettings">
|
|
||||||
<key>pivotPoint</key>
|
|
||||||
<point_f>0.5,0.5</point_f>
|
|
||||||
<key>spriteScale</key>
|
|
||||||
<double>1</double>
|
|
||||||
<key>scale9Enabled</key>
|
|
||||||
<false/>
|
|
||||||
<key>scale9Borders</key>
|
|
||||||
<rect>192,48,384,96</rect>
|
|
||||||
<key>scale9Paddings</key>
|
|
||||||
<rect>192,48,384,96</rect>
|
|
||||||
<key>scale9FromFile</key>
|
|
||||||
<false/>
|
|
||||||
</struct>
|
|
||||||
<key type="filename">sprites/blueprints/painter-double.png</key>
|
|
||||||
<key type="filename">sprites/blueprints/storage.png</key>
|
|
||||||
<key type="filename">sprites/buildings/painter-double.png</key>
|
|
||||||
<key type="filename">sprites/buildings/storage.png</key>
|
|
||||||
<struct type="IndividualSpriteSettings">
|
|
||||||
<key>pivotPoint</key>
|
|
||||||
<point_f>0.5,0.5</point_f>
|
|
||||||
<key>spriteScale</key>
|
|
||||||
<double>1</double>
|
|
||||||
<key>scale9Enabled</key>
|
|
||||||
<false/>
|
|
||||||
<key>scale9Borders</key>
|
|
||||||
<rect>96,96,192,192</rect>
|
|
||||||
<key>scale9Paddings</key>
|
|
||||||
<rect>96,96,192,192</rect>
|
|
||||||
<key>scale9FromFile</key>
|
|
||||||
<false/>
|
|
||||||
</struct>
|
|
||||||
<key type="filename">sprites/buildings/belt_left.png</key>
|
|
||||||
<key type="filename">sprites/buildings/belt_right.png</key>
|
|
||||||
<key type="filename">sprites/buildings/belt_top.png</key>
|
|
||||||
<struct type="IndividualSpriteSettings">
|
|
||||||
<key>pivotPoint</key>
|
|
||||||
<point_f>0.5,0.5</point_f>
|
|
||||||
<key>spriteScale</key>
|
|
||||||
<double>1</double>
|
|
||||||
<key>scale9Enabled</key>
|
|
||||||
<false/>
|
|
||||||
<key>scale9Borders</key>
|
|
||||||
<rect>32,32,63,63</rect>
|
|
||||||
<key>scale9Paddings</key>
|
|
||||||
<rect>32,32,63,63</rect>
|
|
||||||
<key>scale9FromFile</key>
|
|
||||||
<false/>
|
|
||||||
</struct>
|
|
||||||
<key type="filename">sprites/buildings/cutter.png</key>
|
|
||||||
<key type="filename">sprites/buildings/mixer.png</key>
|
|
||||||
<key type="filename">sprites/buildings/painter.png</key>
|
|
||||||
<key type="filename">sprites/buildings/stacker.png</key>
|
|
||||||
<struct type="IndividualSpriteSettings">
|
|
||||||
<key>pivotPoint</key>
|
|
||||||
<point_f>0.5,0.5</point_f>
|
|
||||||
<key>spriteScale</key>
|
|
||||||
<double>1</double>
|
|
||||||
<key>scale9Enabled</key>
|
|
||||||
<false/>
|
|
||||||
<key>scale9Borders</key>
|
|
||||||
<rect>64,32,128,64</rect>
|
|
||||||
<key>scale9Paddings</key>
|
|
||||||
<rect>64,32,128,64</rect>
|
|
||||||
<key>scale9FromFile</key>
|
|
||||||
<false/>
|
|
||||||
</struct>
|
|
||||||
<key type="filename">sprites/buildings/hub.png</key>
|
|
||||||
<struct type="IndividualSpriteSettings">
|
|
||||||
<key>pivotPoint</key>
|
|
||||||
<point_f>0.5,0.5</point_f>
|
|
||||||
<key>spriteScale</key>
|
|
||||||
<double>1</double>
|
|
||||||
<key>scale9Enabled</key>
|
|
||||||
<false/>
|
|
||||||
<key>scale9Borders</key>
|
|
||||||
<rect>192,192,384,384</rect>
|
|
||||||
<key>scale9Paddings</key>
|
|
||||||
<rect>192,192,384,384</rect>
|
|
||||||
<key>scale9FromFile</key>
|
|
||||||
<false/>
|
|
||||||
</struct>
|
|
||||||
<key type="filename">sprites/buildings/miner.png</key>
|
|
||||||
<key type="filename">sprites/buildings/rotater.png</key>
|
|
||||||
<key type="filename">sprites/buildings/trash.png</key>
|
|
||||||
<key type="filename">sprites/misc/processor_disabled.png</key>
|
|
||||||
<key type="filename">sprites/misc/processor_disconnected.png</key>
|
|
||||||
<key type="filename">sprites/wires/logical_acceptor.png</key>
|
|
||||||
<key type="filename">sprites/wires/logical_ejector.png</key>
|
|
||||||
<key type="filename">sprites/wires/overlay_tile.png</key>
|
|
||||||
<struct type="IndividualSpriteSettings">
|
|
||||||
<key>pivotPoint</key>
|
|
||||||
<point_f>0.5,0.5</point_f>
|
|
||||||
<key>spriteScale</key>
|
|
||||||
<double>1</double>
|
|
||||||
<key>scale9Enabled</key>
|
|
||||||
<false/>
|
|
||||||
<key>scale9Borders</key>
|
|
||||||
<rect>32,32,64,64</rect>
|
|
||||||
<key>scale9Paddings</key>
|
|
||||||
<rect>32,32,64,64</rect>
|
|
||||||
<key>scale9FromFile</key>
|
|
||||||
<false/>
|
|
||||||
</struct>
|
|
||||||
<key type="filename">sprites/colors/blue.png</key>
|
|
||||||
<key type="filename">sprites/colors/cyan.png</key>
|
|
||||||
<key type="filename">sprites/colors/green.png</key>
|
|
||||||
<key type="filename">sprites/colors/purple.png</key>
|
|
||||||
<key type="filename">sprites/colors/red.png</key>
|
|
||||||
<key type="filename">sprites/colors/uncolored.png</key>
|
|
||||||
<key type="filename">sprites/colors/white.png</key>
|
|
||||||
<key type="filename">sprites/colors/yellow.png</key>
|
|
||||||
<struct type="IndividualSpriteSettings">
|
|
||||||
<key>pivotPoint</key>
|
|
||||||
<point_f>0.5,0.5</point_f>
|
|
||||||
<key>spriteScale</key>
|
|
||||||
<double>1</double>
|
|
||||||
<key>scale9Enabled</key>
|
|
||||||
<false/>
|
|
||||||
<key>scale9Borders</key>
|
|
||||||
<rect>18,18,36,36</rect>
|
|
||||||
<key>scale9Paddings</key>
|
|
||||||
<rect>18,18,36,36</rect>
|
|
||||||
<key>scale9FromFile</key>
|
|
||||||
<false/>
|
|
||||||
</struct>
|
|
||||||
<key type="filename">sprites/debug/acceptor_slot.png</key>
|
|
||||||
<key type="filename">sprites/debug/ejector_slot.png</key>
|
|
||||||
<key type="filename">sprites/misc/hub_direction_indicator.png</key>
|
|
||||||
<key type="filename">sprites/misc/waypoint.png</key>
|
|
||||||
<struct type="IndividualSpriteSettings">
|
|
||||||
<key>pivotPoint</key>
|
|
||||||
<point_f>0.5,0.5</point_f>
|
|
||||||
<key>spriteScale</key>
|
|
||||||
<double>1</double>
|
|
||||||
<key>scale9Enabled</key>
|
|
||||||
<false/>
|
|
||||||
<key>scale9Borders</key>
|
|
||||||
<rect>8,8,16,16</rect>
|
|
||||||
<key>scale9Paddings</key>
|
|
||||||
<rect>8,8,16,16</rect>
|
|
||||||
<key>scale9FromFile</key>
|
|
||||||
<false/>
|
|
||||||
</struct>
|
|
||||||
<key type="filename">sprites/misc/slot_bad_arrow.png</key>
|
|
||||||
<key type="filename">sprites/misc/slot_good_arrow.png</key>
|
|
||||||
<struct type="IndividualSpriteSettings">
|
|
||||||
<key>pivotPoint</key>
|
|
||||||
<point_f>0.5,0.5</point_f>
|
|
||||||
<key>spriteScale</key>
|
|
||||||
<double>1</double>
|
|
||||||
<key>scale9Enabled</key>
|
|
||||||
<false/>
|
|
||||||
<key>scale9Borders</key>
|
|
||||||
<rect>24,24,48,48</rect>
|
|
||||||
<key>scale9Paddings</key>
|
|
||||||
<rect>24,24,48,48</rect>
|
|
||||||
<key>scale9FromFile</key>
|
|
||||||
<false/>
|
|
||||||
</struct>
|
|
||||||
<key type="filename">sprites/misc/storage_overlay.png</key>
|
|
||||||
<struct type="IndividualSpriteSettings">
|
|
||||||
<key>pivotPoint</key>
|
|
||||||
<point_f>0.5,0.5</point_f>
|
|
||||||
<key>spriteScale</key>
|
|
||||||
<double>1</double>
|
|
||||||
<key>scale9Enabled</key>
|
|
||||||
<false/>
|
|
||||||
<key>scale9Borders</key>
|
|
||||||
<rect>44,22,89,43</rect>
|
|
||||||
<key>scale9Paddings</key>
|
|
||||||
<rect>44,22,89,43</rect>
|
|
||||||
<key>scale9FromFile</key>
|
|
||||||
<false/>
|
|
||||||
</struct>
|
|
||||||
<key type="filename">sprites/wires/boolean_false.png</key>
|
|
||||||
<key type="filename">sprites/wires/boolean_true.png</key>
|
|
||||||
<key type="filename">sprites/wires/network_conflict.png</key>
|
|
||||||
<key type="filename">sprites/wires/network_empty.png</key>
|
|
||||||
<key type="filename">sprites/wires/wires_preview.png</key>
|
|
||||||
<struct type="IndividualSpriteSettings">
|
|
||||||
<key>pivotPoint</key>
|
|
||||||
<point_f>0.5,0.5</point_f>
|
|
||||||
<key>spriteScale</key>
|
|
||||||
<double>1</double>
|
|
||||||
<key>scale9Enabled</key>
|
|
||||||
<false/>
|
|
||||||
<key>scale9Borders</key>
|
|
||||||
<rect>16,16,32,32</rect>
|
|
||||||
<key>scale9Paddings</key>
|
|
||||||
<rect>16,16,32,32</rect>
|
|
||||||
<key>scale9FromFile</key>
|
|
||||||
<false/>
|
|
||||||
</struct>
|
|
||||||
<key type="filename">sprites/wires/display/blue.png</key>
|
|
||||||
<key type="filename">sprites/wires/display/cyan.png</key>
|
|
||||||
<key type="filename">sprites/wires/display/green.png</key>
|
|
||||||
<key type="filename">sprites/wires/display/purple.png</key>
|
|
||||||
<key type="filename">sprites/wires/display/red.png</key>
|
|
||||||
<key type="filename">sprites/wires/display/white.png</key>
|
|
||||||
<key type="filename">sprites/wires/display/yellow.png</key>
|
|
||||||
<struct type="IndividualSpriteSettings">
|
|
||||||
<key>pivotPoint</key>
|
|
||||||
<point_f>0.5,0.5</point_f>
|
|
||||||
<key>spriteScale</key>
|
|
||||||
<double>1</double>
|
|
||||||
<key>scale9Enabled</key>
|
|
||||||
<false/>
|
|
||||||
<key>scale9Borders</key>
|
|
||||||
<rect>11,11,22,22</rect>
|
|
||||||
<key>scale9Paddings</key>
|
|
||||||
<rect>11,11,22,22</rect>
|
|
||||||
<key>scale9FromFile</key>
|
|
||||||
<false/>
|
|
||||||
</struct>
|
|
||||||
</map>
|
|
||||||
<key>fileList</key>
|
|
||||||
<array>
|
|
||||||
<filename>sprites</filename>
|
|
||||||
</array>
|
|
||||||
<key>ignoreFileList</key>
|
|
||||||
<array/>
|
|
||||||
<key>replaceList</key>
|
|
||||||
<array/>
|
|
||||||
<key>ignoredWarnings</key>
|
|
||||||
<array/>
|
|
||||||
<key>commonDivisorX</key>
|
|
||||||
<uint>1</uint>
|
|
||||||
<key>commonDivisorY</key>
|
|
||||||
<uint>1</uint>
|
|
||||||
<key>packNormalMaps</key>
|
|
||||||
<false/>
|
|
||||||
<key>autodetectNormalMaps</key>
|
|
||||||
<true/>
|
|
||||||
<key>normalMapFilter</key>
|
|
||||||
<string></string>
|
|
||||||
<key>normalMapSuffix</key>
|
|
||||||
<string></string>
|
|
||||||
<key>normalMapSheetFileName</key>
|
|
||||||
<filename></filename>
|
|
||||||
<key>exporterProperties</key>
|
|
||||||
<map type="ExporterProperties"/>
|
|
||||||
</struct>
|
|
||||||
</data>
|
|
||||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 9.5 KiB |
|
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 8.5 KiB |
@ -14,6 +14,7 @@
|
|||||||
"vetur.format.defaultFormatter.js": "vscode-typescript",
|
"vetur.format.defaultFormatter.js": "vscode-typescript",
|
||||||
"vetur.format.defaultFormatter.ts": "vscode-typescript",
|
"vetur.format.defaultFormatter.ts": "vscode-typescript",
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
"editor.formatOnSave": true
|
"editor.formatOnSave": true,
|
||||||
|
"files.trimTrailingWhitespace": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -27,7 +27,7 @@
|
|||||||
@include S(border-radius, $globalBorderRadius);
|
@include S(border-radius, $globalBorderRadius);
|
||||||
|
|
||||||
@include DarkThemeOverride {
|
@include DarkThemeOverride {
|
||||||
background-color: rgba(darken($darkModeGameBackground, 15), 0.4);
|
background-color: rgba(darken($darkModeGameBackground, 15), 0.95);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.secondary {
|
&.secondary {
|
||||||
|
|||||||
@ -56,8 +56,9 @@
|
|||||||
|
|
||||||
.helperGif {
|
.helperGif {
|
||||||
@include S(margin-top, 5px);
|
@include S(margin-top, 5px);
|
||||||
|
@include S(width, 150px);
|
||||||
@include S(height, 150px);
|
@include S(height, 150px);
|
||||||
background: center center / contain no-repeat;
|
background: center center / cover no-repeat;
|
||||||
transition: opacity 0.1s ease-out;
|
transition: opacity 0.1s ease-out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,13 +17,10 @@
|
|||||||
grid-template-rows: 1fr 1fr;
|
grid-template-rows: 1fr 1fr;
|
||||||
@include S(margin-bottom, 4px);
|
@include S(margin-bottom, 4px);
|
||||||
color: #333438;
|
color: #333438;
|
||||||
// text-shadow: #{D(1px)} #{D(1px)} 0 rgba(0, 10, 20, 0.2);
|
|
||||||
|
|
||||||
&.unpinable {
|
&.removable {
|
||||||
> canvas {
|
cursor: pointer;
|
||||||
cursor: pointer;
|
pointer-events: all;
|
||||||
pointer-events: all;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
> canvas {
|
> canvas {
|
||||||
@ -31,16 +28,9 @@
|
|||||||
@include S(height, 25px);
|
@include S(height, 25px);
|
||||||
grid-column: 1 / 2;
|
grid-column: 1 / 2;
|
||||||
grid-row: 1 / 3;
|
grid-row: 1 / 3;
|
||||||
pointer-events: all;
|
pointer-events: none;
|
||||||
transition: transform 0.1s ease-in-out;
|
|
||||||
transform-origin: D(2px) center;
|
|
||||||
will-change: transform;
|
|
||||||
position: relative;
|
|
||||||
z-index: 20;
|
z-index: 20;
|
||||||
&:hover {
|
position: relative;
|
||||||
transform: scale(2);
|
|
||||||
z-index: 21;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
> .amountLabel,
|
> .amountLabel,
|
||||||
|
|||||||
@ -4,9 +4,7 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
display: flex;
|
overflow: auto;
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
|
|
||||||
& {
|
& {
|
||||||
@ -33,7 +31,6 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
max-height: 100vh;
|
|
||||||
|
|
||||||
color: #fff;
|
color: #fff;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|||||||
@ -73,8 +73,8 @@ ingame_HUD_KeybindingOverlay,
|
|||||||
ingame_HUD_Notifications,
|
ingame_HUD_Notifications,
|
||||||
ingame_HUD_DebugInfo,
|
ingame_HUD_DebugInfo,
|
||||||
ingame_HUD_EntityDebugger,
|
ingame_HUD_EntityDebugger,
|
||||||
ingame_HUD_InteractiveTutorial,
|
|
||||||
ingame_HUD_TutorialHints,
|
ingame_HUD_TutorialHints,
|
||||||
|
ingame_HUD_InteractiveTutorial,
|
||||||
ingame_HUD_BuildingsToolbar,
|
ingame_HUD_BuildingsToolbar,
|
||||||
ingame_HUD_wires_toolbar,
|
ingame_HUD_wires_toolbar,
|
||||||
ingame_HUD_BlueprintPlacer,
|
ingame_HUD_BlueprintPlacer,
|
||||||
|
|||||||
@ -29,6 +29,7 @@ import { MobileWarningState } from "./states/mobile_warning";
|
|||||||
import { PreloadState } from "./states/preload";
|
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";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import("./platform/game_analytics").GameAnalyticsInterface} GameAnalyticsInterface
|
* @typedef {import("./platform/game_analytics").GameAnalyticsInterface} GameAnalyticsInterface
|
||||||
@ -70,6 +71,9 @@ export class Application {
|
|||||||
this.inputMgr = new InputDistributor(this);
|
this.inputMgr = new InputDistributor(this);
|
||||||
this.backgroundResourceLoader = new BackgroundResourcesLoader(this);
|
this.backgroundResourceLoader = new BackgroundResourcesLoader(this);
|
||||||
|
|
||||||
|
// Restrictions (Like demo etc)
|
||||||
|
this.restrictionMgr = new RestrictionManager(this);
|
||||||
|
|
||||||
// Platform dependent stuff
|
// Platform dependent stuff
|
||||||
|
|
||||||
/** @type {StorageInterface} */
|
/** @type {StorageInterface} */
|
||||||
|
|||||||
@ -1,4 +1,18 @@
|
|||||||
export const CHANGELOG = [
|
export const CHANGELOG = [
|
||||||
|
{
|
||||||
|
version: "1.2.1",
|
||||||
|
date: "unreleased",
|
||||||
|
entries: [
|
||||||
|
"Fixed stacking bug for level 26 which required restarting the game",
|
||||||
|
"Fix reward notification being too long sometimes (by LeopoldTal)",
|
||||||
|
"Use locale decimal separator on belt reader display (by LeopoldTal)",
|
||||||
|
"Vastly improved performance when saving games (by LeopoldTal)",
|
||||||
|
"Prevent some antivirus programs blocking the opening of external links (by LeopoldTal)",
|
||||||
|
"Match tutorials to the correct painter variants (by LeopoldTal)",
|
||||||
|
"Prevent throughput goals containing fractional numbers (by CEbbinghaus)",
|
||||||
|
"Updated translations and added Hungarian",
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
version: "1.2.0",
|
version: "1.2.0",
|
||||||
date: "09.10.2020",
|
date: "09.10.2020",
|
||||||
|
|||||||
@ -1,467 +1,465 @@
|
|||||||
import { createLogger } from "../core/logging";
|
import { createLogger } from "../core/logging";
|
||||||
import { Signal } from "../core/signal";
|
import { Signal } from "../core/signal";
|
||||||
import { fastArrayDelete, fastArrayDeleteValueIfContained } from "./utils";
|
import { fastArrayDelete, fastArrayDeleteValueIfContained } from "./utils";
|
||||||
import { Vector } from "./vector";
|
import { Vector } from "./vector";
|
||||||
import { IS_MOBILE, SUPPORT_TOUCH } from "./config";
|
import { IS_MOBILE, SUPPORT_TOUCH } from "./config";
|
||||||
import { SOUNDS } from "../platform/sound";
|
import { SOUNDS } from "../platform/sound";
|
||||||
import { GLOBAL_APP } from "./globals";
|
import { GLOBAL_APP } from "./globals";
|
||||||
|
|
||||||
const logger = createLogger("click_detector");
|
const logger = createLogger("click_detector");
|
||||||
|
|
||||||
export const MAX_MOVE_DISTANCE_PX = IS_MOBILE ? 20 : 80;
|
export const MAX_MOVE_DISTANCE_PX = IS_MOBILE ? 20 : 80;
|
||||||
|
|
||||||
// For debugging
|
// For debugging
|
||||||
const registerClickDetectors = G_IS_DEV && true;
|
const registerClickDetectors = G_IS_DEV && true;
|
||||||
if (registerClickDetectors) {
|
if (registerClickDetectors) {
|
||||||
/** @type {Array<ClickDetector>} */
|
/** @type {Array<ClickDetector>} */
|
||||||
window.activeClickDetectors = [];
|
window.activeClickDetectors = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store active click detectors so we can cancel them
|
// Store active click detectors so we can cancel them
|
||||||
/** @type {Array<ClickDetector>} */
|
/** @type {Array<ClickDetector>} */
|
||||||
const ongoingClickDetectors = [];
|
const ongoingClickDetectors = [];
|
||||||
|
|
||||||
// Store when the last touch event was registered, to avoid accepting a touch *and* a click event
|
// Store when the last touch event was registered, to avoid accepting a touch *and* a click event
|
||||||
|
|
||||||
export let clickDetectorGlobals = {
|
export let clickDetectorGlobals = {
|
||||||
lastTouchTime: -1000,
|
lastTouchTime: -1000,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Click detector creation payload typehints
|
* Click detector creation payload typehints
|
||||||
* @typedef {{
|
* @typedef {{
|
||||||
* consumeEvents?: boolean,
|
* consumeEvents?: boolean,
|
||||||
* preventDefault?: boolean,
|
* preventDefault?: boolean,
|
||||||
* applyCssClass?: string,
|
* applyCssClass?: string,
|
||||||
* captureTouchmove?: boolean,
|
* captureTouchmove?: boolean,
|
||||||
* targetOnly?: boolean,
|
* targetOnly?: boolean,
|
||||||
* maxDistance?: number,
|
* maxDistance?: number,
|
||||||
* clickSound?: string,
|
* clickSound?: string,
|
||||||
* preventClick?: boolean,
|
* preventClick?: boolean,
|
||||||
* }} ClickDetectorConstructorArgs
|
* }} ClickDetectorConstructorArgs
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Detects clicks
|
// Detects clicks
|
||||||
export class ClickDetector {
|
export class ClickDetector {
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {Element} element
|
* @param {Element} element
|
||||||
* @param {object} param1
|
* @param {object} param1
|
||||||
* @param {boolean=} param1.consumeEvents Whether to call stopPropagation
|
* @param {boolean=} param1.consumeEvents Whether to call stopPropagation
|
||||||
* (Useful for nested elements where the parent has a click handler as wel)
|
* (Useful for nested elements where the parent has a click handler as wel)
|
||||||
* @param {boolean=} param1.preventDefault Whether to call preventDefault (Usually makes the handler faster)
|
* @param {boolean=} param1.preventDefault Whether to call preventDefault (Usually makes the handler faster)
|
||||||
* @param {string=} param1.applyCssClass The css class to add while the element is pressed
|
* @param {string=} param1.applyCssClass The css class to add while the element is pressed
|
||||||
* @param {boolean=} param1.captureTouchmove Whether to capture touchmove events as well
|
* @param {boolean=} param1.captureTouchmove Whether to capture touchmove events as well
|
||||||
* @param {boolean=} param1.targetOnly Whether to also accept clicks on child elements (e.target !== element)
|
* @param {boolean=} param1.targetOnly Whether to also accept clicks on child elements (e.target !== element)
|
||||||
* @param {number=} param1.maxDistance The maximum distance in pixels to accept clicks
|
* @param {number=} param1.maxDistance The maximum distance in pixels to accept clicks
|
||||||
* @param {string=} param1.clickSound Sound key to play on touchdown
|
* @param {string=} param1.clickSound Sound key to play on touchdown
|
||||||
* @param {boolean=} param1.preventClick Whether to prevent click events
|
* @param {boolean=} param1.preventClick Whether to prevent click events
|
||||||
*/
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
element,
|
element,
|
||||||
{
|
{
|
||||||
consumeEvents = false,
|
consumeEvents = false,
|
||||||
preventDefault = true,
|
preventDefault = true,
|
||||||
applyCssClass = "pressed",
|
applyCssClass = "pressed",
|
||||||
captureTouchmove = false,
|
captureTouchmove = false,
|
||||||
targetOnly = false,
|
targetOnly = false,
|
||||||
maxDistance = MAX_MOVE_DISTANCE_PX,
|
maxDistance = MAX_MOVE_DISTANCE_PX,
|
||||||
clickSound = SOUNDS.uiClick,
|
clickSound = SOUNDS.uiClick,
|
||||||
preventClick = false,
|
preventClick = false,
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
assert(element, "No element given!");
|
assert(element, "No element given!");
|
||||||
this.clickDownPosition = null;
|
this.clickDownPosition = null;
|
||||||
|
|
||||||
this.consumeEvents = consumeEvents;
|
this.consumeEvents = consumeEvents;
|
||||||
this.preventDefault = preventDefault;
|
this.preventDefault = preventDefault;
|
||||||
this.applyCssClass = applyCssClass;
|
this.applyCssClass = applyCssClass;
|
||||||
this.captureTouchmove = captureTouchmove;
|
this.captureTouchmove = captureTouchmove;
|
||||||
this.targetOnly = targetOnly;
|
this.targetOnly = targetOnly;
|
||||||
this.clickSound = clickSound;
|
this.clickSound = clickSound;
|
||||||
this.maxDistance = maxDistance;
|
this.maxDistance = maxDistance;
|
||||||
this.preventClick = preventClick;
|
this.preventClick = preventClick;
|
||||||
|
|
||||||
// Signals
|
// Signals
|
||||||
this.click = new Signal();
|
this.click = new Signal();
|
||||||
this.rightClick = new Signal();
|
this.rightClick = new Signal();
|
||||||
this.touchstart = new Signal();
|
this.touchstart = new Signal();
|
||||||
this.touchmove = new Signal();
|
this.touchmove = new Signal();
|
||||||
this.touchend = new Signal();
|
this.touchend = new Signal();
|
||||||
this.touchcancel = new Signal();
|
this.touchcancel = new Signal();
|
||||||
|
|
||||||
// Simple signals which just receive the touch position
|
// Simple signals which just receive the touch position
|
||||||
this.touchstartSimple = new Signal();
|
this.touchstartSimple = new Signal();
|
||||||
this.touchmoveSimple = new Signal();
|
this.touchmoveSimple = new Signal();
|
||||||
this.touchendSimple = new Signal();
|
this.touchendSimple = new Signal();
|
||||||
|
|
||||||
// Store time of touch start
|
// Store time of touch start
|
||||||
this.clickStartTime = null;
|
this.clickStartTime = null;
|
||||||
|
|
||||||
// A click can be cancelled if another detector registers a click
|
// A click can be cancelled if another detector registers a click
|
||||||
this.cancelled = false;
|
this.cancelled = false;
|
||||||
|
|
||||||
this.internalBindTo(/** @type {HTMLElement} */ (element));
|
this.internalBindTo(/** @type {HTMLElement} */ (element));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cleans up all event listeners of this detector
|
* Cleans up all event listeners of this detector
|
||||||
*/
|
*/
|
||||||
cleanup() {
|
cleanup() {
|
||||||
if (this.element) {
|
if (this.element) {
|
||||||
if (registerClickDetectors) {
|
if (registerClickDetectors) {
|
||||||
const index = window.activeClickDetectors.indexOf(this);
|
const index = window.activeClickDetectors.indexOf(this);
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
logger.error("Click detector cleanup but is not active");
|
logger.error("Click detector cleanup but is not active");
|
||||||
} else {
|
} else {
|
||||||
window.activeClickDetectors.splice(index, 1);
|
window.activeClickDetectors.splice(index, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const options = this.internalGetEventListenerOptions();
|
const options = this.internalGetEventListenerOptions();
|
||||||
|
|
||||||
if (SUPPORT_TOUCH) {
|
if (SUPPORT_TOUCH) {
|
||||||
this.element.removeEventListener("touchstart", this.handlerTouchStart, options);
|
this.element.removeEventListener("touchstart", this.handlerTouchStart, options);
|
||||||
this.element.removeEventListener("touchend", this.handlerTouchEnd, options);
|
this.element.removeEventListener("touchend", this.handlerTouchEnd, options);
|
||||||
this.element.removeEventListener("touchcancel", this.handlerTouchCancel, options);
|
this.element.removeEventListener("touchcancel", this.handlerTouchCancel, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.element.removeEventListener("mouseup", this.handlerTouchStart, options);
|
this.element.removeEventListener("mouseup", this.handlerTouchStart, options);
|
||||||
this.element.removeEventListener("mousedown", this.handlerTouchEnd, options);
|
this.element.removeEventListener("mousedown", this.handlerTouchEnd, options);
|
||||||
this.element.removeEventListener("mouseout", this.handlerTouchCancel, options);
|
this.element.removeEventListener("mouseout", this.handlerTouchCancel, options);
|
||||||
|
|
||||||
if (this.captureTouchmove) {
|
if (this.captureTouchmove) {
|
||||||
if (SUPPORT_TOUCH) {
|
if (SUPPORT_TOUCH) {
|
||||||
this.element.removeEventListener("touchmove", this.handlerTouchMove, options);
|
this.element.removeEventListener("touchmove", this.handlerTouchMove, options);
|
||||||
}
|
}
|
||||||
this.element.removeEventListener("mousemove", this.handlerTouchMove, options);
|
this.element.removeEventListener("mousemove", this.handlerTouchMove, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.preventClick) {
|
if (this.preventClick) {
|
||||||
this.element.removeEventListener("click", this.handlerPreventClick, options);
|
this.element.removeEventListener("click", this.handlerPreventClick, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.click.removeAll();
|
this.click.removeAll();
|
||||||
this.touchstart.removeAll();
|
this.touchstart.removeAll();
|
||||||
this.touchmove.removeAll();
|
this.touchmove.removeAll();
|
||||||
this.touchend.removeAll();
|
this.touchend.removeAll();
|
||||||
this.touchcancel.removeAll();
|
this.touchcancel.removeAll();
|
||||||
|
|
||||||
// TODO: Remove pointer captures
|
this.element = null;
|
||||||
|
}
|
||||||
this.element = null;
|
}
|
||||||
}
|
|
||||||
}
|
// INTERNAL METHODS
|
||||||
|
|
||||||
// INTERNAL METHODS
|
/**
|
||||||
|
*
|
||||||
/**
|
* @param {Event} event
|
||||||
*
|
*/
|
||||||
* @param {Event} event
|
internalPreventClick(event) {
|
||||||
*/
|
window.focus();
|
||||||
internalPreventClick(event) {
|
event.preventDefault();
|
||||||
window.focus();
|
}
|
||||||
event.preventDefault();
|
|
||||||
}
|
/**
|
||||||
|
* Internal method to get the options to pass to an event listener
|
||||||
/**
|
*/
|
||||||
* Internal method to get the options to pass to an event listener
|
internalGetEventListenerOptions() {
|
||||||
*/
|
return {
|
||||||
internalGetEventListenerOptions() {
|
capture: this.consumeEvents,
|
||||||
return {
|
passive: !this.preventDefault,
|
||||||
capture: this.consumeEvents,
|
};
|
||||||
passive: !this.preventDefault,
|
}
|
||||||
};
|
|
||||||
}
|
/**
|
||||||
|
* Binds the click detector to an element
|
||||||
/**
|
* @param {HTMLElement} element
|
||||||
* Binds the click detector to an element
|
*/
|
||||||
* @param {HTMLElement} element
|
internalBindTo(element) {
|
||||||
*/
|
const options = this.internalGetEventListenerOptions();
|
||||||
internalBindTo(element) {
|
|
||||||
const options = this.internalGetEventListenerOptions();
|
this.handlerTouchStart = this.internalOnPointerDown.bind(this);
|
||||||
|
this.handlerTouchEnd = this.internalOnPointerEnd.bind(this);
|
||||||
this.handlerTouchStart = this.internalOnPointerDown.bind(this);
|
this.handlerTouchMove = this.internalOnPointerMove.bind(this);
|
||||||
this.handlerTouchEnd = this.internalOnPointerEnd.bind(this);
|
this.handlerTouchCancel = this.internalOnTouchCancel.bind(this);
|
||||||
this.handlerTouchMove = this.internalOnPointerMove.bind(this);
|
|
||||||
this.handlerTouchCancel = this.internalOnTouchCancel.bind(this);
|
if (this.preventClick) {
|
||||||
|
this.handlerPreventClick = this.internalPreventClick.bind(this);
|
||||||
if (this.preventClick) {
|
element.addEventListener("click", this.handlerPreventClick, options);
|
||||||
this.handlerPreventClick = this.internalPreventClick.bind(this);
|
}
|
||||||
element.addEventListener("click", this.handlerPreventClick, options);
|
|
||||||
}
|
if (SUPPORT_TOUCH) {
|
||||||
|
element.addEventListener("touchstart", this.handlerTouchStart, options);
|
||||||
if (SUPPORT_TOUCH) {
|
element.addEventListener("touchend", this.handlerTouchEnd, options);
|
||||||
element.addEventListener("touchstart", this.handlerTouchStart, options);
|
element.addEventListener("touchcancel", this.handlerTouchCancel, options);
|
||||||
element.addEventListener("touchend", this.handlerTouchEnd, options);
|
}
|
||||||
element.addEventListener("touchcancel", this.handlerTouchCancel, options);
|
|
||||||
}
|
element.addEventListener("mousedown", this.handlerTouchStart, options);
|
||||||
|
element.addEventListener("mouseup", this.handlerTouchEnd, options);
|
||||||
element.addEventListener("mousedown", this.handlerTouchStart, options);
|
element.addEventListener("mouseout", this.handlerTouchCancel, options);
|
||||||
element.addEventListener("mouseup", this.handlerTouchEnd, options);
|
|
||||||
element.addEventListener("mouseout", this.handlerTouchCancel, options);
|
if (this.captureTouchmove) {
|
||||||
|
if (SUPPORT_TOUCH) {
|
||||||
if (this.captureTouchmove) {
|
element.addEventListener("touchmove", this.handlerTouchMove, options);
|
||||||
if (SUPPORT_TOUCH) {
|
}
|
||||||
element.addEventListener("touchmove", this.handlerTouchMove, options);
|
element.addEventListener("mousemove", this.handlerTouchMove, options);
|
||||||
}
|
}
|
||||||
element.addEventListener("mousemove", this.handlerTouchMove, options);
|
|
||||||
}
|
if (registerClickDetectors) {
|
||||||
|
window.activeClickDetectors.push(this);
|
||||||
if (registerClickDetectors) {
|
}
|
||||||
window.activeClickDetectors.push(this);
|
this.element = element;
|
||||||
}
|
}
|
||||||
this.element = element;
|
|
||||||
}
|
/**
|
||||||
|
* Returns if the bound element is currently in the DOM.
|
||||||
/**
|
*/
|
||||||
* Returns if the bound element is currently in the DOM.
|
internalIsDomElementAttached() {
|
||||||
*/
|
return this.element && document.documentElement.contains(this.element);
|
||||||
internalIsDomElementAttached() {
|
}
|
||||||
return this.element && document.documentElement.contains(this.element);
|
|
||||||
}
|
/**
|
||||||
|
* Checks if the given event is relevant for this detector
|
||||||
/**
|
* @param {TouchEvent|MouseEvent} event
|
||||||
* Checks if the given event is relevant for this detector
|
*/
|
||||||
* @param {TouchEvent|MouseEvent} event
|
internalEventPreHandler(event, expectedRemainingTouches = 1) {
|
||||||
*/
|
if (!this.element) {
|
||||||
internalEventPreHandler(event, expectedRemainingTouches = 1) {
|
// Already cleaned up
|
||||||
if (!this.element) {
|
return false;
|
||||||
// Already cleaned up
|
}
|
||||||
return false;
|
|
||||||
}
|
if (this.targetOnly && event.target !== this.element) {
|
||||||
|
// Clicked a child element
|
||||||
if (this.targetOnly && event.target !== this.element) {
|
return false;
|
||||||
// Clicked a child element
|
}
|
||||||
return false;
|
|
||||||
}
|
// Stop any propagation and defaults if configured
|
||||||
|
if (this.consumeEvents && event.cancelable) {
|
||||||
// Stop any propagation and defaults if configured
|
event.stopPropagation();
|
||||||
if (this.consumeEvents && event.cancelable) {
|
}
|
||||||
event.stopPropagation();
|
|
||||||
}
|
if (this.preventDefault && event.cancelable) {
|
||||||
|
event.preventDefault();
|
||||||
if (this.preventDefault && event.cancelable) {
|
}
|
||||||
event.preventDefault();
|
|
||||||
}
|
if (window.TouchEvent && event instanceof TouchEvent) {
|
||||||
|
clickDetectorGlobals.lastTouchTime = performance.now();
|
||||||
if (window.TouchEvent && event instanceof TouchEvent) {
|
|
||||||
clickDetectorGlobals.lastTouchTime = performance.now();
|
// console.log("Got touches", event.targetTouches.length, "vs", expectedRemainingTouches);
|
||||||
|
if (event.targetTouches.length !== expectedRemainingTouches) {
|
||||||
// console.log("Got touches", event.targetTouches.length, "vs", expectedRemainingTouches);
|
return false;
|
||||||
if (event.targetTouches.length !== expectedRemainingTouches) {
|
}
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
}
|
if (event instanceof MouseEvent) {
|
||||||
|
if (performance.now() - clickDetectorGlobals.lastTouchTime < 1000.0) {
|
||||||
if (event instanceof MouseEvent) {
|
return false;
|
||||||
if (performance.now() - clickDetectorGlobals.lastTouchTime < 1000.0) {
|
}
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
return true;
|
|
||||||
}
|
/**
|
||||||
|
* Extracts the mous position from an event
|
||||||
/**
|
* @param {TouchEvent|MouseEvent} event
|
||||||
* Extracts the mous position from an event
|
* @returns {Vector} The client space position
|
||||||
* @param {TouchEvent|MouseEvent} event
|
*/
|
||||||
* @returns {Vector} The client space position
|
static extractPointerPosition(event) {
|
||||||
*/
|
if (window.TouchEvent && event instanceof TouchEvent) {
|
||||||
static extractPointerPosition(event) {
|
if (event.changedTouches.length !== 1) {
|
||||||
if (window.TouchEvent && event instanceof TouchEvent) {
|
logger.warn(
|
||||||
if (event.changedTouches.length !== 1) {
|
"Got unexpected target touches:",
|
||||||
logger.warn(
|
event.targetTouches.length,
|
||||||
"Got unexpected target touches:",
|
"->",
|
||||||
event.targetTouches.length,
|
event.targetTouches
|
||||||
"->",
|
);
|
||||||
event.targetTouches
|
return new Vector(0, 0);
|
||||||
);
|
}
|
||||||
return new Vector(0, 0);
|
|
||||||
}
|
const touch = event.changedTouches[0];
|
||||||
|
return new Vector(touch.clientX, touch.clientY);
|
||||||
const touch = event.changedTouches[0];
|
}
|
||||||
return new Vector(touch.clientX, touch.clientY);
|
|
||||||
}
|
if (event instanceof MouseEvent) {
|
||||||
|
return new Vector(event.clientX, event.clientY);
|
||||||
if (event instanceof MouseEvent) {
|
}
|
||||||
return new Vector(event.clientX, event.clientY);
|
|
||||||
}
|
assertAlways(false, "Got unknown event: " + event);
|
||||||
|
|
||||||
assertAlways(false, "Got unknown event: " + event);
|
return new Vector(0, 0);
|
||||||
|
}
|
||||||
return new Vector(0, 0);
|
|
||||||
}
|
/**
|
||||||
|
* Cacnels all ongoing events on this detector
|
||||||
/**
|
*/
|
||||||
* Cacnels all ongoing events on this detector
|
cancelOngoingEvents() {
|
||||||
*/
|
if (this.applyCssClass && this.element) {
|
||||||
cancelOngoingEvents() {
|
this.element.classList.remove(this.applyCssClass);
|
||||||
if (this.applyCssClass && this.element) {
|
}
|
||||||
this.element.classList.remove(this.applyCssClass);
|
this.clickDownPosition = null;
|
||||||
}
|
this.clickStartTime = null;
|
||||||
this.clickDownPosition = null;
|
this.cancelled = true;
|
||||||
this.clickStartTime = null;
|
fastArrayDeleteValueIfContained(ongoingClickDetectors, this);
|
||||||
this.cancelled = true;
|
}
|
||||||
fastArrayDeleteValueIfContained(ongoingClickDetectors, this);
|
|
||||||
}
|
/**
|
||||||
|
* Internal pointer down handler
|
||||||
/**
|
* @param {TouchEvent|MouseEvent} event
|
||||||
* Internal pointer down handler
|
*/
|
||||||
* @param {TouchEvent|MouseEvent} event
|
internalOnPointerDown(event) {
|
||||||
*/
|
window.focus();
|
||||||
internalOnPointerDown(event) {
|
|
||||||
window.focus();
|
if (!this.internalEventPreHandler(event, 1)) {
|
||||||
|
return false;
|
||||||
if (!this.internalEventPreHandler(event, 1)) {
|
}
|
||||||
return false;
|
|
||||||
}
|
const position = /** @type {typeof ClickDetector} */ (this.constructor).extractPointerPosition(event);
|
||||||
|
|
||||||
const position = /** @type {typeof ClickDetector} */ (this.constructor).extractPointerPosition(event);
|
if (event instanceof MouseEvent) {
|
||||||
|
const isRightClick = event.button === 2;
|
||||||
if (event instanceof MouseEvent) {
|
if (isRightClick) {
|
||||||
const isRightClick = event.button === 2;
|
// Ignore right clicks
|
||||||
if (isRightClick) {
|
this.rightClick.dispatch(position, event);
|
||||||
// Ignore right clicks
|
this.cancelled = true;
|
||||||
this.rightClick.dispatch(position, event);
|
this.clickDownPosition = null;
|
||||||
this.cancelled = true;
|
return;
|
||||||
this.clickDownPosition = null;
|
}
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
}
|
if (this.clickDownPosition) {
|
||||||
|
logger.warn("Ignoring double click");
|
||||||
if (this.clickDownPosition) {
|
return false;
|
||||||
logger.warn("Ignoring double click");
|
}
|
||||||
return false;
|
|
||||||
}
|
this.cancelled = false;
|
||||||
|
this.touchstart.dispatch(event);
|
||||||
this.cancelled = false;
|
|
||||||
this.touchstart.dispatch(event);
|
// Store where the touch started
|
||||||
|
this.clickDownPosition = position;
|
||||||
// Store where the touch started
|
this.clickStartTime = performance.now();
|
||||||
this.clickDownPosition = position;
|
this.touchstartSimple.dispatch(this.clickDownPosition.x, this.clickDownPosition.y);
|
||||||
this.clickStartTime = performance.now();
|
|
||||||
this.touchstartSimple.dispatch(this.clickDownPosition.x, this.clickDownPosition.y);
|
// If we are not currently within a click, register it
|
||||||
|
if (ongoingClickDetectors.indexOf(this) < 0) {
|
||||||
// If we are not currently within a click, register it
|
ongoingClickDetectors.push(this);
|
||||||
if (ongoingClickDetectors.indexOf(this) < 0) {
|
} else {
|
||||||
ongoingClickDetectors.push(this);
|
logger.warn("Click detector got pointer down of active pointer twice");
|
||||||
} else {
|
}
|
||||||
logger.warn("Click detector got pointer down of active pointer twice");
|
|
||||||
}
|
// If we should apply any classes, do this now
|
||||||
|
if (this.applyCssClass) {
|
||||||
// If we should apply any classes, do this now
|
this.element.classList.add(this.applyCssClass);
|
||||||
if (this.applyCssClass) {
|
}
|
||||||
this.element.classList.add(this.applyCssClass);
|
|
||||||
}
|
// If we should play any sound, do this
|
||||||
|
if (this.clickSound) {
|
||||||
// If we should play any sound, do this
|
GLOBAL_APP.sound.playUiSound(this.clickSound);
|
||||||
if (this.clickSound) {
|
}
|
||||||
GLOBAL_APP.sound.playUiSound(this.clickSound);
|
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
return false;
|
|
||||||
}
|
/**
|
||||||
|
* Internal pointer move handler
|
||||||
/**
|
* @param {TouchEvent|MouseEvent} event
|
||||||
* Internal pointer move handler
|
*/
|
||||||
* @param {TouchEvent|MouseEvent} event
|
internalOnPointerMove(event) {
|
||||||
*/
|
if (!this.internalEventPreHandler(event, 1)) {
|
||||||
internalOnPointerMove(event) {
|
return false;
|
||||||
if (!this.internalEventPreHandler(event, 1)) {
|
}
|
||||||
return false;
|
this.touchmove.dispatch(event);
|
||||||
}
|
const pos = /** @type {typeof ClickDetector} */ (this.constructor).extractPointerPosition(event);
|
||||||
this.touchmove.dispatch(event);
|
this.touchmoveSimple.dispatch(pos.x, pos.y);
|
||||||
const pos = /** @type {typeof ClickDetector} */ (this.constructor).extractPointerPosition(event);
|
return false;
|
||||||
this.touchmoveSimple.dispatch(pos.x, pos.y);
|
}
|
||||||
return false;
|
|
||||||
}
|
/**
|
||||||
|
* Internal pointer end handler
|
||||||
/**
|
* @param {TouchEvent|MouseEvent} event
|
||||||
* Internal pointer end handler
|
*/
|
||||||
* @param {TouchEvent|MouseEvent} event
|
internalOnPointerEnd(event) {
|
||||||
*/
|
window.focus();
|
||||||
internalOnPointerEnd(event) {
|
|
||||||
window.focus();
|
if (!this.internalEventPreHandler(event, 0)) {
|
||||||
|
return false;
|
||||||
if (!this.internalEventPreHandler(event, 0)) {
|
}
|
||||||
return false;
|
|
||||||
}
|
if (this.cancelled) {
|
||||||
|
// warn(this, "Not dispatching touchend on cancelled listener");
|
||||||
if (this.cancelled) {
|
return false;
|
||||||
// warn(this, "Not dispatching touchend on cancelled listener");
|
}
|
||||||
return false;
|
|
||||||
}
|
if (event instanceof MouseEvent) {
|
||||||
|
const isRightClick = event.button === 2;
|
||||||
if (event instanceof MouseEvent) {
|
if (isRightClick) {
|
||||||
const isRightClick = event.button === 2;
|
return;
|
||||||
if (isRightClick) {
|
}
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
}
|
const index = ongoingClickDetectors.indexOf(this);
|
||||||
|
if (index < 0) {
|
||||||
const index = ongoingClickDetectors.indexOf(this);
|
logger.warn("Got pointer end but click detector is not in pressed state");
|
||||||
if (index < 0) {
|
} else {
|
||||||
logger.warn("Got pointer end but click detector is not in pressed state");
|
fastArrayDelete(ongoingClickDetectors, index);
|
||||||
} else {
|
}
|
||||||
fastArrayDelete(ongoingClickDetectors, index);
|
|
||||||
}
|
let dispatchClick = false;
|
||||||
|
let dispatchClickPos = null;
|
||||||
let dispatchClick = false;
|
|
||||||
let dispatchClickPos = null;
|
// Check for correct down position, otherwise must have pinched or so
|
||||||
|
if (this.clickDownPosition) {
|
||||||
// Check for correct down position, otherwise must have pinched or so
|
const pos = /** @type {typeof ClickDetector} */ (this.constructor).extractPointerPosition(event);
|
||||||
if (this.clickDownPosition) {
|
const distance = pos.distance(this.clickDownPosition);
|
||||||
const pos = /** @type {typeof ClickDetector} */ (this.constructor).extractPointerPosition(event);
|
if (!IS_MOBILE || distance <= this.maxDistance) {
|
||||||
const distance = pos.distance(this.clickDownPosition);
|
dispatchClick = true;
|
||||||
if (!IS_MOBILE || distance <= this.maxDistance) {
|
dispatchClickPos = pos;
|
||||||
dispatchClick = true;
|
} else {
|
||||||
dispatchClickPos = pos;
|
console.warn("[ClickDetector] Touch does not count as click:", "(was", distance, ")");
|
||||||
} else {
|
}
|
||||||
console.warn("[ClickDetector] Touch does not count as click:", "(was", distance, ")");
|
}
|
||||||
}
|
|
||||||
}
|
this.clickDownPosition = null;
|
||||||
|
this.clickStartTime = null;
|
||||||
this.clickDownPosition = null;
|
|
||||||
this.clickStartTime = null;
|
if (this.applyCssClass) {
|
||||||
|
this.element.classList.remove(this.applyCssClass);
|
||||||
if (this.applyCssClass) {
|
}
|
||||||
this.element.classList.remove(this.applyCssClass);
|
|
||||||
}
|
// Dispatch in the end to avoid the element getting invalidated
|
||||||
|
// Also make sure that the element is still in the dom
|
||||||
// Dispatch in the end to avoid the element getting invalidated
|
if (this.internalIsDomElementAttached()) {
|
||||||
// Also make sure that the element is still in the dom
|
this.touchend.dispatch(event);
|
||||||
if (this.internalIsDomElementAttached()) {
|
this.touchendSimple.dispatch();
|
||||||
this.touchend.dispatch(event);
|
|
||||||
this.touchendSimple.dispatch();
|
if (dispatchClick) {
|
||||||
|
const detectors = ongoingClickDetectors.slice();
|
||||||
if (dispatchClick) {
|
for (let i = 0; i < detectors.length; ++i) {
|
||||||
const detectors = ongoingClickDetectors.slice();
|
detectors[i].cancelOngoingEvents();
|
||||||
for (let i = 0; i < detectors.length; ++i) {
|
}
|
||||||
detectors[i].cancelOngoingEvents();
|
this.click.dispatch(dispatchClickPos, event);
|
||||||
}
|
}
|
||||||
this.click.dispatch(dispatchClickPos, event);
|
}
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
/**
|
||||||
|
* Internal touch cancel handler
|
||||||
/**
|
* @param {TouchEvent|MouseEvent} event
|
||||||
* Internal touch cancel handler
|
*/
|
||||||
* @param {TouchEvent|MouseEvent} event
|
internalOnTouchCancel(event) {
|
||||||
*/
|
if (!this.internalEventPreHandler(event, 0)) {
|
||||||
internalOnTouchCancel(event) {
|
return false;
|
||||||
if (!this.internalEventPreHandler(event, 0)) {
|
}
|
||||||
return false;
|
|
||||||
}
|
if (this.cancelled) {
|
||||||
|
// warn(this, "Not dispatching touchcancel on cancelled listener");
|
||||||
if (this.cancelled) {
|
return false;
|
||||||
// warn(this, "Not dispatching touchcancel on cancelled listener");
|
}
|
||||||
return false;
|
|
||||||
}
|
this.cancelOngoingEvents();
|
||||||
|
this.touchcancel.dispatch(event);
|
||||||
this.cancelOngoingEvents();
|
this.touchendSimple.dispatch(event);
|
||||||
this.touchcancel.dispatch(event);
|
return false;
|
||||||
this.touchendSimple.dispatch(event);
|
}
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
import { queryParamOptions } from "./query_parameters";
|
|
||||||
|
|
||||||
export const IS_DEBUG =
|
export const IS_DEBUG =
|
||||||
G_IS_DEV &&
|
G_IS_DEV &&
|
||||||
typeof window !== "undefined" &&
|
typeof window !== "undefined" &&
|
||||||
@ -7,13 +5,10 @@ export const IS_DEBUG =
|
|||||||
(window.location.host.indexOf("localhost:") >= 0 || window.location.host.indexOf("192.168.0.") >= 0) &&
|
(window.location.host.indexOf("localhost:") >= 0 || window.location.host.indexOf("192.168.0.") >= 0) &&
|
||||||
window.location.search.indexOf("nodebug") < 0;
|
window.location.search.indexOf("nodebug") < 0;
|
||||||
|
|
||||||
export const IS_DEMO = queryParamOptions.fullVersion
|
|
||||||
? false
|
|
||||||
: (!G_IS_DEV && !G_IS_STANDALONE) ||
|
|
||||||
(typeof window !== "undefined" && window.location.search.indexOf("demo") >= 0);
|
|
||||||
|
|
||||||
export const SUPPORT_TOUCH = false;
|
export const SUPPORT_TOUCH = false;
|
||||||
|
|
||||||
|
export const IS_MAC = navigator.platform.toLowerCase().indexOf("mac") >= 0;
|
||||||
|
|
||||||
const smoothCanvas = true;
|
const smoothCanvas = true;
|
||||||
|
|
||||||
export const THIRDPARTY_URLS = {
|
export const THIRDPARTY_URLS = {
|
||||||
@ -23,9 +18,16 @@ 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/",
|
||||||
|
|
||||||
|
levelTutorialVideos: {
|
||||||
|
21: "https://www.youtube.com/watch?v=0nUfRLMCcgo&",
|
||||||
|
25: "https://www.youtube.com/watch?v=7OCV1g40Iew&",
|
||||||
|
26: "https://www.youtube.com/watch?v=gfm6dS1dCoY",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const A_B_TESTING_LINK_TYPE = Math.random() > 0.5 ? "steam_1_pr" : "steam_2_npr";
|
// export const A_B_TESTING_LINK_TYPE = Math.random() > 0.95 ? "steam_1_pr" : "steam_2_npr";
|
||||||
|
export const A_B_TESTING_LINK_TYPE = "steam_2_npr";
|
||||||
|
|
||||||
export const globalConfig = {
|
export const globalConfig = {
|
||||||
// Size of a single tile in Pixels.
|
// Size of a single tile in Pixels.
|
||||||
@ -64,7 +66,7 @@ export const globalConfig = {
|
|||||||
|
|
||||||
undergroundBeltMaxTilesByTier: [5, 9],
|
undergroundBeltMaxTilesByTier: [5, 9],
|
||||||
|
|
||||||
readerAnalyzeIntervalSeconds: G_IS_DEV ? 3 : 10,
|
readerAnalyzeIntervalSeconds: 10,
|
||||||
|
|
||||||
buildingSpeeds: {
|
buildingSpeeds: {
|
||||||
cutter: 1 / 4,
|
cutter: 1 / 4,
|
||||||
@ -137,3 +139,8 @@ if (G_IS_DEV && globalConfig.debug.renderForTrailer) {
|
|||||||
if (globalConfig.debug.fastGameEnter) {
|
if (globalConfig.debug.fastGameEnter) {
|
||||||
globalConfig.debug.noArtificialDelays = true;
|
globalConfig.debug.noArtificialDelays = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (G_IS_DEV && globalConfig.debug.noArtificialDelays) {
|
||||||
|
globalConfig.warmupTimeSecondsFast = 0;
|
||||||
|
globalConfig.warmupTimeSecondsRegular = 0;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,26 +1,25 @@
|
|||||||
import { globalConfig } from "./config";
|
import { globalConfig } from "./config";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import("../game/root").GameRoot} GameRoot
|
* @typedef {import("../game/root").GameRoot} GameRoot
|
||||||
* @typedef {import("./rectangle").Rectangle} Rectangle
|
* @typedef {import("./rectangle").Rectangle} Rectangle
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export class DrawParameters {
|
export class DrawParameters {
|
||||||
constructor({ context, visibleRect, desiredAtlasScale, zoomLevel, root }) {
|
constructor({ context, visibleRect, desiredAtlasScale, zoomLevel, root }) {
|
||||||
/** @type {CanvasRenderingContext2D} */
|
/** @type {CanvasRenderingContext2D} */
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
|
||||||
/** @type {Rectangle} */
|
/** @type {Rectangle} */
|
||||||
this.visibleRect = visibleRect;
|
this.visibleRect = visibleRect;
|
||||||
|
|
||||||
/** @type {string} */
|
/** @type {string} */
|
||||||
this.desiredAtlasScale = desiredAtlasScale;
|
this.desiredAtlasScale = desiredAtlasScale;
|
||||||
|
|
||||||
/** @type {number} */
|
/** @type {number} */
|
||||||
this.zoomLevel = zoomLevel;
|
this.zoomLevel = zoomLevel;
|
||||||
|
|
||||||
// FIXME: Not really nice
|
/** @type {GameRoot} */
|
||||||
/** @type {GameRoot} */
|
this.root = root;
|
||||||
this.root = root;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@ -13,6 +13,17 @@ import { getStringForKeyCode } from "../game/key_action_mapper";
|
|||||||
import { createLogger } from "./logging";
|
import { createLogger } from "./logging";
|
||||||
import { T } from "../translations";
|
import { T } from "../translations";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ***************************************************
|
||||||
|
*
|
||||||
|
* LEGACY CODE WARNING
|
||||||
|
*
|
||||||
|
* This is old code from yorg3.io and needs to be refactored
|
||||||
|
* @TODO
|
||||||
|
*
|
||||||
|
* ***************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
const kbEnter = 13;
|
const kbEnter = 13;
|
||||||
const kbCancel = 27;
|
const kbCancel = 27;
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,17 @@ import { BaseItem } from "../game/base_item";
|
|||||||
import { ClickDetector } from "./click_detector";
|
import { ClickDetector } from "./click_detector";
|
||||||
import { Signal } from "./signal";
|
import { Signal } from "./signal";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ***************************************************
|
||||||
|
*
|
||||||
|
* LEGACY CODE WARNING
|
||||||
|
*
|
||||||
|
* This is old code from yorg3.io and needs to be refactored
|
||||||
|
* @TODO
|
||||||
|
*
|
||||||
|
* ***************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
export class FormElement {
|
export class FormElement {
|
||||||
constructor(id, label) {
|
constructor(id, label) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
|||||||
@ -81,10 +81,6 @@ export class ReadWriteProxy {
|
|||||||
return this.writeAsync();
|
return this.writeAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
getCurrentData() {
|
|
||||||
return this.currentData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {object} obj
|
* @param {object} obj
|
||||||
|
|||||||
154
src/js/core/restriction_manager.js
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
/* typehints:start */
|
||||||
|
import { Application } from "../application";
|
||||||
|
/* typehints:end */
|
||||||
|
import { IS_MAC } from "./config";
|
||||||
|
import { ExplainedResult } from "./explained_result";
|
||||||
|
import { queryParamOptions } from "./query_parameters";
|
||||||
|
import { ReadWriteProxy } from "./read_write_proxy";
|
||||||
|
|
||||||
|
export class RestrictionManager extends ReadWriteProxy {
|
||||||
|
/**
|
||||||
|
* @param {Application} app
|
||||||
|
*/
|
||||||
|
constructor(app) {
|
||||||
|
super(app, "restriction-flags.bin");
|
||||||
|
|
||||||
|
this.currentData = this.getDefaultData();
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- RW Proxy Impl
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {any} data
|
||||||
|
*/
|
||||||
|
verify(data) {
|
||||||
|
return ExplainedResult.good();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
getDefaultData() {
|
||||||
|
return {
|
||||||
|
version: this.getCurrentVersion(),
|
||||||
|
savegameV1119Imported: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
getCurrentVersion() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {any} data
|
||||||
|
*/
|
||||||
|
migrate(data) {
|
||||||
|
return ExplainedResult.good();
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize() {
|
||||||
|
return this.readAsync().then(() => {
|
||||||
|
if (this.currentData.savegameV1119Imported) {
|
||||||
|
console.warn("Levelunlock is granted to current user due to past savegame");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- End RW Proxy Impl
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if there are any savegames from the 1.1.19 version
|
||||||
|
*/
|
||||||
|
onHasLegacySavegamesChanged(has119Savegames = false) {
|
||||||
|
if (has119Savegames && !this.currentData.savegameV1119Imported) {
|
||||||
|
this.currentData.savegameV1119Imported = true;
|
||||||
|
console.warn("Current user now has access to all levels due to 1119 savegame");
|
||||||
|
return this.writeAsync();
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if the app is currently running as the limited version
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
isLimitedVersion() {
|
||||||
|
if (IS_MAC) {
|
||||||
|
// On mac, the full version is always active
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (G_IS_STANDALONE) {
|
||||||
|
// Standalone is never limited
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (queryParamOptions.fullVersion) {
|
||||||
|
// Full version is activated via flag
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (G_IS_DEV) {
|
||||||
|
return typeof window !== "undefined" && window.location.search.indexOf("demo") >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if the app markets the standalone version on steam
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
getIsStandaloneMarketingActive() {
|
||||||
|
return this.isLimitedVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if exporting the base as a screenshot is possible
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
getIsExportingScreenshotsPossible() {
|
||||||
|
return !this.isLimitedVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the maximum number of supported waypoints
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
getMaximumWaypoints() {
|
||||||
|
return this.isLimitedVersion() ? 2 : 1e20;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if the user has unlimited savegames
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
getHasUnlimitedSavegames() {
|
||||||
|
return !this.isLimitedVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if the app has all settings available
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
getHasExtendedSettings() {
|
||||||
|
return !this.isLimitedVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if all upgrades are available
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
getHasExtendedUpgrades() {
|
||||||
|
return !this.isLimitedVersion() || this.currentData.savegameV1119Imported;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if all levels & freeplay is available
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
getHasExtendedLevelsAndFreeplay() {
|
||||||
|
return !this.isLimitedVersion() || this.currentData.savegameV1119Imported;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -108,17 +108,6 @@ export class RandomNumberGenerator {
|
|||||||
assert(max > min, "rng: max <= min");
|
assert(max > min, "rng: max <= min");
|
||||||
return Math.floor(this.next() * (max - min) + min);
|
return Math.floor(this.next() * (max - min) + min);
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {number} min
|
|
||||||
* @param {number} max
|
|
||||||
* @returns {number} Integer in range [min, max]
|
|
||||||
*/
|
|
||||||
nextIntRangeInclusive(min, max) {
|
|
||||||
assert(Number.isFinite(min), "Minimum is no integer");
|
|
||||||
assert(Number.isFinite(max), "Maximum is no integer");
|
|
||||||
assert(max > min, "rng: max <= min");
|
|
||||||
return Math.round(this.next() * (max - min) + min);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {number} min
|
* @param {number} min
|
||||||
|
|||||||
@ -558,7 +558,16 @@ export function formatSeconds(secs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats a number like 2.5 to "2.5 items / s"
|
* Formats a number like 2.51 to "2.5"
|
||||||
|
* @param {number} speed
|
||||||
|
* @param {string=} separator The decimal separator for numbers like 50.1 (separator='.')
|
||||||
|
*/
|
||||||
|
export function round1DigitLocalized(speed, separator = T.global.decimalSeparator) {
|
||||||
|
return round1Digit(speed).toString().replace(".", separator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats a number like 2.51 to "2.51 items / s"
|
||||||
* @param {number} speed
|
* @param {number} speed
|
||||||
* @param {boolean=} double
|
* @param {boolean=} double
|
||||||
* @param {string=} separator The decimal separator for numbers like 50.1 (separator='.')
|
* @param {string=} separator The decimal separator for numbers like 50.1 (separator='.')
|
||||||
@ -681,3 +690,72 @@ export function fillInLinkIntoTranslation(translation, link) {
|
|||||||
.replace("<link>", "<a href='" + link + "' target='_blank'>")
|
.replace("<link>", "<a href='" + link + "' target='_blank'>")
|
||||||
.replace("</link>", "</a>");
|
.replace("</link>", "</a>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a file download
|
||||||
|
* @param {string} filename
|
||||||
|
* @param {string} text
|
||||||
|
*/
|
||||||
|
export function generateFileDownload(filename, text) {
|
||||||
|
var element = document.createElement("a");
|
||||||
|
element.setAttribute("href", "data:text/plain;charset=utf-8," + encodeURIComponent(text));
|
||||||
|
element.setAttribute("download", filename);
|
||||||
|
|
||||||
|
element.style.display = "none";
|
||||||
|
document.body.appendChild(element);
|
||||||
|
|
||||||
|
element.click();
|
||||||
|
document.body.removeChild(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts a file chooser
|
||||||
|
* @param {string} acceptedType
|
||||||
|
*/
|
||||||
|
export function startFileChoose(acceptedType = ".bin") {
|
||||||
|
var input = document.createElement("input");
|
||||||
|
input.type = "file";
|
||||||
|
input.accept = acceptedType;
|
||||||
|
|
||||||
|
return new Promise(resolve => {
|
||||||
|
input.onchange = _ => resolve(input.files[0]);
|
||||||
|
input.click();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const romanLiterals = [
|
||||||
|
"0", // NULL
|
||||||
|
"I",
|
||||||
|
"II",
|
||||||
|
"III",
|
||||||
|
"IV",
|
||||||
|
"V",
|
||||||
|
"VI",
|
||||||
|
"VII",
|
||||||
|
"VIII",
|
||||||
|
"IX",
|
||||||
|
"X",
|
||||||
|
"XI",
|
||||||
|
"XII",
|
||||||
|
"XIII",
|
||||||
|
"XIV",
|
||||||
|
"XV",
|
||||||
|
"XVI",
|
||||||
|
"XVII",
|
||||||
|
"XVIII",
|
||||||
|
"XIX",
|
||||||
|
"XX",
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {number} number
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export function getRomanNumber(number) {
|
||||||
|
number = Math.max(0, Math.round(number));
|
||||||
|
if (number < romanLiterals.length) {
|
||||||
|
return romanLiterals[number];
|
||||||
|
}
|
||||||
|
return String(number);
|
||||||
|
}
|
||||||
|
|||||||
@ -1111,7 +1111,7 @@ export class BeltPath extends BasicSerializableObject {
|
|||||||
|
|
||||||
isFirstItemProcessed = false;
|
isFirstItemProcessed = false;
|
||||||
this.spacingToFirstItem += clampedProgress;
|
this.spacingToFirstItem += clampedProgress;
|
||||||
if (remainingVelocity < 0.01) {
|
if (remainingVelocity < 1e-7) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,9 @@
|
|||||||
import { globalConfig } from "../core/config";
|
import { globalConfig } from "../core/config";
|
||||||
import { DrawParameters } from "../core/draw_parameters";
|
import { DrawParameters } from "../core/draw_parameters";
|
||||||
import { createLogger } from "../core/logging";
|
|
||||||
import { findNiceIntegerValue } from "../core/utils";
|
import { findNiceIntegerValue } from "../core/utils";
|
||||||
import { Vector } from "../core/vector";
|
import { Vector } from "../core/vector";
|
||||||
import { Entity } from "./entity";
|
import { Entity } from "./entity";
|
||||||
import { GameRoot } from "./root";
|
import { GameRoot } from "./root";
|
||||||
import { blueprintShape } from "./upgrades";
|
|
||||||
|
|
||||||
const logger = createLogger("blueprint");
|
|
||||||
|
|
||||||
export class Blueprint {
|
export class Blueprint {
|
||||||
/**
|
/**
|
||||||
@ -142,7 +138,7 @@ export class Blueprint {
|
|||||||
* @param {GameRoot} root
|
* @param {GameRoot} root
|
||||||
*/
|
*/
|
||||||
canAfford(root) {
|
canAfford(root) {
|
||||||
return root.hubGoals.getShapesStoredByKey(blueprintShape) >= this.getCost();
|
return root.hubGoals.getShapesStoredByKey(root.gameMode.getBlueprintShapeKey()) >= this.getCost();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -41,7 +41,7 @@ const variantsCache = new Map();
|
|||||||
export function registerBuildingVariant(
|
export function registerBuildingVariant(
|
||||||
code,
|
code,
|
||||||
meta,
|
meta,
|
||||||
variant = "default" /* FIXME: Circular dependency, actually its defaultBuildingVariant */,
|
variant = "default" /* @TODO: Circular dependency, actually its defaultBuildingVariant */,
|
||||||
rotationVariant = 0
|
rotationVariant = 0
|
||||||
) {
|
) {
|
||||||
assert(!gBuildingVariants[code], "Duplicate id: " + code);
|
assert(!gBuildingVariants[code], "Duplicate id: " + code);
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import { BeltComponent } from "../components/belt";
|
|||||||
import { Entity } from "../entity";
|
import { Entity } from "../entity";
|
||||||
import { MetaBuilding } from "../meta_building";
|
import { MetaBuilding } from "../meta_building";
|
||||||
import { GameRoot } from "../root";
|
import { GameRoot } from "../root";
|
||||||
|
import { THEME } from "../theme";
|
||||||
|
|
||||||
export const arrayBeltVariantToRotation = [enumDirection.top, enumDirection.left, enumDirection.right];
|
export const arrayBeltVariantToRotation = [enumDirection.top, enumDirection.left, enumDirection.right];
|
||||||
|
|
||||||
@ -22,7 +23,7 @@ export class MetaBeltBuilding extends MetaBuilding {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getSilhouetteColor() {
|
getSilhouetteColor() {
|
||||||
return "#777";
|
return THEME.map.chunkOverview.beltColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
getPlacementSound() {
|
getPlacementSound() {
|
||||||
|
|||||||
@ -191,7 +191,6 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding {
|
|||||||
) {
|
) {
|
||||||
tile = tile.addScalars(searchVector.x, searchVector.y);
|
tile = tile.addScalars(searchVector.x, searchVector.y);
|
||||||
|
|
||||||
/* WIRES: FIXME */
|
|
||||||
const contents = root.map.getTileContent(tile, "regular");
|
const contents = root.map.getTileContent(tile, "regular");
|
||||||
if (contents) {
|
if (contents) {
|
||||||
const undergroundComp = contents.components.UndergroundBelt;
|
const undergroundComp = contents.components.UndergroundBelt;
|
||||||
|
|||||||
@ -110,12 +110,7 @@ export class MetaVirtualProcessorBuilding extends MetaBuilding {
|
|||||||
pinComp.setSlots([
|
pinComp.setSlots([
|
||||||
{
|
{
|
||||||
pos: new Vector(0, 0),
|
pos: new Vector(0, 0),
|
||||||
direction: enumDirection.left,
|
direction: enumDirection.top,
|
||||||
type: enumPinSlotType.logicalEjector,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
pos: new Vector(0, 0),
|
|
||||||
direction: enumDirection.right,
|
|
||||||
type: enumPinSlotType.logicalEjector,
|
type: enumPinSlotType.logicalEjector,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -511,7 +511,11 @@ export class Camera extends BasicSerializableObject {
|
|||||||
this.clampZoomLevel();
|
this.clampZoomLevel();
|
||||||
this.desiredZoom = null;
|
this.desiredZoom = null;
|
||||||
|
|
||||||
const mousePosition = this.root.app.mousePosition;
|
let mousePosition = this.root.app.mousePosition;
|
||||||
|
if (!this.root.app.settings.getAllSettings().zoomToCursor) {
|
||||||
|
mousePosition = new Vector(this.root.gameWidth / 2, this.root.gameHeight / 2);
|
||||||
|
}
|
||||||
|
|
||||||
if (mousePosition) {
|
if (mousePosition) {
|
||||||
const worldPos = this.root.camera.screenToWorld(mousePosition);
|
const worldPos = this.root.camera.screenToWorld(mousePosition);
|
||||||
const worldDelta = worldPos.sub(this.center);
|
const worldDelta = worldPos.sub(this.center);
|
||||||
|
|||||||
@ -26,7 +26,7 @@ export class ItemEjectorComponent extends Component {
|
|||||||
static getSchema() {
|
static getSchema() {
|
||||||
// The cachedDestSlot, cachedTargetEntity fields are not serialized.
|
// The cachedDestSlot, cachedTargetEntity fields are not serialized.
|
||||||
return {
|
return {
|
||||||
slots: types.array(
|
slots: types.fixedSizeArray(
|
||||||
types.structured({
|
types.structured({
|
||||||
item: types.nullable(typeItemSingleton),
|
item: types.nullable(typeItemSingleton),
|
||||||
progress: types.float,
|
progress: types.float,
|
||||||
|
|||||||
@ -31,7 +31,7 @@ export class WiredPinsComponent extends Component {
|
|||||||
|
|
||||||
static getSchema() {
|
static getSchema() {
|
||||||
return {
|
return {
|
||||||
slots: types.array(
|
slots: types.fixedSizeArray(
|
||||||
types.structured({
|
types.structured({
|
||||||
value: types.nullable(typeItemSingleton),
|
value: types.nullable(typeItemSingleton),
|
||||||
})
|
})
|
||||||
|
|||||||
@ -31,6 +31,7 @@ import { KeyActionMapper } from "./key_action_mapper";
|
|||||||
import { GameLogic } from "./logic";
|
import { GameLogic } from "./logic";
|
||||||
import { MapView } from "./map_view";
|
import { MapView } from "./map_view";
|
||||||
import { defaultBuildingVariant } from "./meta_building";
|
import { defaultBuildingVariant } from "./meta_building";
|
||||||
|
import { RegularGameMode } from "./modes/regular";
|
||||||
import { ProductionAnalytics } from "./production_analytics";
|
import { ProductionAnalytics } from "./production_analytics";
|
||||||
import { GameRoot } from "./root";
|
import { GameRoot } from "./root";
|
||||||
import { ShapeDefinitionManager } from "./shape_definition_manager";
|
import { ShapeDefinitionManager } from "./shape_definition_manager";
|
||||||
@ -101,6 +102,9 @@ export class GameCore {
|
|||||||
// Needs to come first
|
// Needs to come first
|
||||||
root.dynamicTickrate = new DynamicTickrate(root);
|
root.dynamicTickrate = new DynamicTickrate(root);
|
||||||
|
|
||||||
|
// Init game mode
|
||||||
|
root.gameMode = new RegularGameMode(root);
|
||||||
|
|
||||||
// Init classes
|
// Init classes
|
||||||
root.camera = new Camera(root);
|
root.camera = new Camera(root);
|
||||||
root.map = new MapView(root);
|
root.map = new MapView(root);
|
||||||
|
|||||||
@ -182,23 +182,6 @@ export class EntityManager extends BasicSerializableObject {
|
|||||||
return this.componentToEntity[componentHandle.getId()] || [];
|
return this.componentToEntity[componentHandle.getId()] || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return all of a given class. This is SLOW!
|
|
||||||
* @param {object} entityClass
|
|
||||||
* @returns {Array<Entity>} entities
|
|
||||||
*/
|
|
||||||
getAllOfClass(entityClass) {
|
|
||||||
// FIXME: Slow
|
|
||||||
const result = [];
|
|
||||||
for (let i = 0; i < this.entities.length; ++i) {
|
|
||||||
const entity = this.entities[i];
|
|
||||||
if (entity instanceof entityClass) {
|
|
||||||
result.push(entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregisters all components of an entity from the component to entity mapping
|
* Unregisters all components of an entity from the component to entity mapping
|
||||||
* @param {Entity} entity
|
* @param {Entity} entity
|
||||||
|
|||||||
71
src/js/game/game_mode.js
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/* typehints:start */
|
||||||
|
import { enumHubGoalRewards } from "./tutorial_goals";
|
||||||
|
/* typehints:end */
|
||||||
|
|
||||||
|
import { GameRoot } from "./root";
|
||||||
|
|
||||||
|
/** @typedef {{
|
||||||
|
* shape: string,
|
||||||
|
* amount: number
|
||||||
|
* }} UpgradeRequirement */
|
||||||
|
|
||||||
|
/** @typedef {{
|
||||||
|
* required: Array<UpgradeRequirement>
|
||||||
|
* improvement?: number,
|
||||||
|
* excludePrevious?: boolean
|
||||||
|
* }} TierRequirement */
|
||||||
|
|
||||||
|
/** @typedef {Array<TierRequirement>} UpgradeTiers */
|
||||||
|
|
||||||
|
/** @typedef {{
|
||||||
|
* shape: string,
|
||||||
|
* required: number,
|
||||||
|
* reward: enumHubGoalRewards,
|
||||||
|
* throughputOnly?: boolean
|
||||||
|
* }} LevelDefinition */
|
||||||
|
|
||||||
|
export class GameMode {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {GameRoot} root
|
||||||
|
*/
|
||||||
|
constructor(root) {
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should return all available upgrades
|
||||||
|
* @returns {Object<string, UpgradeTiers>}
|
||||||
|
*/
|
||||||
|
getUpgrades() {
|
||||||
|
abstract;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the blueprint shape key
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
getBlueprintShapeKey() {
|
||||||
|
abstract;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the goals for all levels including their reward
|
||||||
|
* @returns {Array<LevelDefinition>}
|
||||||
|
*/
|
||||||
|
getLevelDefinitions() {
|
||||||
|
abstract;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should return whether free play is available or if the game stops
|
||||||
|
* after the predefined levels
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
getIsFreeplayAvailable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,14 +1,13 @@
|
|||||||
import { globalConfig, IS_DEMO } from "../core/config";
|
import { globalConfig } from "../core/config";
|
||||||
import { RandomNumberGenerator } from "../core/rng";
|
import { RandomNumberGenerator } from "../core/rng";
|
||||||
import { clamp, findNiceIntegerValue, randomChoice, randomInt } from "../core/utils";
|
import { clamp } from "../core/utils";
|
||||||
import { BasicSerializableObject, types } from "../savegame/serialization";
|
import { BasicSerializableObject, types } from "../savegame/serialization";
|
||||||
import { enumColors } from "./colors";
|
import { enumColors } from "./colors";
|
||||||
import { enumItemProcessorTypes } from "./components/item_processor";
|
import { enumItemProcessorTypes } from "./components/item_processor";
|
||||||
import { enumAnalyticsDataSource } from "./production_analytics";
|
import { enumAnalyticsDataSource } from "./production_analytics";
|
||||||
import { GameRoot } from "./root";
|
import { GameRoot } from "./root";
|
||||||
import { enumSubShape, ShapeDefinition } from "./shape_definition";
|
import { enumSubShape, ShapeDefinition } from "./shape_definition";
|
||||||
import { enumHubGoalRewards, tutorialGoals } from "./tutorial_goals";
|
import { enumHubGoalRewards } from "./tutorial_goals";
|
||||||
import { UPGRADES } from "./upgrades";
|
|
||||||
|
|
||||||
export class HubGoals extends BasicSerializableObject {
|
export class HubGoals extends BasicSerializableObject {
|
||||||
static getId() {
|
static getId() {
|
||||||
@ -23,27 +22,36 @@ export class HubGoals extends BasicSerializableObject {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
deserialize(data) {
|
/**
|
||||||
|
*
|
||||||
|
* @param {*} data
|
||||||
|
* @param {GameRoot} root
|
||||||
|
*/
|
||||||
|
deserialize(data, root) {
|
||||||
const errorCode = super.deserialize(data);
|
const errorCode = super.deserialize(data);
|
||||||
if (errorCode) {
|
if (errorCode) {
|
||||||
return errorCode;
|
return errorCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_DEMO) {
|
const levels = root.gameMode.getLevelDefinitions();
|
||||||
this.level = Math.min(this.level, tutorialGoals.length);
|
|
||||||
|
// If freeplay is not available, clamp the level
|
||||||
|
if (!root.gameMode.getIsFreeplayAvailable()) {
|
||||||
|
this.level = Math.min(this.level, levels.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute gained rewards
|
// Compute gained rewards
|
||||||
for (let i = 0; i < this.level - 1; ++i) {
|
for (let i = 0; i < this.level - 1; ++i) {
|
||||||
if (i < tutorialGoals.length) {
|
if (i < levels.length) {
|
||||||
const reward = tutorialGoals[i].reward;
|
const reward = levels[i].reward;
|
||||||
this.gainedRewards[reward] = (this.gainedRewards[reward] || 0) + 1;
|
this.gainedRewards[reward] = (this.gainedRewards[reward] || 0) + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute upgrade improvements
|
// Compute upgrade improvements
|
||||||
for (const upgradeId in UPGRADES) {
|
const upgrades = this.root.gameMode.getUpgrades();
|
||||||
const tiers = UPGRADES[upgradeId];
|
for (const upgradeId in upgrades) {
|
||||||
|
const tiers = upgrades[upgradeId];
|
||||||
const level = this.upgradeLevels[upgradeId] || 0;
|
const level = this.upgradeLevels[upgradeId] || 0;
|
||||||
let totalImprovement = 1;
|
let totalImprovement = 1;
|
||||||
for (let i = 0; i < level; ++i) {
|
for (let i = 0; i < level; ++i) {
|
||||||
@ -84,17 +92,16 @@ export class HubGoals extends BasicSerializableObject {
|
|||||||
*/
|
*/
|
||||||
this.upgradeLevels = {};
|
this.upgradeLevels = {};
|
||||||
|
|
||||||
// Reset levels
|
|
||||||
for (const key in UPGRADES) {
|
|
||||||
this.upgradeLevels[key] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the improvements for all upgrades
|
* Stores the improvements for all upgrades
|
||||||
* @type {Object<string, number>}
|
* @type {Object<string, number>}
|
||||||
*/
|
*/
|
||||||
this.upgradeImprovements = {};
|
this.upgradeImprovements = {};
|
||||||
for (const key in UPGRADES) {
|
|
||||||
|
// Reset levels first
|
||||||
|
const upgrades = this.root.gameMode.getUpgrades();
|
||||||
|
for (const key in upgrades) {
|
||||||
|
this.upgradeLevels[key] = 0;
|
||||||
this.upgradeImprovements[key] = 1;
|
this.upgradeImprovements[key] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +127,10 @@ export class HubGoals extends BasicSerializableObject {
|
|||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
isEndOfDemoReached() {
|
isEndOfDemoReached() {
|
||||||
return IS_DEMO && this.level >= tutorialGoals.length;
|
return (
|
||||||
|
!this.root.gameMode.getIsFreeplayAvailable() &&
|
||||||
|
this.level >= this.root.gameMode.getLevelDefinitions().length
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -215,8 +225,9 @@ export class HubGoals extends BasicSerializableObject {
|
|||||||
*/
|
*/
|
||||||
computeNextGoal() {
|
computeNextGoal() {
|
||||||
const storyIndex = this.level - 1;
|
const storyIndex = this.level - 1;
|
||||||
if (storyIndex < tutorialGoals.length) {
|
const levels = this.root.gameMode.getLevelDefinitions();
|
||||||
const { shape, required, reward, throughputOnly } = tutorialGoals[storyIndex];
|
if (storyIndex < levels.length) {
|
||||||
|
const { shape, required, reward, throughputOnly } = levels[storyIndex];
|
||||||
this.currentGoal = {
|
this.currentGoal = {
|
||||||
/** @type {ShapeDefinition} */
|
/** @type {ShapeDefinition} */
|
||||||
definition: this.root.shapeDefinitionMgr.getShapeFromShortKey(shape),
|
definition: this.root.shapeDefinitionMgr.getShapeFromShortKey(shape),
|
||||||
@ -227,7 +238,8 @@ export class HubGoals extends BasicSerializableObject {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const required = Math.min(200, 4 + (this.level - 27) * 0.25);
|
//Floor Required amount to remove confusion
|
||||||
|
const required = Math.min(200, Math.floor(4 + (this.level - 27) * 0.25));
|
||||||
this.currentGoal = {
|
this.currentGoal = {
|
||||||
definition: this.computeFreeplayShape(this.level),
|
definition: this.computeFreeplayShape(this.level),
|
||||||
required,
|
required,
|
||||||
@ -254,7 +266,7 @@ export class HubGoals extends BasicSerializableObject {
|
|||||||
* Returns whether we are playing in free-play
|
* Returns whether we are playing in free-play
|
||||||
*/
|
*/
|
||||||
isFreePlay() {
|
isFreePlay() {
|
||||||
return this.level >= tutorialGoals.length;
|
return this.level >= this.root.gameMode.getLevelDefinitions().length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -262,7 +274,7 @@ export class HubGoals extends BasicSerializableObject {
|
|||||||
* @param {string} upgradeId
|
* @param {string} upgradeId
|
||||||
*/
|
*/
|
||||||
canUnlockUpgrade(upgradeId) {
|
canUnlockUpgrade(upgradeId) {
|
||||||
const tiers = UPGRADES[upgradeId];
|
const tiers = this.root.gameMode.getUpgrades()[upgradeId];
|
||||||
const currentLevel = this.getUpgradeLevel(upgradeId);
|
const currentLevel = this.getUpgradeLevel(upgradeId);
|
||||||
|
|
||||||
if (currentLevel >= tiers.length) {
|
if (currentLevel >= tiers.length) {
|
||||||
@ -270,11 +282,6 @@ export class HubGoals extends BasicSerializableObject {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_DEMO && currentLevel >= 4) {
|
|
||||||
// DEMO
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (G_IS_DEV && globalConfig.debug.upgradesNoCost) {
|
if (G_IS_DEV && globalConfig.debug.upgradesNoCost) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -296,7 +303,7 @@ export class HubGoals extends BasicSerializableObject {
|
|||||||
*/
|
*/
|
||||||
getAvailableUpgradeCount() {
|
getAvailableUpgradeCount() {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
for (const upgradeId in UPGRADES) {
|
for (const upgradeId in this.root.gameMode.getUpgrades()) {
|
||||||
if (this.canUnlockUpgrade(upgradeId)) {
|
if (this.canUnlockUpgrade(upgradeId)) {
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
@ -314,7 +321,7 @@ export class HubGoals extends BasicSerializableObject {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const upgradeTiers = UPGRADES[upgradeId];
|
const upgradeTiers = this.root.gameMode.getUpgrades()[upgradeId];
|
||||||
const currentLevel = this.getUpgradeLevel(upgradeId);
|
const currentLevel = this.getUpgradeLevel(upgradeId);
|
||||||
|
|
||||||
const tierData = upgradeTiers[currentLevel];
|
const tierData = upgradeTiers[currentLevel];
|
||||||
@ -363,7 +370,7 @@ export class HubGoals extends BasicSerializableObject {
|
|||||||
if (allowUncolored) {
|
if (allowUncolored) {
|
||||||
universalColors.push(enumColors.uncolored);
|
universalColors.push(enumColors.uncolored);
|
||||||
}
|
}
|
||||||
const index = rng.nextIntRangeInclusive(0, colorWheel.length - 3);
|
const index = rng.nextIntRange(0, colorWheel.length - 2);
|
||||||
const pickedColors = colorWheel.slice(index, index + 3);
|
const pickedColors = colorWheel.slice(index, index + 3);
|
||||||
pickedColors.push(rng.choice(universalColors));
|
pickedColors.push(rng.choice(universalColors));
|
||||||
return pickedColors;
|
return pickedColors;
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import { HUDKeybindingOverlay } from "./parts/keybinding_overlay";
|
|||||||
import { HUDUnlockNotification } from "./parts/unlock_notification";
|
import { HUDUnlockNotification } from "./parts/unlock_notification";
|
||||||
import { HUDGameMenu } from "./parts/game_menu";
|
import { HUDGameMenu } from "./parts/game_menu";
|
||||||
import { HUDShop } from "./parts/shop";
|
import { HUDShop } from "./parts/shop";
|
||||||
import { IS_MOBILE, globalConfig, IS_DEMO } from "../../core/config";
|
import { IS_MOBILE, globalConfig } from "../../core/config";
|
||||||
import { HUDMassSelector } from "./parts/mass_selector";
|
import { HUDMassSelector } from "./parts/mass_selector";
|
||||||
import { HUDVignetteOverlay } from "./parts/vignette_overlay";
|
import { HUDVignetteOverlay } from "./parts/vignette_overlay";
|
||||||
import { HUDStatistics } from "./parts/statistics";
|
import { HUDStatistics } from "./parts/statistics";
|
||||||
@ -45,9 +45,9 @@ import { HUDLeverToggle } from "./parts/lever_toggle";
|
|||||||
import { HUDLayerPreview } from "./parts/layer_preview";
|
import { HUDLayerPreview } from "./parts/layer_preview";
|
||||||
import { HUDMinerHighlight } from "./parts/miner_highlight";
|
import { HUDMinerHighlight } from "./parts/miner_highlight";
|
||||||
import { HUDBetaOverlay } from "./parts/beta_overlay";
|
import { HUDBetaOverlay } from "./parts/beta_overlay";
|
||||||
import { HUDPerformanceWarning } from "./parts/performance_warning";
|
|
||||||
import { HUDStandaloneAdvantages } from "./parts/standalone_advantages";
|
import { HUDStandaloneAdvantages } from "./parts/standalone_advantages";
|
||||||
import { HUDCatMemes } from "./parts/cat_memes";
|
import { HUDCatMemes } from "./parts/cat_memes";
|
||||||
|
import { HUDTutorialVideoOffer } from "./parts/tutorial_video_offer";
|
||||||
|
|
||||||
export class GameHUD {
|
export class GameHUD {
|
||||||
/**
|
/**
|
||||||
@ -61,6 +61,18 @@ export class GameHUD {
|
|||||||
* Initializes the hud parts
|
* Initializes the hud parts
|
||||||
*/
|
*/
|
||||||
initialize() {
|
initialize() {
|
||||||
|
this.signals = {
|
||||||
|
buildingSelectedForPlacement: /** @type {TypedSignal<[MetaBuilding|null]>} */ (new Signal()),
|
||||||
|
selectedPlacementBuildingChanged: /** @type {TypedSignal<[MetaBuilding|null]>} */ (new Signal()),
|
||||||
|
shapePinRequested: /** @type {TypedSignal<[ShapeDefinition]>} */ (new Signal()),
|
||||||
|
shapeUnpinRequested: /** @type {TypedSignal<[string]>} */ (new Signal()),
|
||||||
|
notification: /** @type {TypedSignal<[string, enumNotificationType]>} */ (new Signal()),
|
||||||
|
buildingsSelectedForCopy: /** @type {TypedSignal<[Array<number>]>} */ (new Signal()),
|
||||||
|
pasteBlueprintRequested: /** @type {TypedSignal<[]>} */ (new Signal()),
|
||||||
|
viewShapeDetailsRequested: /** @type {TypedSignal<[ShapeDefinition]>} */ (new Signal()),
|
||||||
|
unlockNotificationFinished: /** @type {TypedSignal<[]>} */ (new Signal()),
|
||||||
|
};
|
||||||
|
|
||||||
this.parts = {
|
this.parts = {
|
||||||
buildingsToolbar: new HUDBuildingsToolbar(this.root),
|
buildingsToolbar: new HUDBuildingsToolbar(this.root),
|
||||||
wiresToolbar: new HUDWiresToolbar(this.root),
|
wiresToolbar: new HUDWiresToolbar(this.root),
|
||||||
@ -88,7 +100,7 @@ export class GameHUD {
|
|||||||
layerPreview: new HUDLayerPreview(this.root),
|
layerPreview: new HUDLayerPreview(this.root),
|
||||||
|
|
||||||
minerHighlight: new HUDMinerHighlight(this.root),
|
minerHighlight: new HUDMinerHighlight(this.root),
|
||||||
performanceWarning: new HUDPerformanceWarning(this.root),
|
tutorialVideoOffer: new HUDTutorialVideoOffer(this.root),
|
||||||
|
|
||||||
// Typing hints
|
// Typing hints
|
||||||
/* typehints:start */
|
/* typehints:start */
|
||||||
@ -97,17 +109,6 @@ export class GameHUD {
|
|||||||
/* typehints:end */
|
/* typehints:end */
|
||||||
};
|
};
|
||||||
|
|
||||||
this.signals = {
|
|
||||||
buildingSelectedForPlacement: /** @type {TypedSignal<[MetaBuilding|null]>} */ (new Signal()),
|
|
||||||
selectedPlacementBuildingChanged: /** @type {TypedSignal<[MetaBuilding|null]>} */ (new Signal()),
|
|
||||||
shapePinRequested: /** @type {TypedSignal<[ShapeDefinition]>} */ (new Signal()),
|
|
||||||
shapeUnpinRequested: /** @type {TypedSignal<[string]>} */ (new Signal()),
|
|
||||||
notification: /** @type {TypedSignal<[string, enumNotificationType]>} */ (new Signal()),
|
|
||||||
buildingsSelectedForCopy: /** @type {TypedSignal<[Array<number>]>} */ (new Signal()),
|
|
||||||
pasteBlueprintRequested: /** @type {TypedSignal<[]>} */ (new Signal()),
|
|
||||||
viewShapeDetailsRequested: /** @type {TypedSignal<[ShapeDefinition]>} */ (new Signal()),
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!IS_MOBILE) {
|
if (!IS_MOBILE) {
|
||||||
this.parts.keybindingOverlay = new HUDKeybindingOverlay(this.root);
|
this.parts.keybindingOverlay = new HUDKeybindingOverlay(this.root);
|
||||||
}
|
}
|
||||||
@ -116,7 +117,7 @@ export class GameHUD {
|
|||||||
this.parts.entityDebugger = new HUDEntityDebugger(this.root);
|
this.parts.entityDebugger = new HUDEntityDebugger(this.root);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_DEMO) {
|
if (this.root.app.restrictionMgr.getIsStandaloneMarketingActive()) {
|
||||||
this.parts.watermark = new HUDWatermark(this.root);
|
this.parts.watermark = new HUDWatermark(this.root);
|
||||||
this.parts.standaloneAdvantages = new HUDStandaloneAdvantages(this.root);
|
this.parts.standaloneAdvantages = new HUDStandaloneAdvantages(this.root);
|
||||||
this.parts.catMemes = new HUDCatMemes(this.root);
|
this.parts.catMemes = new HUDCatMemes(this.root);
|
||||||
|
|||||||
@ -7,7 +7,7 @@ export class HUDBetaOverlay extends BaseHUDPart {
|
|||||||
parent,
|
parent,
|
||||||
"ingame_HUD_BetaOverlay",
|
"ingame_HUD_BetaOverlay",
|
||||||
[],
|
[],
|
||||||
"<h2>UNSTABLE BETA VERSION</h2><span>Steam Release: 9th October 2020!</span>"
|
"<h2>UNSTABLE BETA VERSION</h2><span>Unfinalized & potential buggy content!</span>"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,202 +1,203 @@
|
|||||||
import { DrawParameters } from "../../../core/draw_parameters";
|
import { DrawParameters } from "../../../core/draw_parameters";
|
||||||
import { STOP_PROPAGATION } from "../../../core/signal";
|
import { STOP_PROPAGATION } from "../../../core/signal";
|
||||||
import { TrackedState } from "../../../core/tracked_state";
|
import { TrackedState } from "../../../core/tracked_state";
|
||||||
import { makeDiv } from "../../../core/utils";
|
import { makeDiv } from "../../../core/utils";
|
||||||
import { Vector } from "../../../core/vector";
|
import { Vector } from "../../../core/vector";
|
||||||
import { T } from "../../../translations";
|
import { SOUNDS } from "../../../platform/sound";
|
||||||
import { enumMouseButton } from "../../camera";
|
import { T } from "../../../translations";
|
||||||
import { KEYMAPPINGS } from "../../key_action_mapper";
|
import { Blueprint } from "../../blueprint";
|
||||||
import { blueprintShape } from "../../upgrades";
|
import { enumMouseButton } from "../../camera";
|
||||||
import { BaseHUDPart } from "../base_hud_part";
|
import { KEYMAPPINGS } from "../../key_action_mapper";
|
||||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
import { BaseHUDPart } from "../base_hud_part";
|
||||||
import { Blueprint } from "../../blueprint";
|
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||||
import { SOUNDS } from "../../../platform/sound";
|
|
||||||
|
export class HUDBlueprintPlacer extends BaseHUDPart {
|
||||||
export class HUDBlueprintPlacer extends BaseHUDPart {
|
createElements(parent) {
|
||||||
createElements(parent) {
|
const blueprintCostShape = this.root.shapeDefinitionMgr.getShapeFromShortKey(
|
||||||
const blueprintCostShape = this.root.shapeDefinitionMgr.getShapeFromShortKey(blueprintShape);
|
this.root.gameMode.getBlueprintShapeKey()
|
||||||
const blueprintCostShapeCanvas = blueprintCostShape.generateAsCanvas(80);
|
);
|
||||||
|
const blueprintCostShapeCanvas = blueprintCostShape.generateAsCanvas(80);
|
||||||
this.costDisplayParent = makeDiv(parent, "ingame_HUD_BlueprintPlacer", [], ``);
|
|
||||||
|
this.costDisplayParent = makeDiv(parent, "ingame_HUD_BlueprintPlacer", [], ``);
|
||||||
makeDiv(this.costDisplayParent, null, ["label"], T.ingame.blueprintPlacer.cost);
|
|
||||||
const costContainer = makeDiv(this.costDisplayParent, null, ["costContainer"], "");
|
makeDiv(this.costDisplayParent, null, ["label"], T.ingame.blueprintPlacer.cost);
|
||||||
this.costDisplayText = makeDiv(costContainer, null, ["costText"], "");
|
const costContainer = makeDiv(this.costDisplayParent, null, ["costContainer"], "");
|
||||||
costContainer.appendChild(blueprintCostShapeCanvas);
|
this.costDisplayText = makeDiv(costContainer, null, ["costText"], "");
|
||||||
}
|
costContainer.appendChild(blueprintCostShapeCanvas);
|
||||||
|
}
|
||||||
initialize() {
|
|
||||||
this.root.hud.signals.buildingsSelectedForCopy.add(this.createBlueprintFromBuildings, this);
|
initialize() {
|
||||||
|
this.root.hud.signals.buildingsSelectedForCopy.add(this.createBlueprintFromBuildings, this);
|
||||||
/** @type {TypedTrackedState<Blueprint?>} */
|
|
||||||
this.currentBlueprint = new TrackedState(this.onBlueprintChanged, this);
|
/** @type {TypedTrackedState<Blueprint?>} */
|
||||||
/** @type {Blueprint?} */
|
this.currentBlueprint = new TrackedState(this.onBlueprintChanged, this);
|
||||||
this.lastBlueprintUsed = null;
|
/** @type {Blueprint?} */
|
||||||
|
this.lastBlueprintUsed = null;
|
||||||
const keyActionMapper = this.root.keyMapper;
|
|
||||||
keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.abortPlacement, this);
|
const keyActionMapper = this.root.keyMapper;
|
||||||
keyActionMapper.getBinding(KEYMAPPINGS.placement.pipette).add(this.abortPlacement, this);
|
keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.abortPlacement, this);
|
||||||
keyActionMapper.getBinding(KEYMAPPINGS.placement.rotateWhilePlacing).add(this.rotateBlueprint, this);
|
keyActionMapper.getBinding(KEYMAPPINGS.placement.pipette).add(this.abortPlacement, this);
|
||||||
keyActionMapper.getBinding(KEYMAPPINGS.massSelect.pasteLastBlueprint).add(this.pasteBlueprint, this);
|
keyActionMapper.getBinding(KEYMAPPINGS.placement.rotateWhilePlacing).add(this.rotateBlueprint, this);
|
||||||
|
keyActionMapper.getBinding(KEYMAPPINGS.massSelect.pasteLastBlueprint).add(this.pasteBlueprint, this);
|
||||||
this.root.camera.downPreHandler.add(this.onMouseDown, this);
|
|
||||||
this.root.camera.movePreHandler.add(this.onMouseMove, this);
|
this.root.camera.downPreHandler.add(this.onMouseDown, this);
|
||||||
|
this.root.camera.movePreHandler.add(this.onMouseMove, this);
|
||||||
this.root.hud.signals.selectedPlacementBuildingChanged.add(this.abortPlacement, this);
|
|
||||||
this.root.signals.editModeChanged.add(this.onEditModeChanged, this);
|
this.root.hud.signals.selectedPlacementBuildingChanged.add(this.abortPlacement, this);
|
||||||
|
this.root.signals.editModeChanged.add(this.onEditModeChanged, this);
|
||||||
this.domAttach = new DynamicDomAttach(this.root, this.costDisplayParent);
|
|
||||||
this.trackedCanAfford = new TrackedState(this.onCanAffordChanged, this);
|
this.domAttach = new DynamicDomAttach(this.root, this.costDisplayParent);
|
||||||
}
|
this.trackedCanAfford = new TrackedState(this.onCanAffordChanged, this);
|
||||||
|
}
|
||||||
abortPlacement() {
|
|
||||||
if (this.currentBlueprint.get()) {
|
abortPlacement() {
|
||||||
this.currentBlueprint.set(null);
|
if (this.currentBlueprint.get()) {
|
||||||
|
this.currentBlueprint.set(null);
|
||||||
return STOP_PROPAGATION;
|
|
||||||
}
|
return STOP_PROPAGATION;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Called when the layer was changed
|
/**
|
||||||
* @param {Layer} layer
|
* Called when the layer was changed
|
||||||
*/
|
* @param {Layer} layer
|
||||||
onEditModeChanged(layer) {
|
*/
|
||||||
// Check if the layer of the blueprint differs and thus we have to deselect it
|
onEditModeChanged(layer) {
|
||||||
const blueprint = this.currentBlueprint.get();
|
// Check if the layer of the blueprint differs and thus we have to deselect it
|
||||||
if (blueprint) {
|
const blueprint = this.currentBlueprint.get();
|
||||||
if (blueprint.layer !== layer) {
|
if (blueprint) {
|
||||||
this.currentBlueprint.set(null);
|
if (blueprint.layer !== layer) {
|
||||||
}
|
this.currentBlueprint.set(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Called when the blueprint is now affordable or not
|
/**
|
||||||
* @param {boolean} canAfford
|
* Called when the blueprint is now affordable or not
|
||||||
*/
|
* @param {boolean} canAfford
|
||||||
onCanAffordChanged(canAfford) {
|
*/
|
||||||
this.costDisplayParent.classList.toggle("canAfford", canAfford);
|
onCanAffordChanged(canAfford) {
|
||||||
}
|
this.costDisplayParent.classList.toggle("canAfford", canAfford);
|
||||||
|
}
|
||||||
update() {
|
|
||||||
const currentBlueprint = this.currentBlueprint.get();
|
update() {
|
||||||
this.domAttach.update(currentBlueprint && currentBlueprint.getCost() > 0);
|
const currentBlueprint = this.currentBlueprint.get();
|
||||||
this.trackedCanAfford.set(currentBlueprint && currentBlueprint.canAfford(this.root));
|
this.domAttach.update(currentBlueprint && currentBlueprint.getCost() > 0);
|
||||||
}
|
this.trackedCanAfford.set(currentBlueprint && currentBlueprint.canAfford(this.root));
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Called when the blueprint was changed
|
/**
|
||||||
* @param {Blueprint} blueprint
|
* Called when the blueprint was changed
|
||||||
*/
|
* @param {Blueprint} blueprint
|
||||||
onBlueprintChanged(blueprint) {
|
*/
|
||||||
if (blueprint) {
|
onBlueprintChanged(blueprint) {
|
||||||
this.lastBlueprintUsed = blueprint;
|
if (blueprint) {
|
||||||
this.costDisplayText.innerText = "" + blueprint.getCost();
|
this.lastBlueprintUsed = blueprint;
|
||||||
}
|
this.costDisplayText.innerText = "" + blueprint.getCost();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* mouse down pre handler
|
/**
|
||||||
* @param {Vector} pos
|
* mouse down pre handler
|
||||||
* @param {enumMouseButton} button
|
* @param {Vector} pos
|
||||||
*/
|
* @param {enumMouseButton} button
|
||||||
onMouseDown(pos, button) {
|
*/
|
||||||
if (button === enumMouseButton.right) {
|
onMouseDown(pos, button) {
|
||||||
if (this.currentBlueprint.get()) {
|
if (button === enumMouseButton.right) {
|
||||||
this.abortPlacement();
|
if (this.currentBlueprint.get()) {
|
||||||
return STOP_PROPAGATION;
|
this.abortPlacement();
|
||||||
}
|
return STOP_PROPAGATION;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
const blueprint = this.currentBlueprint.get();
|
|
||||||
if (!blueprint) {
|
const blueprint = this.currentBlueprint.get();
|
||||||
return;
|
if (!blueprint) {
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
if (!blueprint.canAfford(this.root)) {
|
|
||||||
this.root.soundProxy.playUiError();
|
if (!blueprint.canAfford(this.root)) {
|
||||||
return;
|
this.root.soundProxy.playUiError();
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
const worldPos = this.root.camera.screenToWorld(pos);
|
|
||||||
const tile = worldPos.toTileSpace();
|
const worldPos = this.root.camera.screenToWorld(pos);
|
||||||
if (blueprint.tryPlace(this.root, tile)) {
|
const tile = worldPos.toTileSpace();
|
||||||
const cost = blueprint.getCost();
|
if (blueprint.tryPlace(this.root, tile)) {
|
||||||
this.root.hubGoals.takeShapeByKey(blueprintShape, cost);
|
const cost = blueprint.getCost();
|
||||||
this.root.soundProxy.playUi(SOUNDS.placeBuilding);
|
this.root.hubGoals.takeShapeByKey(this.root.gameMode.getBlueprintShapeKey(), cost);
|
||||||
}
|
this.root.soundProxy.playUi(SOUNDS.placeBuilding);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Mose move handler
|
/**
|
||||||
*/
|
* Mose move handler
|
||||||
onMouseMove() {
|
*/
|
||||||
// Prevent movement while blueprint is selected
|
onMouseMove() {
|
||||||
if (this.currentBlueprint.get()) {
|
// Prevent movement while blueprint is selected
|
||||||
return STOP_PROPAGATION;
|
if (this.currentBlueprint.get()) {
|
||||||
}
|
return STOP_PROPAGATION;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Called when an array of bulidings was selected
|
/**
|
||||||
* @param {Array<number>} uids
|
* Called when an array of bulidings was selected
|
||||||
*/
|
* @param {Array<number>} uids
|
||||||
createBlueprintFromBuildings(uids) {
|
*/
|
||||||
if (uids.length === 0) {
|
createBlueprintFromBuildings(uids) {
|
||||||
return;
|
if (uids.length === 0) {
|
||||||
}
|
return;
|
||||||
this.currentBlueprint.set(Blueprint.fromUids(this.root, uids));
|
}
|
||||||
}
|
this.currentBlueprint.set(Blueprint.fromUids(this.root, uids));
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Attempts to rotate the current blueprint
|
/**
|
||||||
*/
|
* Attempts to rotate the current blueprint
|
||||||
rotateBlueprint() {
|
*/
|
||||||
if (this.currentBlueprint.get()) {
|
rotateBlueprint() {
|
||||||
if (this.root.keyMapper.getBinding(KEYMAPPINGS.placement.rotateInverseModifier).pressed) {
|
if (this.currentBlueprint.get()) {
|
||||||
this.currentBlueprint.get().rotateCcw();
|
if (this.root.keyMapper.getBinding(KEYMAPPINGS.placement.rotateInverseModifier).pressed) {
|
||||||
} else {
|
this.currentBlueprint.get().rotateCcw();
|
||||||
this.currentBlueprint.get().rotateCw();
|
} else {
|
||||||
}
|
this.currentBlueprint.get().rotateCw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Attempts to paste the last blueprint
|
/**
|
||||||
*/
|
* Attempts to paste the last blueprint
|
||||||
pasteBlueprint() {
|
*/
|
||||||
if (this.lastBlueprintUsed !== null) {
|
pasteBlueprint() {
|
||||||
if (this.lastBlueprintUsed.layer !== this.root.currentLayer) {
|
if (this.lastBlueprintUsed !== null) {
|
||||||
// Not compatible
|
if (this.lastBlueprintUsed.layer !== this.root.currentLayer) {
|
||||||
this.root.soundProxy.playUiError();
|
// Not compatible
|
||||||
return;
|
this.root.soundProxy.playUiError();
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
this.root.hud.signals.pasteBlueprintRequested.dispatch();
|
|
||||||
this.currentBlueprint.set(this.lastBlueprintUsed);
|
this.root.hud.signals.pasteBlueprintRequested.dispatch();
|
||||||
} else {
|
this.currentBlueprint.set(this.lastBlueprintUsed);
|
||||||
this.root.soundProxy.playUiError();
|
} else {
|
||||||
}
|
this.root.soundProxy.playUiError();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
*
|
/**
|
||||||
* @param {DrawParameters} parameters
|
*
|
||||||
*/
|
* @param {DrawParameters} parameters
|
||||||
draw(parameters) {
|
*/
|
||||||
const blueprint = this.currentBlueprint.get();
|
draw(parameters) {
|
||||||
if (!blueprint) {
|
const blueprint = this.currentBlueprint.get();
|
||||||
return;
|
if (!blueprint) {
|
||||||
}
|
return;
|
||||||
const mousePosition = this.root.app.mousePosition;
|
}
|
||||||
if (!mousePosition) {
|
const mousePosition = this.root.app.mousePosition;
|
||||||
// Not on screen
|
if (!mousePosition) {
|
||||||
return;
|
// Not on screen
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
const worldPos = this.root.camera.screenToWorld(mousePosition);
|
|
||||||
const tile = worldPos.toTileSpace();
|
const worldPos = this.root.camera.screenToWorld(mousePosition);
|
||||||
blueprint.draw(parameters, tile);
|
const tile = worldPos.toTileSpace();
|
||||||
}
|
blueprint.draw(parameters, tile);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -6,23 +6,25 @@ import { DynamicDomAttach } from "../dynamic_dom_attach";
|
|||||||
import { TrackedState } from "../../../core/tracked_state";
|
import { TrackedState } from "../../../core/tracked_state";
|
||||||
import { cachebust } from "../../../core/cachebust";
|
import { cachebust } from "../../../core/cachebust";
|
||||||
import { T } from "../../../translations";
|
import { T } from "../../../translations";
|
||||||
|
import { enumItemProcessorTypes, ItemProcessorComponent } from "../../components/item_processor";
|
||||||
|
import { ShapeItem } from "../../items/shape_item";
|
||||||
|
import { WireComponent } from "../../components/wire";
|
||||||
|
import { LeverComponent } from "../../components/lever";
|
||||||
|
|
||||||
|
// @todo: Make dictionary
|
||||||
const tutorialsByLevel = [
|
const tutorialsByLevel = [
|
||||||
// Level 1
|
// Level 1
|
||||||
[
|
[
|
||||||
// 1.1. place an extractor
|
// 1.1. place an extractor
|
||||||
{
|
{
|
||||||
id: "1_1_extractor",
|
id: "1_1_extractor",
|
||||||
condition: /** @param {GameRoot} root */ root => {
|
condition: /** @param {GameRoot} root */ root =>
|
||||||
return root.entityMgr.getAllWithComponent(MinerComponent).length === 0;
|
root.entityMgr.getAllWithComponent(MinerComponent).length === 0,
|
||||||
},
|
|
||||||
},
|
},
|
||||||
// 1.2. connect to hub
|
// 1.2. connect to hub
|
||||||
{
|
{
|
||||||
id: "1_2_conveyor",
|
id: "1_2_conveyor",
|
||||||
condition: /** @param {GameRoot} root */ root => {
|
condition: /** @param {GameRoot} root */ root => root.hubGoals.getCurrentGoalDelivered() === 0,
|
||||||
return root.hubGoals.getCurrentGoalDelivered() === 0;
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
// 1.3 wait for completion
|
// 1.3 wait for completion
|
||||||
{
|
{
|
||||||
@ -30,6 +32,108 @@ const tutorialsByLevel = [
|
|||||||
condition: () => true,
|
condition: () => true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
// Level 2
|
||||||
|
[
|
||||||
|
// 2.1 place a cutter
|
||||||
|
{
|
||||||
|
id: "2_1_place_cutter",
|
||||||
|
condition: /** @param {GameRoot} root */ root =>
|
||||||
|
root.entityMgr
|
||||||
|
.getAllWithComponent(ItemProcessorComponent)
|
||||||
|
.filter(e => e.components.ItemProcessor.type === enumItemProcessorTypes.cutter).length ===
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
// 2.2 place trash
|
||||||
|
{
|
||||||
|
id: "2_2_place_trash",
|
||||||
|
condition: /** @param {GameRoot} root */ root =>
|
||||||
|
root.entityMgr
|
||||||
|
.getAllWithComponent(ItemProcessorComponent)
|
||||||
|
.filter(e => e.components.ItemProcessor.type === enumItemProcessorTypes.trash).length ===
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
// 2.3 place more cutters
|
||||||
|
{
|
||||||
|
id: "2_3_more_cutters",
|
||||||
|
condition: /** @param {GameRoot} root */ root =>
|
||||||
|
root.entityMgr
|
||||||
|
.getAllWithComponent(ItemProcessorComponent)
|
||||||
|
.filter(e => e.components.ItemProcessor.type === enumItemProcessorTypes.cutter).length <
|
||||||
|
3,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
// Level 3
|
||||||
|
[
|
||||||
|
// 3.1. rectangles
|
||||||
|
{
|
||||||
|
id: "3_1_rectangles",
|
||||||
|
condition: /** @param {GameRoot} root */ root =>
|
||||||
|
// 4 miners placed above rectangles and 10 delivered
|
||||||
|
root.hubGoals.getCurrentGoalDelivered() < 10 ||
|
||||||
|
root.entityMgr.getAllWithComponent(MinerComponent).filter(entity => {
|
||||||
|
const tile = entity.components.StaticMapEntity.origin;
|
||||||
|
const below = root.map.getLowerLayerContentXY(tile.x, tile.y);
|
||||||
|
if (below && below.getItemType() === "shape") {
|
||||||
|
const shape = /** @type {ShapeItem} */ (below).definition.getHash();
|
||||||
|
return shape === "RuRuRuRu";
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}).length < 4,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
[], // Level 4
|
||||||
|
[], // Level 5
|
||||||
|
[], // Level 6
|
||||||
|
[], // Level 7
|
||||||
|
[], // Level 8
|
||||||
|
[], // Level 9
|
||||||
|
[], // Level 10
|
||||||
|
[], // Level 11
|
||||||
|
[], // Level 12
|
||||||
|
[], // Level 13
|
||||||
|
[], // Level 14
|
||||||
|
[], // Level 15
|
||||||
|
[], // Level 16
|
||||||
|
[], // Level 17
|
||||||
|
[], // Level 18
|
||||||
|
[], // Level 19
|
||||||
|
[], // Level 20
|
||||||
|
|
||||||
|
// Level 21
|
||||||
|
[
|
||||||
|
// 21.1 place quad painter
|
||||||
|
{
|
||||||
|
id: "21_1_place_quad_painter",
|
||||||
|
condition: /** @param {GameRoot} root */ root =>
|
||||||
|
root.entityMgr
|
||||||
|
.getAllWithComponent(ItemProcessorComponent)
|
||||||
|
.filter(e => e.components.ItemProcessor.type === enumItemProcessorTypes.painterQuad)
|
||||||
|
.length === 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 21.2 switch to wires layer
|
||||||
|
{
|
||||||
|
id: "21_2_switch_to_wires",
|
||||||
|
condition: /** @param {GameRoot} root */ root =>
|
||||||
|
root.entityMgr.getAllWithComponent(WireComponent).length < 5,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 21.3 place button
|
||||||
|
{
|
||||||
|
id: "21_3_place_button",
|
||||||
|
condition: /** @param {GameRoot} root */ root =>
|
||||||
|
root.entityMgr.getAllWithComponent(LeverComponent).length === 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 21.4 activate button
|
||||||
|
{
|
||||||
|
id: "21_4_press_button",
|
||||||
|
condition: /** @param {GameRoot} root */ root =>
|
||||||
|
root.entityMgr.getAllWithComponent(LeverComponent).some(e => !e.components.Lever.toggled),
|
||||||
|
},
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
export class HUDInteractiveTutorial extends BaseHUDPart {
|
export class HUDInteractiveTutorial extends BaseHUDPart {
|
||||||
|
|||||||
@ -1,16 +0,0 @@
|
|||||||
import { T } from "../../../translations";
|
|
||||||
import { BaseHUDPart } from "../base_hud_part";
|
|
||||||
|
|
||||||
export class HUDPerformanceWarning extends BaseHUDPart {
|
|
||||||
initialize() {
|
|
||||||
this.warningShown = false;
|
|
||||||
this.root.signals.entityManuallyPlaced.add(this.checkAfterPlace, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
checkAfterPlace() {
|
|
||||||
if (!this.warningShown && this.root.entityMgr.entities.length > 10000) {
|
|
||||||
this.root.hud.parts.dialogs.showInfo(T.dialogs.entityWarning.title, T.dialogs.entityWarning.desc);
|
|
||||||
this.warningShown = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,12 +1,11 @@
|
|||||||
import { ClickDetector } from "../../../core/click_detector";
|
import { ClickDetector } from "../../../core/click_detector";
|
||||||
import { formatBigNumber, makeDiv, arrayDeleteValue } from "../../../core/utils";
|
|
||||||
import { ShapeDefinition } from "../../shape_definition";
|
|
||||||
import { BaseHUDPart } from "../base_hud_part";
|
|
||||||
import { blueprintShape, UPGRADES } from "../../upgrades";
|
|
||||||
import { enumHubGoalRewards } from "../../tutorial_goals";
|
|
||||||
import { enumAnalyticsDataSource } from "../../production_analytics";
|
|
||||||
import { T } from "../../../translations";
|
|
||||||
import { globalConfig } from "../../../core/config";
|
import { globalConfig } from "../../../core/config";
|
||||||
|
import { arrayDeleteValue, formatBigNumber, makeDiv } from "../../../core/utils";
|
||||||
|
import { T } from "../../../translations";
|
||||||
|
import { enumAnalyticsDataSource } from "../../production_analytics";
|
||||||
|
import { ShapeDefinition } from "../../shape_definition";
|
||||||
|
import { enumHubGoalRewards } from "../../tutorial_goals";
|
||||||
|
import { BaseHUDPart } from "../base_hud_part";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages the pinned shapes on the left side of the screen
|
* Manages the pinned shapes on the left side of the screen
|
||||||
@ -82,7 +81,7 @@ export class HUDPinnedShapes extends BaseHUDPart {
|
|||||||
updateShapesAfterUpgrade() {
|
updateShapesAfterUpgrade() {
|
||||||
for (let i = 0; i < this.pinnedShapes.length; ++i) {
|
for (let i = 0; i < this.pinnedShapes.length; ++i) {
|
||||||
const key = this.pinnedShapes[i];
|
const key = this.pinnedShapes[i];
|
||||||
if (key === blueprintShape) {
|
if (key === this.root.gameMode.getBlueprintShapeKey()) {
|
||||||
// Ignore blueprint shapes
|
// Ignore blueprint shapes
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -107,13 +106,14 @@ export class HUDPinnedShapes extends BaseHUDPart {
|
|||||||
if (key === this.root.hubGoals.currentGoal.definition.getHash()) {
|
if (key === this.root.hubGoals.currentGoal.definition.getHash()) {
|
||||||
return this.root.hubGoals.currentGoal.required;
|
return this.root.hubGoals.currentGoal.required;
|
||||||
}
|
}
|
||||||
if (key === blueprintShape) {
|
if (key === this.root.gameMode.getBlueprintShapeKey()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if this shape is required for any upgrade
|
// Check if this shape is required for any upgrade
|
||||||
for (const upgradeId in UPGRADES) {
|
const upgrades = this.root.gameMode.getUpgrades();
|
||||||
const upgradeTiers = UPGRADES[upgradeId];
|
for (const upgradeId in upgrades) {
|
||||||
|
const upgradeTiers = upgrades[upgradeId];
|
||||||
const currentTier = this.root.hubGoals.getUpgradeLevel(upgradeId);
|
const currentTier = this.root.hubGoals.getUpgradeLevel(upgradeId);
|
||||||
const tierHandle = upgradeTiers[currentTier];
|
const tierHandle = upgradeTiers[currentTier];
|
||||||
|
|
||||||
@ -138,7 +138,10 @@ export class HUDPinnedShapes extends BaseHUDPart {
|
|||||||
* @param {string} key
|
* @param {string} key
|
||||||
*/
|
*/
|
||||||
isShapePinned(key) {
|
isShapePinned(key) {
|
||||||
if (key === this.root.hubGoals.currentGoal.definition.getHash() || key === blueprintShape) {
|
if (
|
||||||
|
key === this.root.hubGoals.currentGoal.definition.getHash() ||
|
||||||
|
key === this.root.gameMode.getBlueprintShapeKey()
|
||||||
|
) {
|
||||||
// This is a "special" shape which is always pinned
|
// This is a "special" shape which is always pinned
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -178,7 +181,7 @@ export class HUDPinnedShapes extends BaseHUDPart {
|
|||||||
// Pin blueprint shape as well
|
// Pin blueprint shape as well
|
||||||
if (this.root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_blueprints)) {
|
if (this.root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_blueprints)) {
|
||||||
this.internalPinShape({
|
this.internalPinShape({
|
||||||
key: blueprintShape,
|
key: this.root.gameMode.getBlueprintShapeKey(),
|
||||||
canUnpin: false,
|
canUnpin: false,
|
||||||
className: "blueprint",
|
className: "blueprint",
|
||||||
});
|
});
|
||||||
@ -214,11 +217,11 @@ export class HUDPinnedShapes extends BaseHUDPart {
|
|||||||
|
|
||||||
let detector = null;
|
let detector = null;
|
||||||
if (canUnpin) {
|
if (canUnpin) {
|
||||||
element.classList.add("unpinable");
|
element.classList.add("removable");
|
||||||
detector = new ClickDetector(element, {
|
detector = new ClickDetector(element, {
|
||||||
consumeEvents: true,
|
consumeEvents: true,
|
||||||
preventDefault: true,
|
preventDefault: true,
|
||||||
targetOnly: true,
|
targetOnly: false,
|
||||||
});
|
});
|
||||||
detector.click.add(() => this.unpinShape(key));
|
detector.click.add(() => this.unpinShape(key));
|
||||||
} else {
|
} else {
|
||||||
@ -291,6 +294,7 @@ export class HUDPinnedShapes extends BaseHUDPart {
|
|||||||
* @param {string} key
|
* @param {string} key
|
||||||
*/
|
*/
|
||||||
unpinShape(key) {
|
unpinShape(key) {
|
||||||
|
console.log("unpin", key);
|
||||||
arrayDeleteValue(this.pinnedShapes, key);
|
arrayDeleteValue(this.pinnedShapes, key);
|
||||||
this.rerenderFull();
|
this.rerenderFull();
|
||||||
}
|
}
|
||||||
@ -306,7 +310,7 @@ export class HUDPinnedShapes extends BaseHUDPart {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key === blueprintShape) {
|
if (key === this.root.gameMode.getBlueprintShapeKey()) {
|
||||||
// Can not pin the blueprint shape
|
// Can not pin the blueprint shape
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
import { BaseHUDPart } from "../base_hud_part";
|
|
||||||
import { makeDiv } from "../../../core/utils";
|
import { makeDiv } from "../../../core/utils";
|
||||||
|
import { BaseHUDPart } from "../base_hud_part";
|
||||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||||
import { blueprintShape, UPGRADES } from "../../upgrades";
|
|
||||||
import { enumNotificationType } from "./notifications";
|
import { enumNotificationType } from "./notifications";
|
||||||
import { tutorialGoals } from "../../tutorial_goals";
|
|
||||||
|
|
||||||
export class HUDSandboxController extends BaseHUDPart {
|
export class HUDSandboxController extends BaseHUDPart {
|
||||||
createElements(parent) {
|
createElements(parent) {
|
||||||
@ -75,10 +73,11 @@ export class HUDSandboxController extends BaseHUDPart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
giveBlueprints() {
|
giveBlueprints() {
|
||||||
if (!this.root.hubGoals.storedShapes[blueprintShape]) {
|
const shape = this.root.gameMode.getBlueprintShapeKey();
|
||||||
this.root.hubGoals.storedShapes[blueprintShape] = 0;
|
if (!this.root.hubGoals.storedShapes[shape]) {
|
||||||
|
this.root.hubGoals.storedShapes[shape] = 0;
|
||||||
}
|
}
|
||||||
this.root.hubGoals.storedShapes[blueprintShape] += 1e9;
|
this.root.hubGoals.storedShapes[shape] += 1e9;
|
||||||
}
|
}
|
||||||
|
|
||||||
maxOutAll() {
|
maxOutAll() {
|
||||||
@ -89,7 +88,7 @@ export class HUDSandboxController extends BaseHUDPart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
modifyUpgrade(id, amount) {
|
modifyUpgrade(id, amount) {
|
||||||
const upgradeTiers = UPGRADES[id];
|
const upgradeTiers = this.root.gameMode.getUpgrades()[id];
|
||||||
const maxLevel = upgradeTiers.length;
|
const maxLevel = upgradeTiers.length;
|
||||||
|
|
||||||
this.root.hubGoals.upgradeLevels[id] = Math.max(
|
this.root.hubGoals.upgradeLevels[id] = Math.max(
|
||||||
@ -122,9 +121,10 @@ export class HUDSandboxController extends BaseHUDPart {
|
|||||||
|
|
||||||
// Compute gained rewards
|
// Compute gained rewards
|
||||||
hubGoals.gainedRewards = {};
|
hubGoals.gainedRewards = {};
|
||||||
|
const levels = this.root.gameMode.getLevelDefinitions();
|
||||||
for (let i = 0; i < hubGoals.level - 1; ++i) {
|
for (let i = 0; i < hubGoals.level - 1; ++i) {
|
||||||
if (i < tutorialGoals.length) {
|
if (i < levels.length) {
|
||||||
const reward = tutorialGoals[i].reward;
|
const reward = levels[i].reward;
|
||||||
hubGoals.gainedRewards[reward] = (hubGoals.gainedRewards[reward] || 0) + 1;
|
hubGoals.gainedRewards[reward] = (hubGoals.gainedRewards[reward] || 0) + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
import { BaseHUDPart } from "../base_hud_part";
|
|
||||||
import { KEYMAPPINGS } from "../../key_action_mapper";
|
|
||||||
import { IS_DEMO, globalConfig } from "../../../core/config";
|
|
||||||
import { T } from "../../../translations";
|
|
||||||
import { createLogger } from "../../../core/logging";
|
|
||||||
import { StaticMapEntityComponent } from "../../components/static_map_entity";
|
|
||||||
import { Vector } from "../../../core/vector";
|
|
||||||
import { makeOffscreenBuffer } from "../../../core/buffer_utils";
|
import { makeOffscreenBuffer } from "../../../core/buffer_utils";
|
||||||
|
import { globalConfig } from "../../../core/config";
|
||||||
import { DrawParameters } from "../../../core/draw_parameters";
|
import { DrawParameters } from "../../../core/draw_parameters";
|
||||||
|
import { createLogger } from "../../../core/logging";
|
||||||
import { Rectangle } from "../../../core/rectangle";
|
import { Rectangle } from "../../../core/rectangle";
|
||||||
|
import { Vector } from "../../../core/vector";
|
||||||
|
import { T } from "../../../translations";
|
||||||
|
import { StaticMapEntityComponent } from "../../components/static_map_entity";
|
||||||
|
import { KEYMAPPINGS } from "../../key_action_mapper";
|
||||||
|
import { BaseHUDPart } from "../base_hud_part";
|
||||||
|
|
||||||
const logger = createLogger("screenshot_exporter");
|
const logger = createLogger("screenshot_exporter");
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ export class HUDScreenshotExporter extends BaseHUDPart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
startExport() {
|
startExport() {
|
||||||
if (IS_DEMO) {
|
if (!this.root.app.restrictionMgr.getIsExportingScreenshotsPossible()) {
|
||||||
this.root.hud.parts.dialogs.showFeatureRestrictionInfo(T.demo.features.exportingBase);
|
this.root.hud.parts.dialogs.showFeatureRestrictionInfo(T.demo.features.exportingBase);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -87,7 +87,7 @@ export class HUDScreenshotExporter extends BaseHUDPart {
|
|||||||
const parameters = new DrawParameters({
|
const parameters = new DrawParameters({
|
||||||
context,
|
context,
|
||||||
visibleRect,
|
visibleRect,
|
||||||
desiredAtlasScale: chunkScale,
|
desiredAtlasScale: 0.25,
|
||||||
root: this.root,
|
root: this.root,
|
||||||
zoomLevel: chunkScale,
|
zoomLevel: chunkScale,
|
||||||
});
|
});
|
||||||
|
|||||||