Merge branch 'master' into patch-1
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
|
||||
4
.gitattributes
vendored
@ -1,4 +0,0 @@
|
||||
*.wav filter=lfs diff=lfs merge=lfs -text
|
||||
*.webm filter=lfs diff=lfs merge=lfs -text
|
||||
*.mp3 filter=lfs diff=lfs merge=lfs -text
|
||||
*.psd filter=lfs diff=lfs merge=lfs -text
|
||||
18
.github/workflows/ci.yml
vendored
@ -35,19 +35,23 @@ jobs:
|
||||
cd gulp/
|
||||
yarn
|
||||
cd ..
|
||||
|
||||
- name: Lint
|
||||
run: |
|
||||
yarn lint
|
||||
|
||||
- name: YAML Lint
|
||||
uses: ibiqlik/action-yamllint@v1.0.0
|
||||
with:
|
||||
file_or_dir: translations/*.yaml
|
||||
|
||||
- name: TSLint
|
||||
run: |
|
||||
cd gulp
|
||||
yarn gulp translations.fullBuild
|
||||
cd ..
|
||||
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
|
||||
*.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)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
@ -53,18 +30,9 @@ typings/
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
@ -72,41 +40,11 @@ typings/
|
||||
.env
|
||||
.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
|
||||
build
|
||||
res_built
|
||||
|
||||
gulp/runnable-texturepacker.jar
|
||||
tmp_standalone_files
|
||||
|
||||
# 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:
|
||||
level: warning
|
||||
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"]
|
||||
45
README.md
@ -22,15 +22,24 @@ Your goal is to produce shapes by cutting, rotating, merging and painting parts
|
||||
|
||||
## Building
|
||||
|
||||
- Make sure git `git lfs` extension is on your path
|
||||
- Run `git lfs pull` to download sound assets
|
||||
- Make sure `ffmpeg` is on your path
|
||||
- Install Node.js and Yarn
|
||||
- Install Java (required for textures)
|
||||
- Run `yarn` in the root folder
|
||||
- Cd into `gulp` folder
|
||||
- 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 `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
|
||||
|
||||
@ -64,7 +73,7 @@ This project is based on ES5. Some ES2015 features are used but most of them are
|
||||
5. Add a constructor. **The constructor must be called with optional parameters only!** `new MyFancyComponent({})` should always work.
|
||||
6. Add any props you need in the constructor.
|
||||
7. Add the component in `src/js/game/component_registry.js`
|
||||
8. Add the componetn in `src/js/game/entity_components.js`
|
||||
8. Add the component in `src/js/game/entity_components.js`
|
||||
9. Done! You can use your component now
|
||||
|
||||
#### Adding a new building
|
||||
@ -81,7 +90,7 @@ This project is based on ES5. Some ES2015 features are used but most of them are
|
||||
8. In `translations/base-en.yaml` add it to two sections: `buildings.[my_building].XXX` (See other buildings) and also `keybindings.mappings.[my_building]`. Be sure to do it the same way as other buildings do!
|
||||
9. Create a icon (128x128, [prefab](https://github.com/tobspr/shapez.io-artwork/blob/master/ui/toolbar-icons.psd)) for your building and save it in `res/ui/buildings_icons` with the id of your building
|
||||
10. Create a tutorial image (600x600) for your building and save it in `res/ui/building_tutorials`
|
||||
11. In `src/css/icons.scss` add your building to `$buildings` as well as `$buildingAndVariants`
|
||||
11. In `src/css/resources.scss` add your building to `$buildings` as well as `$buildingAndVariants`
|
||||
12. Done! Optional: Add a new reward for unlocking your building at some point.
|
||||
|
||||
#### Adding a new game system
|
||||
@ -92,10 +101,32 @@ This project is based on ES5. Some ES2015 features are used but most of them are
|
||||
4. Add the system in `src/js/game/game_system_manager.js` (To `this.systems` and also call `add` in the `internalInitSystems()` method)
|
||||
5. If your system should draw stuff, this is a bit more complicated. Have a look at existing systems on how they do it.
|
||||
|
||||
#### Checklist for a new building / testing it
|
||||
|
||||
This is a quick checklist, if a new building is added this points should be fulfilled:
|
||||
|
||||
2. The translation for all variants is done and finalized
|
||||
3. The artwork (regular sprite) is finalized
|
||||
4. The blueprint sprite has been generated and is up to date
|
||||
5. The building has been added to the appropriate toolbar
|
||||
6. The building has a keybinding which makes sense
|
||||
7. The building has a reward assigned and is unlocked at a meaningful point
|
||||
8. The reward for the building has a proper translation
|
||||
9. The reward for the building has a proper image
|
||||
10. The building has a proper tutorial image assigned
|
||||
11. The buliding has a proper toolbar icon
|
||||
12. The reward requires a proper shape
|
||||
13. The building has a proper silhouette color
|
||||
14. The building has a proper matrix for being rendered on the minimap
|
||||
15. The building has proper statistics in the dialog
|
||||
16. The building properly contributes to the shapes produced analytics
|
||||
17. The building is properly persisted in the savegame
|
||||
18. The building is explained properly, ideally via an interactive tutorial
|
||||
|
||||
### 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 thats 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">
|
||||
|
||||
@ -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 url = require("url");
|
||||
const childProcess = require("child_process");
|
||||
const { ipcMain } = require("electron");
|
||||
const { ipcMain, shell } = require("electron");
|
||||
const fs = require("fs");
|
||||
const isDev = process.argv.indexOf("--dev") >= 0;
|
||||
const isLocal = process.argv.indexOf("--local") >= 0;
|
||||
@ -67,11 +67,7 @@ function createWindow() {
|
||||
|
||||
win.webContents.on("new-window", (event, pth) => {
|
||||
event.preventDefault();
|
||||
if (process.platform == "win32") {
|
||||
childProcess.execSync("start " + pth);
|
||||
} else if (process.platform == "linux") {
|
||||
childProcess.execSync("xdg-open " + pth);
|
||||
}
|
||||
shell.openExternal(pth);
|
||||
});
|
||||
|
||||
win.on("closed", () => {
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"startDev": "electron --disable-direct-composition --in-process-gpu . --dev --local",
|
||||
"startDevGpu": "electron --enable-gpu-rasterization --enable-accelerated-2d-canvas --num-raster-threads=8 --enable-zero-copy . --dev --local",
|
||||
"start": "electron --disable-direct-composition --in-process-gpu ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "^6.1.12"
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"startDev": "electron --disable-direct-composition --in-process-gpu . --dev --local",
|
||||
"startDevGpu": "electron --enable-gpu-rasterization --enable-accelerated-2d-canvas --num-raster-threads=8 --enable-zero-copy . --dev --local",
|
||||
"start": "electron --disable-direct-composition --in-process-gpu ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "10.1.3"
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
|
||||
1533
electron/yarn.lock
1
gulp/.gitattributes
vendored
@ -1 +0,0 @@
|
||||
*.wav filter=lfs diff=lfs merge=lfs -text
|
||||
3
gulp/.gitignore
vendored
@ -1,2 +1 @@
|
||||
additional_build_files
|
||||
steampipe
|
||||
additional_build_files
|
||||
|
||||
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 };
|
||||
@ -25,6 +25,14 @@ module.exports = {
|
||||
});
|
||||
},
|
||||
|
||||
getTag() {
|
||||
try {
|
||||
return execSync("git describe --tag --exact-match").toString("ascii");
|
||||
} catch (e) {
|
||||
throw new Error('Current git HEAD is not a version tag');
|
||||
}
|
||||
},
|
||||
|
||||
getVersion() {
|
||||
return trim(fs.readFileSync(path.join(__dirname, "..", "version")).toString());
|
||||
},
|
||||
|
||||
@ -1,96 +0,0 @@
|
||||
// Converts the atlas description to a JSON file
|
||||
|
||||
String.prototype.replaceAll = function (search, replacement) {
|
||||
var target = this;
|
||||
return target.split(search).join(replacement);
|
||||
};
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const folder = path.join(__dirname, "res_built", "atlas");
|
||||
const files = fs.readdirSync(folder);
|
||||
|
||||
const metadata = [];
|
||||
|
||||
files.forEach(filename => {
|
||||
if (filename.endsWith(".atlas")) {
|
||||
// Read content
|
||||
|
||||
const content = fs.readFileSync(path.join(folder, filename), "ascii");
|
||||
|
||||
const lines = content.replaceAll("\r", "").replaceAll("\t", "").split("\n");
|
||||
|
||||
const readLine = () => lines.splice(0, 1)[0];
|
||||
const readValue = () => readLine().replaceAll(" ", "").split(":")[1];
|
||||
const readVector = () =>
|
||||
readValue()
|
||||
.split(",")
|
||||
.map(d => parseInt(d, 10));
|
||||
|
||||
let maxAtlas = 100;
|
||||
|
||||
atlasLoop: while (maxAtlas-- > 0 && lines.length >= 7) {
|
||||
const result = {
|
||||
entries: [],
|
||||
};
|
||||
|
||||
// Extract header
|
||||
const header_fileStart = readLine();
|
||||
const header_fileName = readLine();
|
||||
const header_size = readVector();
|
||||
const header_format = readLine();
|
||||
const header_filter = readLine();
|
||||
const header_repeat = readLine();
|
||||
const baseAtlasName = header_fileName.replace(".png", "");
|
||||
|
||||
// Store size
|
||||
result.size = header_size;
|
||||
|
||||
lineLoop: while (lines.length >= 7) {
|
||||
const entryResult = {};
|
||||
|
||||
const nextLine = lines[0];
|
||||
if (nextLine.length === 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
const entry_fileName = readLine() + ".png";
|
||||
|
||||
const entry_rotate = readValue();
|
||||
const entry_xy = readVector();
|
||||
const entry_size = readVector();
|
||||
const entry_orig = readVector();
|
||||
const entry_offset = readVector();
|
||||
const entry_index = readValue();
|
||||
|
||||
entryResult.filename = entry_fileName;
|
||||
entryResult.xy = entry_xy;
|
||||
entryResult.size = entry_size;
|
||||
// entryResult.offset = entry_offset;
|
||||
|
||||
entryResult.origSize = entry_orig;
|
||||
|
||||
let offset = [0, 0];
|
||||
|
||||
// GDX Atlas packer uses 1 - y coordinates. This sucks, and we have to convert it
|
||||
offset[0] = entry_offset[0];
|
||||
offset[1] = entry_orig[1] - entry_offset[1] - entry_size[1];
|
||||
|
||||
entryResult.offset = offset;
|
||||
|
||||
result.entries.push(entryResult);
|
||||
}
|
||||
|
||||
console.log("[Atlas]", "'" + baseAtlasName + "'", "has", result.entries.length, "entries");
|
||||
// fs.writeFileSync(path.join(folder, baseAtlasName + ".gen.json"), JSON.stringify(result));
|
||||
|
||||
metadata.push({
|
||||
filename: baseAtlasName + ".png",
|
||||
entries: result,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
fs.writeFileSync(path.join(folder, "meta.gen.json"), JSON.stringify(metadata, null, 4));
|
||||
236
gulp/css.js
@ -1,99 +1,137 @@
|
||||
const path = require("path");
|
||||
const buildUtils = require("./buildutils");
|
||||
|
||||
function gulptasksCSS($, gulp, buildFolder, browserSync) {
|
||||
// The assets plugin copies the files
|
||||
const commitHash = buildUtils.getRevision();
|
||||
const postcssAssetsPlugin = cachebust =>
|
||||
$.postcssAssets({
|
||||
loadPaths: [path.join(buildFolder, "res", "ui")],
|
||||
basePath: buildFolder,
|
||||
baseUrl: ".",
|
||||
cachebuster: cachebust
|
||||
? (filePath, urlPathname) => ({
|
||||
pathname: buildUtils.cachebust(urlPathname, commitHash),
|
||||
})
|
||||
: "",
|
||||
});
|
||||
|
||||
// Postcss configuration
|
||||
const postcssPlugins = (prod, { cachebust = false }) => {
|
||||
const plugins = [postcssAssetsPlugin(cachebust)];
|
||||
if (prod) {
|
||||
plugins.unshift(
|
||||
$.postcssUnprefix(),
|
||||
$.postcssPresetEnv({
|
||||
browsers: ["> 0.1%"],
|
||||
})
|
||||
);
|
||||
|
||||
plugins.push(
|
||||
$.cssMqpacker({
|
||||
sort: true,
|
||||
}),
|
||||
$.cssnano({
|
||||
preset: [
|
||||
"advanced",
|
||||
{
|
||||
cssDeclarationSorter: false,
|
||||
discardUnused: true,
|
||||
mergeIdents: false,
|
||||
reduceIdents: true,
|
||||
zindex: true,
|
||||
},
|
||||
],
|
||||
}),
|
||||
$.postcssRoundSubpixels()
|
||||
);
|
||||
}
|
||||
return plugins;
|
||||
};
|
||||
|
||||
// Performs linting on css
|
||||
gulp.task("css.lint", () => {
|
||||
return gulp
|
||||
.src(["../src/css/**/*.scss"])
|
||||
.pipe($.sassLint({ configFile: ".sasslint.yml" }))
|
||||
.pipe($.sassLint.format())
|
||||
.pipe($.sassLint.failOnError());
|
||||
});
|
||||
|
||||
// Builds the css in dev mode
|
||||
gulp.task("css.dev", () => {
|
||||
return gulp
|
||||
.src(["../src/css/main.scss"])
|
||||
.pipe($.plumber())
|
||||
.pipe($.sass.sync().on("error", $.sass.logError))
|
||||
.pipe($.postcss(postcssPlugins(false, {})))
|
||||
.pipe(gulp.dest(buildFolder))
|
||||
.pipe(browserSync.stream());
|
||||
});
|
||||
|
||||
// Builds the css in production mode (=minified)
|
||||
gulp.task("css.prod", () => {
|
||||
return (
|
||||
gulp
|
||||
.src("../src/css/main.scss", { cwd: __dirname })
|
||||
.pipe($.plumber())
|
||||
.pipe($.sass.sync({ outputStyle: "compressed" }).on("error", $.sass.logError))
|
||||
.pipe($.postcss(postcssPlugins(true, { cachebust: true })))
|
||||
.pipe(gulp.dest(buildFolder))
|
||||
);
|
||||
});
|
||||
|
||||
// Builds the css in production mode (=minified), without cachebusting
|
||||
gulp.task("css.prod-standalone", () => {
|
||||
return (
|
||||
gulp
|
||||
.src("../src/css/main.scss", { cwd: __dirname })
|
||||
.pipe($.plumber())
|
||||
.pipe($.sass.sync({ outputStyle: "compressed" }).on("error", $.sass.logError))
|
||||
.pipe($.postcss(postcssPlugins(true, { cachebust: false })))
|
||||
.pipe(gulp.dest(buildFolder))
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
gulptasksCSS,
|
||||
};
|
||||
const path = require("path");
|
||||
const buildUtils = require("./buildutils");
|
||||
|
||||
function gulptasksCSS($, gulp, buildFolder, browserSync) {
|
||||
// The assets plugin copies the files
|
||||
const commitHash = buildUtils.getRevision();
|
||||
const postcssAssetsPlugin = cachebust =>
|
||||
$.postcssAssets({
|
||||
loadPaths: [path.join(buildFolder, "res", "ui")],
|
||||
basePath: buildFolder,
|
||||
baseUrl: ".",
|
||||
cachebuster: cachebust
|
||||
? (filePath, urlPathname) => ({
|
||||
pathname: buildUtils.cachebust(urlPathname, commitHash),
|
||||
})
|
||||
: "",
|
||||
});
|
||||
|
||||
// Postcss configuration
|
||||
const postcssPlugins = (prod, { cachebust = false }) => {
|
||||
const plugins = [postcssAssetsPlugin(cachebust)];
|
||||
if (prod) {
|
||||
plugins.unshift(
|
||||
$.postcssUnprefix(),
|
||||
$.postcssPresetEnv({
|
||||
browsers: ["> 0.1%"],
|
||||
})
|
||||
);
|
||||
|
||||
plugins.push(
|
||||
$.cssMqpacker({
|
||||
sort: true,
|
||||
}),
|
||||
$.cssnano({
|
||||
preset: [
|
||||
"advanced",
|
||||
{
|
||||
cssDeclarationSorter: false,
|
||||
discardUnused: true,
|
||||
mergeIdents: false,
|
||||
reduceIdents: true,
|
||||
zindex: true,
|
||||
},
|
||||
],
|
||||
}),
|
||||
$.postcssRoundSubpixels()
|
||||
);
|
||||
}
|
||||
return plugins;
|
||||
};
|
||||
|
||||
// Performs linting on css
|
||||
gulp.task("css.lint", () => {
|
||||
return gulp
|
||||
.src(["../src/css/**/*.scss"])
|
||||
.pipe($.sassLint({ configFile: ".sasslint.yml" }))
|
||||
.pipe($.sassLint.format())
|
||||
.pipe($.sassLint.failOnError());
|
||||
});
|
||||
|
||||
function resourcesTask({ cachebust, isProd }) {
|
||||
return gulp
|
||||
.src("../src/css/main.scss", { cwd: __dirname })
|
||||
.pipe($.plumber())
|
||||
.pipe($.sass.sync().on("error", $.sass.logError))
|
||||
.pipe(
|
||||
$.postcss([
|
||||
$.postcssCriticalSplit({
|
||||
blockTag: "@load-async",
|
||||
}),
|
||||
])
|
||||
)
|
||||
.pipe($.rename("async-resources.css"))
|
||||
.pipe($.postcss(postcssPlugins(isProd, { cachebust })))
|
||||
.pipe(gulp.dest(buildFolder))
|
||||
.pipe(browserSync.stream());
|
||||
}
|
||||
|
||||
// Builds the css resources
|
||||
gulp.task("css.resources.dev", () => {
|
||||
return resourcesTask({ cachebust: false, isProd: false });
|
||||
});
|
||||
|
||||
// Builds the css resources in prod (=minified)
|
||||
gulp.task("css.resources.prod", () => {
|
||||
return resourcesTask({ cachebust: true, isProd: true });
|
||||
});
|
||||
|
||||
// Builds the css resources in prod (=minified), without cachebusting
|
||||
gulp.task("css.resources.prod-standalone", () => {
|
||||
return resourcesTask({ cachebust: false, isProd: true });
|
||||
});
|
||||
|
||||
function mainTask({ cachebust, isProd }) {
|
||||
return gulp
|
||||
.src("../src/css/main.scss", { cwd: __dirname })
|
||||
.pipe($.plumber())
|
||||
.pipe($.sass.sync().on("error", $.sass.logError))
|
||||
.pipe(
|
||||
$.postcss([
|
||||
$.postcssCriticalSplit({
|
||||
blockTag: "@load-async",
|
||||
output: "rest",
|
||||
}),
|
||||
])
|
||||
)
|
||||
.pipe($.postcss(postcssPlugins(isProd, { cachebust })))
|
||||
.pipe(gulp.dest(buildFolder))
|
||||
.pipe(browserSync.stream());
|
||||
}
|
||||
|
||||
// Builds the css main
|
||||
gulp.task("css.main.dev", () => {
|
||||
return mainTask({ cachebust: false, isProd: false });
|
||||
});
|
||||
|
||||
// Builds the css main in prod (=minified)
|
||||
gulp.task("css.main.prod", () => {
|
||||
return mainTask({ cachebust: true, isProd: true });
|
||||
});
|
||||
|
||||
// Builds the css main in prod (=minified), without cachebusting
|
||||
gulp.task("css.main.prod-standalone", () => {
|
||||
return mainTask({ cachebust: false, isProd: true });
|
||||
});
|
||||
|
||||
gulp.task("css.dev", gulp.parallel("css.main.dev", "css.resources.dev"));
|
||||
gulp.task("css.prod", gulp.parallel("css.main.prod", "css.resources.prod"));
|
||||
gulp.task(
|
||||
"css.prod-standalone",
|
||||
gulp.parallel("css.main.prod-standalone", "css.resources.prod-standalone")
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
gulptasksCSS,
|
||||
};
|
||||
|
||||
12
gulp/entitlements.plist
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.debugger</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
660
gulp/gulpfile.js
@ -1,325 +1,335 @@
|
||||
/* eslint-disable */
|
||||
|
||||
require("colors");
|
||||
|
||||
const gulp = require("gulp");
|
||||
const browserSync = require("browser-sync").create({});
|
||||
const path = require("path");
|
||||
const deleteEmpty = require("delete-empty");
|
||||
const execSync = require("child_process").execSync;
|
||||
|
||||
const lfsOutput = execSync("git lfs install", { encoding: "utf-8" });
|
||||
if (!lfsOutput.toLowerCase().includes("git lfs initialized")) {
|
||||
console.error(`
|
||||
Git LFS is not installed, unable to build.
|
||||
|
||||
To install Git LFS on Linux:
|
||||
- Arch:
|
||||
sudo pacman -S git-lfs
|
||||
- Debian/Ubuntu:
|
||||
sudo apt install git-lfs
|
||||
|
||||
For other systems, see:
|
||||
https://github.com/git-lfs/git-lfs/wiki/Installation
|
||||
`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Load other plugins dynamically
|
||||
const $ = require("gulp-load-plugins")({
|
||||
scope: ["devDependencies"],
|
||||
pattern: "*",
|
||||
});
|
||||
|
||||
// Check environment variables
|
||||
|
||||
const envVars = [
|
||||
"SHAPEZ_CLI_SERVER_HOST",
|
||||
// "SHAPEZ_CLI_PHONEGAP_KEY",
|
||||
"SHAPEZ_CLI_ALPHA_FTP_USER",
|
||||
"SHAPEZ_CLI_ALPHA_FTP_PW",
|
||||
"SHAPEZ_CLI_STAGING_FTP_USER",
|
||||
"SHAPEZ_CLI_STAGING_FTP_PW",
|
||||
"SHAPEZ_CLI_LIVE_FTP_USER",
|
||||
"SHAPEZ_CLI_LIVE_FTP_PW",
|
||||
];
|
||||
|
||||
for (let i = 0; i < envVars.length; ++i) {
|
||||
if (!process.env[envVars[i]]) {
|
||||
console.warn("Please set", envVars[i]);
|
||||
// process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
const baseDir = path.join(__dirname, "..");
|
||||
const buildFolder = path.join(baseDir, "build");
|
||||
|
||||
const imgres = require("./image-resources");
|
||||
imgres.gulptasksImageResources($, gulp, buildFolder);
|
||||
|
||||
const css = require("./css");
|
||||
css.gulptasksCSS($, gulp, buildFolder, browserSync);
|
||||
|
||||
const sounds = require("./sounds");
|
||||
sounds.gulptasksSounds($, gulp, buildFolder);
|
||||
|
||||
const js = require("./js");
|
||||
js.gulptasksJS($, gulp, buildFolder, browserSync);
|
||||
|
||||
const html = require("./html");
|
||||
html.gulptasksHTML($, gulp, buildFolder, browserSync);
|
||||
|
||||
const ftp = require("./ftp");
|
||||
ftp.gulptasksFTP($, gulp, buildFolder);
|
||||
|
||||
const docs = require("./docs");
|
||||
docs.gulptasksDocs($, gulp, buildFolder);
|
||||
|
||||
const standalone = require("./standalone");
|
||||
standalone.gulptasksStandalone($, gulp, buildFolder);
|
||||
|
||||
const translations = require("./translations");
|
||||
translations.gulptasksTranslations($, gulp, buildFolder);
|
||||
|
||||
// FIXME
|
||||
// const cordova = require("./cordova");
|
||||
// cordova.gulptasksCordova($, gulp, buildFolder);
|
||||
|
||||
///////////////////// BUILD TASKS /////////////////////
|
||||
|
||||
// Cleans up everything
|
||||
gulp.task("utils.cleanBuildFolder", () => {
|
||||
return gulp.src(buildFolder, { read: false, allowEmpty: true }).pipe($.clean({ force: true }));
|
||||
});
|
||||
gulp.task("utils.cleanBuildTempFolder", () => {
|
||||
return gulp
|
||||
.src(path.join(__dirname, "..", "src", "js", "built-temp"), { read: false, allowEmpty: true })
|
||||
.pipe($.clean({ force: true }));
|
||||
});
|
||||
|
||||
gulp.task("utils.cleanup", gulp.series("utils.cleanBuildFolder", "utils.cleanBuildTempFolder"));
|
||||
|
||||
// Requires no uncomitted files
|
||||
gulp.task("utils.requireCleanWorkingTree", cb => {
|
||||
let output = $.trim(execSync("git status -su").toString("ascii")).replace(/\r/gi, "").split("\n");
|
||||
|
||||
// Filter files which are OK to be untracked
|
||||
output = output
|
||||
.map(x => x.replace(/[\r\n]+/gi, ""))
|
||||
.filter(x => x.indexOf(".local.js") < 0)
|
||||
.filter(x => x.length > 0);
|
||||
if (output.length > 0) {
|
||||
console.error("\n\nYou have unstaged changes, please commit everything first!");
|
||||
console.error("Unstaged files:");
|
||||
console.error(output.map(x => "'" + x + "'").join("\n"));
|
||||
process.exit(1);
|
||||
}
|
||||
cb();
|
||||
});
|
||||
|
||||
gulp.task("utils.copyAdditionalBuildFiles", cb => {
|
||||
const additionalFolder = path.join("additional_build_files");
|
||||
const additionalSrcGlobs = [
|
||||
path.join(additionalFolder, "**/*.*"),
|
||||
path.join(additionalFolder, "**/.*"),
|
||||
path.join(additionalFolder, "**/*"),
|
||||
];
|
||||
|
||||
return gulp.src(additionalSrcGlobs).pipe(gulp.dest(buildFolder));
|
||||
});
|
||||
|
||||
// Starts a webserver on the built directory (useful for testing prod build)
|
||||
gulp.task("main.webserver", () => {
|
||||
return gulp.src(buildFolder).pipe(
|
||||
$.webserver({
|
||||
livereload: {
|
||||
enable: true,
|
||||
},
|
||||
directoryListing: false,
|
||||
open: true,
|
||||
port: 3005,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
function serve({ standalone }) {
|
||||
browserSync.init({
|
||||
server: buildFolder,
|
||||
port: 3005,
|
||||
ghostMode: {
|
||||
clicks: false,
|
||||
scroll: false,
|
||||
location: false,
|
||||
forms: false,
|
||||
},
|
||||
logLevel: "info",
|
||||
logPrefix: "BS",
|
||||
online: false,
|
||||
xip: false,
|
||||
notify: false,
|
||||
reloadDebounce: 100,
|
||||
reloadOnRestart: true,
|
||||
watchEvents: ["add", "change"],
|
||||
});
|
||||
|
||||
// Watch .scss files, those trigger a css rebuild
|
||||
gulp.watch(["../src/**/*.scss"], gulp.series("css.dev"));
|
||||
|
||||
// Watch .html files, those trigger a html rebuild
|
||||
gulp.watch("../src/**/*.html", gulp.series(standalone ? "html.standalone-dev" : "html.dev"));
|
||||
|
||||
// Watch sound files
|
||||
// gulp.watch(["../res_raw/sounds/**/*.mp3", "../res_raw/sounds/**/*.wav"], gulp.series("sounds.dev"));
|
||||
|
||||
// Watch translations
|
||||
gulp.watch("../translations/**/*.yaml", gulp.series("translations.convertToJson"));
|
||||
|
||||
gulp.watch(
|
||||
["../res_raw/sounds/sfx/*.mp3", "../res_raw/sounds/sfx/*.wav"],
|
||||
gulp.series("sounds.sfx", "sounds.copy")
|
||||
);
|
||||
gulp.watch(
|
||||
["../res_raw/sounds/music/*.mp3", "../res_raw/sounds/music/*.wav"],
|
||||
gulp.series("sounds.music", "sounds.copy")
|
||||
);
|
||||
|
||||
// Watch resource files and copy them on change
|
||||
gulp.watch(imgres.nonImageResourcesGlobs, gulp.series("imgres.copyNonImageResources"));
|
||||
gulp.watch(imgres.imageResourcesGlobs, gulp.series("imgres.copyImageResources"));
|
||||
|
||||
// Watch .atlas files and recompile the atlas on change
|
||||
gulp.watch("../res_built/atlas/*.json", gulp.series("imgres.atlas"));
|
||||
|
||||
// Watch the build folder and reload when anything changed
|
||||
const extensions = ["html", "js", "png", "gif", "jpg", "svg", "mp3", "ico", "woff2", "json"];
|
||||
gulp.watch(extensions.map(ext => path.join(buildFolder, "**", "*." + ext))).on("change", function (path) {
|
||||
return gulp.src(path).pipe(browserSync.reload({ stream: true }));
|
||||
});
|
||||
|
||||
gulp.watch("../src/js/built-temp/*.json").on("change", function (path) {
|
||||
return gulp.src(path).pipe(browserSync.reload({ stream: true }));
|
||||
});
|
||||
|
||||
// Start the webpack watching server (Will never return)
|
||||
if (standalone) {
|
||||
gulp.series("js.standalone-dev.watch")(() => true);
|
||||
} else {
|
||||
gulp.series("js.dev.watch")(() => true);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////// RUNNABLE TASKS /////////////////////
|
||||
|
||||
// Pre and postbuild
|
||||
gulp.task("step.baseResources", gulp.series("imgres.allOptimized"));
|
||||
gulp.task("step.deleteEmpty", cb => {
|
||||
deleteEmpty.sync(buildFolder);
|
||||
cb();
|
||||
});
|
||||
|
||||
gulp.task("step.postbuild", gulp.series("imgres.cleanupUnusedCssInlineImages", "step.deleteEmpty"));
|
||||
|
||||
// Builds everything (dev)
|
||||
gulp.task(
|
||||
"build.dev",
|
||||
gulp.series(
|
||||
"utils.cleanup",
|
||||
"utils.copyAdditionalBuildFiles",
|
||||
"imgres.atlas",
|
||||
"sounds.dev",
|
||||
"imgres.copyImageResources",
|
||||
"imgres.copyNonImageResources",
|
||||
"translations.fullBuild",
|
||||
"css.dev",
|
||||
"html.dev"
|
||||
)
|
||||
);
|
||||
|
||||
// Builds everything (standalone -dev)
|
||||
gulp.task(
|
||||
"build.standalone.dev",
|
||||
gulp.series(
|
||||
"utils.cleanup",
|
||||
"imgres.atlas",
|
||||
"sounds.dev",
|
||||
"imgres.copyImageResources",
|
||||
"imgres.copyNonImageResources",
|
||||
"translations.fullBuild",
|
||||
"js.standalone-dev",
|
||||
"css.dev",
|
||||
"html.standalone-dev"
|
||||
)
|
||||
);
|
||||
|
||||
// Builds everything (staging)
|
||||
gulp.task("step.staging.code", gulp.series("sounds.fullbuild", "translations.fullBuild", "js.staging"));
|
||||
gulp.task(
|
||||
"step.staging.mainbuild",
|
||||
gulp.parallel("utils.copyAdditionalBuildFiles", "step.baseResources", "step.staging.code")
|
||||
);
|
||||
gulp.task("step.staging.all", gulp.series("step.staging.mainbuild", "css.prod", "html.staging"));
|
||||
gulp.task("build.staging", gulp.series("utils.cleanup", "step.staging.all", "step.postbuild"));
|
||||
|
||||
// Builds everything (prod)
|
||||
gulp.task("step.prod.code", gulp.series("sounds.fullbuild", "translations.fullBuild", "js.prod"));
|
||||
gulp.task(
|
||||
"step.prod.mainbuild",
|
||||
gulp.parallel("utils.copyAdditionalBuildFiles", "step.baseResources", "step.prod.code")
|
||||
);
|
||||
gulp.task("step.prod.all", gulp.series("step.prod.mainbuild", "css.prod", "html.prod"));
|
||||
gulp.task("build.prod", gulp.series("utils.cleanup", "step.prod.all", "step.postbuild"));
|
||||
|
||||
// Builds everything (standalone-beta)
|
||||
gulp.task(
|
||||
"step.standalone-beta.code",
|
||||
gulp.series("sounds.fullbuildHQ", "translations.fullBuild", "js.standalone-beta")
|
||||
);
|
||||
gulp.task("step.standalone-beta.mainbuild", gulp.parallel("step.baseResources", "step.standalone-beta.code"));
|
||||
gulp.task(
|
||||
"step.standalone-beta.all",
|
||||
gulp.series("step.standalone-beta.mainbuild", "css.prod-standalone", "html.standalone-beta")
|
||||
);
|
||||
gulp.task(
|
||||
"build.standalone-beta",
|
||||
gulp.series("utils.cleanup", "step.standalone-beta.all", "step.postbuild")
|
||||
);
|
||||
|
||||
// Builds everything (standalone-prod)
|
||||
gulp.task(
|
||||
"step.standalone-prod.code",
|
||||
gulp.series("sounds.fullbuildHQ", "translations.fullBuild", "js.standalone-prod")
|
||||
);
|
||||
gulp.task("step.standalone-prod.mainbuild", gulp.parallel("step.baseResources", "step.standalone-prod.code"));
|
||||
gulp.task(
|
||||
"step.standalone-prod.all",
|
||||
gulp.series("step.standalone-prod.mainbuild", "css.prod-standalone", "html.standalone-prod")
|
||||
);
|
||||
gulp.task(
|
||||
"build.standalone-prod",
|
||||
gulp.series("utils.cleanup", "step.standalone-prod.all", "step.postbuild")
|
||||
);
|
||||
|
||||
// Deploying!
|
||||
gulp.task(
|
||||
"main.deploy.alpha",
|
||||
gulp.series("utils.requireCleanWorkingTree", "build.staging", "ftp.upload.alpha")
|
||||
);
|
||||
gulp.task(
|
||||
"main.deploy.staging",
|
||||
gulp.series("utils.requireCleanWorkingTree", "build.staging", "ftp.upload.staging")
|
||||
);
|
||||
gulp.task("main.deploy.prod", gulp.series("utils.requireCleanWorkingTree", "build.prod", "ftp.upload.prod"));
|
||||
gulp.task("main.deploy.all", gulp.series("main.deploy.staging", "main.deploy.prod"));
|
||||
gulp.task("main.standalone", gulp.series("build.standalone-prod", "standalone.package.prod"));
|
||||
|
||||
// Live-development
|
||||
gulp.task(
|
||||
"main.serveDev",
|
||||
gulp.series("build.dev", () => serve({ standalone: false }))
|
||||
);
|
||||
gulp.task(
|
||||
"main.serveStandalone",
|
||||
gulp.series("build.standalone.dev", () => serve({ standalone: true }))
|
||||
);
|
||||
|
||||
gulp.task("default", gulp.series("main.serveDev"));
|
||||
/* eslint-disable */
|
||||
|
||||
require("colors");
|
||||
|
||||
const gulp = require("gulp");
|
||||
const browserSync = require("browser-sync").create({});
|
||||
const path = require("path");
|
||||
const deleteEmpty = require("delete-empty");
|
||||
const execSync = require("child_process").execSync;
|
||||
|
||||
// Load other plugins dynamically
|
||||
const $ = require("gulp-load-plugins")({
|
||||
scope: ["devDependencies"],
|
||||
pattern: "*",
|
||||
});
|
||||
|
||||
// Check environment variables
|
||||
|
||||
const envVars = [
|
||||
"SHAPEZ_CLI_SERVER_HOST",
|
||||
// "SHAPEZ_CLI_PHONEGAP_KEY",
|
||||
"SHAPEZ_CLI_ALPHA_FTP_USER",
|
||||
"SHAPEZ_CLI_ALPHA_FTP_PW",
|
||||
"SHAPEZ_CLI_STAGING_FTP_USER",
|
||||
"SHAPEZ_CLI_STAGING_FTP_PW",
|
||||
"SHAPEZ_CLI_LIVE_FTP_USER",
|
||||
"SHAPEZ_CLI_LIVE_FTP_PW",
|
||||
"SHAPEZ_CLI_APPLE_ID",
|
||||
"SHAPEZ_CLI_APPLE_CERT_NAME",
|
||||
"SHAPEZ_CLI_GITHUB_USER",
|
||||
"SHAPEZ_CLI_GITHUB_TOKEN",
|
||||
];
|
||||
|
||||
for (let i = 0; i < envVars.length; ++i) {
|
||||
if (!process.env[envVars[i]]) {
|
||||
console.warn("Please set", envVars[i]);
|
||||
// process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
const baseDir = path.join(__dirname, "..");
|
||||
const buildFolder = path.join(baseDir, "build");
|
||||
|
||||
const imgres = require("./image-resources");
|
||||
imgres.gulptasksImageResources($, gulp, buildFolder);
|
||||
|
||||
const css = require("./css");
|
||||
css.gulptasksCSS($, gulp, buildFolder, browserSync);
|
||||
|
||||
const sounds = require("./sounds");
|
||||
sounds.gulptasksSounds($, gulp, buildFolder);
|
||||
|
||||
const js = require("./js");
|
||||
js.gulptasksJS($, gulp, buildFolder, browserSync);
|
||||
|
||||
const html = require("./html");
|
||||
html.gulptasksHTML($, gulp, buildFolder, browserSync);
|
||||
|
||||
const ftp = require("./ftp");
|
||||
ftp.gulptasksFTP($, gulp, buildFolder);
|
||||
|
||||
const docs = require("./docs");
|
||||
docs.gulptasksDocs($, gulp, buildFolder);
|
||||
|
||||
const standalone = require("./standalone");
|
||||
standalone.gulptasksStandalone($, gulp, buildFolder);
|
||||
|
||||
const releaseUploader = require("./release-uploader");
|
||||
releaseUploader.gulptasksReleaseUploader($, gulp, buildFolder);
|
||||
|
||||
const translations = require("./translations");
|
||||
translations.gulptasksTranslations($, gulp, buildFolder);
|
||||
|
||||
///////////////////// BUILD TASKS /////////////////////
|
||||
|
||||
// Cleans up everything
|
||||
gulp.task("utils.cleanBuildFolder", () => {
|
||||
return gulp.src(buildFolder, { read: false, allowEmpty: true }).pipe($.clean({ force: true }));
|
||||
});
|
||||
gulp.task("utils.cleanBuildTempFolder", () => {
|
||||
return gulp
|
||||
.src(path.join(__dirname, "..", "src", "js", "built-temp"), { read: false, allowEmpty: 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.cleanImageBuildFolder", "utils.cleanBuildTempFolder")
|
||||
);
|
||||
|
||||
// Requires no uncomitted files
|
||||
gulp.task("utils.requireCleanWorkingTree", cb => {
|
||||
let output = $.trim(execSync("git status -su").toString("ascii")).replace(/\r/gi, "").split("\n");
|
||||
|
||||
// Filter files which are OK to be untracked
|
||||
output = output
|
||||
.map(x => x.replace(/[\r\n]+/gi, ""))
|
||||
.filter(x => x.indexOf(".local.js") < 0)
|
||||
.filter(x => x.length > 0);
|
||||
if (output.length > 0) {
|
||||
console.error("\n\nYou have unstaged changes, please commit everything first!");
|
||||
console.error("Unstaged files:");
|
||||
console.error(output.map(x => "'" + x + "'").join("\n"));
|
||||
process.exit(1);
|
||||
}
|
||||
cb();
|
||||
});
|
||||
|
||||
gulp.task("utils.copyAdditionalBuildFiles", cb => {
|
||||
const additionalFolder = path.join("additional_build_files");
|
||||
const additionalSrcGlobs = [
|
||||
path.join(additionalFolder, "**/*.*"),
|
||||
path.join(additionalFolder, "**/.*"),
|
||||
path.join(additionalFolder, "**/*"),
|
||||
];
|
||||
|
||||
return gulp.src(additionalSrcGlobs).pipe(gulp.dest(buildFolder));
|
||||
});
|
||||
|
||||
// Starts a webserver on the built directory (useful for testing prod build)
|
||||
gulp.task("main.webserver", () => {
|
||||
return gulp.src(buildFolder).pipe(
|
||||
$.webserver({
|
||||
livereload: {
|
||||
enable: true,
|
||||
},
|
||||
directoryListing: false,
|
||||
open: true,
|
||||
port: 3005,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
function serve({ standalone }) {
|
||||
browserSync.init({
|
||||
server: buildFolder,
|
||||
port: 3005,
|
||||
ghostMode: {
|
||||
clicks: false,
|
||||
scroll: false,
|
||||
location: false,
|
||||
forms: false,
|
||||
},
|
||||
logLevel: "info",
|
||||
logPrefix: "BS",
|
||||
online: false,
|
||||
xip: false,
|
||||
notify: false,
|
||||
reloadDebounce: 100,
|
||||
reloadOnRestart: true,
|
||||
watchEvents: ["add", "change"],
|
||||
});
|
||||
|
||||
// Watch .scss files, those trigger a css rebuild
|
||||
gulp.watch(["../src/**/*.scss"], gulp.series("css.dev"));
|
||||
|
||||
// Watch .html files, those trigger a html rebuild
|
||||
gulp.watch("../src/**/*.html", gulp.series(standalone ? "html.standalone-dev" : "html.dev"));
|
||||
|
||||
// Watch sound files
|
||||
// gulp.watch(["../res_raw/sounds/**/*.mp3", "../res_raw/sounds/**/*.wav"], gulp.series("sounds.dev"));
|
||||
|
||||
// Watch translations
|
||||
gulp.watch("../translations/**/*.yaml", gulp.series("translations.convertToJson"));
|
||||
|
||||
gulp.watch(
|
||||
["../res_raw/sounds/sfx/*.mp3", "../res_raw/sounds/sfx/*.wav"],
|
||||
gulp.series("sounds.sfx", "sounds.copy")
|
||||
);
|
||||
gulp.watch(
|
||||
["../res_raw/sounds/music/*.mp3", "../res_raw/sounds/music/*.wav"],
|
||||
gulp.series("sounds.music", "sounds.copy")
|
||||
);
|
||||
|
||||
// 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.imageResourcesGlobs, gulp.series("imgres.copyImageResources"));
|
||||
|
||||
// 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"));
|
||||
|
||||
// Watch the build folder and reload when anything changed
|
||||
const extensions = ["html", "js", "png", "gif", "jpg", "svg", "mp3", "ico", "woff2", "json"];
|
||||
gulp.watch(extensions.map(ext => path.join(buildFolder, "**", "*." + ext))).on("change", function (path) {
|
||||
return gulp.src(path).pipe(browserSync.reload({ stream: true }));
|
||||
});
|
||||
|
||||
gulp.watch("../src/js/built-temp/*.json").on("change", function (path) {
|
||||
return gulp.src(path).pipe(browserSync.reload({ stream: true }));
|
||||
});
|
||||
|
||||
// Start the webpack watching server (Will never return)
|
||||
if (standalone) {
|
||||
gulp.series("js.standalone-dev.watch")(() => true);
|
||||
} else {
|
||||
gulp.series("js.dev.watch")(() => true);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////// RUNNABLE TASKS /////////////////////
|
||||
|
||||
// Pre and postbuild
|
||||
gulp.task("step.baseResources", gulp.series("imgres.allOptimized"));
|
||||
gulp.task("step.deleteEmpty", cb => {
|
||||
deleteEmpty.sync(buildFolder);
|
||||
cb();
|
||||
});
|
||||
|
||||
gulp.task("step.postbuild", gulp.series("imgres.cleanupUnusedCssInlineImages", "step.deleteEmpty"));
|
||||
|
||||
// Builds everything (dev)
|
||||
gulp.task(
|
||||
"build.dev",
|
||||
gulp.series(
|
||||
"utils.cleanup",
|
||||
"utils.copyAdditionalBuildFiles",
|
||||
"imgres.buildAtlas",
|
||||
"imgres.atlasToJson",
|
||||
"imgres.atlas",
|
||||
"sounds.dev",
|
||||
"imgres.copyImageResources",
|
||||
"imgres.copyNonImageResources",
|
||||
"translations.fullBuild",
|
||||
"css.dev",
|
||||
"html.dev"
|
||||
)
|
||||
);
|
||||
|
||||
// Builds everything (standalone -dev)
|
||||
gulp.task(
|
||||
"build.standalone.dev",
|
||||
gulp.series(
|
||||
"utils.cleanup",
|
||||
"imgres.buildAtlas",
|
||||
"imgres.atlasToJson",
|
||||
"imgres.atlas",
|
||||
"sounds.dev",
|
||||
"imgres.copyImageResources",
|
||||
"imgres.copyNonImageResources",
|
||||
"translations.fullBuild",
|
||||
"css.dev",
|
||||
"html.standalone-dev"
|
||||
)
|
||||
);
|
||||
|
||||
// Builds everything (staging)
|
||||
gulp.task("step.staging.code", gulp.series("sounds.fullbuild", "translations.fullBuild", "js.staging"));
|
||||
gulp.task(
|
||||
"step.staging.mainbuild",
|
||||
gulp.parallel("utils.copyAdditionalBuildFiles", "step.baseResources", "step.staging.code")
|
||||
);
|
||||
gulp.task("step.staging.all", gulp.series("step.staging.mainbuild", "css.prod", "html.staging"));
|
||||
gulp.task("build.staging", gulp.series("utils.cleanup", "step.staging.all", "step.postbuild"));
|
||||
|
||||
// Builds everything (prod)
|
||||
gulp.task("step.prod.code", gulp.series("sounds.fullbuild", "translations.fullBuild", "js.prod"));
|
||||
gulp.task(
|
||||
"step.prod.mainbuild",
|
||||
gulp.parallel("utils.copyAdditionalBuildFiles", "step.baseResources", "step.prod.code")
|
||||
);
|
||||
gulp.task("step.prod.all", gulp.series("step.prod.mainbuild", "css.prod", "html.prod"));
|
||||
gulp.task("build.prod", gulp.series("utils.cleanup", "step.prod.all", "step.postbuild"));
|
||||
|
||||
// Builds everything (standalone-beta)
|
||||
gulp.task(
|
||||
"step.standalone-beta.code",
|
||||
gulp.series("sounds.fullbuildHQ", "translations.fullBuild", "js.standalone-beta")
|
||||
);
|
||||
gulp.task("step.standalone-beta.mainbuild", gulp.parallel("step.baseResources", "step.standalone-beta.code"));
|
||||
gulp.task(
|
||||
"step.standalone-beta.all",
|
||||
gulp.series("step.standalone-beta.mainbuild", "css.prod-standalone", "html.standalone-beta")
|
||||
);
|
||||
gulp.task(
|
||||
"build.standalone-beta",
|
||||
gulp.series("utils.cleanup", "step.standalone-beta.all", "step.postbuild")
|
||||
);
|
||||
|
||||
// Builds everything (standalone-prod)
|
||||
gulp.task(
|
||||
"step.standalone-prod.code",
|
||||
gulp.series("sounds.fullbuildHQ", "translations.fullBuild", "js.standalone-prod")
|
||||
);
|
||||
gulp.task("step.standalone-prod.mainbuild", gulp.parallel("step.baseResources", "step.standalone-prod.code"));
|
||||
gulp.task(
|
||||
"step.standalone-prod.all",
|
||||
gulp.series("step.standalone-prod.mainbuild", "css.prod-standalone", "html.standalone-prod")
|
||||
);
|
||||
gulp.task(
|
||||
"build.standalone-prod",
|
||||
gulp.series("utils.cleanup", "step.standalone-prod.all", "step.postbuild")
|
||||
);
|
||||
|
||||
// OS X build and release upload
|
||||
gulp.task(
|
||||
"build.darwin64-prod",
|
||||
gulp.series(
|
||||
"build.standalone-prod",
|
||||
"standalone.prepare",
|
||||
"standalone.package.prod.darwin64",
|
||||
"standalone.uploadRelease.darwin64"
|
||||
)
|
||||
);
|
||||
|
||||
// Deploying!
|
||||
gulp.task(
|
||||
"main.deploy.alpha",
|
||||
gulp.series("utils.requireCleanWorkingTree", "build.staging", "ftp.upload.alpha")
|
||||
);
|
||||
gulp.task(
|
||||
"main.deploy.staging",
|
||||
gulp.series("utils.requireCleanWorkingTree", "build.staging", "ftp.upload.staging")
|
||||
);
|
||||
gulp.task("main.deploy.prod", gulp.series("utils.requireCleanWorkingTree", "build.prod", "ftp.upload.prod"));
|
||||
gulp.task("main.deploy.all", gulp.series("main.deploy.staging", "main.deploy.prod"));
|
||||
gulp.task("main.standalone", gulp.series("build.standalone-prod", "standalone.package.prod"));
|
||||
|
||||
// Live-development
|
||||
gulp.task(
|
||||
"main.serveDev",
|
||||
gulp.series("build.dev", () => serve({ standalone: false }))
|
||||
);
|
||||
gulp.task(
|
||||
"main.serveStandalone",
|
||||
gulp.series("build.standalone.dev", () => serve({ standalone: true }))
|
||||
);
|
||||
|
||||
gulp.task("default", gulp.series("main.serveDev"));
|
||||
|
||||
584
gulp/html.js
@ -1,283 +1,301 @@
|
||||
const buildUtils = require("./buildutils");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const crypto = require("crypto");
|
||||
|
||||
function computeIntegrityHash(fullPath, algorithm = "sha256") {
|
||||
const file = fs.readFileSync(fullPath);
|
||||
const hash = crypto.createHash(algorithm).update(file).digest("base64");
|
||||
return algorithm + "-" + hash;
|
||||
}
|
||||
|
||||
function gulptasksHTML($, gulp, buildFolder) {
|
||||
const commitHash = buildUtils.getRevision();
|
||||
async function buildHtml(
|
||||
apiUrl,
|
||||
{ analytics = false, standalone = false, app = false, integrity = true, enableCachebust = true }
|
||||
) {
|
||||
function cachebust(url) {
|
||||
if (enableCachebust) {
|
||||
return buildUtils.cachebust(url, commitHash);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
const hasLocalFiles = standalone || app;
|
||||
|
||||
return gulp
|
||||
.src("../src/html/" + (standalone ? "index.standalone.html" : "index.html"))
|
||||
.pipe(
|
||||
$.dom(/** @this {Document} **/ function () {
|
||||
const document = this;
|
||||
|
||||
// Preconnect to api
|
||||
const prefetchLink = document.createElement("link");
|
||||
prefetchLink.rel = "preconnect";
|
||||
prefetchLink.href = apiUrl;
|
||||
prefetchLink.setAttribute("crossorigin", "anonymous");
|
||||
document.head.appendChild(prefetchLink);
|
||||
|
||||
// Append css
|
||||
const css = document.createElement("link");
|
||||
css.rel = "stylesheet";
|
||||
css.type = "text/css";
|
||||
css.media = "none";
|
||||
css.setAttribute("onload", "this.media='all'");
|
||||
css.href = cachebust("main.css");
|
||||
if (integrity) {
|
||||
css.setAttribute(
|
||||
"integrity",
|
||||
computeIntegrityHash(path.join(buildFolder, "main.css"))
|
||||
);
|
||||
}
|
||||
document.head.appendChild(css);
|
||||
|
||||
if (app) {
|
||||
// Append cordova link
|
||||
const cdv = document.createElement("script");
|
||||
cdv.src = "cordova.js";
|
||||
cdv.type = "text/javascript";
|
||||
document.head.appendChild(cdv);
|
||||
}
|
||||
|
||||
// Google analytics
|
||||
if (analytics) {
|
||||
const tagManagerScript = document.createElement("script");
|
||||
tagManagerScript.src = "https://www.googletagmanager.com/gtag/js?id=UA-165342524-1";
|
||||
tagManagerScript.setAttribute("async", "");
|
||||
document.head.appendChild(tagManagerScript);
|
||||
|
||||
const initScript = document.createElement("script");
|
||||
initScript.textContent = `
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'UA-165342524-1', { anonymize_ip: true });
|
||||
`;
|
||||
document.head.appendChild(initScript);
|
||||
|
||||
const abTestingScript = document.createElement("script");
|
||||
abTestingScript.setAttribute(
|
||||
"src",
|
||||
"https://www.googleoptimize.com/optimize.js?id=OPT-M5NHCV7"
|
||||
);
|
||||
abTestingScript.setAttribute("async", "");
|
||||
document.head.appendChild(abTestingScript);
|
||||
}
|
||||
|
||||
// Do not need to preload in app or standalone
|
||||
if (!hasLocalFiles) {
|
||||
// Preload essentials
|
||||
const preloads = ["fonts/GameFont.woff2"];
|
||||
|
||||
preloads.forEach(src => {
|
||||
const preloadLink = document.createElement("link");
|
||||
preloadLink.rel = "preload";
|
||||
preloadLink.href = cachebust("res/" + src);
|
||||
if (src.endsWith(".woff2")) {
|
||||
preloadLink.setAttribute("crossorigin", "anonymous");
|
||||
preloadLink.setAttribute("as", "font");
|
||||
} else {
|
||||
preloadLink.setAttribute("as", "image");
|
||||
}
|
||||
document.head.appendChild(preloadLink);
|
||||
});
|
||||
}
|
||||
|
||||
const loadingSvg = `background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHN0eWxlPSJtYXJnaW46YXV0bztiYWNrZ3JvdW5kOjAgMCIgd2lkdGg9IjIwMCIgaGVpZ2h0PSIyMDAiIHZpZXdCb3g9IjAgMCAxMDAgMTAwIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCIgZGlzcGxheT0iYmxvY2siPjxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzM5Mzc0NyIgc3Ryb2tlLXdpZHRoPSIzIiByPSI0MiIgc3Ryb2tlLWRhc2hhcnJheT0iMTk3LjkyMDMzNzE3NjE1Njk4IDY3Ljk3MzQ0NTcyNTM4NTY2IiB0cmFuc2Zvcm09InJvdGF0ZSg0OC4yNjUgNTAgNTApIj48YW5pbWF0ZVRyYW5zZm9ybSBhdHRyaWJ1dGVOYW1lPSJ0cmFuc2Zvcm0iIHR5cGU9InJvdGF0ZSIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIGR1cj0iNS41NTU1NTU1NTU1NTU1NTVzIiB2YWx1ZXM9IjAgNTAgNTA7MzYwIDUwIDUwIiBrZXlUaW1lcz0iMDsxIi8+PC9jaXJjbGU+PC9zdmc+")`;
|
||||
|
||||
const loadingCss = `
|
||||
@font-face {
|
||||
font-family: 'GameFont';
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-display: swap;
|
||||
src: url('${cachebust("res/fonts/GameFont.woff2")}') format('woff2');
|
||||
}
|
||||
|
||||
#ll_fp {
|
||||
font-family: GameFont;
|
||||
font-size: 14px;
|
||||
position: fixed;
|
||||
z-index: -1;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 0.05;
|
||||
}
|
||||
|
||||
#ll_p {
|
||||
display: flex;
|
||||
position: fixed;
|
||||
z-index: 99999;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
justify-content:
|
||||
center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#ll_p > div {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
bottom: 40px;
|
||||
left: 20px;
|
||||
right: 20px;
|
||||
color: #393747;
|
||||
font-family: 'GameFont', sans-serif;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
#ll_p > span {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
display: inline-flex;
|
||||
background: center center / contain no-repeat;
|
||||
${loadingSvg};
|
||||
}
|
||||
`;
|
||||
|
||||
const style = document.createElement("style");
|
||||
style.setAttribute("type", "text/css");
|
||||
style.textContent = loadingCss;
|
||||
document.head.appendChild(style);
|
||||
|
||||
// Append loader, but not in standalone (directly include bundle there)
|
||||
if (standalone) {
|
||||
const bundleScript = document.createElement("script");
|
||||
bundleScript.type = "text/javascript";
|
||||
bundleScript.src = "bundle.js";
|
||||
if (integrity) {
|
||||
bundleScript.setAttribute(
|
||||
"integrity",
|
||||
computeIntegrityHash(path.join(buildFolder, "bundle.js"))
|
||||
);
|
||||
}
|
||||
document.head.appendChild(bundleScript);
|
||||
} else {
|
||||
const loadJs = document.createElement("script");
|
||||
loadJs.type = "text/javascript";
|
||||
let scriptContent = "";
|
||||
scriptContent += `var bundleSrc = '${cachebust("bundle.js")}';\n`;
|
||||
scriptContent += `var bundleSrcTranspiled = '${cachebust(
|
||||
"bundle-transpiled.js"
|
||||
)}';\n`;
|
||||
|
||||
if (integrity) {
|
||||
scriptContent +=
|
||||
"var bundleIntegrity = '" +
|
||||
computeIntegrityHash(path.join(buildFolder, "bundle.js")) +
|
||||
"';\n";
|
||||
scriptContent +=
|
||||
"var bundleIntegrityTranspiled = '" +
|
||||
computeIntegrityHash(path.join(buildFolder, "bundle-transpiled.js")) +
|
||||
"';\n";
|
||||
} else {
|
||||
scriptContent += "var bundleIntegrity = null;\n";
|
||||
scriptContent += "var bundleIntegrityTranspiled = null;\n";
|
||||
}
|
||||
|
||||
scriptContent += fs.readFileSync("./bundle-loader.js").toString();
|
||||
loadJs.textContent = scriptContent;
|
||||
document.head.appendChild(loadJs);
|
||||
}
|
||||
|
||||
const bodyContent = `
|
||||
<div id="ll_fp">_</div>
|
||||
<div id="ll_p">
|
||||
<span></span>
|
||||
<div>${hasLocalFiles ? "Loading" : "Downloading"} Game Files</div >
|
||||
</div >
|
||||
`;
|
||||
|
||||
document.body.innerHTML = bodyContent;
|
||||
})
|
||||
)
|
||||
.pipe(
|
||||
$.htmlmin({
|
||||
caseSensitive: true,
|
||||
collapseBooleanAttributes: true,
|
||||
collapseInlineTagWhitespace: true,
|
||||
collapseWhitespace: true,
|
||||
preserveLineBreaks: true,
|
||||
minifyJS: true,
|
||||
minifyCSS: true,
|
||||
quoteCharacter: '"',
|
||||
useShortDoctype: true,
|
||||
})
|
||||
)
|
||||
.pipe($.htmlBeautify())
|
||||
.pipe($.rename("index.html"))
|
||||
.pipe(gulp.dest(buildFolder));
|
||||
}
|
||||
|
||||
gulp.task("html.dev", () => {
|
||||
return buildHtml("http://localhost:5005", {
|
||||
analytics: false,
|
||||
integrity: false,
|
||||
enableCachebust: false,
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task("html.staging", () => {
|
||||
return buildHtml("https://api-staging.shapez.io", {
|
||||
analytics: true,
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task("html.prod", () => {
|
||||
return buildHtml("https://analytics.shapez.io", {
|
||||
analytics: true,
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task("html.standalone-dev", () => {
|
||||
return buildHtml("https://localhost:5005", {
|
||||
analytics: false,
|
||||
standalone: true,
|
||||
integrity: false,
|
||||
enableCachebust: false,
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task("html.standalone-beta", () => {
|
||||
return buildHtml("https://api-staging.shapez.io", {
|
||||
analytics: false,
|
||||
standalone: true,
|
||||
enableCachebust: false,
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task("html.standalone-prod", () => {
|
||||
return buildHtml("https://analytics.shapez.io", {
|
||||
analytics: false,
|
||||
standalone: true,
|
||||
enableCachebust: false,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
gulptasksHTML,
|
||||
};
|
||||
const buildUtils = require("./buildutils");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const crypto = require("crypto");
|
||||
|
||||
function computeIntegrityHash(fullPath, algorithm = "sha256") {
|
||||
const file = fs.readFileSync(fullPath);
|
||||
const hash = crypto.createHash(algorithm).update(file).digest("base64");
|
||||
return algorithm + "-" + hash;
|
||||
}
|
||||
|
||||
function gulptasksHTML($, gulp, buildFolder) {
|
||||
const commitHash = buildUtils.getRevision();
|
||||
async function buildHtml(
|
||||
apiUrl,
|
||||
{ analytics = false, standalone = false, app = false, integrity = true, enableCachebust = true }
|
||||
) {
|
||||
function cachebust(url) {
|
||||
if (enableCachebust) {
|
||||
return buildUtils.cachebust(url, commitHash);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
const hasLocalFiles = standalone || app;
|
||||
|
||||
return gulp
|
||||
.src("../src/html/" + (standalone ? "index.standalone.html" : "index.html"))
|
||||
.pipe(
|
||||
$.dom(
|
||||
/** @this {Document} **/ function () {
|
||||
const document = this;
|
||||
|
||||
// Preconnect to api
|
||||
const prefetchLink = document.createElement("link");
|
||||
prefetchLink.rel = "preconnect";
|
||||
prefetchLink.href = apiUrl;
|
||||
prefetchLink.setAttribute("crossorigin", "anonymous");
|
||||
document.head.appendChild(prefetchLink);
|
||||
|
||||
// Append css
|
||||
const css = document.createElement("link");
|
||||
css.rel = "stylesheet";
|
||||
css.type = "text/css";
|
||||
css.media = "none";
|
||||
css.setAttribute("onload", "this.media='all'");
|
||||
css.href = cachebust("main.css");
|
||||
if (integrity) {
|
||||
css.setAttribute(
|
||||
"integrity",
|
||||
computeIntegrityHash(path.join(buildFolder, "main.css"))
|
||||
);
|
||||
}
|
||||
document.head.appendChild(css);
|
||||
|
||||
// Append async css
|
||||
// const asyncCss = document.createElement("link");
|
||||
// asyncCss.rel = "stylesheet";
|
||||
// asyncCss.type = "text/css";
|
||||
// asyncCss.media = "none";
|
||||
// asyncCss.setAttribute("onload", "this.media='all'");
|
||||
// asyncCss.href = cachebust("async-resources.css");
|
||||
// if (integrity) {
|
||||
// asyncCss.setAttribute(
|
||||
// "integrity",
|
||||
// computeIntegrityHash(path.join(buildFolder, "async-resources.css"))
|
||||
// );
|
||||
// }
|
||||
// document.head.appendChild(asyncCss);
|
||||
|
||||
if (app) {
|
||||
// Append cordova link
|
||||
const cdv = document.createElement("script");
|
||||
cdv.src = "cordova.js";
|
||||
cdv.type = "text/javascript";
|
||||
document.head.appendChild(cdv);
|
||||
}
|
||||
|
||||
// Google analytics
|
||||
if (analytics) {
|
||||
const tagManagerScript = document.createElement("script");
|
||||
tagManagerScript.src =
|
||||
"https://www.googletagmanager.com/gtag/js?id=UA-165342524-1";
|
||||
tagManagerScript.setAttribute("async", "");
|
||||
document.head.appendChild(tagManagerScript);
|
||||
|
||||
const initScript = document.createElement("script");
|
||||
initScript.textContent = `
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'UA-165342524-1', { anonymize_ip: true });
|
||||
`;
|
||||
document.head.appendChild(initScript);
|
||||
|
||||
const abTestingScript = document.createElement("script");
|
||||
abTestingScript.setAttribute(
|
||||
"src",
|
||||
"https://www.googleoptimize.com/optimize.js?id=OPT-M5NHCV7"
|
||||
);
|
||||
abTestingScript.setAttribute("async", "");
|
||||
document.head.appendChild(abTestingScript);
|
||||
}
|
||||
|
||||
// Do not need to preload in app or standalone
|
||||
if (!hasLocalFiles) {
|
||||
// Preload essentials
|
||||
const preloads = ["fonts/GameFont.woff2"];
|
||||
|
||||
preloads.forEach(src => {
|
||||
const preloadLink = document.createElement("link");
|
||||
preloadLink.rel = "preload";
|
||||
preloadLink.href = cachebust("res/" + src);
|
||||
if (src.endsWith(".woff2")) {
|
||||
preloadLink.setAttribute("crossorigin", "anonymous");
|
||||
preloadLink.setAttribute("as", "font");
|
||||
} else {
|
||||
preloadLink.setAttribute("as", "image");
|
||||
}
|
||||
document.head.appendChild(preloadLink);
|
||||
});
|
||||
}
|
||||
|
||||
const loadingSvg = `background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHN0eWxlPSJtYXJnaW46YXV0bztiYWNrZ3JvdW5kOjAgMCIgd2lkdGg9IjIwMCIgaGVpZ2h0PSIyMDAiIHZpZXdCb3g9IjAgMCAxMDAgMTAwIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCIgZGlzcGxheT0iYmxvY2siPjxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzM5Mzc0NyIgc3Ryb2tlLXdpZHRoPSIzIiByPSI0MiIgc3Ryb2tlLWRhc2hhcnJheT0iMTk3LjkyMDMzNzE3NjE1Njk4IDY3Ljk3MzQ0NTcyNTM4NTY2IiB0cmFuc2Zvcm09InJvdGF0ZSg0OC4yNjUgNTAgNTApIj48YW5pbWF0ZVRyYW5zZm9ybSBhdHRyaWJ1dGVOYW1lPSJ0cmFuc2Zvcm0iIHR5cGU9InJvdGF0ZSIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIGR1cj0iNS41NTU1NTU1NTU1NTU1NTVzIiB2YWx1ZXM9IjAgNTAgNTA7MzYwIDUwIDUwIiBrZXlUaW1lcz0iMDsxIi8+PC9jaXJjbGU+PC9zdmc+")`;
|
||||
|
||||
const loadingCss = `
|
||||
@font-face {
|
||||
font-family: 'GameFont';
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-display: swap;
|
||||
src: url('${cachebust("res/fonts/GameFont.woff2")}') format('woff2');
|
||||
}
|
||||
|
||||
#ll_fp {
|
||||
font-family: GameFont;
|
||||
font-size: 14px;
|
||||
position: fixed;
|
||||
z-index: -1;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 0.05;
|
||||
}
|
||||
|
||||
#ll_p {
|
||||
display: flex;
|
||||
position: fixed;
|
||||
z-index: 99999;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
justify-content:
|
||||
center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#ll_p > div {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
bottom: 40px;
|
||||
left: 20px;
|
||||
right: 20px;
|
||||
color: #393747;
|
||||
font-family: 'GameFont', sans-serif;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
#ll_p > span {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
display: inline-flex;
|
||||
background: center center / contain no-repeat;
|
||||
${loadingSvg};
|
||||
}
|
||||
`;
|
||||
|
||||
const style = document.createElement("style");
|
||||
style.setAttribute("type", "text/css");
|
||||
style.textContent = loadingCss;
|
||||
document.head.appendChild(style);
|
||||
|
||||
// Append loader, but not in standalone (directly include bundle there)
|
||||
if (standalone) {
|
||||
const bundleScript = document.createElement("script");
|
||||
bundleScript.type = "text/javascript";
|
||||
bundleScript.src = "bundle.js";
|
||||
if (integrity) {
|
||||
bundleScript.setAttribute(
|
||||
"integrity",
|
||||
computeIntegrityHash(path.join(buildFolder, "bundle.js"))
|
||||
);
|
||||
}
|
||||
document.head.appendChild(bundleScript);
|
||||
} else {
|
||||
const loadJs = document.createElement("script");
|
||||
loadJs.type = "text/javascript";
|
||||
let scriptContent = "";
|
||||
scriptContent += `var bundleSrc = '${cachebust("bundle.js")}';\n`;
|
||||
scriptContent += `var bundleSrcTranspiled = '${cachebust(
|
||||
"bundle-transpiled.js"
|
||||
)}';\n`;
|
||||
|
||||
if (integrity) {
|
||||
scriptContent +=
|
||||
"var bundleIntegrity = '" +
|
||||
computeIntegrityHash(path.join(buildFolder, "bundle.js")) +
|
||||
"';\n";
|
||||
scriptContent +=
|
||||
"var bundleIntegrityTranspiled = '" +
|
||||
computeIntegrityHash(path.join(buildFolder, "bundle-transpiled.js")) +
|
||||
"';\n";
|
||||
} else {
|
||||
scriptContent += "var bundleIntegrity = null;\n";
|
||||
scriptContent += "var bundleIntegrityTranspiled = null;\n";
|
||||
}
|
||||
|
||||
scriptContent += fs.readFileSync("./bundle-loader.js").toString();
|
||||
loadJs.textContent = scriptContent;
|
||||
document.head.appendChild(loadJs);
|
||||
}
|
||||
|
||||
const bodyContent = `
|
||||
<div id="ll_fp">_</div>
|
||||
<div id="ll_p">
|
||||
<span></span>
|
||||
<div>${hasLocalFiles ? "Loading" : "Downloading"} Game Files</div >
|
||||
</div >
|
||||
`;
|
||||
|
||||
document.body.innerHTML = bodyContent;
|
||||
}
|
||||
)
|
||||
)
|
||||
.pipe(
|
||||
$.htmlmin({
|
||||
caseSensitive: true,
|
||||
collapseBooleanAttributes: true,
|
||||
collapseInlineTagWhitespace: true,
|
||||
collapseWhitespace: true,
|
||||
preserveLineBreaks: true,
|
||||
minifyJS: true,
|
||||
minifyCSS: true,
|
||||
quoteCharacter: '"',
|
||||
useShortDoctype: true,
|
||||
})
|
||||
)
|
||||
.pipe($.htmlBeautify())
|
||||
.pipe($.rename("index.html"))
|
||||
.pipe(gulp.dest(buildFolder));
|
||||
}
|
||||
|
||||
gulp.task("html.dev", () => {
|
||||
return buildHtml("http://localhost:5005", {
|
||||
analytics: false,
|
||||
integrity: false,
|
||||
enableCachebust: false,
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task("html.staging", () => {
|
||||
return buildHtml("https://api-staging.shapez.io", {
|
||||
analytics: true,
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task("html.prod", () => {
|
||||
return buildHtml("https://analytics.shapez.io", {
|
||||
analytics: true,
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task("html.standalone-dev", () => {
|
||||
return buildHtml("https://localhost:5005", {
|
||||
analytics: false,
|
||||
standalone: true,
|
||||
integrity: false,
|
||||
enableCachebust: false,
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task("html.standalone-beta", () => {
|
||||
return buildHtml("https://api-staging.shapez.io", {
|
||||
analytics: false,
|
||||
standalone: true,
|
||||
enableCachebust: false,
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task("html.standalone-prod", () => {
|
||||
return buildHtml("https://analytics.shapez.io", {
|
||||
analytics: false,
|
||||
standalone: true,
|
||||
enableCachebust: false,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
gulptasksHTML,
|
||||
};
|
||||
|
||||
@ -1,148 +1,205 @@
|
||||
// @ts-ignore
|
||||
const path = require("path");
|
||||
|
||||
// Globs for non-ui resources
|
||||
const nonImageResourcesGlobs = ["../res/**/*.woff2", "../res/*.ico", "../res/**/*.webm"];
|
||||
|
||||
// Globs for ui resources
|
||||
const imageResourcesGlobs = ["../res/**/*.png", "../res/**/*.svg", "../res/**/*.jpg", "../res/**/*.gif"];
|
||||
|
||||
function gulptasksImageResources($, gulp, buildFolder) {
|
||||
// Lossless options
|
||||
const minifyImagesOptsLossless = () => [
|
||||
$.imageminJpegtran({
|
||||
progressive: true,
|
||||
}),
|
||||
$.imagemin.svgo({}),
|
||||
$.imagemin.optipng({
|
||||
optimizationLevel: 3,
|
||||
}),
|
||||
$.imageminGifsicle({
|
||||
optimizationLevel: 3,
|
||||
colors: 128,
|
||||
}),
|
||||
];
|
||||
|
||||
// Lossy options
|
||||
const minifyImagesOpts = () => [
|
||||
$.imagemin.mozjpeg({
|
||||
quality: 80,
|
||||
maxMemory: 1024 * 1024 * 8,
|
||||
}),
|
||||
$.imagemin.svgo({}),
|
||||
$.imageminPngquant({
|
||||
speed: 1,
|
||||
strip: true,
|
||||
quality: [0.65, 0.9],
|
||||
dithering: false,
|
||||
verbose: false,
|
||||
}),
|
||||
$.imagemin.optipng({
|
||||
optimizationLevel: 3,
|
||||
}),
|
||||
$.imageminGifsicle({
|
||||
optimizationLevel: 3,
|
||||
colors: 128,
|
||||
}),
|
||||
];
|
||||
|
||||
// Where the resources folder are
|
||||
const resourcesDestFolder = path.join(buildFolder, "res");
|
||||
|
||||
/**
|
||||
* Determines if an atlas must use lossless compression
|
||||
* @param {string} fname
|
||||
*/
|
||||
function fileMustBeLossless(fname) {
|
||||
return fname.indexOf("lossless") >= 0;
|
||||
}
|
||||
|
||||
/////////////// ATLAS /////////////////////
|
||||
|
||||
// Copies the atlas to the final destination
|
||||
gulp.task("imgres.atlas", () => {
|
||||
return gulp
|
||||
.src(["../res_built/atlas/*.png"])
|
||||
.pipe($.cached("imgres.atlas"))
|
||||
.pipe(gulp.dest(resourcesDestFolder));
|
||||
});
|
||||
|
||||
// Copies the atlas to the final destination after optimizing it (lossy compression)
|
||||
gulp.task("imgres.atlasOptimized", () => {
|
||||
return gulp
|
||||
.src(["../res_built/atlas/*.png"])
|
||||
.pipe($.cached("imgres.atlasOptimized"))
|
||||
.pipe(
|
||||
$.if(
|
||||
fname => fileMustBeLossless(fname.history[0]),
|
||||
$.imagemin(minifyImagesOptsLossless()),
|
||||
$.imagemin(minifyImagesOpts())
|
||||
)
|
||||
)
|
||||
.pipe(gulp.dest(resourcesDestFolder));
|
||||
});
|
||||
|
||||
//////////////////// RESOURCES //////////////////////
|
||||
|
||||
// Copies all resources which are no ui resources
|
||||
gulp.task("imgres.copyNonImageResources", () => {
|
||||
return gulp
|
||||
.src(nonImageResourcesGlobs)
|
||||
.pipe($.cached("imgres.copyNonImageResources"))
|
||||
.pipe(gulp.dest(resourcesDestFolder));
|
||||
});
|
||||
|
||||
// Copies all ui resources
|
||||
gulp.task("imgres.copyImageResources", () => {
|
||||
return gulp
|
||||
.src(imageResourcesGlobs)
|
||||
.pipe($.cached("copyImageResources"))
|
||||
.pipe(gulp.dest(path.join(resourcesDestFolder)));
|
||||
});
|
||||
|
||||
// Copies all ui resources and optimizes them
|
||||
gulp.task("imgres.copyImageResourcesOptimized", () => {
|
||||
return gulp
|
||||
.src(imageResourcesGlobs)
|
||||
.pipe($.cached("imgres.copyImageResourcesOptimized"))
|
||||
.pipe(
|
||||
$.if(
|
||||
fname => fileMustBeLossless(fname.history[0]),
|
||||
$.imagemin(minifyImagesOptsLossless()),
|
||||
$.imagemin(minifyImagesOpts())
|
||||
)
|
||||
)
|
||||
.pipe(gulp.dest(path.join(resourcesDestFolder)));
|
||||
});
|
||||
|
||||
// Copies all resources and optimizes them
|
||||
gulp.task(
|
||||
"imgres.allOptimized",
|
||||
gulp.parallel(
|
||||
"imgres.atlasOptimized",
|
||||
"imgres.copyNonImageResources",
|
||||
"imgres.copyImageResourcesOptimized"
|
||||
)
|
||||
);
|
||||
|
||||
// Cleans up unused images which are instead inline into the css
|
||||
gulp.task("imgres.cleanupUnusedCssInlineImages", () => {
|
||||
return gulp
|
||||
.src(
|
||||
[
|
||||
path.join(buildFolder, "res", "ui", "**", "*.png"),
|
||||
path.join(buildFolder, "res", "ui", "**", "*.jpg"),
|
||||
path.join(buildFolder, "res", "ui", "**", "*.svg"),
|
||||
path.join(buildFolder, "res", "ui", "**", "*.gif"),
|
||||
],
|
||||
{ read: false }
|
||||
)
|
||||
.pipe($.if(fname => fname.history[0].indexOf("noinline") < 0, $.clean({ force: true })));
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
nonImageResourcesGlobs,
|
||||
imageResourcesGlobs,
|
||||
gulptasksImageResources,
|
||||
};
|
||||
const { existsSync } = require("fs");
|
||||
// @ts-ignore
|
||||
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
|
||||
const nonImageResourcesGlobs = ["../res/**/*.woff2", "../res/*.ico", "../res/**/*.webm"];
|
||||
|
||||
// Globs for ui resources
|
||||
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) {
|
||||
// Lossless options
|
||||
const minifyImagesOptsLossless = () => [
|
||||
$.imageminJpegtran({
|
||||
progressive: true,
|
||||
}),
|
||||
$.imagemin.svgo({}),
|
||||
$.imagemin.optipng({
|
||||
optimizationLevel: 3,
|
||||
}),
|
||||
$.imageminGifsicle({
|
||||
optimizationLevel: 3,
|
||||
colors: 128,
|
||||
}),
|
||||
];
|
||||
|
||||
// Lossy options
|
||||
const minifyImagesOpts = () => [
|
||||
$.imagemin.mozjpeg({
|
||||
quality: 80,
|
||||
maxMemory: 1024 * 1024 * 8,
|
||||
}),
|
||||
$.imagemin.svgo({}),
|
||||
$.imageminPngquant({
|
||||
speed: 1,
|
||||
strip: true,
|
||||
quality: [0.65, 0.9],
|
||||
dithering: false,
|
||||
verbose: false,
|
||||
}),
|
||||
$.imagemin.optipng({
|
||||
optimizationLevel: 3,
|
||||
}),
|
||||
$.imageminGifsicle({
|
||||
optimizationLevel: 3,
|
||||
colors: 128,
|
||||
}),
|
||||
];
|
||||
|
||||
// Where the resources folder are
|
||||
const resourcesDestFolder = path.join(buildFolder, "res");
|
||||
|
||||
/**
|
||||
* Determines if an atlas must use lossless compression
|
||||
* @param {string} fname
|
||||
*/
|
||||
function fileMustBeLossless(fname) {
|
||||
return fname.indexOf("lossless") >= 0;
|
||||
}
|
||||
|
||||
/////////////// 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
|
||||
gulp.task("imgres.atlas", () => {
|
||||
return gulp.src(["../res_built/atlas/*.png"]).pipe(gulp.dest(resourcesDestFolder));
|
||||
});
|
||||
|
||||
// Copies the atlas to the final destination after optimizing it (lossy compression)
|
||||
gulp.task("imgres.atlasOptimized", () => {
|
||||
return gulp
|
||||
.src(["../res_built/atlas/*.png"])
|
||||
.pipe(
|
||||
$.if(
|
||||
fname => fileMustBeLossless(fname.history[0]),
|
||||
$.imagemin(minifyImagesOptsLossless()),
|
||||
$.imagemin(minifyImagesOpts())
|
||||
)
|
||||
)
|
||||
.pipe(gulp.dest(resourcesDestFolder));
|
||||
});
|
||||
|
||||
//////////////////// RESOURCES //////////////////////
|
||||
|
||||
// Copies all resources which are no ui resources
|
||||
gulp.task("imgres.copyNonImageResources", () => {
|
||||
return gulp.src(nonImageResourcesGlobs).pipe(gulp.dest(resourcesDestFolder));
|
||||
});
|
||||
|
||||
// Copies all ui resources
|
||||
gulp.task("imgres.copyImageResources", () => {
|
||||
return gulp
|
||||
.src(imageResourcesGlobs)
|
||||
|
||||
.pipe($.cached("imgres.copyImageResources"))
|
||||
.pipe(gulp.dest(path.join(resourcesDestFolder)));
|
||||
});
|
||||
|
||||
// Copies all ui resources and optimizes them
|
||||
gulp.task("imgres.copyImageResourcesOptimized", () => {
|
||||
return gulp
|
||||
.src(imageResourcesGlobs)
|
||||
.pipe(
|
||||
$.if(
|
||||
fname => fileMustBeLossless(fname.history[0]),
|
||||
$.imagemin(minifyImagesOptsLossless()),
|
||||
$.imagemin(minifyImagesOpts())
|
||||
)
|
||||
)
|
||||
.pipe(gulp.dest(path.join(resourcesDestFolder)));
|
||||
});
|
||||
|
||||
// Copies all resources and optimizes them
|
||||
gulp.task(
|
||||
"imgres.allOptimized",
|
||||
gulp.parallel(
|
||||
"imgres.buildAtlas",
|
||||
"imgres.atlasToJson",
|
||||
"imgres.atlasOptimized",
|
||||
"imgres.copyNonImageResources",
|
||||
"imgres.copyImageResourcesOptimized"
|
||||
)
|
||||
);
|
||||
|
||||
// Cleans up unused images which are instead inline into the css
|
||||
gulp.task("imgres.cleanupUnusedCssInlineImages", () => {
|
||||
return gulp
|
||||
.src(
|
||||
[
|
||||
path.join(buildFolder, "res", "ui", "**", "*.png"),
|
||||
path.join(buildFolder, "res", "ui", "**", "*.jpg"),
|
||||
path.join(buildFolder, "res", "ui", "**", "*.svg"),
|
||||
path.join(buildFolder, "res", "ui", "**", "*.gif"),
|
||||
],
|
||||
{ read: false }
|
||||
)
|
||||
.pipe($.if(fname => fname.history[0].indexOf("noinline") < 0, $.clean({ force: true })));
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
rawImageResourcesGlobs,
|
||||
nonImageResourcesGlobs,
|
||||
imageResourcesGlobs,
|
||||
gulptasksImageResources,
|
||||
};
|
||||
|
||||
@ -1,110 +1,114 @@
|
||||
{
|
||||
"name": "builder",
|
||||
"version": "1.0.0",
|
||||
"description": "builder",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"gulp": "gulp"
|
||||
},
|
||||
"author": "tobspr",
|
||||
"license": "private",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.9.0",
|
||||
"@babel/plugin-transform-block-scoping": "^7.4.4",
|
||||
"@babel/plugin-transform-classes": "^7.5.5",
|
||||
"@babel/preset-env": "^7.5.4",
|
||||
"@types/cordova": "^0.0.34",
|
||||
"@types/filesystem": "^0.0.29",
|
||||
"@types/node": "^12.7.5",
|
||||
"ajv": "^6.10.2",
|
||||
"audiosprite": "^0.7.2",
|
||||
"babel-loader": "^8.1.0",
|
||||
"browser-sync": "^2.26.10",
|
||||
"circular-dependency-plugin": "^5.0.2",
|
||||
"circular-json": "^0.5.9",
|
||||
"clipboard-copy": "^3.1.0",
|
||||
"colors": "^1.3.3",
|
||||
"core-js": "3",
|
||||
"crypto": "^1.0.1",
|
||||
"cssnano-preset-advanced": "^4.0.7",
|
||||
"delete-empty": "^3.0.0",
|
||||
"email-validator": "^2.0.4",
|
||||
"eslint": "^5.9.0",
|
||||
"fastdom": "^1.0.9",
|
||||
"flatted": "^2.0.1",
|
||||
"fs-extra": "^8.1.0",
|
||||
"gulp-audiosprite": "^1.1.0",
|
||||
"howler": "^2.1.2",
|
||||
"html-loader": "^0.5.5",
|
||||
"ignore-loader": "^0.1.2",
|
||||
"lz-string": "^1.4.4",
|
||||
"markdown-loader": "^5.1.0",
|
||||
"node-sri": "^1.1.1",
|
||||
"phonegap-plugin-mobile-accessibility": "^1.0.5",
|
||||
"promise-polyfill": "^8.1.0",
|
||||
"query-string": "^6.8.1",
|
||||
"rusha": "^0.8.13",
|
||||
"serialize-error": "^3.0.0",
|
||||
"strictdom": "^1.0.1",
|
||||
"string-replace-webpack-plugin": "^0.1.3",
|
||||
"terser-webpack-plugin": "^1.1.0",
|
||||
"through2": "^3.0.1",
|
||||
"uglify-template-string-loader": "^1.1.0",
|
||||
"unused-files-webpack-plugin": "^3.4.0",
|
||||
"webpack": "^4.43.0",
|
||||
"webpack-cli": "^3.1.0",
|
||||
"webpack-deep-scope-plugin": "^1.6.0",
|
||||
"webpack-plugin-replace": "^1.1.1",
|
||||
"webpack-strip-block": "^0.2.0",
|
||||
"whatwg-fetch": "^3.0.0",
|
||||
"worker-loader": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^9.4.3",
|
||||
"babel-plugin-closure-elimination": "^1.3.0",
|
||||
"babel-plugin-console-source": "^2.0.2",
|
||||
"babel-plugin-danger-remove-unused-import": "^1.1.2",
|
||||
"css-mqpacker": "^7.0.0",
|
||||
"cssnano": "^4.1.10",
|
||||
"electron-packager": "^14.0.6",
|
||||
"faster.js": "^1.1.0",
|
||||
"glob": "^7.1.3",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-cache": "^1.1.3",
|
||||
"gulp-cached": "^1.1.1",
|
||||
"gulp-clean": "^0.4.0",
|
||||
"gulp-dom": "^1.0.0",
|
||||
"gulp-flatten": "^0.4.0",
|
||||
"gulp-fluent-ffmpeg": "^2.0.0",
|
||||
"gulp-html-beautify": "^1.0.1",
|
||||
"gulp-htmlmin": "^5.0.1",
|
||||
"gulp-if": "^3.0.0",
|
||||
"gulp-imagemin": "^7.1.0",
|
||||
"gulp-load-plugins": "^2.0.3",
|
||||
"gulp-phonegap-build": "^0.1.5",
|
||||
"gulp-plumber": "^1.2.1",
|
||||
"gulp-pngquant": "^1.0.13",
|
||||
"gulp-postcss": "^8.0.0",
|
||||
"gulp-rename": "^2.0.0",
|
||||
"gulp-sass": "^4.1.0",
|
||||
"gulp-sass-lint": "^1.4.0",
|
||||
"gulp-sftp": "git+https://git@github.com/webksde/gulp-sftp",
|
||||
"gulp-terser": "^1.2.0",
|
||||
"gulp-webserver": "^0.9.1",
|
||||
"gulp-yaml": "^2.0.4",
|
||||
"imagemin-gifsicle": "^7.0.0",
|
||||
"imagemin-jpegtran": "^7.0.0",
|
||||
"imagemin-pngquant": "^9.0.0",
|
||||
"jimp": "^0.6.1",
|
||||
"js-yaml": "^3.13.1",
|
||||
"postcss-assets": "^5.0.0",
|
||||
"postcss-preset-env": "^6.5.0",
|
||||
"postcss-round-subpixels": "^1.2.0",
|
||||
"postcss-unprefix": "^2.1.3",
|
||||
"sass-unused": "^0.3.0",
|
||||
"strip-json-comments": "^3.0.1",
|
||||
"trim": "^0.0.1",
|
||||
"webpack-stream": "^5.2.1",
|
||||
"yaml-loader": "^0.6.0"
|
||||
}
|
||||
}
|
||||
{
|
||||
"name": "builder",
|
||||
"version": "1.0.0",
|
||||
"description": "builder",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"gulp": "gulp"
|
||||
},
|
||||
"author": "tobspr",
|
||||
"license": "private",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.9.0",
|
||||
"@babel/plugin-transform-block-scoping": "^7.4.4",
|
||||
"@babel/plugin-transform-classes": "^7.5.5",
|
||||
"@babel/preset-env": "^7.5.4",
|
||||
"@types/cordova": "^0.0.34",
|
||||
"@types/filesystem": "^0.0.29",
|
||||
"@types/node": "^12.7.5",
|
||||
"ajv": "^6.10.2",
|
||||
"audiosprite": "^0.7.2",
|
||||
"babel-core": "^6.26.3",
|
||||
"babel-loader": "^8.1.0",
|
||||
"browser-sync": "^2.26.10",
|
||||
"circular-dependency-plugin": "^5.0.2",
|
||||
"circular-json": "^0.5.9",
|
||||
"clipboard-copy": "^3.1.0",
|
||||
"colors": "^1.3.3",
|
||||
"core-js": "3",
|
||||
"crypto": "^1.0.1",
|
||||
"cssnano-preset-advanced": "^4.0.7",
|
||||
"delete-empty": "^3.0.0",
|
||||
"email-validator": "^2.0.4",
|
||||
"eslint": "^5.9.0",
|
||||
"fastdom": "^1.0.9",
|
||||
"flatted": "^2.0.1",
|
||||
"fs-extra": "^8.1.0",
|
||||
"gulp-audiosprite": "^1.1.0",
|
||||
"howler": "^2.1.2",
|
||||
"html-loader": "^0.5.5",
|
||||
"ignore-loader": "^0.1.2",
|
||||
"lz-string": "^1.4.4",
|
||||
"markdown-loader": "^5.1.0",
|
||||
"node-sri": "^1.1.1",
|
||||
"phonegap-plugin-mobile-accessibility": "^1.0.5",
|
||||
"promise-polyfill": "^8.1.0",
|
||||
"query-string": "^6.8.1",
|
||||
"rusha": "^0.8.13",
|
||||
"serialize-error": "^3.0.0",
|
||||
"stream-browserify": "^3.0.0",
|
||||
"strictdom": "^1.0.1",
|
||||
"string-replace-webpack-plugin": "^0.1.3",
|
||||
"strip-indent": "^3.0.0",
|
||||
"terser-webpack-plugin": "^1.1.0",
|
||||
"through2": "^3.0.1",
|
||||
"uglify-template-string-loader": "^1.1.0",
|
||||
"unused-files-webpack-plugin": "^3.4.0",
|
||||
"webpack": "^4.43.0",
|
||||
"webpack-cli": "^3.1.0",
|
||||
"webpack-deep-scope-plugin": "^1.6.0",
|
||||
"webpack-plugin-replace": "^1.1.1",
|
||||
"webpack-strip-block": "^0.2.0",
|
||||
"whatwg-fetch": "^3.0.0",
|
||||
"worker-loader": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^9.4.3",
|
||||
"babel-plugin-closure-elimination": "^1.3.0",
|
||||
"babel-plugin-console-source": "^2.0.2",
|
||||
"babel-plugin-danger-remove-unused-import": "^1.1.2",
|
||||
"css-mqpacker": "^7.0.0",
|
||||
"cssnano": "^4.1.10",
|
||||
"electron-packager": "^14.0.6",
|
||||
"faster.js": "^1.1.0",
|
||||
"glob": "^7.1.3",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-cache": "^1.1.3",
|
||||
"gulp-cached": "^1.1.1",
|
||||
"gulp-clean": "^0.4.0",
|
||||
"gulp-dom": "^1.0.0",
|
||||
"gulp-flatten": "^0.4.0",
|
||||
"gulp-fluent-ffmpeg": "^2.0.0",
|
||||
"gulp-html-beautify": "^1.0.1",
|
||||
"gulp-htmlmin": "^5.0.1",
|
||||
"gulp-if": "^3.0.0",
|
||||
"gulp-imagemin": "^7.1.0",
|
||||
"gulp-load-plugins": "^2.0.3",
|
||||
"gulp-phonegap-build": "^0.1.5",
|
||||
"gulp-plumber": "^1.2.1",
|
||||
"gulp-pngquant": "^1.0.13",
|
||||
"gulp-postcss": "^8.0.0",
|
||||
"gulp-rename": "^2.0.0",
|
||||
"gulp-sass": "^4.1.0",
|
||||
"gulp-sass-lint": "^1.4.0",
|
||||
"gulp-sftp": "git+https://git@github.com/webksde/gulp-sftp",
|
||||
"gulp-terser": "^1.2.0",
|
||||
"gulp-webserver": "^0.9.1",
|
||||
"gulp-yaml": "^2.0.4",
|
||||
"imagemin-gifsicle": "^7.0.0",
|
||||
"imagemin-jpegtran": "^7.0.0",
|
||||
"imagemin-pngquant": "^9.0.0",
|
||||
"jimp": "^0.6.1",
|
||||
"js-yaml": "^3.13.1",
|
||||
"postcss-assets": "^5.0.0",
|
||||
"postcss-critical-split": "^2.5.3",
|
||||
"postcss-preset-env": "^6.5.0",
|
||||
"postcss-round-subpixels": "^1.2.0",
|
||||
"postcss-unprefix": "^2.1.3",
|
||||
"sass-unused": "^0.3.0",
|
||||
"strip-json-comments": "^3.0.1",
|
||||
"trim": "^0.0.1",
|
||||
"webpack-stream": "^5.2.1",
|
||||
"yaml-loader": "^0.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
66
gulp/release-uploader.js
Normal file
@ -0,0 +1,66 @@
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const execSync = require("child_process").execSync;
|
||||
const { Octokit } = require("@octokit/rest");
|
||||
const buildutils = require("./buildutils");
|
||||
|
||||
function gulptasksReleaseUploader($, gulp, buildFolder) {
|
||||
const standaloneDir = path.join(__dirname, "..", "tmp_standalone_files");
|
||||
const darwinApp = path.join(standaloneDir, "shapez.io-standalone-darwin-x64", "shapez.io-standalone.app");
|
||||
const dmgName = "shapez.io-standalone.dmg";
|
||||
const dmgPath = path.join(standaloneDir, "shapez.io-standalone-darwin-x64", dmgName);
|
||||
|
||||
gulp.task("standalone.uploadRelease.darwin64.cleanup", () => {
|
||||
return gulp.src(dmgPath, { read: false, allowEmpty: true }).pipe($.clean({ force: true }));
|
||||
});
|
||||
|
||||
gulp.task("standalone.uploadRelease.darwin64.compress", cb => {
|
||||
console.log("Packaging disk image", dmgPath);
|
||||
execSync(`hdiutil create -format UDBZ -srcfolder ${darwinApp} ${dmgPath}`);
|
||||
cb();
|
||||
});
|
||||
|
||||
gulp.task("standalone.uploadRelease.darwin64.upload", async cb => {
|
||||
const currentTag = buildutils.getTag();
|
||||
|
||||
const octokit = new Octokit({
|
||||
auth: process.env.SHAPEZ_CLI_GITHUB_TOKEN
|
||||
});
|
||||
|
||||
const createdRelease = await octokit.request("POST /repos/{owner}/{repo}/releases", {
|
||||
owner: process.env.SHAPEZ_CLI_GITHUB_USER,
|
||||
repo: "shapez.io",
|
||||
tag_name: currentTag,
|
||||
name: currentTag,
|
||||
draft: true
|
||||
});
|
||||
|
||||
const { data: { id, upload_url } } = createdRelease;
|
||||
console.log(`Created release ${id} for tag ${currentTag}`);
|
||||
|
||||
const dmgContents = fs.readFileSync(dmgPath);
|
||||
const dmgSize = fs.statSync(dmgPath).size;
|
||||
console.log("Uploading", dmgContents.length / 1024 / 1024, "MB to", upload_url);
|
||||
|
||||
await octokit.request({
|
||||
method: "POST",
|
||||
url: upload_url,
|
||||
headers: {
|
||||
"content-type": "application/x-apple-diskimage"
|
||||
},
|
||||
name: dmgName,
|
||||
data: dmgContents
|
||||
});
|
||||
|
||||
cb();
|
||||
});
|
||||
|
||||
gulp.task("standalone.uploadRelease.darwin64",
|
||||
gulp.series(
|
||||
"standalone.uploadRelease.darwin64.cleanup",
|
||||
"standalone.uploadRelease.darwin64.compress",
|
||||
"standalone.uploadRelease.darwin64.upload"
|
||||
));
|
||||
}
|
||||
|
||||
module.exports = { gulptasksReleaseUploader };
|
||||
@ -16,6 +16,12 @@ function gulptasksSounds($, gulp, buildFolder) {
|
||||
cacheDirName: "shapezio-precompiled-sounds",
|
||||
});
|
||||
|
||||
function getFileCacheValue(file) {
|
||||
const { _isVinyl, base, cwd, contents, history, stat, path } = file;
|
||||
const encodedContents = Buffer.from(contents).toString("base64");
|
||||
return { _isVinyl, base, cwd, contents: encodedContents, history, stat, path };
|
||||
}
|
||||
|
||||
// Encodes the game music
|
||||
gulp.task("sounds.music", () => {
|
||||
return gulp
|
||||
@ -34,6 +40,7 @@ function gulptasksSounds($, gulp, buildFolder) {
|
||||
{
|
||||
name: "music",
|
||||
fileCache,
|
||||
value: getFileCacheValue,
|
||||
}
|
||||
)
|
||||
)
|
||||
@ -58,6 +65,7 @@ function gulptasksSounds($, gulp, buildFolder) {
|
||||
{
|
||||
name: "music-high-quality",
|
||||
fileCache,
|
||||
value: getFileCacheValue,
|
||||
}
|
||||
)
|
||||
)
|
||||
@ -110,7 +118,6 @@ function gulptasksSounds($, gulp, buildFolder) {
|
||||
return gulp
|
||||
.src(path.join(builtSoundsDir, "**", "*.mp3"))
|
||||
.pipe($.plumber())
|
||||
.pipe($.cached("sounds.copy"))
|
||||
.pipe(gulp.dest(path.join(buildFolder, "res", "sounds")));
|
||||
});
|
||||
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
require("colors");
|
||||
const packager = require("electron-packager");
|
||||
const path = require("path");
|
||||
const { getVersion } = require("./buildutils");
|
||||
const fs = require("fs");
|
||||
const fse = require("fs-extra");
|
||||
const buildutils = require("./buildutils");
|
||||
const execSync = require("child_process").execSync;
|
||||
|
||||
function gulptasksStandalone($, gulp) {
|
||||
@ -46,6 +48,20 @@ function gulptasksStandalone($, gulp) {
|
||||
cb();
|
||||
});
|
||||
|
||||
gulp.task("standalone.prepareVDF", cb => {
|
||||
const hash = buildutils.getRevision();
|
||||
|
||||
const steampipeDir = path.join(__dirname, "steampipe", "scripts");
|
||||
const templateContents = fs
|
||||
.readFileSync(path.join(steampipeDir, "app.vdf.template"), { encoding: "utf-8" })
|
||||
.toString();
|
||||
|
||||
const convertedContents = templateContents.replace("$DESC$", "Commit " + hash);
|
||||
fs.writeFileSync(path.join(steampipeDir, "app.vdf"), convertedContents);
|
||||
|
||||
cb();
|
||||
});
|
||||
|
||||
gulp.task("standalone.prepare.minifyCode", () => {
|
||||
return gulp.src(path.join(electronBaseDir, "*.js")).pipe(gulp.dest(tempDestBuildDir));
|
||||
});
|
||||
@ -80,8 +96,9 @@ function gulptasksStandalone($, gulp) {
|
||||
* @param {'win32'|'linux'|'darwin'} platform
|
||||
* @param {'x64'|'ia32'} arch
|
||||
* @param {function():void} cb
|
||||
* @param {boolean=} isRelease
|
||||
*/
|
||||
function packageStandalone(platform, arch, cb) {
|
||||
function packageStandalone(platform, arch, cb, isRelease = true) {
|
||||
const tomlFile = fs.readFileSync(path.join(__dirname, ".itch.toml"));
|
||||
|
||||
packager({
|
||||
@ -99,6 +116,21 @@ function gulptasksStandalone($, gulp) {
|
||||
overwrite: true,
|
||||
appBundleId: "io.shapez.standalone",
|
||||
appCategoryType: "public.app-category.games",
|
||||
...(isRelease &&
|
||||
platform === "darwin" && {
|
||||
osxSign: {
|
||||
"identity": process.env.SHAPEZ_CLI_APPLE_CERT_NAME,
|
||||
"hardened-runtime": true,
|
||||
"hardenedRuntime": true,
|
||||
"entitlements": "entitlements.plist",
|
||||
"entitlements-inherit": "entitlements.plist",
|
||||
"signature-flags": "library",
|
||||
},
|
||||
osxNotarize: {
|
||||
appleId: process.env.SHAPEZ_CLI_APPLE_ID,
|
||||
appleIdPassword: "@keychain:SHAPEZ_CLI_APPLE_ID",
|
||||
},
|
||||
}),
|
||||
}).then(
|
||||
appPaths => {
|
||||
console.log("Packages created:", appPaths);
|
||||
@ -123,7 +155,15 @@ function gulptasksStandalone($, gulp) {
|
||||
fs.chmodSync(path.join(appPath, "play.sh"), 0o775);
|
||||
}
|
||||
|
||||
if (platform === "darwin") {
|
||||
if (process.platform === "win32" && platform === "darwin") {
|
||||
console.warn(
|
||||
"Cross-building for macOS on Windows: dereferencing symlinks.\n".red +
|
||||
"This will nearly double app size and make code signature invalid. Sorry!\n"
|
||||
.red.bold +
|
||||
"For more information, see " +
|
||||
"https://github.com/electron/electron-packager/issues/71".underline
|
||||
);
|
||||
|
||||
// Clear up framework folders
|
||||
fs.writeFileSync(
|
||||
path.join(appPath, "play.sh"),
|
||||
@ -175,6 +215,9 @@ function gulptasksStandalone($, gulp) {
|
||||
gulp.task("standalone.package.prod.linux64", cb => packageStandalone("linux", "x64", cb));
|
||||
gulp.task("standalone.package.prod.linux32", cb => packageStandalone("linux", "ia32", cb));
|
||||
gulp.task("standalone.package.prod.darwin64", cb => packageStandalone("darwin", "x64", cb));
|
||||
gulp.task("standalone.package.prod.darwin64.unsigned", cb =>
|
||||
packageStandalone("darwin", "x64", cb, false)
|
||||
);
|
||||
|
||||
gulp.task(
|
||||
"standalone.package.prod",
|
||||
|
||||
2
gulp/steampipe/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
steamtemp
|
||||
app.vdf
|
||||
15
gulp/steampipe/scripts/app.vdf.template
Normal file
@ -0,0 +1,15 @@
|
||||
"appbuild"
|
||||
{
|
||||
"appid" "1318690"
|
||||
"desc" "$DESC$"
|
||||
"buildoutput" "C:\work\shapez\shapez.io\gulp\steampipe\steamtemp"
|
||||
"contentroot" ""
|
||||
"setlive" ""
|
||||
"preview" "0"
|
||||
"local" ""
|
||||
"depots"
|
||||
{
|
||||
"1318691" "C:\work\shapez\shapez.io\gulp\steampipe\scripts\windows.vdf"
|
||||
"1318692" "C:\work\shapez\shapez.io\gulp\steampipe\scripts\linux.vdf"
|
||||
}
|
||||
}
|
||||
12
gulp/steampipe/scripts/linux.vdf
Normal file
@ -0,0 +1,12 @@
|
||||
"DepotBuildConfig"
|
||||
{
|
||||
"DepotID" "1318692"
|
||||
"contentroot" "C:\work\shapez\shapez.io\tmp_standalone_files\shapez.io-standalone-linux-x64"
|
||||
"FileMapping"
|
||||
{
|
||||
"LocalPath" "*"
|
||||
"DepotPath" "."
|
||||
"recursive" "1"
|
||||
}
|
||||
"FileExclusion" "*.pdb"
|
||||
}
|
||||
12
gulp/steampipe/scripts/windows.vdf
Normal file
@ -0,0 +1,12 @@
|
||||
"DepotBuildConfig"
|
||||
{
|
||||
"DepotID" "1318691"
|
||||
"contentroot" "C:\work\shapez\shapez.io\tmp_standalone_files\shapez.io-standalone-win32-x64"
|
||||
"FileMapping"
|
||||
{
|
||||
"LocalPath" "*"
|
||||
"DepotPath" "."
|
||||
"recursive" "1"
|
||||
}
|
||||
"FileExclusion" "*.pdb"
|
||||
}
|
||||
4
gulp/steampipe/upload.bat
Normal file
@ -0,0 +1,4 @@
|
||||
@echo off
|
||||
cmd /c gulp standalone.prepareVDF
|
||||
steamcmd +login %STEAM_UPLOAD_SHAPEZ_ID% %STEAM_UPLOAD_SHAPEZ_USER% +run_app_build %cd%/scripts/app.vdf +quit
|
||||
start https://partner.steamgames.com/apps/builds/1318690
|
||||
@ -1,22 +1,89 @@
|
||||
const path = require("path");
|
||||
|
||||
const yaml = require("gulp-yaml");
|
||||
|
||||
const translationsSourceDir = path.join(__dirname, "..", "translations");
|
||||
const translationsJsonDir = path.join(__dirname, "..", "src", "js", "built-temp");
|
||||
|
||||
function gulptasksTranslations($, gulp) {
|
||||
gulp.task("translations.convertToJson", () => {
|
||||
return gulp
|
||||
.src(path.join(translationsSourceDir, "*.yaml"))
|
||||
.pipe($.plumber())
|
||||
.pipe(yaml({ space: 2, safe: true }))
|
||||
.pipe(gulp.dest(translationsJsonDir));
|
||||
});
|
||||
|
||||
gulp.task("translations.fullBuild", gulp.series("translations.convertToJson"));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
gulptasksTranslations,
|
||||
};
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const gulpYaml = require("gulp-yaml");
|
||||
const YAML = require("yaml");
|
||||
const stripIndent = require("strip-indent");
|
||||
const trim = require("trim");
|
||||
|
||||
const translationsSourceDir = path.join(__dirname, "..", "translations");
|
||||
const translationsJsonDir = path.join(__dirname, "..", "src", "js", "built-temp");
|
||||
|
||||
function gulptasksTranslations($, gulp) {
|
||||
gulp.task("translations.convertToJson", () => {
|
||||
return gulp
|
||||
.src(path.join(translationsSourceDir, "*.yaml"))
|
||||
.pipe($.plumber())
|
||||
.pipe(gulpYaml({ space: 2, safe: true }))
|
||||
.pipe(gulp.dest(translationsJsonDir));
|
||||
});
|
||||
|
||||
gulp.task("translations.fullBuild", gulp.series("translations.convertToJson"));
|
||||
|
||||
gulp.task("translations.prepareSteamPage", cb => {
|
||||
const files = fs.readdirSync(translationsSourceDir);
|
||||
|
||||
files
|
||||
.filter(name => name.endsWith(".yaml"))
|
||||
.forEach(fname => {
|
||||
const languageName = fname.replace(".yaml", "");
|
||||
const abspath = path.join(translationsSourceDir, fname);
|
||||
|
||||
const destpath = path.join(translationsSourceDir, "tmp", languageName + "-store.txt");
|
||||
|
||||
const contents = fs.readFileSync(abspath, { encoding: "utf-8" });
|
||||
const data = YAML.parse(contents);
|
||||
|
||||
const storePage = data.steamPage;
|
||||
|
||||
const content = `
|
||||
[img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img]
|
||||
|
||||
${storePage.intro.replace(/\n/gi, "\n\n")}
|
||||
|
||||
[h2]${storePage.title_advantages}[/h2]
|
||||
|
||||
[list]
|
||||
${storePage.advantages
|
||||
.map(x => "[*] " + x.replace(/<b>/, "[b]").replace(/<\/b>/, "[/b]"))
|
||||
.join("\n")}
|
||||
[/list]
|
||||
|
||||
[h2]${storePage.title_future}[/h2]
|
||||
|
||||
[list]
|
||||
${storePage.planned
|
||||
.map(x => "[*] " + x.replace(/<b>/, "[b]").replace(/<\/b>/, "[/b]"))
|
||||
.join("\n")}
|
||||
[/list]
|
||||
|
||||
[h2]${storePage.title_open_source}[/h2]
|
||||
|
||||
${storePage.text_open_source.replace(/\n/gi, "\n\n")}
|
||||
|
||||
[h2]${storePage.title_links}[/h2]
|
||||
|
||||
[list]
|
||||
[*] [url=https://discord.com/invite/HN7EVzV]${storePage.links.discord}[/url]
|
||||
[*] [url=https://trello.com/b/ISQncpJP/shapezio]${storePage.links.roadmap}[/url]
|
||||
[*] [url=https://www.reddit.com/r/shapezio]${storePage.links.subreddit}[/url]
|
||||
[*] [url=https://github.com/tobspr/shapez.io]${storePage.links.source_code}[/url]
|
||||
[*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]${
|
||||
storePage.links.translate
|
||||
}[/url]
|
||||
[/list]
|
||||
|
||||
|
||||
`;
|
||||
|
||||
fs.writeFileSync(destpath, trim(content.replace(/(\n[ \t\r]*)/gi, "\n")), {
|
||||
encoding: "utf-8",
|
||||
});
|
||||
});
|
||||
|
||||
cb();
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
gulptasksTranslations,
|
||||
};
|
||||
|
||||
27341
gulp/yarn.lock
@ -28,6 +28,7 @@
|
||||
"@types/cordova": "^0.0.34",
|
||||
"@types/filesystem": "^0.0.29",
|
||||
"ajv": "^6.10.2",
|
||||
"babel-core": "^6.26.3",
|
||||
"babel-loader": "^8.0.4",
|
||||
"circular-dependency-plugin": "^5.0.2",
|
||||
"circular-json": "^0.5.9",
|
||||
@ -49,6 +50,7 @@
|
||||
"markdown-loader": "^4.0.0",
|
||||
"match-all": "^1.2.5",
|
||||
"phonegap-plugin-mobile-accessibility": "^1.0.5",
|
||||
"postcss": ">=5.0.0",
|
||||
"promise-polyfill": "^8.1.0",
|
||||
"query-string": "^6.8.1",
|
||||
"rusha": "^0.8.13",
|
||||
@ -71,6 +73,7 @@
|
||||
"yawn-yaml": "^1.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@octokit/rest": "^18.0.6",
|
||||
"@typescript-eslint/eslint-plugin": "3.0.1",
|
||||
"@typescript-eslint/parser": "3.0.1",
|
||||
"autoprefixer": "^9.4.3",
|
||||
|
||||
BIN
res/ui/building_icons/analyzer.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
res/ui/building_icons/balancer.png
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.5 KiB |
BIN
res/ui/building_icons/comparator.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.2 KiB |
BIN
res/ui/building_icons/item_producer.png
Normal file
|
After Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.4 KiB |
BIN
res/ui/building_icons/storage.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
res/ui/building_icons/transistor.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 3.8 KiB |
BIN
res/ui/building_tutorials/analyzer.png
Normal file
|
After Width: | Height: | Size: 233 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
BIN
res/ui/building_tutorials/balancer-splitter.png
Normal file
|
After Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
BIN
res/ui/building_tutorials/comparator.png
Normal file
|
After Width: | Height: | Size: 114 KiB |
BIN
res/ui/building_tutorials/constant_signal.png
Normal file
|
After Width: | Height: | Size: 157 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 36 KiB |
BIN
res/ui/building_tutorials/display.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
res/ui/building_tutorials/item_producer.png
Normal file
|
After Width: | Height: | Size: 271 KiB |
BIN
res/ui/building_tutorials/lever.png
Normal file
|
After Width: | Height: | Size: 68 KiB |
BIN
res/ui/building_tutorials/logic_gate-and.png
Normal file
|
After Width: | Height: | Size: 281 KiB |
BIN
res/ui/building_tutorials/logic_gate-not.png
Normal file
|
After Width: | Height: | Size: 287 KiB |
BIN
res/ui/building_tutorials/logic_gate-or.png
Normal file
|
After Width: | Height: | Size: 283 KiB |
BIN
res/ui/building_tutorials/logic_gate-xor.png
Normal file
|
After Width: | Height: | Size: 286 KiB |
BIN
res/ui/building_tutorials/painter-mirrored.png
Normal file
|
After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 165 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 44 KiB |
BIN
res/ui/building_tutorials/reader.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 34 KiB |
BIN
res/ui/building_tutorials/rotater-rotate180.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 106 KiB |
BIN
res/ui/building_tutorials/storage.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
res/ui/building_tutorials/transistor.png
Normal file
|
After Width: | Height: | Size: 260 KiB |
|
Before Width: | Height: | Size: 40 KiB |
BIN
res/ui/building_tutorials/virtual_processor-cutter.png
Normal file
|
After Width: | Height: | Size: 116 KiB |
BIN
res/ui/building_tutorials/virtual_processor-painter.png
Normal file
|
After Width: | Height: | Size: 116 KiB |
BIN
res/ui/building_tutorials/virtual_processor-rotater.png
Normal file
|
After Width: | Height: | Size: 132 KiB |
BIN
res/ui/building_tutorials/virtual_processor-stacker.png
Normal file
|
After Width: | Height: | Size: 121 KiB |
BIN
res/ui/building_tutorials/virtual_processor-unstacker.png
Normal file
|
After Width: | Height: | Size: 121 KiB |
BIN
res/ui/building_tutorials/wire-second.png
Normal file
|
After Width: | Height: | Size: 114 KiB |
BIN
res/ui/building_tutorials/wire.png
Normal file
|
After Width: | Height: | Size: 138 KiB |
BIN
res/ui/building_tutorials/wire_tunnel.png
Normal file
|
After Width: | Height: | Size: 91 KiB |
BIN
res/ui/get_on_steam_with_price.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
res/ui/icons/advantage_buildings.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
res/ui/icons/advantage_dark_mode.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |