XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESpaceNinjaServer

A simple server for a small space ninja game

公开
关注 0 Fork 0 Star 0
返回提交历史

XFEstudio/XFESpaceNinjaServer

chore: use build & start process for development as well (#2222)

Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/2222 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>

f84cc54c
Sainan <63328889+Sainan@users.noreply.github.com>
提交于

代码差异

13 个文件 +138 -546
Modified docker-entrypoint.sh +1 -1
@@ -5,4 +5,4 @@ if [ ! -f conf/config.json ]; then
5 5 jq --arg value "mongodb://openwfagent:spaceninjaserver@mongodb:27017/" '.mongodbUrl = $value' /app/config.json.example > /app/conf/config.json
6 6 fi
7 7
8 exec npm run start conf/config.json
8 exec npm run start -- --configPath conf/config.json
Modified package.json +5 -3
@@ -5,8 +5,10 @@
5 5 "main": "index.ts",
6 6 "scripts": {
7 7 "start": "node --enable-source-maps --import ./build/src/pathman.js build/src/index.js",
8 "dev": "ts-node-dev --openssl-legacy-provider -r tsconfig-paths/register src/index.ts ",
9 8 "build": "tsc --incremental --sourceMap && ncp static/webui build/static/webui",
9 "build:dev": "tsc --incremental --sourceMap",
10 "build-and-start": "npm run build && npm run start",
11 "dev": "node scripts/dev.js",
10 12 "verify": "tsgo --noEmit",
11 13 "lint": "eslint --ext .ts .",
12 14 "lint:ci": "eslint --ext .ts --rule \"prettier/prettier: off\" .",
@@ -36,10 +38,10 @@
36 38 "@typescript-eslint/eslint-plugin": "^8.28.0",
37 39 "@typescript-eslint/parser": "^8.28.0",
38 40 "@typescript/native-preview": "^7.0.0-dev.20250523.1",
41 "chokidar": "^4.0.3",
39 42 "eslint": "^8",
40 43 "eslint-plugin-prettier": "^5.2.5",
41 44 "prettier": "^3.5.3",
42 "ts-node-dev": "^2.0.0",
43 "tsconfig-paths": "^4.2.0"
45 "tree-kill": "^1.2.2"
44 46 }
45 47 }
Added scripts/dev.js +49 -0
@@ -0,0 +1,49 @@
1 /* eslint-disable */
2 const { spawn } = require("child_process");
3 const chokidar = require("chokidar");
4 const kill = require("tree-kill");
5
6 let secret = "";
7 for (let i = 0; i != 10; ++i) {
8 secret += String.fromCharCode(Math.floor(Math.random() * 26) + 0x41);
9 }
10
11 const args = [...process.argv].splice(2);
12 args.push("--dev");
13 args.push("--secret");
14 args.push(secret);
15
16 let buildproc, runproc;
17 function run(changedFile) {
18 if (changedFile) {
19 console.log(`Change to ${changedFile} detected`);
20 }
21
22 if (buildproc) {
23 kill(buildproc.pid);
24 buildproc = undefined;
25 }
26 if (runproc) {
27 kill(runproc.pid);
28 runproc = undefined;
29 }
30
31 buildproc = spawn("npm", ["run", "build:dev"], { stdio: "inherit", shell: true });
32 buildproc.on("exit", code => {
33 buildproc = undefined;
34 if (code === 0) {
35 runproc = spawn("npm", ["run", "start", "--", ...args], { stdio: "inherit", shell: true });
36 runproc.on("exit", () => {
37 runproc = undefined;
38 });
39 }
40 });
41 }
42
43 run();
44 chokidar.watch("src").on("change", run);
45 chokidar.watch("static/fixed_responses").on("change", run);
46
47 chokidar.watch("static/webui").on("change", () => {
48 fetch("http://localhost/custom/webuiFileChangeDetected?secret=" + secret);
49 });
Modified scripts/update-translations.js +1 -0
@@ -1,6 +1,7 @@
1 1 // Based on https://onlyg.it/OpenWF/Translations/src/branch/main/update.php
2 2 // Converted via ChatGPT-4o
3 3
4 /* eslint-disable */
4 5 const fs = require("fs");
5 6
6 7 function extractStrings(content) {
Added src/controllers/custom/webuiFileChangeDetectedController.ts +11 -0
@@ -0,0 +1,11 @@
1 import { args } from "@/src/helpers/commandLineArguments";
2 import { config } from "@/src/services/configService";
3 import { sendWsBroadcast } from "@/src/services/webService";
4 import { RequestHandler } from "express";
5
6 export const webuiFileChangeDetectedController: RequestHandler = (req, res) => {
7 if (args.dev && args.secret && req.query.secret == args.secret) {
8 sendWsBroadcast({ ports: { http: config.httpPort, https: config.httpsPort } });
9 }
10 res.end();
11 };
Added src/helpers/commandLineArguments.ts +23 -0
@@ -0,0 +1,23 @@
1 interface IArguments {
2 configPath?: string;
3 dev?: boolean;
4 secret?: string;
5 }
6
7 export const args: IArguments = {};
8
9 for (let i = 2; i < process.argv.length; ) {
10 switch (process.argv[i++]) {
11 case "--configPath":
12 args.configPath = process.argv[i++];
13 break;
14
15 case "--dev":
16 args.dev = true;
17 break;
18
19 case "--secret":
20 args.secret = process.argv[i++];
21 break;
22 }
23 }
Modified src/helpers/pathHelper.ts +1 -2
@@ -1,5 +1,4 @@
1 1 import path from "path";
2 2
3 3 export const rootDir = path.join(__dirname, "../..");
4 export const isDev = path.basename(rootDir) != "build";
5 export const repoDir = isDev ? rootDir : path.join(rootDir, "..");
4 export const repoDir = path.basename(rootDir) != "build" ? rootDir : path.join(rootDir, "..");
Modified src/routes/custom.ts +3 -1
@@ -11,6 +11,7 @@ import { renameAccountController } from "@/src/controllers/custom/renameAccountC
11 11 import { ircDroppedController } from "@/src/controllers/custom/ircDroppedController";
12 12 import { unlockAllIntrinsicsController } from "@/src/controllers/custom/unlockAllIntrinsicsController";
13 13 import { addMissingMaxRankModsController } from "@/src/controllers/custom/addMissingMaxRankModsController";
14 import { webuiFileChangeDetectedController } from "@/src/controllers/custom/webuiFileChangeDetectedController";
14 15
15 16 import { createAccountController } from "@/src/controllers/custom/createAccountController";
16 17 import { createMessageController } from "@/src/controllers/custom/createMessageController";
@@ -20,10 +21,10 @@ import { addXpController } from "@/src/controllers/custom/addXpController";
20 21 import { importController } from "@/src/controllers/custom/importController";
21 22 import { manageQuestsController } from "@/src/controllers/custom/manageQuestsController";
22 23 import { setEvolutionProgressController } from "@/src/controllers/custom/setEvolutionProgressController";
24 import { setBoosterController } from "@/src/controllers/custom/setBoosterController";
23 25
24 26 import { getConfigDataController } from "@/src/controllers/custom/getConfigDataController";
25 27 import { updateConfigDataController } from "@/src/controllers/custom/updateConfigDataController";
26 import { setBoosterController } from "../controllers/custom/setBoosterController";
27 28
28 29 const customRouter = express.Router();
29 30
@@ -38,6 +39,7 @@ customRouter.get("/renameAccount", renameAccountController);
38 39 customRouter.get("/ircDropped", ircDroppedController);
39 40 customRouter.get("/unlockAllIntrinsics", unlockAllIntrinsicsController);
40 41 customRouter.get("/addMissingMaxRankMods", addMissingMaxRankModsController);
42 customRouter.get("/webuiFileChangeDetected", webuiFileChangeDetectedController);
41 43
42 44 customRouter.post("/createAccount", createAccountController);
43 45 customRouter.post("/createMessage", createMessageController);
Modified src/routes/webui.ts +12 -9
@@ -1,6 +1,9 @@
1 1 import express from "express";
2 2 import path from "path";
3 3 import { repoDir, rootDir } from "@/src/helpers/pathHelper";
4 import { args } from "@/src/helpers/commandLineArguments";
5
6 const baseDir = args.dev ? repoDir : rootDir;
4 7
5 8 const webuiRouter = express.Router();
6 9
@@ -19,29 +22,29 @@ webuiRouter.use("/webui", (req, res, next) => {
19 22
20 23 // Serve virtual routes
21 24 webuiRouter.get("/webui/inventory", (_req, res) => {
22 res.sendFile(path.join(rootDir, "static/webui/index.html"));
25 res.sendFile(path.join(baseDir, "static/webui/index.html"));
23 26 });
24 27 webuiRouter.get(/webui\/powersuit\/(.+)/, (_req, res) => {
25 res.sendFile(path.join(rootDir, "static/webui/index.html"));
28 res.sendFile(path.join(baseDir, "static/webui/index.html"));
26 29 });
27 30 webuiRouter.get("/webui/mods", (_req, res) => {
28 res.sendFile(path.join(rootDir, "static/webui/index.html"));
31 res.sendFile(path.join(baseDir, "static/webui/index.html"));
29 32 });
30 33 webuiRouter.get("/webui/settings", (_req, res) => {
31 res.sendFile(path.join(rootDir, "static/webui/index.html"));
34 res.sendFile(path.join(baseDir, "static/webui/index.html"));
32 35 });
33 36 webuiRouter.get("/webui/quests", (_req, res) => {
34 res.sendFile(path.join(rootDir, "static/webui/index.html"));
37 res.sendFile(path.join(baseDir, "static/webui/index.html"));
35 38 });
36 39 webuiRouter.get("/webui/cheats", (_req, res) => {
37 res.sendFile(path.join(rootDir, "static/webui/index.html"));
40 res.sendFile(path.join(baseDir, "static/webui/index.html"));
38 41 });
39 42 webuiRouter.get("/webui/import", (_req, res) => {
40 res.sendFile(path.join(rootDir, "static/webui/index.html"));
43 res.sendFile(path.join(baseDir, "static/webui/index.html"));
41 44 });
42 45
43 46 // Serve static files
44 webuiRouter.use("/webui", express.static(path.join(rootDir, "static/webui")));
47 webuiRouter.use("/webui", express.static(path.join(baseDir, "static/webui")));
45 48
46 49 // Serve favicon
47 50 webuiRouter.get("/favicon.ico", (_req, res) => {
@@ -58,7 +61,7 @@ webuiRouter.get("/webui/riven-tool/RivenParser.js", (_req, res) => {
58 61
59 62 // Serve translations
60 63 webuiRouter.get("/translations/:file", (req, res) => {
61 res.sendFile(path.join(rootDir, `static/webui/translations/${req.params.file}`));
64 res.sendFile(path.join(baseDir, `static/webui/translations/${req.params.file}`));
62 65 });
63 66
64 67 export { webuiRouter };
Modified src/services/configService.ts +2 -1
@@ -1,6 +1,7 @@
1 1 import fs from "fs";
2 2 import path from "path";
3 3 import { repoDir } from "@/src/helpers/pathHelper";
4 import { args } from "@/src/helpers/commandLineArguments";
4 5
5 6 export interface IConfig {
6 7 mongodbUrl: string;
@@ -79,7 +80,7 @@ export interface IConfig {
79 80 };
80 81 }
81 82
82 export const configPath = path.join(repoDir, process.argv[2] ?? "config.json");
83 export const configPath = path.join(repoDir, args.configPath ?? "config.json");
83 84
84 85 export const config: IConfig = {
85 86 mongodbUrl: "mongodb://127.0.0.1:27017/openWF",
Modified src/services/serversideVendorsService.ts +2 -2
@@ -1,5 +1,5 @@
1 1 import { unixTimesInMs } from "@/src/constants/timeConstants";
2 import { isDev } from "@/src/helpers/pathHelper";
2 import { args } from "@/src/helpers/commandLineArguments";
3 3 import { catBreadHash } from "@/src/helpers/stringHelpers";
4 4 import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
5 5 import { mixSeeds, SRng } from "@/src/services/rngService";
@@ -421,7 +421,7 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
421 421 return cacheEntry;
422 422 };
423 423
424 if (isDev) {
424 if (args.dev) {
425 425 if (
426 426 getCycleDuration(ExportVendors["/Lotus/Types/Game/VendorManifests/Hubs/TeshinHardModeVendorManifest"]) !=
427 427 unixTimesInMs.week
Modified static/webui/script.js +15 -2
@@ -1,3 +1,13 @@
1 /* eslint-disable @typescript-eslint/no-unsafe-return */
2 /* eslint-disable @typescript-eslint/no-floating-promises */
3 /* eslint-disable @typescript-eslint/no-unused-vars */
4 /* eslint-disable @typescript-eslint/no-unsafe-argument */
5 /* eslint-disable no-undef */
6 /* eslint-disable @typescript-eslint/no-unsafe-call */
7 /* eslint-disable @typescript-eslint/no-unsafe-assignment */
8 /* eslint-disable @typescript-eslint/no-unsafe-member-access */
9 /* eslint-disable @typescript-eslint/explicit-function-return-type */
10
1 11 function openWebSocket() {
2 12 window.ws = new WebSocket("/custom/ws");
3 13 window.ws.onmessage = e => {
@@ -64,6 +74,7 @@ function doLoginRequest(succ_cb, fail_cb) {
64 74 time: parseInt(new Date() / 1000),
65 75 s: "W0RFXVN0ZXZlIGxpa2VzIGJpZyBidXR0cw==", // signature of some kind
66 76 lang: "en",
77 // eslint-disable-next-line no-loss-of-precision
67 78 date: 1501230947855458660, // ???
68 79 ClientType: registerSubmit ? "webui-register" : "webui",
69 80 PS: "W0RFXVN0ZXZlIGxpa2VzIGJpZyBidXR0cw==" // anti-cheat data
@@ -1697,7 +1708,9 @@ function doAcquireRiven() {
1697 1708 if (typeof fingerprint !== "object") {
1698 1709 fingerprint = JSON.parse(fingerprint);
1699 1710 }
1700 } catch (e) {}
1711 } catch (e) {
1712 /* empty */
1713 }
1701 1714 if (
1702 1715 typeof fingerprint !== "object" ||
1703 1716 !("compat" in fingerprint) ||
@@ -1950,7 +1963,7 @@ function doAddAllMods() {
1950 1963 const req = $.get("/api/inventory.php?" + window.authz + "&xpBasedLevelCapDisabled=1");
1951 1964 req.done(data => {
1952 1965 for (const modOwned of data.RawUpgrades) {
1953 if (modOwned.ItemCount ?? 1 > 0) {
1966 if ((modOwned.ItemCount ?? 1) > 0) {
1954 1967 modsAll.delete(modOwned.ItemType);
1955 1968 }
1956 1969 }