返回提交历史
Modified
src/services/importService.ts
+1
-1
Modified
src/services/inventoryService.ts
+64
-53
Modified
src/services/purchaseService.ts
+4
-0
XFEstudio/XFESpaceNinjaServer
feat: handle oneTimePurchasable (#4370)
Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/4370 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>
4299fa96
代码差异
3 个文件
+69
-54
@@ -432,7 +432,7 @@ export const importInventory = (db: TInventoryDatabaseDocument, client: Partial<
432
432
"UsedDailyDeals",
433
433
"Wishlist",
434
434
"NemesisAbandonedRewards",
435
//"OneTimePurchases", // TODO: Import Antiques
435
"OneTimePurchases",
436
436
"EntratiLabConquestActiveFrameVariants",
437
437
"EchoesHexConquestActiveFrameVariants",
438
438
"EchoesHexConquestActiveStickers",
@@ -25,7 +25,6 @@ import type {
25
25
IDialogueDatabase,
26
26
IKubrowPetPrintClient,
27
27
IWeeklyMissionChallengeInfo,
28
IKubrowPetEgg,
29
28
ITauPrequelQuestCustomData,
30
29
ICollectibleEntry,
31
30
TInventorySlot
@@ -210,12 +209,7 @@ const setupAntique = (
210
209
throw new Error(`unknown antique: ${weaponType}`);
211
210
}
212
211
213
inventory.OneTimePurchases ??= [];
214
if (!inventory.OneTimePurchases.includes(weaponType)) {
215
inventory.OneTimePurchases.push(weaponType);
216
inventoryChanges.OneTimePurchases ??= [];
217
inventoryChanges.OneTimePurchases.push(weaponType);
218
}
212
handleOneTimePurchasable(inventory, weaponType, inventoryChanges);
219
213
220
214
if (!inventory.FocusUpgrades.some(x => x.ItemType === meta.focusAbility)) {
221
215
inventory.FocusUpgrades.push({ ItemType: meta.focusAbility });
@@ -543,26 +537,35 @@ export const addItem = async (
543
537
544
538
// Strict typing
545
539
if (typeName in ExportRecipes || typeName in supplementalRecipes) {
546
const recipeChanges = [
540
const inventoryChanges: IInventoryChanges = {};
541
inventoryChanges.Recipes = [
547
542
{
548
543
ItemType: typeName,
549
544
ItemCount: quantity
550
545
} satisfies ITypeCount
551
546
];
552
addRecipes(inventory, recipeChanges);
553
return {
554
Recipes: recipeChanges
555
};
547
if (
548
(typeName in ExportRecipes && ExportRecipes[typeName].oneTimePurchasable) ||
549
(typeName in supplementalRecipes && supplementalRecipes[typeName].oneTimePurchasable)
550
) {
551
handleOneTimePurchasable(inventory, typeName, inventoryChanges);
552
}
553
addRecipes(inventory, inventoryChanges.Recipes);
554
return inventoryChanges;
556
555
}
557
556
if (typeName in ExportResources) {
557
const inventoryChanges: IInventoryChanges = {};
558
if (ExportResources[typeName].oneTimePurchasable) {
559
handleOneTimePurchasable(inventory, typeName, inventoryChanges);
560
}
558
561
if (ExportResources[typeName].productCategory == "MiscItems") {
559
const miscItemChanges = [
562
inventoryChanges.MiscItems = [
560
563
{
561
564
ItemType: typeName,
562
565
ItemCount: quantity
563
566
} satisfies IMiscItem
564
567
];
565
addMiscItems(inventory, miscItemChanges);
568
addMiscItems(inventory, inventoryChanges.MiscItems);
566
569
567
570
if (
568
571
typeName == "/Lotus/Types/Game/KubrowPet/Eggs/KubrowEgg" &&
@@ -578,69 +581,61 @@ export const addItem = async (
578
581
?.ItemCount ?? 0,
579
582
PRE_U40_MAX_KUBROW_EGGS
580
583
);
581
const changes: IKubrowPetEgg[] = [];
584
inventoryChanges.KubrowPetEggs ??= [];
585
delete inventoryChanges.MiscItems;
582
586
for (let i = 0; i != quantity; ++i) {
583
changes.push({
587
inventoryChanges.KubrowPetEggs.push({
584
588
ItemType: "/Lotus/Types/Game/KubrowPet/Eggs/KubrowEgg",
585
589
ExpirationDate: toMongoDate2(2000000000000, buildLabel),
586
590
ItemId: toOid2((idBase + i).toString().padStart(24, "0"), buildLabel)
587
591
});
588
592
}
589
return { KubrowPetEggs: changes };
590
593
}
591
594
592
return {
593
MiscItems: miscItemChanges
594
};
595
return inventoryChanges;
595
596
} else if (ExportResources[typeName].productCategory == "FusionTreasures") {
596
const fusionTreasureChanges = [
597
inventoryChanges.FusionTreasures = [
597
598
{
598
599
ItemType: typeName,
599
600
ItemCount: quantity,
600
601
Sockets: 0
601
602
} satisfies IFusionTreasure
602
603
];
603
addFusionTreasures(inventory, fusionTreasureChanges);
604
return {
605
FusionTreasures: fusionTreasureChanges
606
};
604
addFusionTreasures(inventory, inventoryChanges.FusionTreasures);
605
return inventoryChanges;
607
606
} else if (ExportResources[typeName].productCategory == "Ships") {
608
607
if (quantity != 1) {
609
608
throw new Error(`unexpected acquisition quantity of Ships: got ${quantity}, expected 1`);
610
609
}
611
610
const oid = await createShip(inventory.accountOwnerId, typeName);
612
611
inventory.Ships.push(oid);
613
return {
614
Ships: [
615
{
616
ItemId: { $oid: oid.toString() },
617
ItemType: typeName
618
}
619
]
620
};
612
inventoryChanges.Ships = [
613
{
614
ItemId: { $oid: oid.toString() },
615
ItemType: typeName
616
}
617
];
618
return inventoryChanges;
621
619
} else if (ExportResources[typeName].productCategory == "CrewShips") {
622
620
if (quantity != 1) {
623
621
throw new Error(`unexpected acquisition quantity of CrewShips: got ${quantity}, expected 1`);
624
622
}
625
return {
626
...(await addCrewShip(inventory, typeName)),
627
// fix to unlock railjack modding, item bellow supposed to be obtained from archwing quest
628
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
629
...(!inventory.CrewShipHarnesses?.length
630
? addCrewShipHarness(inventory, "/Lotus/Types/Game/CrewShip/RailJack/DefaultHarness")
631
: {})
632
};
623
await addCrewShip(inventory, typeName, inventoryChanges);
624
// fix to unlock railjack modding, item bellow supposed to be obtained from archwing quest
625
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
626
if (!inventory.CrewShipHarnesses?.length) {
627
addCrewShipHarness(inventory, "/Lotus/Types/Game/CrewShip/RailJack/DefaultHarness", inventoryChanges);
628
}
629
return inventoryChanges;
633
630
} else if (ExportResources[typeName].productCategory == "ShipDecorations") {
634
const changes = [
631
inventoryChanges.ShipDecorations = [
635
632
{
636
633
ItemType: typeName,
637
634
ItemCount: quantity
638
635
} satisfies IMiscItem
639
636
];
640
addShipDecorations(inventory, changes);
641
return {
642
ShipDecorations: changes
643
};
637
addShipDecorations(inventory, inventoryChanges.ShipDecorations);
638
return inventoryChanges;
644
639
} else {
645
640
throw new Error(`unknown product category: ${ExportResources[typeName].productCategory}`);
646
641
}
@@ -769,6 +764,10 @@ export const addItem = async (
769
764
}
770
765
if (typeName in ExportWeapons) {
771
766
const weapon = ExportWeapons[typeName];
767
const inventoryChanges: IInventoryChanges = {};
768
if (weapon.oneTimePurchasable) {
769
handleOneTimePurchasable(inventory, typeName, inventoryChanges);
770
}
772
771
if (weapon.totalDamage != 0) {
773
772
if (quantity != 1) {
774
773
throw new Error(
@@ -816,7 +815,6 @@ export const addItem = async (
816
815
defaultOverwrites.UpgradeFingerprint = JSON.stringify(targetFingerprintObj.UpgradeFingerprint);
817
816
defaultOverwrites.ItemName = targetFingerprintObj.Name;
818
817
}
819
const inventoryChanges: IInventoryChanges = {};
820
818
defaultOverwrites.Configs = applyDefaultUpgrades(inventory, weapon.defaultUpgrades, inventoryChanges);
821
819
if (
822
820
weapon.bayonetOtherWeaponType && // Is this a bayonet?
@@ -858,7 +856,6 @@ export const addItem = async (
858
856
}
859
857
const targetFingerprintObj = JSON.parse(targetFingerprint) as INemesisPetTargetFingerprint;
860
858
const head = targetFingerprintObj.Parts[0];
861
const inventoryChanges: IInventoryChanges = {};
862
859
const defaultOverwrites: Partial<IEquipmentDatabase> = {
863
860
ModularParts: targetFingerprintObj.Parts,
864
861
ItemName: targetFingerprintObj.Name,
@@ -879,16 +876,14 @@ export const addItem = async (
879
876
};
880
877
} else {
881
878
// Modular weapon parts
882
const miscItemChanges = [
879
inventoryChanges.MiscItems = [
883
880
{
884
881
ItemType: typeName,
885
882
ItemCount: quantity
886
883
} satisfies IMiscItem
887
884
];
888
addMiscItems(inventory, miscItemChanges);
889
return {
890
MiscItems: miscItemChanges
891
};
885
addMiscItems(inventory, inventoryChanges.MiscItems);
886
return inventoryChanges;
892
887
}
893
888
}
894
889
if (typeName in ExportRailjackWeapons) {
@@ -3762,6 +3757,22 @@ export const processGoalProgressUpdates = async (
3762
3757
}
3763
3758
};
3764
3759
3760
export const handleOneTimePurchasable = (
3761
inventory: Pick<TInventoryDatabaseDocument, "OneTimePurchases">,
3762
typeName: string,
3763
inventoryChanges: IInventoryChanges = {}
3764
): IInventoryChanges => {
3765
inventory.OneTimePurchases ??= [];
3766
if (!inventory.OneTimePurchases.includes(typeName)) {
3767
inventory.OneTimePurchases.push(typeName);
3768
inventoryChanges.OneTimePurchases ??= [];
3769
inventoryChanges.OneTimePurchases.push(typeName);
3770
} else {
3771
logger.warn(`${typeName} is already in OneTimePurchases`);
3772
}
3773
return inventoryChanges;
3774
};
3775
3765
3776
const goalMessagesByKey: Record<
3766
3777
string,
3767
3778
{ sndr: string; msg: string; sub: string; icon: string; arg?: string[]; minBuildLabel?: string }
@@ -5,6 +5,7 @@ import {
5
5
addItems,
6
6
addMiscItems,
7
7
combineInventoryChanges,
8
handleOneTimePurchasable,
8
9
updateCurrency,
9
10
updateSlots
10
11
} from "./inventoryService.ts";
@@ -491,6 +492,9 @@ export const handleBundleAcquisition = async (
491
492
): Promise<IInventoryChanges> => {
492
493
const bundle = getBundle(storeItemName, buildLabel)!;
493
494
logger.debug("acquiring bundle", bundle);
495
if (bundle.oneTimePurchasable) {
496
handleOneTimePurchasable(inventory, storeItemName, inventoryChanges);
497
}
494
498
for (const component of bundle.components) {
495
499
combineInventoryChanges(
496
500
inventoryChanges,