返回提交历史
Modified
package-lock.json
+4
-4
Modified
package.json
+1
-1
Modified
src/controllers/api/inventoryController.ts
+1
-1
Modified
src/controllers/api/modularWeaponCraftingController.ts
+1
-1
Modified
src/controllers/custom/getItemListsController.ts
+1
-1
Modified
src/services/inventoryService.ts
+2
-2
Modified
src/services/itemDataService.ts
+40
-37
Modified
src/services/missionInventoryUpdateService.ts
+5
-5
Modified
src/services/purchaseService.ts
+1
-1
Modified
src/services/rngService.ts
+4
-4
Modified
src/services/worldStateService.ts
+1
-1
Modified
src/types/inboxTypes.ts
+2
-2
Modified
src/types/publicExportTypes.ts
+14
-14
Modified
src/types/worldStateTypes.ts
+1
-1
Modified
src/utils/ts-utils.ts
+4
-0
XFEstudio/XFESpaceNinjaServer
chore: use PE+ data as readonly (#4446)
This helped me identify and fix 2 bugs afaict Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/4446 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
12c4cb97
代码差异
15 个文件
+82
-75
@@ -16,7 +16,7 @@
16
16
"mongoose": "^9.6.2",
17
17
"morgan": "^1.10.0",
18
18
"undici": "^7.10.0",
19
"warframe-public-export-plus": "^0.6.6",
19
"warframe-public-export-plus": "^0.6.7",
20
20
"warframe-riven-info": "^0.1.2",
21
21
"winston": "^3.17.0",
22
22
"winston-daily-rotate-file": "^5.0.0",
@@ -4894,9 +4894,9 @@
4894
4894
}
4895
4895
},
4896
4896
"node_modules/warframe-public-export-plus": {
4897
"version": "0.6.6",
4898
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.6.6.tgz",
4899
"integrity": "sha512-7xcbSCm9gJQsGecdFURdZzoarUQWoirOyCD2faMLW0/3dmnG/53x4HC/4YDekMxFKzOsClNdJMC1snqagH4ioQ=="
4897
"version": "0.6.7",
4898
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.6.7.tgz",
4899
"integrity": "sha512-Ybe14BSi1WBIBmZNsNoaUqX5ZvrljcqY+4yuXcexz9ajZaSaSeJk9LDtEF5fZU0iCzhyKmOLCokCp16Kb+2ABw=="
4900
4900
},
4901
4901
"node_modules/warframe-riven-info": {
4902
4902
"version": "0.1.2",
@@ -36,7 +36,7 @@
36
36
"mongoose": "^9.6.2",
37
37
"morgan": "^1.10.0",
38
38
"undici": "^7.10.0",
39
"warframe-public-export-plus": "^0.6.6",
39
"warframe-public-export-plus": "^0.6.7",
40
40
"warframe-riven-info": "^0.1.2",
41
41
"winston": "^3.17.0",
42
42
"winston-daily-rotate-file": "^5.0.0",
@@ -282,7 +282,7 @@ export const inventoryController: RequestHandler = async (request, response) =>
282
282
}
283
283
if (invasion.Completed) {
284
284
let factionSidedWith: string | undefined;
285
let battlePay: ICountedItem[] | undefined;
285
let battlePay: readonly ICountedItem[] | undefined;
286
286
if (qi.AttackerScore >= 3) {
287
287
factionSidedWith = invasion.Faction;
288
288
battlePay = invasion.AttackerReward.countedItems;
@@ -38,7 +38,7 @@ export const modularWeaponCraftingController: RequestHandler = async (req, res)
38
38
const category = modularWeaponTypes[data.WeaponType];
39
39
const inventory = await getInventory(accountId, undefined); // Projection is complicated a bit by defaultWeapon for MoaPets
40
40
41
let defaultUpgrades: IDefaultUpgrade[] | undefined;
41
let defaultUpgrades: readonly IDefaultUpgrade[] | undefined;
42
42
const defaultOverwrites: Partial<IKubrowPetDatabase> = {
43
43
ModularParts: data.Parts
44
44
};
@@ -46,7 +46,7 @@ interface ListedItem {
46
46
name: string;
47
47
subtype?: string;
48
48
fusionLimit?: number;
49
exalted?: string[];
49
exalted?: readonly string[];
50
50
badReason?: "starter" | "frivolous" | "notraw";
51
51
partType?: string;
52
52
chainLength?: number;
@@ -1373,7 +1373,7 @@ export const addItem = async (
1373
1373
1374
1374
export const addItems = async (
1375
1375
inventory: TInventoryDatabaseDocument,
1376
items: ITypeCount[] | string[],
1376
items: readonly ITypeCount[] | readonly string[],
1377
1377
inventoryChanges: IInventoryChanges = {}
1378
1378
): Promise<IInventoryChanges> => {
1379
1379
let inventoryDelta;
@@ -1390,7 +1390,7 @@ export const addItems = async (
1390
1390
1391
1391
export const applyDefaultUpgrades = (
1392
1392
inventory: TInventoryDatabaseDocument,
1393
defaultUpgrades: IDefaultUpgrade[] | undefined,
1393
defaultUpgrades: readonly IDefaultUpgrade[] | undefined,
1394
1394
inventoryChanges: IInventoryChanges
1395
1395
): IItemConfigDatabase[] => {
1396
1396
const modsToGive: IRawUpgrade[] = [];
@@ -85,6 +85,7 @@ import type { TInventorySlot } from "../types/inventoryTypes/inventoryTypes.ts";
85
85
import { shouldDoServerQol } from "./configService.ts";
86
86
import { buildLabelToVersionInt, wikiDateToBuildVersionInt } from "../helpers/versionHelper.ts";
87
87
import baro from "../constants/baro.ts";
88
import type { Mutable } from "../utils/ts-utils.ts";
88
89
89
90
export type WeaponTypeInternal =
90
91
| "LongGuns"
@@ -3574,85 +3575,86 @@ export const getRecipe = (uniqueName: string, buildLabel: string): IRecipe | und
3574
3575
3575
3576
if (uniqueName.startsWith("/Lotus/StoreItems/Types/Recipes/EidolonRecipes/Arcanes/")) {
3576
3577
if (version_compare(buildLabel, gameToBuildVersion["22.2.4"]) >= 0) {
3578
const wdata = structuredClone(data) as Mutable<IRecipe>;
3577
3579
if (uniqueName.endsWith("ArmourOnOperatorModeBlueprint")) {
3578
data.ingredients[0].ItemCount = 20;
3579
data.ingredients[3] = {
3580
wdata.ingredients[0].ItemCount = 20;
3581
wdata.ingredients[3] = {
3580
3582
ItemType: "/Lotus/Types/Items/MiscItems/Cryotic",
3581
3583
ItemCount: 7100
3582
3584
};
3583
3585
} else if (uniqueName.endsWith("AttackSpeedOnKillBlueprint")) {
3584
data.ingredients[0].ItemCount = 20;
3585
data.ingredients[3] = {
3586
wdata.ingredients[0].ItemCount = 20;
3587
wdata.ingredients[3] = {
3586
3588
ItemType: "/Lotus/Types/Items/MiscItems/Plastids",
3587
3589
ItemCount: 3500
3588
3590
};
3589
3591
} else if (uniqueName.endsWith("CriticalChanceOnHeadshotBlueprint")) {
3590
data.ingredients[0].ItemCount = 3;
3591
data.ingredients[3] = {
3592
wdata.ingredients[0].ItemCount = 3;
3593
wdata.ingredients[3] = {
3592
3594
ItemType: "/Lotus/Types/Items/MiscItems/Rubedo",
3593
3595
ItemCount: 5200
3594
3596
};
3595
3597
} else if (uniqueName.endsWith("HealOnTransferenceInBlueprint")) {
3596
data.ingredients[0].ItemCount = 3;
3597
data.ingredients[1].ItemCount = 3;
3598
data.ingredients[3] = {
3598
wdata.ingredients[0].ItemCount = 3;
3599
wdata.ingredients[1].ItemCount = 3;
3600
wdata.ingredients[3] = {
3599
3601
ItemType: "/Lotus/Types/Items/MiscItems/OxiumAlloy",
3600
3602
ItemCount: 2300
3601
3603
};
3602
3604
} else if (uniqueName.endsWith("HealOnTransferenceOutBlueprint")) {
3603
data.ingredients[0].ItemCount = 3;
3604
data.ingredients[1].ItemCount = 3;
3605
data.ingredients[3] = {
3605
wdata.ingredients[0].ItemCount = 3;
3606
wdata.ingredients[1].ItemCount = 3;
3607
wdata.ingredients[3] = {
3606
3608
ItemType: "/Lotus/Types/Items/MiscItems/PolymerBundle",
3607
3609
ItemCount: 8700
3608
3610
};
3609
3611
} else if (uniqueName.endsWith("HealOnVoidDashBlueprint")) {
3610
data.ingredients[0].ItemCount = 3;
3611
data.ingredients[1].ItemCount = 3;
3612
data.ingredients[3] = {
3612
wdata.ingredients[0].ItemCount = 3;
3613
wdata.ingredients[1].ItemCount = 3;
3614
wdata.ingredients[3] = {
3613
3615
ItemType: "/Lotus/Types/Items/MiscItems/Salvage",
3614
3616
ItemCount: 9200
3615
3617
};
3616
3618
} else if (uniqueName.endsWith("HealthOnOperatorModeBlueprint")) {
3617
data.ingredients[0].ItemCount = 20;
3618
data.ingredients[3] = {
3619
wdata.ingredients[0].ItemCount = 20;
3620
wdata.ingredients[3] = {
3619
3621
ItemType: "/Lotus/Types/Items/MiscItems/AlloyPlate",
3620
3622
ItemCount: 6400
3621
3623
};
3622
3624
} else if (uniqueName.endsWith("ImmunityFallDamageOnVoidDashBlueprint")) {
3623
data.ingredients[0].ItemCount = 3;
3624
data.ingredients[3] = {
3625
wdata.ingredients[0].ItemCount = 3;
3626
wdata.ingredients[3] = {
3625
3627
ItemType: "/Lotus/Types/Items/MiscItems/Ferrite",
3626
3628
ItemCount: 7600
3627
3629
};
3628
3630
} else if (uniqueName.endsWith("IncreasedCriticalDamageOnCriticalStrikeBlueprint")) {
3629
data.ingredients[0].ItemCount = 3;
3630
data.ingredients[3] = {
3631
wdata.ingredients[0].ItemCount = 3;
3632
wdata.ingredients[3] = {
3631
3633
ItemType: "/Lotus/Types/Items/MiscItems/Circuits",
3632
3634
ItemCount: 4400
3633
3635
};
3634
3636
} else if (uniqueName.endsWith("IncreasedDamageOnStatusProcBlueprint")) {
3635
data.ingredients[0].ItemCount = 3;
3636
data.ingredients[3] = {
3637
wdata.ingredients[0].ItemCount = 3;
3638
wdata.ingredients[3] = {
3637
3639
ItemType: "/Lotus/Types/Items/MiscItems/Rubedo",
3638
3640
ItemCount: 4100
3639
3641
};
3640
3642
} else if (uniqueName.endsWith("OperatorAmmoRegenOnKillBlueprint")) {
3641
data.ingredients[0].ItemCount = 20;
3642
data.ingredients[3] = {
3643
wdata.ingredients[0].ItemCount = 20;
3644
wdata.ingredients[3] = {
3643
3645
ItemType: "/Lotus/Types/Items/MiscItems/Circuits",
3644
3646
ItemCount: 3200
3645
3647
};
3646
3648
} else if (uniqueName.endsWith("SpeedOnVoidDashBlueprint")) {
3647
data.ingredients[0].ItemCount = 3;
3648
data.ingredients[1].ItemCount = 3;
3649
data.ingredients[3] = {
3649
wdata.ingredients[0].ItemCount = 3;
3650
wdata.ingredients[1].ItemCount = 3;
3651
wdata.ingredients[3] = {
3650
3652
ItemType: "/Lotus/Types/Items/MiscItems/Nanospores",
3651
3653
ItemCount: 8100
3652
3654
};
3653
3655
} else if (uniqueName.endsWith("StatusChanceOnHeadshotBlueprint")) {
3654
data.ingredients[0].ItemCount = 3;
3655
data.ingredients[3] = {
3656
wdata.ingredients[0].ItemCount = 3;
3657
wdata.ingredients[3] = {
3656
3658
ItemType: "/Lotus/Types/Items/MiscItems/Plastids",
3657
3659
ItemCount: 4800
3658
3660
};
@@ -3660,16 +3662,17 @@ export const getRecipe = (uniqueName: string, buildLabel: string): IRecipe | und
3660
3662
uniqueName.endsWith("ChannelKillEnergyRateBlueprint") ||
3661
3663
uniqueName.endsWith("CritChannelingDamageBlueprint")
3662
3664
) {
3663
data.ingredients[0].ItemCount = 10;
3665
wdata.ingredients[0].ItemCount = 10;
3664
3666
} else if (
3665
3667
uniqueName.endsWith("FinisherLifestealBlueprint") ||
3666
3668
uniqueName.endsWith("GroundSlamPullBlueprint") ||
3667
3669
uniqueName.endsWith("StatusChannelingDamageBlueprint") ||
3668
3670
uniqueName.endsWith("StatusTriggerRadialDamageBlueprint")
3669
3671
) {
3670
data.ingredients[0].ItemCount = 10;
3671
data.ingredients[2].ItemCount = 5;
3672
wdata.ingredients[0].ItemCount = 10;
3673
wdata.ingredients[2].ItemCount = 5;
3672
3674
}
3675
data = wdata;
3673
3676
}
3674
3677
if (version_compare(buildLabel, "2017.12.08.15.29") >= 0) {
3675
3678
// Should be 22.3.4 - 2017-11-16
@@ -3815,7 +3818,7 @@ export const getNormalizedString = (key: string, dict: Record<string, string>):
3815
3818
return getString(key, dict).replaceAll("‘", "'").replaceAll("’", "'").replaceAll("\r\n", " ");
3816
3819
};
3817
3820
3818
export const getKeyChainItems = ({ KeyChain, ChainStage }: IKeyChainRequest, buildLabel: string): string[] => {
3821
export const getKeyChainItems = ({ KeyChain, ChainStage }: IKeyChainRequest, buildLabel: string): readonly string[] => {
3819
3822
const chainStages = getKey(KeyChain, buildLabel)?.chainStages;
3820
3823
if (!chainStages) {
3821
3824
throw new Error(`KeyChain ${KeyChain} does not contain chain stages`);
@@ -3839,7 +3842,7 @@ export const getKeyChainItems = ({ KeyChain, ChainStage }: IKeyChainRequest, bui
3839
3842
export const getLevelKeyRewards = (
3840
3843
levelKey: string,
3841
3844
buildLabel: string
3842
): { levelKeyRewards?: IMissionReward; levelKeyRewards2?: TReward[]; levelMission?: Partial<IRegion> } => {
3845
): { levelKeyRewards?: IMissionReward; levelKeyRewards2?: readonly TReward[]; levelMission?: Partial<IRegion> } => {
3843
3846
const key = getKey(levelKey, buildLabel);
3844
3847
3845
3848
const levelKeyRewards = key?.missionReward;
@@ -4024,7 +4027,7 @@ export const getBoosterPack = async (
4024
4027
version_compare(buildLabel, gameToBuildVersion["18.16.0"]) < 0 &&
4025
4028
uniqueName == "/Lotus/Types/BoosterPacks/RandomKey"
4026
4029
) {
4027
const boosterPack: IBoosterPack = {
4030
const boosterPack: Mutable<IBoosterPack> = {
4028
4031
name: "/Lotus/Language/Items/RandomKey",
4029
4032
description: "/Lotus/Language/Items/RandomKeyDesc",
4030
4033
icon: "/Lotus/Interface/Icons/Store/OrokinKey.png",
@@ -4264,7 +4267,7 @@ export const getKey = (uniqueName: string, buildLabel: string = BL_LATEST): IKey
4264
4267
return ExportKeys[uniqueName] ?? supplementalKeys[uniqueName];
4265
4268
};
4266
4269
4267
export const getMissionDeck = (uniqueName: string, buildLabel: string): TMissionDeck | undefined => {
4270
export const getMissionDeck = (uniqueName: string, buildLabel: string): Readonly<TMissionDeck> | undefined => {
4268
4271
if (
4269
4272
uniqueName == "/Lotus/Types/Game/MissionDecks/BossMissionRewards/YinYangRewards" &&
4270
4273
!shouldDoServerQol("tylRegorDropsTwoEquinoxParts", buildLabel, gameToBuildVersion["42.0.0"])
@@ -218,13 +218,13 @@ const getRotations = async (rewardInfo: IRewardInfo, buildLabel: string, tierOve
218
218
return rotatedValues;
219
219
};
220
220
221
const getRandomRewardByChance = (pool: IReward[], rng?: SRng): IRngResult | undefined => {
221
const getRandomRewardByChance = (pool: readonly IReward[], rng?: SRng): IRngResult | undefined => {
222
222
if (rng) {
223
const res = rng.randomReward(pool as IRngResult[]);
223
const res = rng.randomReward(pool as readonly IRngResult[]);
224
224
rng.randomFloat(); // something related to rewards multiplier
225
225
return res;
226
226
}
227
return getRandomReward(pool as IRngResult[]);
227
return getRandomReward(pool as readonly IRngResult[]);
228
228
};
229
229
230
230
//type TMissionInventoryUpdateKeys = keyof IMissionInventoryUpdateRequest;
@@ -2056,7 +2056,7 @@ async function getRandomMissionDrops(
2056
2056
}
2057
2057
const region = await getRegion(RewardInfo.node, buildLabel);
2058
2058
if (region) {
2059
let rewardManifests: string[];
2059
let rewardManifests: readonly string[];
2060
2060
if (RewardInfo.periodicMissionTag == "EliteAlert" || RewardInfo.periodicMissionTag == "EliteAlertB") {
2061
2061
rewardManifests = ["/Lotus/Types/Game/MissionDecks/EliteAlertMissionRewards/EliteAlertMissionRewards"];
2062
2062
} else if (RewardInfo.invasionId && region.missionType == "MT_ASSASSINATION") {
@@ -2362,7 +2362,7 @@ async function getRandomMissionDrops(
2362
2362
for (let dropitem = 0; dropitem < droptimes; ++dropitem) {
2363
2363
const drop = getRandomRewardByChance(table![0], rng);
2364
2364
drops.push({ StoreItem: drop!.type, ItemCount: drop!.itemCount });
2365
table![0] = table![0].filter((item: IReward) => item.type !== drop!.type);
2365
//table![0] = table![0].filter((item: IReward) => item.type !== drop!.type);
2366
2366
}
2367
2367
}
2368
2368
}
@@ -464,7 +464,7 @@ export const handlePurchase = async (
464
464
465
465
const handleItemPrices = async (
466
466
inventory: TInventoryDatabaseDocument,
467
itemPrices: IMiscItem[],
467
itemPrices: readonly IMiscItem[],
468
468
purchaseQuantity: number,
469
469
inventoryChanges: IInventoryChanges
470
470
): Promise<void> => {
@@ -34,7 +34,7 @@ export const generateRewardSeed = (): bigint => {
34
34
};
35
35
36
36
export const getRewardAtPercentage = <T extends { probability: number }>(
37
pool: T[],
37
pool: readonly T[],
38
38
percentage: number
39
39
): T | undefined => {
40
40
if (pool.length == 0) return;
@@ -52,7 +52,7 @@ export const getRewardAtPercentage = <T extends { probability: number }>(
52
52
return pool[pool.length - 1];
53
53
};
54
54
55
export const getRandomReward = <T extends { probability: number }>(pool: T[]): T | undefined => {
55
export const getRandomReward = <T extends { probability: number }>(pool: readonly T[]): T | undefined => {
56
56
return getRewardAtPercentage(pool, Math.random());
57
57
};
58
58
@@ -75,7 +75,7 @@ export const getRandomWeightedReward = <T extends { rarity: TRarity }>(
75
75
};
76
76
77
77
export const getRandomWeightedRewardUc = <T extends { Rarity: TRarity }>(
78
pool: T[],
78
pool: readonly T[],
79
79
weights: Record<TRarity, number>
80
80
): (T & { probability: number }) | undefined => {
81
81
const resultPool: (T & { probability: number })[] = [];
@@ -137,7 +137,7 @@ export class SRng {
137
137
return (Number(this.state >> 38n) & 0xffffff) * 0.000000059604645;
138
138
}
139
139
140
randomReward<T extends { probability: number }>(pool: T[]): T | undefined {
140
randomReward<T extends { probability: number }>(pool: readonly T[]): T | undefined {
141
141
return getRewardAtPercentage(pool, this.randomFloat());
142
142
}
143
143
@@ -826,7 +826,7 @@ const validateSortieSeed = (seed: number, enemyFaction: TFaction, variants: ISor
826
826
};
827
827
828
828
interface IRotatingSeasonChallengePools {
829
daily: string[];
829
daily: readonly string[];
830
830
weekly: string[];
831
831
hardWeekly: string[];
832
832
weeklyPermanent: string[];
@@ -40,8 +40,8 @@ export interface IMessage {
40
40
highPriority?: boolean;
41
41
lowPrioNewPlayers?: boolean;
42
42
transmission?: string;
43
att?: string[];
44
countedAtt?: ITypeCount[];
43
att?: readonly string[];
44
countedAtt?: readonly ITypeCount[];
45
45
startDate?: Date;
46
46
endDate?: Date;
47
47
QuestReq?: string;