返回提交历史
Modified
src/constants/gameToBuildVersion.ts
+4
-0
Modified
src/services/worldStateService.ts
+69
-56
XFEstudio/SpaceNinjaServer
chore: more version checks in worldstate (#4267)
Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/4267 Reviewed-by: Sainan <63328889+sainan@users.noreply.github.com> Co-authored-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com> Co-committed-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
51e421a5
代码差异
2 个文件
+73
-56
@@ -9,8 +9,10 @@ const gameToBuildVersion = {
9
9
"38.5.11": "2025.04.15.15.16",
10
10
"38.5.0": "2025.03.14.10.56",
11
11
"38.0.8": "2025.02.05.11.19",
12
"38.0.0": "2024.12.11.14.26",
12
13
"37.0.0": "2024.09.30.16.56",
13
14
"36.1.2": "2024.08.21.20.02",
15
"36.0.0": "2024.06.12.18.42",
14
16
"35.6.0": "2024.05.15.11.07",
15
17
"35.5.9": "2024.04.29.11.14",
16
18
"35.5.0": "2024.03.24.20.00",
@@ -32,6 +34,7 @@ const gameToBuildVersion = {
32
34
"29.0.0": "2020.08.25.18.35",
33
35
"28.3.0": "2020.08.12.19.57",
34
36
"28.0.0": "2020.06.12.16.46",
37
"27.3.0": "2020.03.24.20.24",
35
38
"27.2.0": "2020.03.05.16.06",
36
39
"26.0.0": "2019.10.31.22.42",
37
40
"25.7.0": "2019.08.29.20.01",
@@ -63,6 +66,7 @@ const gameToBuildVersion = {
63
66
"16.5.5": "2015.05.14.16.29",
64
67
"16.0.2": "2015.03.21.08.17",
65
68
"15.14.1": "2015.02.13.10.41",
69
"15.5.0": "2014.11.27.14.35",
66
70
"15.0.6": "2014.10.27.17.07",
67
71
"15.0.0": "2014.10.24.08.24",
68
72
"14.0.0": "2014.07.21.18.38",
@@ -2266,8 +2266,7 @@ export const getWorldState = (
2266
2266
});
2267
2267
}
2268
2268
2269
// < U38.6.0
2270
if (version_compare(buildLabel, "2025.05.20.10.18") >= 0) {
2269
if (version_compare(buildLabel, gameToBuildVersion["38.6.0"]) >= 0) {
2271
2270
// The client gets kinda confused when multiple goals have the same tag, so considering these mutually exclusive.
2272
2271
if (config.worldState?.galleonOfGhouls == 1) {
2273
2272
worldState.Goals.push({
@@ -3439,7 +3438,7 @@ export const getWorldState = (
3439
3438
pushFlashSales(worldState, storeItems, activation, expiry, "SEASONAL", buildLabel);
3440
3439
}
3441
3440
3442
if (config.worldState?.bellyOfTheBeast && version_compare(buildLabel, "2024.06.12.18.42") >= 0) {
3441
if (config.worldState?.bellyOfTheBeast && version_compare(buildLabel, gameToBuildVersion["36.0.0"]) >= 0) {
3443
3442
worldState.Goals.push({
3444
3443
_id: toOid2("67a5035c2a198564d62e165e", buildLabel),
3445
3444
Activation: toMongoDate2(1738868400000, buildLabel),
@@ -3487,7 +3486,7 @@ export const getWorldState = (
3487
3486
}
3488
3487
3489
3488
// <U39
3490
if (config.worldState?.eightClaw && version_compare(buildLabel, "2025.06.23.11.39") >= 0) {
3489
if (config.worldState?.eightClaw && version_compare(buildLabel, gameToBuildVersion["39.0.0"]) >= 0) {
3491
3490
worldState.Goals.push({
3492
3491
_id: toOid2("685c15f80000000000000000", buildLabel),
3493
3492
Activation: toMongoDate2(1750865400000, buildLabel),
@@ -3509,7 +3508,7 @@ export const getWorldState = (
3509
3508
});
3510
3509
}
3511
3510
3512
if (config.worldState?.scarletSpear) {
3511
if (config.worldState?.scarletSpear && version_compare(buildLabel, gameToBuildVersion["27.3.0"]) >= 0) {
3513
3512
worldState.Goals.push({
3514
3513
_id: toOid2("5e7a3e2389e3090b0c6a998b", buildLabel),
3515
3514
Activation: {
@@ -4051,39 +4050,45 @@ export const getWorldState = (
4051
4050
do {
4052
4051
const bountyCycleStart = Math.trunc((bountyEpoch + bountyCycle * eidolonCycleDuration) * 1000);
4053
4052
bountyCycleEnd = Math.trunc(bountyCycleStart + eidolonCycleDuration * 1000);
4054
worldState.SyndicateMissions.push({
4055
_id: toOid2(
4056
((bountyCycleStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + "0000000000000029",
4057
buildLabel
4058
),
4059
Activation: toMongoDate2(bountyCycleStart, buildLabel),
4060
Expiry: toMongoDate2(bountyCycleEnd, buildLabel),
4061
Tag: "ZarimanSyndicate",
4062
Seed: bountyCycle,
4063
Nodes: []
4064
});
4065
worldState.SyndicateMissions.push({
4066
_id: toOid2(
4067
((bountyCycleStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + "0000000000000004",
4068
buildLabel
4069
),
4070
Activation: toMongoDate2(bountyCycleStart, buildLabel),
4071
Expiry: toMongoDate2(bountyCycleEnd, buildLabel),
4072
Tag: "EntratiLabSyndicate",
4073
Seed: bountyCycle,
4074
Nodes: []
4075
});
4076
worldState.SyndicateMissions.push({
4077
_id: toOid2(
4078
((bountyCycleStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + "0000000000000006",
4079
buildLabel
4080
),
4081
Activation: toMongoDate2(bountyCycleStart, buildLabel),
4082
Expiry: toMongoDate2(bountyCycleEnd, buildLabel),
4083
Tag: "HexSyndicate",
4084
Seed: bountyCycle,
4085
Nodes: []
4086
});
4053
if (version_compare(buildLabel, gameToBuildVersion["29.0.0"]) >= 0) {
4054
worldState.SyndicateMissions.push({
4055
_id: toOid2(
4056
((bountyCycleStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + "0000000000000004",
4057
buildLabel
4058
),
4059
Activation: toMongoDate2(bountyCycleStart, buildLabel),
4060
Expiry: toMongoDate2(bountyCycleEnd, buildLabel),
4061
Tag: "EntratiLabSyndicate",
4062
Seed: bountyCycle,
4063
Nodes: []
4064
});
4065
}
4066
if (version_compare(buildLabel, gameToBuildVersion["31.5.0"]) >= 0) {
4067
worldState.SyndicateMissions.push({
4068
_id: toOid2(
4069
((bountyCycleStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + "0000000000000029",
4070
buildLabel
4071
),
4072
Activation: toMongoDate2(bountyCycleStart, buildLabel),
4073
Expiry: toMongoDate2(bountyCycleEnd, buildLabel),
4074
Tag: "ZarimanSyndicate",
4075
Seed: bountyCycle,
4076
Nodes: []
4077
});
4078
}
4079
if (version_compare(buildLabel, gameToBuildVersion["38.0.0"]) >= 0) {
4080
worldState.SyndicateMissions.push({
4081
_id: toOid2(
4082
((bountyCycleStart / 1000) & 0xffffffff).toString(16).padStart(8, "0") + "0000000000000006",
4083
buildLabel
4084
),
4085
Activation: toMongoDate2(bountyCycleStart, buildLabel),
4086
Expiry: toMongoDate2(bountyCycleEnd, buildLabel),
4087
Tag: "HexSyndicate",
4088
Seed: bountyCycle,
4089
Nodes: []
4090
});
4091
}
4087
4092
4088
4093
pushClassicBounties(worldState.SyndicateMissions, bountyCycle, buildLabel);
4089
4094
} while (isBeforeNextExpectedWorldStateRefresh(timeMs, bountyCycleEnd) && ++bountyCycle);
@@ -4270,7 +4275,8 @@ export const getWorldState = (
4270
4275
}
4271
4276
4272
4277
// Baro
4273
{
4278
// Introdused in U15.6
4279
if (version_compare(buildLabel, gameToBuildVersion["15.5.0"]) > 0) {
4274
4280
const baroIndex = Math.trunc((Date.now() - 910800000) / (unixTimesInMs.day * 14));
4275
4281
const baroStart = baroIndex * (unixTimesInMs.day * 14) + 910800000;
4276
4282
const baroActualStart = baroStart + unixTimesInMs.day * (config.worldState?.baroAlwaysAvailable ? 0 : 12);
@@ -4387,19 +4393,21 @@ export const getWorldState = (
4387
4393
}
4388
4394
4389
4395
// Void Storms
4390
const hour = Math.trunc(timeMs / unixTimesInMs.hour);
4391
const overLastHourStormExpiry = hour * unixTimesInMs.hour + 10 * unixTimesInMs.minute;
4392
const thisHourStormActivation = hour * unixTimesInMs.hour + 40 * unixTimesInMs.minute;
4393
if (overLastHourStormExpiry > timeMs) {
4394
pushVoidStorms(worldState.VoidStorms, hour - 2);
4395
}
4396
pushVoidStorms(worldState.VoidStorms, hour - 1);
4397
if (isBeforeNextExpectedWorldStateRefresh(timeMs, thisHourStormActivation)) {
4398
pushVoidStorms(worldState.VoidStorms, hour);
4396
if (version_compare(buildLabel, gameToBuildVersion["30.0.0"]) >= 0) {
4397
const hour = Math.trunc(timeMs / unixTimesInMs.hour);
4398
const overLastHourStormExpiry = hour * unixTimesInMs.hour + 10 * unixTimesInMs.minute;
4399
const thisHourStormActivation = hour * unixTimesInMs.hour + 40 * unixTimesInMs.minute;
4400
if (overLastHourStormExpiry > timeMs) {
4401
pushVoidStorms(worldState.VoidStorms, hour - 2);
4402
}
4403
pushVoidStorms(worldState.VoidStorms, hour - 1);
4404
if (isBeforeNextExpectedWorldStateRefresh(timeMs, thisHourStormActivation)) {
4405
pushVoidStorms(worldState.VoidStorms, hour);
4406
}
4399
4407
}
4400
4408
4401
4409
// Sortie & syndicate missions cycling every day (at 16:00 or 17:00 UTC depending on if London, OT is observing DST)
4402
{
4410
if (version_compare(buildLabel, gameToBuildVersion["15.0.0"]) >= 0) {
4403
4411
const rollover = getSortieTime(day);
4404
4412
4405
4413
// Omit sorties for pre-Star Chart 3.0 clients to avoid breaking them.
@@ -4503,9 +4511,11 @@ export const getWorldState = (
4503
4511
}
4504
4512
4505
4513
// Archon Hunt cycling every week
4506
worldState.LiteSorties.push(getLiteSortie(week));
4507
if (isBeforeNextExpectedWorldStateRefresh(timeMs, weekEnd)) {
4508
worldState.LiteSorties.push(getLiteSortie(week + 1));
4514
if (version_compare(buildLabel, gameToBuildVersion["32.0.0"]) >= 0) {
4515
worldState.LiteSorties.push(getLiteSortie(week));
4516
if (isBeforeNextExpectedWorldStateRefresh(timeMs, weekEnd)) {
4517
worldState.LiteSorties.push(getLiteSortie(week + 1));
4518
}
4509
4519
}
4510
4520
4511
4521
// Circuit choices cycling every week
@@ -4524,14 +4534,16 @@ export const getWorldState = (
4524
4534
CategoryChoices: getEndlessXpChoices(week + 1)
4525
4535
});
4526
4536
}
4527
} else {
4537
} else if (version_compare(buildLabel, gameToBuildVersion["33.0.0"]) >= 0) {
4528
4538
worldState.EndlessXpChoices = getEndlessXpChoices(week);
4529
4539
}
4530
4540
4531
4541
// 1999 Calendar Season cycling every week + YearIteration every 4 weeks
4532
worldState.KnownCalendarSeasons.push(getCalendarSeason(week));
4533
if (isBeforeNextExpectedWorldStateRefresh(timeMs, weekEnd)) {
4534
worldState.KnownCalendarSeasons.push(getCalendarSeason(week + 1));
4542
if (version_compare(buildLabel, gameToBuildVersion["38.0.0"]) >= 0) {
4543
worldState.KnownCalendarSeasons.push(getCalendarSeason(week));
4544
if (isBeforeNextExpectedWorldStateRefresh(timeMs, weekEnd)) {
4545
worldState.KnownCalendarSeasons.push(getCalendarSeason(week + 1));
4546
}
4535
4547
}
4536
4548
4537
4549
const season = (["CST_WINTER", "CST_SPRING", "CST_SUMMER", "CST_FALL"] as const)[week % 4];
@@ -4725,6 +4737,7 @@ const convertGoalsToV9 = (goals: IGoal[]): void => {
4725
4737
};
4726
4738
4727
4739
export const populateFissures = async (worldState: IWorldState): Promise<void> => {
4740
if (version_compare(worldState.BuildLabel, gameToBuildVersion["18.16.0"]) < 0) return;
4728
4741
if (config.worldState?.allTheFissures) {
4729
4742
let i = 0;
4730
4743
for (const [tier, nodes] of Object.entries(fissureMissions)) {