返回提交历史
Added
src/constants/gameToBuildVersionInt.ts
+8
-0
Modified
src/controllers/api/inboxController.ts
+7
-11
Modified
src/controllers/api/loginController.ts
+20
-18
Modified
src/controllers/api/trainingResultController.ts
+3
-8
Modified
src/helpers/inventoryHelpers.ts
+1
-0
Added
src/helpers/versionHelper.ts
+8
-0
Modified
src/services/configWatcherService.ts
+3
-4
Modified
src/services/inboxService.ts
+1
-1
Modified
src/services/inventoryService.ts
+2
-1
Modified
src/services/loginService.ts
+1
-5
XFEstudio/XFESpaceNinjaServer
chore: initial usage of integers for version comparisons (#4269)
This is only really useful in cases where version_compare is otherwise used excessively, such as createLoginResponse, which I have converted here. worldState would also be a good candidate which can be converted later. Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/4269 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
fc1a815a
代码差异
10 个文件
+54
-48
@@ -0,0 +1,8 @@
1
import { buildVersionToInt } from "../helpers/versionHelper.ts";
2
import gameToBuildVersion from "./gameToBuildVersion.ts";
3
4
const gameToBuildVersionInt: Record<string, number> = {};
5
for (const [gameVersion, buildVersion] of Object.entries(gameToBuildVersion)) {
6
gameToBuildVersionInt[gameVersion] = buildVersionToInt(buildVersion);
7
}
8
export default gameToBuildVersionInt as Record<keyof typeof gameToBuildVersion, number>;
@@ -11,7 +11,6 @@ import {
11
11
type IMessageCreationTemplate
12
12
} from "../../services/inboxService.ts";
13
13
import {
14
buildVersionToInt,
15
14
getAccountForRequest,
16
15
getAccountFromSuffixedName,
17
16
getBuildLabel,
@@ -34,8 +33,8 @@ import type { IOid } from "../../types/commonTypes.ts";
34
33
import { unixTimesInMs } from "../../constants/timeConstants.ts";
35
34
import { config } from "../../services/configService.ts";
36
35
import { Types } from "mongoose";
37
import gameToBuildVersion from "../../constants/gameToBuildVersion.ts";
38
36
import type { IInventoryChanges } from "../../types/purchaseTypes.ts";
37
import gameToBuildVersionInt from "../../constants/gameToBuildVersionInt.ts";
39
38
40
39
export const inboxController: RequestHandler = async (req, res) => {
41
40
const { deleteId, lastMessage: latestClientMessageId, messageId } = req.query;
@@ -198,10 +197,7 @@ const createNewEventMessages = async (account: TAccountDocument): Promise<void>
198
197
}
199
198
],
200
199
date: new Date(baroActualStart),
201
minBuildVersion:
202
evilBaroStage > 0
203
? buildVersionToInt(gameToBuildVersion["40.0.0"])
204
: buildVersionToInt(gameToBuildVersion["18.18.0"]) // Baro was introduced in U15.6. Unclear when exactly this inbox message was introduced, tho.
200
minBuildVersion: evilBaroStage > 0 ? gameToBuildVersionInt["40.0.0"] : gameToBuildVersionInt["18.18.0"] // Baro was introduced in U15.6. Unclear when exactly this inbox message was introduced, tho.
205
201
});
206
202
}
207
203
if (Date.now() >= prevBaroEnd && account.LatestEventMessageDate.getTime() < prevBaroEnd && evilBaroStage == 4) {
@@ -216,7 +212,7 @@ const createNewEventMessages = async (account: TAccountDocument): Promise<void>
216
212
att: ["/Lotus/Types/StoreItems/AvatarImages/ImageBaroKiteerEvil"],
217
213
CrossPlatform: true,
218
214
date: new Date(prevBaroEnd),
219
minBuildVersion: buildVersionToInt(gameToBuildVersion["40.0.0"])
215
minBuildVersion: gameToBuildVersionInt["40.0.0"]
220
216
});
221
217
}
222
218
@@ -267,7 +263,7 @@ const createNewEventMessages = async (account: TAccountDocument): Promise<void>
267
263
att: ["/Lotus/Upgrades/Skins/Events/OgrisOldSchool"],
268
264
startDate: new Date(),
269
265
goalTag: "GalleonRobbery",
270
minBuildVersion: buildVersionToInt(gameToBuildVersion["38.5.11"])
266
minBuildVersion: gameToBuildVersionInt["38.5.11"]
271
267
});
272
268
}
273
269
if (config.worldState?.bloodOfPerita && !account.receivedEventMessage_bloodOfPerita) {
@@ -280,7 +276,7 @@ const createNewEventMessages = async (account: TAccountDocument): Promise<void>
280
276
startDate: new Date(),
281
277
transmission: "/Lotus/Sounds/Dialog/Tau/RoatheEventOutroInbox/DRoatheEventIntroInbox0010Roathe",
282
278
QuestReq: "/Lotus/Types/Keys/TauPrequel/TauPrequelQuestKeyChain",
283
minBuildVersion: buildVersionToInt(gameToBuildVersion["41.0.0"])
279
minBuildVersion: gameToBuildVersionInt["41.0.0"]
284
280
});
285
281
}
286
282
if (config.worldState?.longShadow && !account.receivedEventMessage_longShadow) {
@@ -305,7 +301,7 @@ const createNewEventMessages = async (account: TAccountDocument): Promise<void>
305
301
startDate: new Date(),
306
302
QuestReq: "/Lotus/Types/Keys/PriestFrameQuest/PriestQuestKeyChain",
307
303
CrossPlatform: true,
308
minBuildVersion: buildVersionToInt(gameToBuildVersion["42.0.0"])
304
minBuildVersion: gameToBuildVersionInt["42.0.0"]
309
305
});
310
306
}
311
307
if (config.worldState?.breedingGrounds && !account.receivedEventMessage_breedingGrounds) {
@@ -317,7 +313,7 @@ const createNewEventMessages = async (account: TAccountDocument): Promise<void>
317
313
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
318
314
startDate: new Date(),
319
315
CrossPlatform: true,
320
minBuildVersion: buildVersionToInt(gameToBuildVersion["14.0.0"])
316
minBuildVersion: gameToBuildVersionInt["14.0.0"]
321
317
});
322
318
}
323
319
@@ -4,7 +4,6 @@ import { config, getReflexiveAddress } from "../../services/configService.ts";
4
4
5
5
import { Account } from "../../models/loginModel.ts";
6
6
import {
7
buildVersionToInt,
8
7
createAccount,
9
8
createNonce,
10
9
getBuildLabelForUnauthenticatedRequest,
@@ -28,6 +27,8 @@ import { getTokenForClient, getTunablesForClient } from "../../services/tunables
28
27
import type { AddressInfo } from "node:net";
29
28
import gameToBuildVersion from "../../constants/gameToBuildVersion.ts";
30
29
import { args } from "../../helpers/commandLineArguments.ts";
30
import { buildLabelToVersionInt } from "../../helpers/versionHelper.ts";
31
import gameToBuildVersionInt from "../../constants/gameToBuildVersionInt.ts";
31
32
32
33
export const loginController: RequestHandler = async (request, response) => {
33
34
const loginRequest = JSON.parse(String(request.body)) as ILoginRequest; // parse octet stream of json data to json object
@@ -173,10 +174,11 @@ const createLoginResponse = (request: Request, account: IDatabaseAccountJson, bu
173
174
DisplayName: account.DisplayName,
174
175
Nonce: account.Nonce
175
176
};
176
if (version_compare(buildLabel, gameToBuildVersion["7.3.0"]) >= 0) {
177
const buildVersionInt = buildLabelToVersionInt(buildLabel);
178
if (buildVersionInt >= gameToBuildVersionInt["7.3.0"]) {
177
179
resp.BuildLabel = buildLabel; // U5 no likey
178
180
}
179
if (version_compare(buildLabel, gameToBuildVersion["12.5.2"]) >= 0) {
181
if (buildVersionInt >= gameToBuildVersionInt["12.5.2"]) {
180
182
// U12.5 and up
181
183
182
184
// CountryCode should be based on the IP address so the client can pick a good matchmaking region automatically.
@@ -192,28 +194,28 @@ const createLoginResponse = (request: Request, account: IDatabaseAccountJson, bu
192
194
.join("")
193
195
.padEnd(128, "0");
194
196
195
if (version_compare(buildLabel, gameToBuildVersion["7.3.0"]) >= 0) {
197
if (buildVersionInt >= gameToBuildVersionInt["7.3.0"]) {
196
198
resp.SteamId = "0"; // U5 no likey
197
199
}
198
200
}
199
if (version_compare(buildLabel, gameToBuildVersion["15.14.1"]) >= 0) {
201
if (buildVersionInt >= gameToBuildVersionInt["15.14.1"]) {
200
202
resp.NRS = (config.nrsAddresses ?? []).map(x => x.replaceAll("%THIS_MACHINE%", myAddress));
201
203
// U16 ~ U28 are known to show an "Internal error." popup with an empty array.
202
if (resp.NRS.length == 0 && version_compare(buildLabel, gameToBuildVersion["29.0.0"]) < 0) {
204
if (resp.NRS.length == 0 && buildVersionInt < gameToBuildVersionInt["29.0.0"]) {
203
205
resp.NRS.push(myAddress);
204
206
}
205
207
}
206
if (version_compare(buildLabel, gameToBuildVersion["16.5.5"]) >= 0) {
208
if (buildVersionInt >= gameToBuildVersionInt["16.5.5"]) {
207
209
resp.IRC = [(config.ircAddress || "%THIS_MACHINE%").replaceAll("%THIS_MACHINE%", myAddress)];
208
210
}
209
if (version_compare(buildLabel, gameToBuildVersion["24.0.0"]) >= 0) {
211
if (buildVersionInt >= gameToBuildVersionInt["24.0.0"]) {
210
212
resp.ConsentNeeded = false;
211
213
resp.TrackedSettings = [];
212
214
}
213
if (version_compare(buildLabel, gameToBuildVersion["25.7.0"]) >= 0) {
215
if (buildVersionInt >= gameToBuildVersionInt["25.7.0"]) {
214
216
resp.ForceLogoutVersion = 0;
215
217
}
216
if (version_compare(buildLabel, gameToBuildVersion["26.0.0"]) >= 0) {
218
if (buildVersionInt >= gameToBuildVersionInt["26.0.0"]) {
217
219
// Example values from live:
218
220
// - [{"experiment":"landingPageAB2368","experimentGroup":"control"},{"experiment":"InGameMarketRelatedItemsData","experimentGroup":"related_items_priority_control"},{"experiment":"GamesightAB","experimentGroup":"b"}]
219
221
// - [{"experiment":"LandingPageAB2368","experimentGroup":"control"},{"experiment":"GamesightAB","experimentGroup":"b"},{"experiment":"InGameMarketRelatedItemsData","experimentGroup":"related_items_priority_control"},{"experiment":"InGameMarketRelatedItemsDisplay","experimentGroup":"related_items_preview_control"},{"experiment":"ConsoleBonusPlatLowGDP","experimentGroup":"LowGDP_FewerLargerBonuses"}]
@@ -227,24 +229,24 @@ const createLoginResponse = (request: Request, account: IDatabaseAccountJson, bu
227
229
//{ experiment: "quick_buy_visible", experimentGroup: "quick_buy_visible" } // Shows "quick buy" market section for MR 4+ players
228
230
];
229
231
}
230
if (version_compare(buildLabel, gameToBuildVersion["30.0.0"]) >= 0) {
232
if (buildVersionInt >= gameToBuildVersionInt["30.0.0"]) {
231
233
resp.DTLS = config.dtls ?? 0; // bit 0 enables DTLS. if enabled, additional bits can be set, e.g. bit 2 to enable logging. on live, the value is 99.
232
234
}
233
if (version_compare(buildLabel, gameToBuildVersion["31.5.0"]) >= 0) {
235
if (buildVersionInt >= gameToBuildVersionInt["31.5.0"]) {
234
236
resp.ClientType = account.ClientType;
235
237
}
236
if (version_compare(buildLabel, gameToBuildVersion["32.0.0"]) >= 0) {
238
if (buildVersionInt >= gameToBuildVersionInt["32.0.0"]) {
237
239
resp.CrossPlatformAllowed = true;
238
240
resp.HUB = `${myUrlBase}/api/`;
239
241
240
242
// The MatchmakingBuildId is a 64-bit integer represented as a decimal string. On live, the value is seemingly random per build, but really any value that is different across builds should work.
241
resp.MatchmakingBuildId = buildVersionToInt(buildLabel).toString();
243
resp.MatchmakingBuildId = buildVersionInt.toString();
242
244
}
243
if (version_compare(buildLabel, gameToBuildVersion["33.0.0"]) >= 0) {
244
if (version_compare(buildLabel, gameToBuildVersion["40.0.0"]) >= 0) {
245
if (buildVersionInt >= gameToBuildVersionInt["33.0.0"]) {
246
if (buildVersionInt >= gameToBuildVersionInt["40.0.0"]) {
245
247
// U40 is when they changed this from content.warframe.com/dynamic/ to api.warframe.com/cdn/
246
248
resp.platformCDNs = [`${myUrlBase}/cdn/`];
247
} else if (version_compare(buildLabel, gameToBuildVersion["39.1.0"]) >= 0) {
249
} else if (buildVersionInt >= gameToBuildVersionInt["39.1.0"]) {
248
250
// U39.1 is when they made dynamic/ explicit
249
251
resp.platformCDNs = [`${myUrlBase}/dynamic/`];
250
252
} else {
@@ -252,7 +254,7 @@ const createLoginResponse = (request: Request, account: IDatabaseAccountJson, bu
252
254
resp.platformCDNs = [`${myUrlBase}/`];
253
255
}
254
256
}
255
if (version_compare(buildLabel, gameToBuildVersion["42.0.0"]) >= 0) {
257
if (buildVersionInt >= gameToBuildVersionInt["42.0.0"]) {
256
258
resp.Token =
257
259
Math.trunc(Date.now() / 1000)
258
260
.toString(16)
@@ -1,9 +1,4 @@
1
import {
2
buildVersionToInt,
3
getAccountForRequest,
4
getBuildLabel,
5
type TAccountDocument
6
} from "../../services/loginService.ts";
1
import { getAccountForRequest, getBuildLabel, type TAccountDocument } from "../../services/loginService.ts";
7
2
import { getJSONfromString } from "../../helpers/stringHelpers.ts";
8
3
import { getInventory } from "../../services/inventoryService.ts";
9
4
import type { IMongoDateWithLegacySupport } from "../../types/commonTypes.ts";
@@ -12,8 +7,8 @@ import { unixTimesInMs } from "../../constants/timeConstants.ts";
12
7
import type { IInventoryChanges } from "../../types/purchaseTypes.ts";
13
8
import { createMessage } from "../../services/inboxService.ts";
14
9
import { toMongoDate2 } from "../../helpers/inventoryHelpers.ts";
15
import gameToBuildVersion from "../../constants/gameToBuildVersion.ts";
16
10
import { config } from "../../services/configService.ts";
11
import gameToBuildVersionInt from "../../constants/gameToBuildVersionInt.ts";
17
12
18
13
interface ITrainingResultsRequest {
19
14
numLevelsGained: number;
@@ -74,7 +69,7 @@ const handleTrainingProgress = async (
74
69
sub: "/Lotus/Language/Inbox/MasteryRewardTitle",
75
70
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
76
71
highPriority: true,
77
minBuildVersion: buildVersionToInt(gameToBuildVersion["29.5.0"])
72
minBuildVersion: gameToBuildVersionInt["29.5.0"]
78
73
}
79
74
]);
80
75
}
@@ -5,6 +5,7 @@ import type { IFusionTreasure } from "../types/inventoryTypes/inventoryTypes.ts"
5
5
import type { IColor } from "../types/inventoryTypes/commonInventoryTypes.ts";
6
6
import gameToBuildVersion from "../constants/gameToBuildVersion.ts";
7
7
8
// TODO: Move to versionHelper?
8
9
export const version_compare = (a: string, b: string): number => {
9
10
const a_digits = a
10
11
.split("/")[0]
@@ -0,0 +1,8 @@
1
export const buildVersionToInt = (buildVersion: string): number => {
2
const [year, month, day, hour, minute] = buildVersion.split(".").map(x => parseInt(x));
3
return year * 1_00_00_00_00 + month * 1_00_00_00 + day * 1_00_00 + hour * 1_00 + minute;
4
};
5
6
export const buildLabelToVersionInt = (buildLabel: string): number => {
7
return buildVersionToInt(buildLabel.split("/")[0]);
8
};
@@ -24,8 +24,7 @@ import { getTunablesForClient } from "./tunablesService.ts";
24
24
import { Account } from "../models/loginModel.ts";
25
25
import { Inbox } from "../models/inboxModel.ts";
26
26
import { createMessage } from "./inboxService.ts";
27
import { buildVersionToInt } from "./loginService.ts";
28
import gameToBuildVersion from "../constants/gameToBuildVersion.ts";
27
import gameToBuildVersionInt from "../constants/gameToBuildVersionInt.ts";
29
28
30
29
chokidar.watch(configPath).on("change", () => {
31
30
if (shouldReloadConfig()) {
@@ -272,7 +271,7 @@ export const syncConfigWithDatabase = (): void => {
272
271
// startDate & endDate would be present with the event dates but MongoDB would delete the message if we set an endDate in the past.
273
272
transmission: "/Lotus/Sounds/Dialog/Tau/RoatheEventOutroInbox/DRoatheEventOutroInbox0020Roathe",
274
273
QuestReq: "/Lotus/Types/Keys/TauPrequel/TauPrequelQuestKeyChain",
275
minBuildVersion: buildVersionToInt(gameToBuildVersion["41.0.0"])
274
minBuildVersion: gameToBuildVersionInt["41.0.0"]
276
275
}
277
276
]);
278
277
}
@@ -296,7 +295,7 @@ export const syncConfigWithDatabase = (): void => {
296
295
QuestReq: "/Lotus/Types/Keys/PriestFrameQuest/PriestQuestKeyChain",
297
296
att: ["/Lotus/Types/Items/ShipDecos/Props/ShadowgrapherEaselShipDeco"],
298
297
CrossPlatform: true,
299
minBuildVersion: buildVersionToInt(gameToBuildVersion["42.0.0"])
298
minBuildVersion: gameToBuildVersionInt["42.0.0"]
300
299
}
301
300
]);
302
301
}
@@ -3,7 +3,7 @@ import type { IMessageClient, IMessageDatabase } from "../types/inboxTypes.ts";
3
3
import type { TMessageDocument } from "../models/inboxModel.ts";
4
4
import { Inbox } from "../models/inboxModel.ts";
5
5
import type { QueryFilter, Types } from "mongoose";
6
import { buildVersionToInt } from "./loginService.ts";
6
import { buildVersionToInt } from "../helpers/versionHelper.ts";
7
7
8
8
export const getInboxFilter = (
9
9
accountId: string | Types.ObjectId,
@@ -107,7 +107,7 @@ import { getNightwaveSyndicateTag, getWorldState } from "./worldStateService.ts"
107
107
import type { ICalendarSeason } from "../types/worldStateTypes.ts";
108
108
import type { INemesisProfile } from "../helpers/nemesisHelpers.ts";
109
109
import { generateNemesisProfile } from "../helpers/nemesisHelpers.ts";
110
import { buildVersionToInt, type TAccountDocument } from "./loginService.ts";
110
import { type TAccountDocument } from "./loginService.ts";
111
111
import { KAHL_EPOCH, unixTimesInMs } from "../constants/timeConstants.ts";
112
112
import { addString } from "../helpers/stringHelpers.ts";
113
113
import type {
@@ -128,6 +128,7 @@ import kuriaMessage100 from "../../static/fixed_responses/kuriaMessages/oneHundr
128
128
import { BL_LATEST } from "../constants/gameVersions.ts";
129
129
import { Guild } from "../models/guildModel.ts";
130
130
import { handleGuildGoalProgress } from "./guildService.ts";
131
import { buildVersionToInt } from "../helpers/versionHelper.ts";
131
132
132
133
type OperatorAntiqueMeta = {
133
134
focusAbility: string;
@@ -86,6 +86,7 @@ const createPersonalRooms = async (accountId: Types.ObjectId, shipId: Types.Obje
86
86
await personalRooms.save();
87
87
};
88
88
89
// TODO: Move to loginModel
89
90
export type TAccountDocument = Document<unknown, {}, IDatabaseAccountJson> &
90
91
IDatabaseAccountJson & { _id: Types.ObjectId; __v: number };
91
92
@@ -246,8 +247,3 @@ export const stripUnicodeSuffix = (name: string): string => {
246
247
}
247
248
return name;
248
249
};
249
250
export const buildVersionToInt = (buildVersion: string): number => {
251
const [year, month, day, hour, minute] = buildVersion.split(".").map(x => parseInt(x));
252
return year * 1_00_00_00_00 + month * 1_00_00_00 + day * 1_00_00 + hour * 1_00 + minute;
253
};