From 9af0e06b70b98d7c4edb1776871c63dee4fed85f Mon Sep 17 00:00:00 2001 From: Sainan <63328889+Sainan@users.noreply.github.com> Date: Wed, 18 Jun 2025 05:51:56 -0700 Subject: [PATCH] feat: add worldState.circuitGameModes config option (#2192) Closes #749 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/2192 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com> --- README.md | 1 + config.json.example | 3 ++- src/services/configService.ts | 1 + src/services/worldStateService.ts | 12 ++++++--- src/types/worldStateTypes.ts | 45 +++++++++++++++++++++++++++++++ 5 files changed, 57 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index e8d2b419..dc57e796 100644 --- a/README.md +++ b/README.md @@ -33,3 +33,4 @@ SpaceNinjaServer requires a `config.json`. To set it up, you can copy the [confi - `RadioLegion2Syndicate` for The Emissary - `RadioLegionIntermissionSyndicate` for Intermission I - `RadioLegionSyndicate` for The Wolf of Saturn Six +- `worldState.circuitGameModes` can be provided with an array of valid game modes (`Survival`, `VoidFlood`, `Excavation`, `Defense`, `Exterminate`, `Assassination`, `Alchemy`) diff --git a/config.json.example b/config.json.example index bf6eae91..8f839751 100644 --- a/config.json.example +++ b/config.json.example @@ -58,7 +58,8 @@ "starDays": true, "eidolonOverride": "", "vallisOverride": "", - "nightwaveOverride": "" + "nightwaveOverride": "", + "circuitGameModes": null }, "dev": { "keepVendorsExpired": false diff --git a/src/services/configService.ts b/src/services/configService.ts index 82cc4f31..fbcda8af 100644 --- a/src/services/configService.ts +++ b/src/services/configService.ts @@ -65,6 +65,7 @@ interface IConfig { eidolonOverride?: string; vallisOverride?: string; nightwaveOverride?: string; + circuitGameModes?: string[]; }; dev?: { keepVendorsExpired?: boolean; diff --git a/src/services/worldStateService.ts b/src/services/worldStateService.ts index a19abee5..5f2df857 100644 --- a/src/services/worldStateService.ts +++ b/src/services/worldStateService.ts @@ -16,8 +16,10 @@ import { ISortie, ISortieMission, ISyndicateMissionInfo, + ITmp, IVoidStorm, - IWorldState + IWorldState, + TCircuitGameMode } from "../types/worldStateTypes"; import { version_compare } from "../helpers/inventoryHelpers"; import { logger } from "../utils/logger"; @@ -1303,10 +1305,9 @@ export const getWorldState = (buildLabel?: string): IWorldState => { const cheeseInterval = hourInSeconds * 8; const cheeseDuration = hourInSeconds * 2; const cheeseIndex = Math.trunc(timeSecs / cheeseInterval); - const tmp = { + const tmp: ITmp = { cavabegin: "1690761600", PurchasePlatformLockEnabled: true, - tcsn: true, pgr: { ts: "1732572900", en: "CUSTOM DECALS @ ZEVILA", @@ -1330,10 +1331,13 @@ export const getWorldState = (buildLabel?: string): IWorldState => { fbst: { a: cheeseIndex * cheeseInterval, // This has a bug where the client shows a negative time for "Xtra cheese starts in ..." until it refreshes the world state. This is because we're only providing the new activation as soon as that time/date is reached. However, this is 100% faithful to live. e: cheeseIndex * cheeseInterval + cheeseDuration, - n: (cheeseIndex + 1) * hourInSeconds * 8 + n: (cheeseIndex + 1) * cheeseInterval }, sfn: [550, 553, 554, 555][halfHour % 4] }; + if (Array.isArray(config.worldState?.circuitGameModes)) { + tmp.edg = config.worldState.circuitGameModes as TCircuitGameMode[]; + } worldState.Tmp = JSON.stringify(tmp); return worldState; diff --git a/src/types/worldStateTypes.ts b/src/types/worldStateTypes.ts index 880c5800..bd8ab138 100644 --- a/src/types/worldStateTypes.ts +++ b/src/types/worldStateTypes.ts @@ -191,3 +191,48 @@ export interface ICalendarEvent { dialogueName?: string; dialogueConvo?: string; } + +export type TCircuitGameMode = + | "Survival" + | "VoidFlood" + | "Excavation" + | "Defense" + | "Exterminate" + | "Assassination" + | "Alchemy"; + +export interface ITmp { + cavabegin: string; + PurchasePlatformLockEnabled: boolean; // Seems unused + pgr: IPgr; + ennnd?: boolean; // True if 1999 demo is available (no effect for >=38.6.0) + mbrt?: boolean; // Related to mobile app rating request + fbst: IFbst; + sfn: number; + edg?: TCircuitGameMode[]; // The Circuit game modes overwrite +} + +interface IPgr { + ts: string; + en: string; + fr: string; + it: string; + de: string; + es: string; + pt: string; + ru: string; + pl: string; + uk: string; + tr: string; + ja: string; + zh: string; + ko: string; + tc: string; + th: string; +} + +interface IFbst { + a: number; + e: number; + n: number; +}