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

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
AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
提交于

代码差异

3 个文件 +69 -54
Modified src/services/importService.ts +1 -1
@@ -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",
Modified src/services/inventoryService.ts +64 -53
@@ -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 }
Modified src/services/purchaseService.ts +4 -0
@@ -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,