Port node build tool to 0.97
This commit is contained in:
parent
15c8ec22fd
commit
d628c4c3f0
|
@ -11,3 +11,27 @@ jobs:
|
|||
- run:
|
||||
name: Validate Config style
|
||||
command: python tools/config_style_checker.py
|
||||
|
||||
pack:
|
||||
docker:
|
||||
- image: circleci/node
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: npm install --loglevel=error
|
||||
working_directory: ~/project/tools/buildtool
|
||||
- run:
|
||||
name: Pack PBOs
|
||||
command: npx gulp
|
||||
working_directory: ~/project/tools/buildtool
|
||||
- store_artifacts:
|
||||
path: ~/project/_build/pbo
|
||||
destination: 'KP-Liberation'
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
build:
|
||||
jobs:
|
||||
- pack
|
||||
- validate
|
||||
|
|
|
@ -47,4 +47,5 @@ Temporary Items
|
|||
.apdisk
|
||||
|
||||
# Build directory
|
||||
build/
|
||||
_build/
|
||||
node_modules/
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
@echo off
|
||||
|
||||
rem Check that https://nodejs.org/en/download/ exists before continuing
|
||||
where /q node
|
||||
if ERRORLEVEL 1 (
|
||||
echo node is missing. Ensure it is installed. It can be downloaded from:
|
||||
echo https://nodejs.org/en/download/
|
||||
timeout 30
|
||||
exit /b
|
||||
)
|
||||
|
||||
rem CD into build tool directory
|
||||
cd %~dp0buildtool
|
||||
|
||||
rem Install dependencies and build missions
|
||||
call npm install --loglevel=error
|
||||
call npx gulp
|
||||
|
||||
cd ..
|
||||
|
||||
echo.
|
||||
|
||||
pause
|
||||
exit /b
|
|
@ -0,0 +1,84 @@
|
|||
# KP Liberation builder
|
||||
|
||||
## Requirements
|
||||
|
||||
nodejs version >=7.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
npm install
|
||||
|
||||
# Run mission build
|
||||
npm run build
|
||||
|
||||
|
||||
# Run task with local gulp via npx
|
||||
npx gulp <task_name>
|
||||
|
||||
# With gulp-cli and gulp 4 installed globally
|
||||
gulp <task_name>
|
||||
|
||||
```
|
||||
| Task | Desc |
|
||||
| ----------- | ---------------------------------------------- |
|
||||
| clean | removes `build/` dir |
|
||||
| build | assembles missionfolder and sets config values |
|
||||
| pbo | packs missionfolders into PBOs |
|
||||
| zip | creates release ZIPs |
|
||||
| __default__ | runs _build_, _pbo_ and _zip_ |
|
||||
|
||||
Build files will be outputted to `build/` dir.
|
||||
|
||||
## Configuration
|
||||
|
||||
### presets.json
|
||||
|
||||
This file should contain an JSON __array__ of `Presets`, for every preset one mission file will be built.
|
||||
|
||||
Every `Preset` entry should have following structure:
|
||||
```javascript
|
||||
{
|
||||
// Source folder with mission.sqm, relative to <missionsFolder>
|
||||
// If mission.sqm is in root of <missionsFolder> should be set to empty string
|
||||
"sourceFolder": "kp_liberation.Altis",
|
||||
|
||||
// Name and map is used to build output directory: <missionName>.<map>
|
||||
// Name different than source allows to build multiple version of mission on same map
|
||||
// Combination of <missionName> and <map> should be unique for every preset
|
||||
"missionName": "kp_liberation",
|
||||
"map": "Altis",
|
||||
|
||||
// Keys of <variables> object represent variables in <configFile>.
|
||||
// These variables values will be set to corresponding value in <variables>
|
||||
"configFile": "kp_liberation_config.sqf",
|
||||
"variables": {
|
||||
"KP_liberation_preset_blufor": 0,
|
||||
"KP_liberation_preset_opfor": 0,
|
||||
"KP_liberation_preset_resistance": 0,
|
||||
"KP_liberation_preset_civilians": 0,
|
||||
"KP_liberation_arsenal": 0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### gulpfile.ts
|
||||
|
||||
`paths` variable in _gulpfile_ holds filesystem paths required to build missions.
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* Mission folders configuration
|
||||
*/
|
||||
const paths: FolderStructureInfo = {
|
||||
// Folder with mission scripts
|
||||
frameworkFolder: resolve('..', 'Missionframework'),
|
||||
|
||||
// Folder with base mission.sqm folders
|
||||
missionsFolder: resolve('..', 'Missionbasefiles'),
|
||||
|
||||
// Output directory
|
||||
workDir: resolve("./build")
|
||||
};
|
||||
```
|
|
@ -0,0 +1,10 @@
|
|||
[
|
||||
{
|
||||
"sourceFolder": "kp_liberation.Altis",
|
||||
"missionName": "kp_liberation",
|
||||
"map": "Altis",
|
||||
"configFile": "KPLIB_config.sqf",
|
||||
"variables": {
|
||||
}
|
||||
}
|
||||
]
|
|
@ -0,0 +1,139 @@
|
|||
import * as gulp from "gulp";
|
||||
import * as gulpReplace from "gulp-replace";
|
||||
import * as gulpPbo from "gulp-armapbo";
|
||||
import * as gulpZip from "gulp-zip";
|
||||
import * as vinylPaths from "vinyl-paths";
|
||||
import * as del from "del";
|
||||
|
||||
import { resolve } from "path";
|
||||
|
||||
import { MissionPaths } from "./src";
|
||||
import { Preset, FolderStructureInfo } from "./src";
|
||||
|
||||
const ROOT_DIR = resolve('..', '..');
|
||||
|
||||
const presets: Preset[] = require('./_presets.json');
|
||||
|
||||
/**
|
||||
* Mission folders configuration
|
||||
*/
|
||||
const paths: FolderStructureInfo = {
|
||||
frameworkFolder: resolve(ROOT_DIR, 'Missionframework'),
|
||||
missionsFolder: resolve(ROOT_DIR, 'Missionbasefiles'),
|
||||
workDir: resolve(ROOT_DIR, "_build")
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create gulp tasks
|
||||
*/
|
||||
let taskNames: string[] = [];
|
||||
let taskNamesPbo: string[] = [];
|
||||
let taskNamesZip: string[] = [];
|
||||
|
||||
for (let preset of presets) {
|
||||
const mission = new MissionPaths(preset, paths);
|
||||
const taskName = [preset.missionName, preset.map].join('.');
|
||||
|
||||
|
||||
taskNames.push('mission_' + taskName);
|
||||
|
||||
gulp.task('mission_' + taskName, gulp.series(
|
||||
/** Copy mission framework to output dir */
|
||||
function copyFramework() {
|
||||
return gulp.src(mission.getFrameworkPath().concat('/**/*'))
|
||||
.pipe(gulp.dest(mission.getOutputDir()));
|
||||
},
|
||||
|
||||
/** Copy mission.sqm to output dir */
|
||||
function copyMissionSQM() {
|
||||
return gulp.src(mission.getMissionSqmPath())
|
||||
.pipe(gulp.dest(mission.getOutputDir()));
|
||||
},
|
||||
|
||||
/** Replace variables values in configuration file */
|
||||
function replaceVariables() {
|
||||
let src = gulp.src(mission.getMissionConfigFilePath());
|
||||
|
||||
const variables = Object.getOwnPropertyNames(preset.variables);
|
||||
for (let variable of variables) {
|
||||
// https://regex101.com/r/YknC8r/1
|
||||
const regex = new RegExp(`(${variable} += +)(?:\\d+|".+")`, 'ig');
|
||||
const value = JSON.stringify(preset.variables[variable]);
|
||||
|
||||
// replace variable value
|
||||
src = src.pipe(gulpReplace(regex, `$1${value}`));
|
||||
}
|
||||
|
||||
return src.pipe(gulp.dest(mission.getOutputDir()));
|
||||
}
|
||||
));
|
||||
|
||||
/**
|
||||
* Pack PBOs
|
||||
*/
|
||||
taskNamesPbo.push('pack_' + taskName);
|
||||
|
||||
gulp.task('pack_' + taskName, () => {
|
||||
return gulp.src(mission.getOutputDir() + '/**/*')
|
||||
.pipe(gulpPbo({
|
||||
fileName: mission.getFullName() + '.pbo',
|
||||
progress: false,
|
||||
verbose: false,
|
||||
// Do not compress (SLOW)
|
||||
compress: true ? [] : [
|
||||
'**/*.sqf',
|
||||
'mission.sqm',
|
||||
'description.ext'
|
||||
]
|
||||
}))
|
||||
.pipe(gulp.dest(mission.getWorkDir() + '/pbo'));
|
||||
});
|
||||
|
||||
/**
|
||||
* Create ZIP files
|
||||
*/
|
||||
taskNamesZip.push('zip_' + taskName);
|
||||
|
||||
gulp.task('zip_' + taskName, () => {
|
||||
return gulp.src([
|
||||
resolve(ROOT_DIR, 'LICENSE'),
|
||||
resolve(ROOT_DIR, 'CHANGELOG.md'),
|
||||
resolve(ROOT_DIR, 'README.md')
|
||||
], {
|
||||
base: ROOT_DIR // Change base dir to have correct relative paths in ZIP
|
||||
})
|
||||
.pipe(
|
||||
gulp.src(
|
||||
resolve(mission.getWorkDir(), 'pbo', mission.getFullName() + '.pbo'), {
|
||||
base: resolve(mission.getWorkDir(), 'pbo') // Change base dir to have correct relative paths in ZIP
|
||||
})
|
||||
)
|
||||
.pipe(gulpZip(
|
||||
mission.getFullName() + '.zip'
|
||||
))
|
||||
.pipe(gulp.dest(mission.getWorkDir()))
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Main tasks
|
||||
gulp.task('clean', () => {
|
||||
return gulp.src(paths.workDir)
|
||||
.pipe(vinylPaths(del));
|
||||
});
|
||||
|
||||
gulp.task('build', gulp.series(taskNames));
|
||||
|
||||
gulp.task('pbo', gulp.series(taskNamesPbo));
|
||||
|
||||
gulp.task('zip', gulp.series(taskNamesZip));
|
||||
|
||||
gulp.task('default',
|
||||
gulp.series(
|
||||
gulp.task('build'),
|
||||
gulp.task('pbo'),
|
||||
// gulp.task('zip'),
|
||||
)
|
||||
);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"name": "kp_liberation",
|
||||
"engines": {
|
||||
"node": ">=7"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/del": "^3.0.0",
|
||||
"@types/gulp": "^4.0.5",
|
||||
"@types/gulp-replace": "0.0.31",
|
||||
"@types/gulp-zip": "^4.0.0",
|
||||
"@types/vinyl-paths": "0.0.31",
|
||||
"del": "^3.0.0",
|
||||
"gulp": "^4.0.0",
|
||||
"gulp-armapbo": "^1.1.3",
|
||||
"gulp-replace": "^0.6.1",
|
||||
"gulp-zip": "^4.1.0",
|
||||
"smart-zip": "0.0.9",
|
||||
"ts-node": "^4.1.0",
|
||||
"typescript": "^2.7.1",
|
||||
"vinyl-paths": "^2.1.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "npx gulp"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
export interface Preset {
|
||||
/**
|
||||
* Path to folder with mission.sqm relative to "missionsFolder".
|
||||
* If mission.sqm is in root of "missionsFolder" should be empty string.
|
||||
*
|
||||
* @see FolderStructureInfo.missionsFolder
|
||||
*/
|
||||
readonly sourceFolder: string;
|
||||
|
||||
/**
|
||||
* Path to file with mission configuration.
|
||||
* Replacement of variables will be applied here.
|
||||
*/
|
||||
readonly configFile: string;
|
||||
|
||||
/**
|
||||
* Name of mission (part before mapname)
|
||||
*/
|
||||
readonly missionName: string;
|
||||
|
||||
/**
|
||||
* Map name
|
||||
*/
|
||||
readonly map: string;
|
||||
|
||||
/**
|
||||
* key=>val of values to replace in config file
|
||||
* @see {VariablesReplacements}
|
||||
*/
|
||||
readonly variables: VariablesReplacements;
|
||||
}
|
||||
|
||||
export interface VariablesReplacements {
|
||||
/** Key should be name of variable as set in SQF file, its value will be replaced with one from entry. */
|
||||
readonly [key: string]: any;
|
||||
}
|
||||
|
||||
export interface FolderStructureInfo {
|
||||
/**
|
||||
* Folder of folders with mission.sqm.
|
||||
* Value of "sourceFolder" from Preset will be appended to this path.
|
||||
*
|
||||
* @see {Preset}
|
||||
*/
|
||||
readonly missionsFolder: string;
|
||||
|
||||
/**
|
||||
* Path to folder with mission framework files.
|
||||
*/
|
||||
readonly frameworkFolder: string;
|
||||
|
||||
/**
|
||||
* Directory containing built missions
|
||||
*/
|
||||
readonly workDir: string;
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
import { Preset, FolderStructureInfo } from './Config';
|
||||
import * as path from "path";
|
||||
|
||||
export class MissionPaths {
|
||||
|
||||
static readonly missionSQM = 'mission.sqm';
|
||||
|
||||
private preset: Preset;
|
||||
|
||||
private folderStructure: FolderStructureInfo;
|
||||
|
||||
constructor(preset: Preset, folderStructure: FolderStructureInfo) {
|
||||
this.preset = preset;
|
||||
this.folderStructure = folderStructure;
|
||||
}
|
||||
|
||||
public getMap(): string {
|
||||
return this.preset.map;
|
||||
}
|
||||
|
||||
public getName(): string {
|
||||
return this.preset.missionName;
|
||||
}
|
||||
|
||||
public getFullName(): string {
|
||||
return [this.getName(), this.getMap()].join('.');
|
||||
}
|
||||
|
||||
public getWorkDir(): string {
|
||||
return this.folderStructure.workDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get path to source mission.sqm file
|
||||
*/
|
||||
public getMissionSqmPath(): string {
|
||||
return path.resolve(
|
||||
this.folderStructure.missionsFolder,
|
||||
this.preset.sourceFolder,
|
||||
'mission.sqm'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get path to folder with mission framework files.
|
||||
*/
|
||||
public getFrameworkPath(): string {
|
||||
return path.resolve(this.folderStructure.frameworkFolder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get path to folder containing mission files
|
||||
*/
|
||||
public getOutputDir(): string {
|
||||
return path.resolve(
|
||||
this.folderStructure.workDir,
|
||||
this.getFullName()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get path to file with mission configuration.
|
||||
* As defined in preset.
|
||||
*/
|
||||
public getMissionConfigFilePath(): string {
|
||||
return path.resolve(
|
||||
this.getOutputDir(),
|
||||
this.preset.configFile
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
export * from "./MissionPaths";
|
||||
|
||||
export * from "./Config";
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist/",
|
||||
"sourceMap": true,
|
||||
"strictNullChecks": true,
|
||||
"module": "commonjs",
|
||||
"target": "es6",
|
||||
"noUnusedParameters": true,
|
||||
"noUnusedLocals": true,
|
||||
"noImplicitAny": true
|
||||
},
|
||||
"include": [
|
||||
"./src/"
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue