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: 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
Sainan <63328889+Sainan@users.noreply.github.com>
提交于

代码差异

10 个文件 +54 -48
Added src/constants/gameToBuildVersionInt.ts +8 -0
@@ -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>;
Modified src/controllers/api/inboxController.ts +7 -11
@@ -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
Modified src/controllers/api/loginController.ts +20 -18
@@ -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)
Modified src/controllers/api/trainingResultController.ts +3 -8
@@ -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 }
Modified src/helpers/inventoryHelpers.ts +1 -0
@@ -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]
Added src/helpers/versionHelper.ts +8 -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 };
Modified src/services/configWatcherService.ts +3 -4
@@ -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 }
Modified src/services/inboxService.ts +1 -1
@@ -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,
Modified src/services/inventoryService.ts +2 -1
@@ -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;
Modified src/services/loginService.ts +1 -5
@@ -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 };