返回提交历史
Modified
package-lock.json
+4
-4
Modified
package.json
+1
-1
Modified
src/helpers/nemesisHelpers.ts
+6
-6
Modified
src/services/inventoryService.ts
+3
-3
Modified
src/services/missionInventoryUpdateService.ts
+14
-10
Modified
src/services/purchaseService.ts
+5
-6
Modified
src/services/worldStateService.ts
+19
-20
XFEstudio/SpaceNinjaServer
chore: update PE+ (#2765)
Some things were deprecated in it Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/2765 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
8a7db2cd
代码差异
7 个文件
+52
-50
@@ -17,7 +17,7 @@
17
17
"morgan": "^1.10.0",
18
18
"ncp": "^2.0.0",
19
19
"undici": "^7.10.0",
20
"warframe-public-export-plus": "^0.5.83",
20
"warframe-public-export-plus": "^0.5.86",
21
21
"warframe-riven-info": "^0.1.2",
22
22
"winston": "^3.17.0",
23
23
"winston-daily-rotate-file": "^5.0.0",
@@ -5532,9 +5532,9 @@
5532
5532
}
5533
5533
},
5534
5534
"node_modules/warframe-public-export-plus": {
5535
"version": "0.5.84",
5536
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.84.tgz",
5537
"integrity": "sha512-ZpI1Y5CgWDmCwM4/oQpv9u0GD6KFvsJ9f1vJVXYhm5VD9DdOJcFzXgXgg98HXJ5JHbO16ZGIj83117qdpd0RQA=="
5535
"version": "0.5.86",
5536
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.86.tgz",
5537
"integrity": "sha512-tWJudKs4WdjFNiF6ipav9md3sboPXJFvSItTfSmT9ko+Xgg1QP75vS/qPsuPw67pqzMaSnAbHpEzNn/rZ4mCug=="
5538
5538
},
5539
5539
"node_modules/warframe-riven-info": {
5540
5540
"version": "0.1.2",
@@ -35,7 +35,7 @@
35
35
"morgan": "^1.10.0",
36
36
"ncp": "^2.0.0",
37
37
"undici": "^7.10.0",
38
"warframe-public-export-plus": "^0.5.83",
38
"warframe-public-export-plus": "^0.5.86",
39
39
"warframe-riven-info": "^0.1.2",
40
40
"winston": "^3.17.0",
41
41
"winston-daily-rotate-file": "^5.0.0",
@@ -212,12 +212,12 @@ export const getInfNodes = (manifest: INemesisManifest, rank: number): IInfNode[
212
212
value.systemIndex === systemIndex &&
213
213
value.nodeType != 3 && // not hub
214
214
value.nodeType != 7 && // not junction
215
value.missionIndex && // must have a mission type and not assassination
216
value.missionIndex != 28 && // not open world
217
value.missionIndex != 32 && // not railjack
218
value.missionIndex != 41 && // not saya's visions
219
value.missionIndex != 42 && // not face off
220
value.name.indexOf("1999NodeI") == -1 && // not stage defence
215
value.missionType != "MT_ASSASSINATION" &&
216
value.missionType != "MT_LANDSCAPE" &&
217
value.missionType != "MT_RAILJACK" &&
218
value.missionType != "MT_OFFERING" &&
219
value.missionType != "MT_PVPVE" &&
220
value.name.indexOf("1999NodeI") == -1 && // not stage defense
221
221
value.name.indexOf("1999NodeJ") == -1 && // not lich bounty
222
222
!isArchwingMission(value)
223
223
) {
@@ -2160,7 +2160,7 @@ export const addMissionComplete = (inventory: TInventoryDatabaseDocument, { Tag,
2160
2160
}
2161
2161
};
2162
2162
2163
export const addBooster = (ItemType: string, time: number, inventory: TInventoryDatabaseDocument): void => {
2163
export const addBooster = (ItemType: string, timeSecs: number, inventory: TInventoryDatabaseDocument): void => {
2164
2164
const currentTime = Math.floor(Date.now() / 1000);
2165
2165
2166
2166
const { Boosters } = inventory;
@@ -2169,9 +2169,9 @@ export const addBooster = (ItemType: string, time: number, inventory: TInventory
2169
2169
2170
2170
if (itemIndex !== -1) {
2171
2171
const existingBooster = Boosters[itemIndex];
2172
existingBooster.ExpiryDate = Math.max(existingBooster.ExpiryDate, currentTime) + time;
2172
existingBooster.ExpiryDate = Math.max(existingBooster.ExpiryDate, currentTime) + timeSecs;
2173
2173
} else {
2174
Boosters.push({ ItemType, ExpiryDate: currentTime + time });
2174
Boosters.push({ ItemType, ExpiryDate: currentTime + timeSecs });
2175
2175
}
2176
2176
};
2177
2177
@@ -1,4 +1,9 @@
1
import type { IMissionReward as IMissionRewardExternal, IRegion, IReward } from "warframe-public-export-plus";
1
import type {
2
IMissionReward as IMissionRewardExternal,
3
IRegion,
4
IReward,
5
TMissionType
6
} from "warframe-public-export-plus";
2
7
import {
3
8
ExportEnemies,
4
9
ExportFusionBundles,
@@ -102,10 +107,9 @@ const getRotations = (rewardInfo: IRewardInfo, tierOverride?: number): number[]
102
107
}
103
108
104
109
const region = ExportRegions[rewardInfo.node] as IRegion | undefined;
105
const missionIndex: number | undefined = region?.missionIndex;
110
const missionType: TMissionType | undefined = region?.missionType;
106
111
107
// For Rescue missions
108
if (missionIndex == 3 && rewardInfo.rewardTier) {
112
if (missionType == "MT_RESCUE" && rewardInfo.rewardTier) {
109
113
return [rewardInfo.rewardTier];
110
114
}
111
115
@@ -123,7 +127,7 @@ const getRotations = (rewardInfo: IRewardInfo, tierOverride?: number): number[]
123
127
// Empty or absent rewardQualifications should not give rewards when:
124
128
// - Completing only 1 zone of (E)SO (https://onlyg.it/OpenWF/SpaceNinjaServer/issues/1823)
125
129
// - Aborting a railjack mission (https://onlyg.it/OpenWF/SpaceNinjaServer/issues/1741)
126
if (rotationCount == 0 && missionIndex != 30 && missionIndex != 32) {
130
if (rotationCount == 0 && missionType != "MT_ENDLESS_EXTERMINATION" && missionType != "MT_RAILJACK") {
127
131
return [0];
128
132
}
129
133
@@ -1095,8 +1099,8 @@ const isEligibleForCreditReward = (rewardInfo: IRewardInfo, missions: IMission,
1095
1099
}
1096
1100
// The rest here might not be needed anymore, but just to be sure we don't give undue credits...
1097
1101
return (
1098
node.missionIndex != 23 && // junction
1099
node.missionIndex != 28 && // open world
1102
node.missionType != "MT_JUNCTION" &&
1103
node.missionType != "MT_LANDSCAPE" &&
1100
1104
missions.Tag != "SolNode761" && // the index
1101
1105
missions.Tag != "SolNode762" && // the index
1102
1106
missions.Tag != "SolNode763" && // the index
@@ -1792,14 +1796,14 @@ function getRandomMissionDrops(
1792
1796
let rewardManifests: string[];
1793
1797
if (RewardInfo.periodicMissionTag == "EliteAlert" || RewardInfo.periodicMissionTag == "EliteAlertB") {
1794
1798
rewardManifests = ["/Lotus/Types/Game/MissionDecks/EliteAlertMissionRewards/EliteAlertMissionRewards"];
1795
} else if (RewardInfo.invasionId && region.missionIndex == 0) {
1799
} else if (RewardInfo.invasionId && region.missionType == "MT_ASSASSINATION") {
1796
1800
// Invasion assassination has Phorid has the boss who should drop Nyx parts
1797
1801
// TODO: Check that the invasion faction is indeed FC_INFESTATION once the Invasions in worldState are more dynamic
1798
1802
rewardManifests = ["/Lotus/Types/Game/MissionDecks/BossMissionRewards/NyxRewards"];
1799
1803
} else if (RewardInfo.sortieId) {
1800
1804
// Sortie mission types differ from the underlying node and hence also don't give rewards from the underlying nodes.
1801
1805
// Assassinations in non-lite sorties are an exception to this.
1802
if (region.missionIndex == 0) {
1806
if (region.missionType == "MT_ASSASSINATION") {
1803
1807
const arr = RewardInfo.sortieId.split("_");
1804
1808
let giveNodeReward = false;
1805
1809
if (arr[1] != "Lite") {
@@ -2165,7 +2169,7 @@ function getRandomMissionDrops(
2165
2169
const deck = ExportRewards["/Lotus/Types/Game/MissionDecks/NightmareModeRewards"];
2166
2170
let rotation = 0;
2167
2171
2168
if (region.missionIndex === 3 && RewardInfo.rewardTier) {
2172
if (region.missionType == "MT_RESCUE" && RewardInfo.rewardTier) {
2169
2173
rotation = RewardInfo.rewardTier;
2170
2174
} else if ([6, 7, 8, 10, 11].includes(region.systemIndex)) {
2171
2175
rotation = 2;
@@ -20,7 +20,6 @@ import type {
20
20
import { PurchaseSource } from "../types/purchaseTypes.ts";
21
21
import { logger } from "../utils/logger.ts";
22
22
import { getWorldState } from "./worldStateService.ts";
23
import type { TRarity } from "warframe-public-export-plus";
24
23
import {
25
24
ExportBoosterPacks,
26
25
ExportBoosters,
@@ -419,7 +418,7 @@ export const handleBundleAcqusition = async (
419
418
component.typeName,
420
419
inventory,
421
420
component.purchaseQuantity * quantity,
422
component.durability,
421
component.durabilityDays,
423
422
true
424
423
)
425
424
).InventoryChanges
@@ -432,7 +431,7 @@ export const handleStoreItemAcquisition = async (
432
431
storeItemName: string,
433
432
inventory: TInventoryDatabaseDocument,
434
433
quantity: number = 1,
435
durability: TRarity = "COMMON",
434
durabilityDays: number = 3,
436
435
ignorePurchaseQuantity: boolean = false,
437
436
premiumPurchase: boolean = true,
438
437
seed?: bigint
@@ -482,7 +481,7 @@ export const handleStoreItemAcquisition = async (
482
481
);
483
482
break;
484
483
case "Boosters":
485
purchaseResponse = handleBoostersPurchase(storeItemName, inventory, durability);
484
purchaseResponse = handleBoostersPurchase(storeItemName, inventory, durabilityDays);
486
485
break;
487
486
}
488
487
}
@@ -672,7 +671,7 @@ const handleTypesPurchase = async (
672
671
const handleBoostersPurchase = (
673
672
boosterStoreName: string,
674
673
inventory: TInventoryDatabaseDocument,
675
durability: TRarity
674
durabilityDays: number
676
675
): { InventoryChanges: IInventoryChanges } => {
677
676
if (!(boosterStoreName in ExportBoosters)) {
678
677
logger.error(`unknown booster type: ${boosterStoreName}`);
@@ -680,7 +679,7 @@ const handleBoostersPurchase = (
680
679
}
681
680
682
681
const ItemType = ExportBoosters[boosterStoreName].typeName;
683
const ExpiryDate = ExportMisc.boosterDurations[durability];
682
const ExpiryDate = durabilityDays * 86400;
684
683
685
684
addBooster(ItemType, ExpiryDate, inventory);
686
685
@@ -13,8 +13,8 @@ import { buildConfig } from "./buildConfigService.ts";
13
13
import { unixTimesInMs } from "../constants/timeConstants.ts";
14
14
import { config } from "./configService.ts";
15
15
import { getRandomElement, getRandomInt, sequentiallyUniqueRandomElement, SRng } from "./rngService.ts";
16
import type { IMissionReward, IRegion } from "warframe-public-export-plus";
17
import { eMissionType, ExportRegions, ExportSyndicates } from "warframe-public-export-plus";
16
import type { IMissionReward, IRegion, TFaction } from "warframe-public-export-plus";
17
import { ExportRegions, ExportSyndicates } from "warframe-public-export-plus";
18
18
import type {
19
19
ICalendarDay,
20
20
ICalendarEvent,
@@ -87,11 +87,11 @@ const sortieFactionToSystemIndexes: Record<string, number[]> = {
87
87
FC_OROKIN: [14]
88
88
};
89
89
90
const sortieFactionToFactionIndexes: Record<string, number[]> = {
91
FC_GRINEER: [0],
92
FC_CORPUS: [1],
93
FC_INFESTATION: [0, 1, 2],
94
FC_OROKIN: [3]
90
const sortieFactionToFactions: Record<string, TFaction[]> = {
91
FC_GRINEER: ["FC_GRINEER"],
92
FC_CORPUS: ["FC_CORPUS"],
93
FC_INFESTATION: ["FC_GRINEER", "FC_CORPUS", "FC_INFESTATION"],
94
FC_OROKIN: ["FC_OROKIN"]
95
95
};
96
96
97
97
const sortieBossNode: Record<Exclude<TSortieBoss, "SORTIE_BOSS_CORRUPTED_VOR">, string> = {
@@ -271,7 +271,7 @@ export const getSortie = (day: number): ISortie => {
271
271
for (const [key, value] of Object.entries(ExportRegions)) {
272
272
if (
273
273
sortieFactionToSystemIndexes[sortieBossToFaction[boss]].includes(value.systemIndex) &&
274
sortieFactionToFactionIndexes[sortieBossToFaction[boss]].includes(value.factionIndex!) &&
274
sortieFactionToFactions[sortieBossToFaction[boss]].includes(value.faction!) &&
275
275
key in sortieTilesets &&
276
276
(key != "SolNode228" || sortieBossToFaction[boss] == "FC_GRINEER") // PoE does not work for non-infested enemies
277
277
) {
@@ -339,10 +339,10 @@ export const getSortie = (day: number): ISortie => {
339
339
modifiers.push("SORTIE_MODIFIER_HAZARD_RADIATION");
340
340
}
341
341
342
if (ExportRegions[node].factionIndex == 0) {
342
if (ExportRegions[node].faction == "FC_GRINEER") {
343
343
// Grineer
344
344
modifiers.push("SORTIE_MODIFIER_ARMOR");
345
} else if (ExportRegions[node].factionIndex == 1) {
345
} else if (ExportRegions[node].faction == "FC_CORPUS") {
346
346
// Corpus
347
347
modifiers.push("SORTIE_MODIFIER_SHIELDS");
348
348
}
@@ -1306,7 +1306,7 @@ const createInvasion = (day: number, idx: number): IInvasion => {
1306
1306
),
1307
1307
Goal: 30000, // Value seems to range from 30000 to 98000 in intervals of 1000. Higher values are increasingly rare. I don't think this is relevant for the frontend besides dividing count by it.
1308
1308
LocTag: isInfestationOutbreak
1309
? ExportRegions[node].missionIndex == 0
1309
? ExportRegions[node].missionType == "MT_ASSASSINATION"
1310
1310
? "/Lotus/Language/Menu/InfestedInvasionBoss"
1311
1311
: "/Lotus/Language/Menu/InfestedInvasionGeneric"
1312
1312
: attacker == "FC_CORPUS"
@@ -3179,7 +3179,7 @@ export const populateFissures = async (worldState: IWorldState): Promise<void> =
3179
3179
Activation: { $date: { $numberLong: "1000000000000" } },
3180
3180
Expiry: { $date: { $numberLong: "2000000000000" } },
3181
3181
Node: node,
3182
MissionType: eMissionType[meta.missionIndex].tag,
3182
MissionType: meta.missionType,
3183
3183
Modifier: tier,
3184
3184
Hard: config.worldState.allTheFissures == "hard"
3185
3185
});
@@ -3199,7 +3199,7 @@ export const populateFissures = async (worldState: IWorldState): Promise<void> =
3199
3199
: toMongoDate(fissure.Activation),
3200
3200
Expiry: toMongoDate(fissure.Expiry),
3201
3201
Node: fissure.Node,
3202
MissionType: eMissionType[meta.missionIndex].tag,
3202
MissionType: meta.missionType,
3203
3203
Modifier: fissure.Modifier,
3204
3204
Hard: fissure.Hard
3205
3205
});
@@ -3246,13 +3246,12 @@ export const getLiteSortie = (week: number): ILiteSortie => {
3246
3246
for (const [key, value] of Object.entries(ExportRegions)) {
3247
3247
if (
3248
3248
value.systemIndex === systemIndex &&
3249
value.factionIndex !== undefined &&
3250
value.factionIndex < 2 &&
3249
(value.faction == "FC_GRINEER" || value.faction == "FC_CORPUS") &&
3251
3250
!isArchwingMission(value) &&
3252
value.missionIndex != 0 && // Exclude MT_ASSASSINATION
3253
value.missionIndex != 23 && // Exclude junctions
3254
value.missionIndex != 28 && // Exclude open worlds
3255
value.missionIndex != 32 // Exclude railjack
3251
value.missionType != "MT_ASSASSINATION" &&
3252
value.missionType != "MT_JUNCTION" &&
3253
value.missionType != "MT_LANDSCAPE" &&
3254
value.missionType != "MT_RAILJACK"
3256
3255
) {
3257
3256
nodes.push(key);
3258
3257
}
@@ -3309,7 +3308,7 @@ export const isArchwingMission = (node: IRegion): boolean => {
3309
3308
return true;
3310
3309
}
3311
3310
// SettlementNode10
3312
if (node.missionIndex == 25) {
3311
if (node.missionType == "MT_RACE") {
3313
3312
return true;
3314
3313
}
3315
3314
return false;