feat: add worldState.circuitGameModes config option (#2192)
Some checks failed
Build Docker image / docker (push) Waiting to run
Build / build (push) Has been cancelled

Closes #749

Reviewed-on: #2192
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
This commit is contained in:
Sainan 2025-06-18 05:51:56 -07:00 committed by Sainan
parent f8d0c9e0cb
commit 9af0e06b70
5 changed files with 57 additions and 5 deletions

View File

@ -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`)

View File

@ -58,7 +58,8 @@
"starDays": true,
"eidolonOverride": "",
"vallisOverride": "",
"nightwaveOverride": ""
"nightwaveOverride": "",
"circuitGameModes": null
},
"dev": {
"keepVendorsExpired": false

View File

@ -65,6 +65,7 @@ interface IConfig {
eidolonOverride?: string;
vallisOverride?: string;
nightwaveOverride?: string;
circuitGameModes?: string[];
};
dev?: {
keepVendorsExpired?: boolean;

View File

@ -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;

View File

@ -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;
}