Fixed issues in runjs
This commit is contained in:
parent
5f0732b39b
commit
4838c74236
2
TODO.md
2
TODO.md
|
@ -103,8 +103,6 @@ Common UI
|
|||
Technical
|
||||
---------
|
||||
|
||||
* Fix "npm test" returning 0 even on failure
|
||||
* Fix "npm start" stopping when there is an error in initial build
|
||||
* Pack sounds
|
||||
* Add toggles for shaders, automatically disable them if too slow, and initially disable them on mobile
|
||||
|
||||
|
|
|
@ -10,5 +10,5 @@ fi
|
|||
|
||||
vdir="./.venv"
|
||||
test -x "${vdir}/bin/nodeenv" || ( virtualenv -p python3 "${vdir}" && "${vdir}/bin/pip" install --upgrade nodeenv )
|
||||
test -e "${vdir}/node/bin/activate" || "${vdir}/bin/nodeenv" --node=9.3.0 --force "${vdir}/node"
|
||||
test -e "${vdir}/node/bin/activate" || "${vdir}/bin/nodeenv" --node=9.11.1 --force "${vdir}/node"
|
||||
source "${vdir}/node/bin/activate"
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
"main": "out/build.js",
|
||||
"scripts": {
|
||||
"build": "run build",
|
||||
"test": "run test",
|
||||
"test": "run ci",
|
||||
"start": "run continuous",
|
||||
"codecov": "remap-istanbul -i out/coverage/coverage.json -o out/coverage/mapped.json -t json && codecov -f out/coverage/mapped.json",
|
||||
"deploy": "run deploy"
|
||||
|
@ -41,4 +41,4 @@
|
|||
"parse": "^1.11.0",
|
||||
"phaser": "2.6.2"
|
||||
}
|
||||
}
|
||||
}
|
237
runfile.js
237
runfile.js
|
@ -14,6 +14,8 @@ String.prototype.rsplit = function (sep, maxsplit) {
|
|||
return maxsplit ? [split.slice(0, -maxsplit).join(sep)].concat(split.slice(-maxsplit)) : split;
|
||||
}
|
||||
|
||||
let forever = () => new Promise(() => null);
|
||||
|
||||
/**
|
||||
* Promise-compatible version of glob
|
||||
*/
|
||||
|
@ -26,141 +28,139 @@ function list(pattern) {
|
|||
/**
|
||||
* Asynchronous execution of shell commands
|
||||
*/
|
||||
function exec(command) {
|
||||
return run(command, { async: true });
|
||||
async function exec(command) {
|
||||
await run(command, { async: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Build app from typescript sources
|
||||
*/
|
||||
function ts(dist = false) {
|
||||
async function ts(dist = false) {
|
||||
console.log("Building app...");
|
||||
return exec(`tsc -p ${dist ? "./tsconfig.dist.json" : "."}`);
|
||||
await exec(`tsc -p ${dist ? "./tsconfig.dist.json" : "."}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start watching for typescript changes
|
||||
*/
|
||||
function watch_ts() {
|
||||
async function watch_ts() {
|
||||
watch(["./src/**/*.ts", "package.json"], () => ts());
|
||||
await forever();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an atlas of images for a given stage
|
||||
*/
|
||||
function atlas(stage) {
|
||||
async function atlas(stage) {
|
||||
shell.rm('-f', `out/assets/atlas${stage}-*`);
|
||||
return list(`data/stage${stage}/image/**/*.{png,jpg}`).then(files => {
|
||||
let opts = {
|
||||
name: `out/assets/atlas${stage}`,
|
||||
fullpath: true,
|
||||
width: 2048,
|
||||
height: 2048,
|
||||
square: true,
|
||||
powerOfTwo: true,
|
||||
padding: 2
|
||||
};
|
||||
return new Promise(resolve => gfPacker(files, opts, resolve));
|
||||
}).then(() => {
|
||||
return list(`out/assets/atlas${stage}-*.json`);
|
||||
}).then(outfiles => {
|
||||
return Promise.resolve(outfiles.map(file => path.basename(file).replace('.json', '')))
|
||||
});
|
||||
|
||||
let files = await list(`data/stage${stage}/image/**/*.{png,jpg}`);
|
||||
|
||||
let opts = {
|
||||
name: `out/assets/atlas${stage}`,
|
||||
fullpath: true,
|
||||
width: 2048,
|
||||
height: 2048,
|
||||
square: true,
|
||||
powerOfTwo: true,
|
||||
padding: 2
|
||||
};
|
||||
await new Promise(resolve => gfPacker(files, opts, resolve));
|
||||
let outfiles = await list(`out/assets/atlas${stage}-*.json`);
|
||||
return outfiles.map(file => path.basename(file).replace('.json', ''));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a single data pack
|
||||
*/
|
||||
function pack(stage) {
|
||||
async function pack(stage) {
|
||||
console.log(`Building pack ${stage}...`);
|
||||
|
||||
let getKey = x => x.replace(/\//g, "-").replace(/\.[a-z0-9]+$/, '');
|
||||
|
||||
return atlas(stage).then(files => {
|
||||
return Promise.resolve(files.map(file => {
|
||||
let fname = path.basename(file);
|
||||
return {
|
||||
type: "atlasJSONHash",
|
||||
key: fname,
|
||||
atlasURL: `assets/${fname}.json?t=${Date.now()}`,
|
||||
textureURL: `assets/${fname}.png`,
|
||||
atlasData: null
|
||||
}
|
||||
}));
|
||||
}).then(items => {
|
||||
return list(`data/stage${stage}/sound/**/*.{mp3,wav}`).then(files => {
|
||||
return Promise.resolve(items.concat(files.map(file => {
|
||||
const [name, ext] = file.rsplit('.');
|
||||
const key = getKey(name.replace(`data/stage${stage}/sound/`, ''));
|
||||
shell.cp(file, `out/assets/${key}.${ext}`);
|
||||
return {
|
||||
type: "audio",
|
||||
key: key,
|
||||
urls: [`assets/${key}.${ext}?t=${Date.now()}`],
|
||||
autoDecode: (ext == 'mp3')
|
||||
};
|
||||
})));
|
||||
});
|
||||
}).then(items => {
|
||||
return list(`data/stage${stage}/shader/**/*.glsl`).then(files => {
|
||||
return Promise.resolve(items.concat(files.map(file => {
|
||||
const [name, ext] = file.rsplit('.');
|
||||
const key = getKey(name.replace(`data/stage${stage}/shader/`, ''));
|
||||
shell.cp(file, `out/assets/${key}.${ext}`);
|
||||
return {
|
||||
type: "shader",
|
||||
key: key,
|
||||
url: `assets/${key}.${ext}?t=${Date.now()}`
|
||||
};
|
||||
})));
|
||||
});
|
||||
}).then(items => {
|
||||
let packdata = {};
|
||||
packdata[`stage${stage}`] = items;
|
||||
return new Promise(resolve => fs.writeFile(`out/assets/pack${stage}.json`, JSON.stringify(packdata), 'utf8', resolve));
|
||||
let files = await atlas(stage)
|
||||
let items = files.map(file => {
|
||||
let fname = path.basename(file);
|
||||
return {
|
||||
type: "atlasJSONHash",
|
||||
key: fname,
|
||||
atlasURL: `assets/${fname}.json?t=${Date.now()}`,
|
||||
textureURL: `assets/${fname}.png`,
|
||||
atlasData: null
|
||||
}
|
||||
});
|
||||
|
||||
files = await list(`data/stage${stage}/sound/**/*.{mp3,wav}`);
|
||||
items = items.concat(files.map(file => {
|
||||
const [name, ext] = file.rsplit('.');
|
||||
const key = getKey(name.replace(`data/stage${stage}/sound/`, ''));
|
||||
shell.cp(file, `out/assets/${key}.${ext}`);
|
||||
return {
|
||||
type: "audio",
|
||||
key: key,
|
||||
urls: [`assets/${key}.${ext}?t=${Date.now()}`],
|
||||
autoDecode: (ext == 'mp3')
|
||||
};
|
||||
}));
|
||||
|
||||
files = await list(`data/stage${stage}/shader/**/*.glsl`);
|
||||
items = items.concat(files.map(file => {
|
||||
const [name, ext] = file.rsplit('.');
|
||||
const key = getKey(name.replace(`data/stage${stage}/shader/`, ''));
|
||||
shell.cp(file, `out/assets/${key}.${ext}`);
|
||||
return {
|
||||
type: "shader",
|
||||
key: key,
|
||||
url: `assets/${key}.${ext}?t=${Date.now()}`
|
||||
};
|
||||
}));
|
||||
|
||||
let packdata = {};
|
||||
packdata[`stage${stage}`] = items;
|
||||
await new Promise(resolve => fs.writeFile(`out/assets/pack${stage}.json`, JSON.stringify(packdata), 'utf8', resolve));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build data packs
|
||||
*/
|
||||
function data() {
|
||||
async function data() {
|
||||
shell.mkdir("-p", "out/assets");
|
||||
return Promise.all([1, 2, 3].map(stage => pack(stage)));
|
||||
await Promise.all([1, 2, 3].map(stage => pack(stage)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Start watch for data changes
|
||||
*/
|
||||
function watch_data() {
|
||||
async function watch_data() {
|
||||
watch(["./data/**/*.*"], () => data());
|
||||
await forever();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the vendors from node_modules to dist directory
|
||||
*/
|
||||
function vendors() {
|
||||
async function vendors() {
|
||||
console.log("Copying vendors...");
|
||||
shell.rm('-rf', 'out/vendor');
|
||||
shell.mkdir('-p', 'out/vendor');
|
||||
shell.cp('-R', 'node_modules/phaser/build', 'out/vendor/phaser');
|
||||
shell.cp('-R', 'node_modules/parse/dist', 'out/vendor/parse');
|
||||
shell.cp('-R', 'node_modules/jasmine-core/lib/jasmine-core', 'out/vendor/jasmine');
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start watching for vendors changes
|
||||
*/
|
||||
function watch_vendors() {
|
||||
async function watch_vendors() {
|
||||
watch(['package.json'], () => vendors());
|
||||
await forever();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger a single build
|
||||
*/
|
||||
function build(dist = false) {
|
||||
return Promise.all([
|
||||
async function build(dist = false) {
|
||||
await Promise.all([
|
||||
ts(dist),
|
||||
data(),
|
||||
vendors()
|
||||
|
@ -170,35 +170,47 @@ function build(dist = false) {
|
|||
/**
|
||||
* Optimize the build for production
|
||||
*/
|
||||
function optimize() {
|
||||
async function optimize() {
|
||||
// TODO do not overwrite dev build
|
||||
return exec("uglifyjs out/build.dist.js --source-map --output out/build.js");
|
||||
await exec("uglifyjs out/build.dist.js --source-map --output out/build.js");
|
||||
}
|
||||
|
||||
/**
|
||||
* Deploy to production
|
||||
*/
|
||||
function deploy(task) {
|
||||
return build(true).then(optimize).then(() => {
|
||||
return exec("rsync -avz --delete ./out/ hosting.thunderk.net:/srv/website/spacetac/")
|
||||
});
|
||||
async function deploy(task) {
|
||||
await build(true);
|
||||
await optimize();
|
||||
await exec("rsync -avz --delete ./out/ hosting.thunderk.net:/srv/website/spacetac/");
|
||||
}
|
||||
|
||||
/**
|
||||
* Run tests in karma, using freshly built app
|
||||
* Run tests in karma
|
||||
*/
|
||||
function test(task) {
|
||||
return Promise.all([ts(), vendors()]).then(() => {
|
||||
return exec("karma start spec/support/karma.conf.js");
|
||||
}).then(() => {
|
||||
return exec("remap-istanbul -i out/coverage/coverage.json -o out/coverage -t html");
|
||||
});
|
||||
async function karma() {
|
||||
await exec("karma start spec/support/karma.conf.js");
|
||||
}
|
||||
|
||||
/**
|
||||
* Run tests in karma (suppose is already built)
|
||||
*/
|
||||
async function test(task) {
|
||||
await karma();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run tests in karma, using freshly built app (for continuous integration)
|
||||
*/
|
||||
async function ci(task) {
|
||||
await Promise.all([ts(), vendors()]);
|
||||
await karma();
|
||||
await exec("remap-istanbul -i out/coverage/coverage.json -o out/coverage -t html");
|
||||
}
|
||||
|
||||
/**
|
||||
* Serve the app for dev purpose
|
||||
*/
|
||||
function serve() {
|
||||
async function serve() {
|
||||
liveServer.start({
|
||||
host: '127.0.0.1',
|
||||
port: 8012,
|
||||
|
@ -206,31 +218,52 @@ function serve() {
|
|||
ignore: 'coverage',
|
||||
wait: 500
|
||||
});
|
||||
return new Promise(() => null);
|
||||
await new Promise(() => null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Continuous development server
|
||||
*/
|
||||
function continuous() {
|
||||
return build().then(() => Promise.all([
|
||||
async function continuous() {
|
||||
try {
|
||||
await build();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
await Promise.all([
|
||||
serve(),
|
||||
watch_ts(),
|
||||
watch_data(),
|
||||
watch_vendors()
|
||||
]));
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper around an async execution function, to make it a runjs command
|
||||
*/
|
||||
function command(func) {
|
||||
return async function () {
|
||||
try {
|
||||
await func();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
ts,
|
||||
watch_ts,
|
||||
data,
|
||||
watch_data,
|
||||
vendors,
|
||||
watch_vendors,
|
||||
build,
|
||||
test,
|
||||
deploy,
|
||||
serve,
|
||||
continuous
|
||||
ts: command(ts),
|
||||
watch_ts: command(watch_ts),
|
||||
data: command(data),
|
||||
watch_data: command(watch_data),
|
||||
vendors: command(vendors),
|
||||
watch_vendors: command(watch_vendors),
|
||||
build: command(build),
|
||||
test: command(test),
|
||||
deploy: command(deploy),
|
||||
serve: command(serve),
|
||||
continuous: command(continuous),
|
||||
ci: command(ci)
|
||||
}
|
||||
|
|
|
@ -24,25 +24,25 @@ module TK.SpaceTac.Specs {
|
|||
intruder_count: 0,
|
||||
intruder_effects: [new ValueEffect("hull", -1)]
|
||||
});
|
||||
check.equals(action.getEffectsDescription(), "Watch a 120km area (power usage 2):\n• hull -1 for all incoming ships");
|
||||
check.equals(action.getEffectsDescription(), "Watch a 120km area (power usage 2):\n• hull -1 on all incoming ships");
|
||||
|
||||
action = new VigilanceAction("Reactive Fire", { power: 2, radius: 120 }, {
|
||||
intruder_count: 1,
|
||||
intruder_effects: [new ValueEffect("hull", -1)]
|
||||
});
|
||||
check.equals(action.getEffectsDescription(), "Watch a 120km area (power usage 2):\n• hull -1 for the first incoming ship");
|
||||
check.equals(action.getEffectsDescription(), "Watch a 120km area (power usage 2):\n• hull -1 on the first incoming ship");
|
||||
|
||||
action = new VigilanceAction("Reactive Fire", { power: 2, radius: 120 }, {
|
||||
intruder_count: 3,
|
||||
intruder_effects: [new ValueEffect("hull", -1)]
|
||||
});
|
||||
check.equals(action.getEffectsDescription(), "Watch a 120km area (power usage 2):\n• hull -1 for the first 3 incoming ships");
|
||||
check.equals(action.getEffectsDescription(), "Watch a 120km area (power usage 2):\n• hull -1 on the first 3 incoming ships");
|
||||
|
||||
action = new VigilanceAction("Reactive Fire", { power: 2, radius: 120, filter: ActionTargettingFilter.ALLIES }, {
|
||||
intruder_count: 3,
|
||||
intruder_effects: [new ValueEffect("hull", -1)]
|
||||
});
|
||||
check.equals(action.getEffectsDescription(), "Watch a 120km area (power usage 2):\n• hull -1 for the first 3 incoming team members");
|
||||
check.equals(action.getEffectsDescription(), "Watch a 120km area (power usage 2):\n• hull -1 on the first 3 incoming team members");
|
||||
});
|
||||
|
||||
test.case("handles the vigilance effect to know who to target", check => {
|
||||
|
|
|
@ -49,11 +49,11 @@ module TK.SpaceTac {
|
|||
|
||||
let suffix: string;
|
||||
if (this.intruder_count == 0) {
|
||||
suffix = `for all incoming ${BaseAction.getFilterDesc(this.filter)}`;
|
||||
suffix = `on all incoming ${BaseAction.getFilterDesc(this.filter)}`;
|
||||
} else if (this.intruder_count == 1) {
|
||||
suffix = `for the first incoming ${BaseAction.getFilterDesc(this.filter, false)}`;
|
||||
suffix = `on the first incoming ${BaseAction.getFilterDesc(this.filter, false)}`;
|
||||
} else {
|
||||
suffix = `for the first ${this.intruder_count} incoming ${BaseAction.getFilterDesc(this.filter)}`;
|
||||
suffix = `on the first ${this.intruder_count} incoming ${BaseAction.getFilterDesc(this.filter)}`;
|
||||
}
|
||||
|
||||
let effects = this.intruder_effects.map(effect => {
|
||||
|
|
Loading…
Reference in a new issue