XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

SpaceNinjaServer

A simple server for a small space ninja game

公开
关注 0 Fork 1 Star 0
返回提交历史

XFEstudio/SpaceNinjaServer

fix: consume a slot when item is crafted instead of bought via plat (#1029)

Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1029

a5c45bb6
Sainan <sainan@calamity.inc>
提交于

代码差异

6 个文件 +103 -88
Modified src/controllers/api/claimCompletedRecipeController.ts +1 -1
@@ -91,7 +91,7 @@ export const claimCompletedRecipeController: RequestHandler = async (req, res) =
91 91 }
92 92 InventoryChanges = {
93 93 ...InventoryChanges,
94 ...(await addItem(inventory, recipe.resultType, recipe.num)).InventoryChanges
94 ...(await addItem(inventory, recipe.resultType, recipe.num, false)).InventoryChanges
95 95 };
96 96 await inventory.save();
97 97 res.json({ InventoryChanges });
Modified src/controllers/api/guildTechController.ts +2 -4
@@ -54,10 +54,8 @@ export const guildTechController: RequestHandler = async (req, res) => {
54 54 }
55 55 }
56 56 addMiscItems(inventory, miscItemChanges);
57 const inventoryChanges: IInventoryChanges = {
58 ...updateCurrency(inventory, contributions.RegularCredits, false),
59 MiscItems: miscItemChanges
60 };
57 const inventoryChanges: IInventoryChanges = updateCurrency(inventory, contributions.RegularCredits, false);
58 inventoryChanges.MiscItems = miscItemChanges;
61 59
62 60 if (techProject.ReqCredits == 0 && !techProject.ReqItems.find(x => x.ItemCount > 0)) {
63 61 // This research is now fully funded.
Modified src/controllers/custom/addItemsController.ts +1 -1
@@ -7,7 +7,7 @@ export const addItemsController: RequestHandler = async (req, res) => {
7 7 const requests = req.body as IAddItemRequest[];
8 8 const inventory = await getInventory(accountId);
9 9 for (const request of requests) {
10 await addItem(inventory, request.ItemType, request.ItemCount);
10 await addItem(inventory, request.ItemType, request.ItemCount, true);
11 11 }
12 12 await inventory.save();
13 13 res.end();
Modified src/services/inventoryService.ts +49 -44
@@ -5,7 +5,7 @@ import {
5 5 } from "@/src/models/inventoryModels/inventoryModel";
6 6 import { config } from "@/src/services/configService";
7 7 import { HydratedDocument, Types } from "mongoose";
8 import { SlotNames, IInventoryChanges, IBinChanges, ICurrencyChanges } from "@/src/types/purchaseTypes";
8 import { SlotNames, IInventoryChanges, IBinChanges, slotNames } from "@/src/types/purchaseTypes";
9 9 import {
10 10 IChallengeProgress,
11 11 IConsumable,
@@ -126,13 +126,17 @@ export const combineInventoryChanges = (InventoryChanges: IInventoryChanges, del
126 126 for (const item of right) {
127 127 left.push(item);
128 128 }
129 } else if (typeof delta[key] == "object") {
130 console.assert(key.substring(-3) == "Bin");
131 console.assert(key != "InfestedFoundry");
132 const left = InventoryChanges[key] as IBinChanges;
133 const right = delta[key] as IBinChanges;
134 left.count += right.count;
135 left.platinum += right.platinum;
129 } else if (slotNames.indexOf(key as SlotNames) != -1) {
130 const left = InventoryChanges[key as SlotNames]!;
131 const right = delta[key as SlotNames]!;
132 if (right.count) {
133 left.count ??= 0;
134 left.count += right.count;
135 }
136 if (right.platinum) {
137 left.platinum ??= 0;
138 left.platinum += right.platinum;
139 }
136 140 left.Slots += right.Slots;
137 141 if (right.Extra) {
138 142 left.Extra ??= 0;
@@ -159,10 +163,32 @@ export const getInventory = async (
159 163 return inventory;
160 164 };
161 165
166 const occupySlot = (
167 inventory: TInventoryDatabaseDocument,
168 bin: InventorySlot,
169 premiumPurchase: boolean
170 ): IInventoryChanges => {
171 const slotChanges = {
172 Slots: 0,
173 Extra: 0
174 };
175 if (premiumPurchase) {
176 slotChanges.Extra += 1;
177 } else {
178 // { count: 1, platinum: 0, Slots: -1 }
179 slotChanges.Slots -= 1;
180 }
181 updateSlots(inventory, bin, slotChanges.Slots, slotChanges.Extra);
182 const inventoryChanges: IInventoryChanges = {};
183 inventoryChanges[bin] = slotChanges satisfies IBinChanges;
184 return inventoryChanges;
185 };
186
162 187 export const addItem = async (
163 188 inventory: TInventoryDatabaseDocument,
164 189 typeName: string,
165 quantity: number = 1
190 quantity: number = 1,
191 premiumPurchase: boolean = false
166 192 ): Promise<{ InventoryChanges: IInventoryChanges }> => {
167 193 // Bundles are technically StoreItems but a) they don't have a normal counterpart, and b) they are used in non-StoreItem contexts, e.g. email attachments.
168 194 if (typeName in ExportBundles) {
@@ -302,14 +328,13 @@ export const addItem = async (
302 328 const inventoryChanges = addEquipment(inventory, weapon.productCategory, typeName);
303 329 if (weapon.additionalItems) {
304 330 for (const item of weapon.additionalItems) {
305 combineInventoryChanges(inventoryChanges, await addItem(inventory, item, 1));
331 combineInventoryChanges(inventoryChanges, (await addItem(inventory, item, 1)).InventoryChanges);
306 332 }
307 333 }
308 updateSlots(inventory, InventorySlot.WEAPONS, 0, 1);
309 334 return {
310 335 InventoryChanges: {
311 336 ...inventoryChanges,
312 WeaponBin: { count: 1, platinum: 0, Slots: -1 }
337 ...occupySlot(inventory, InventorySlot.WEAPONS, premiumPurchase)
313 338 }
314 339 };
315 340 } else {
@@ -378,44 +403,26 @@ export const addItem = async (
378 403 case "Powersuits":
379 404 switch (typeName.substr(1).split("/")[2]) {
380 405 default: {
381 const inventoryChanges = addPowerSuit(inventory, typeName);
382 updateSlots(inventory, InventorySlot.SUITS, 0, 1);
383 406 return {
384 407 InventoryChanges: {
385 ...inventoryChanges,
386 SuitBin: {
387 count: 1,
388 platinum: 0,
389 Slots: -1
390 }
408 ...addPowerSuit(inventory, typeName),
409 ...occupySlot(inventory, InventorySlot.SUITS, premiumPurchase)
391 410 }
392 411 };
393 412 }
394 413 case "Archwing": {
395 const inventoryChanges = addSpaceSuit(inventory, typeName);
396 updateSlots(inventory, InventorySlot.SPACESUITS, 0, 1);
397 414 return {
398 415 InventoryChanges: {
399 ...inventoryChanges,
400 SpaceSuitBin: {
401 count: 1,
402 platinum: 0,
403 Slots: -1
404 }
416 ...addSpaceSuit(inventory, typeName),
417 ...occupySlot(inventory, InventorySlot.SPACESUITS, premiumPurchase)
405 418 }
406 419 };
407 420 }
408 421 case "EntratiMech": {
409 const inventoryChanges = addMechSuit(inventory, typeName);
410 updateSlots(inventory, InventorySlot.MECHSUITS, 0, 1);
411 422 return {
412 423 InventoryChanges: {
413 ...inventoryChanges,
414 MechBin: {
415 count: 1,
416 platinum: 0,
417 Slots: -1
418 }
424 ...addMechSuit(inventory, typeName),
425 ...occupySlot(inventory, InventorySlot.MECHSUITS, premiumPurchase)
419 426 }
420 427 };
421 428 }
@@ -446,12 +453,10 @@ export const addItem = async (
446 453 case "Types":
447 454 switch (typeName.substr(1).split("/")[2]) {
448 455 case "Sentinels": {
449 const inventoryChanges = addSentinel(inventory, typeName);
450 updateSlots(inventory, InventorySlot.SENTINELS, 0, 1);
451 456 return {
452 457 InventoryChanges: {
453 ...inventoryChanges,
454 SentinelBin: { count: 1, platinum: 0, Slots: -1 }
458 ...addSentinel(inventory, typeName),
459 ...occupySlot(inventory, InventorySlot.SENTINELS, premiumPurchase)
455 460 }
456 461 };
457 462 }
@@ -531,9 +536,9 @@ export const addItems = async (
531 536 let inventoryDelta;
532 537 for (const item of items) {
533 538 if (typeof item === "string") {
534 inventoryDelta = await addItem(inventory, item);
539 inventoryDelta = await addItem(inventory, item, 1, true);
535 540 } else {
536 inventoryDelta = await addItem(inventory, item.ItemType, item.ItemCount);
541 inventoryDelta = await addItem(inventory, item.ItemType, item.ItemCount, true);
537 542 }
538 543 combineInventoryChanges(inventoryChanges, inventoryDelta.InventoryChanges);
539 544 }
@@ -682,8 +687,8 @@ export const updateCurrency = (
682 687 inventory: TInventoryDatabaseDocument,
683 688 price: number,
684 689 usePremium: boolean
685 ): ICurrencyChanges => {
686 const currencyChanges: ICurrencyChanges = {};
690 ): IInventoryChanges => {
691 const currencyChanges: IInventoryChanges = {};
687 692 if (price != 0 && isCurrencyTracked(usePremium)) {
688 693 if (usePremium) {
689 694 if (inventory.PremiumCreditsFree > 0) {
Modified src/services/purchaseService.ts +11 -13
@@ -164,7 +164,7 @@ export const handlePurchase = async (
164 164 addMiscItems(inventory, [invItem]);
165 165
166 166 purchaseResponse.InventoryChanges.MiscItems ??= [];
167 (purchaseResponse.InventoryChanges.MiscItems as IMiscItem[]).push(invItem);
167 purchaseResponse.InventoryChanges.MiscItems.push(invItem);
168 168 } else if (!config.infiniteRegalAya) {
169 169 inventory.PrimeTokens -= offer.PrimePrice! * purchaseRequest.PurchaseParams.Quantity;
170 170 }
@@ -191,11 +191,11 @@ const handleItemPrices = (
191 191 addMiscItems(inventory, [invItem]);
192 192
193 193 inventoryChanges.MiscItems ??= [];
194 const change = (inventoryChanges.MiscItems as IMiscItem[]).find(x => x.ItemType == item.ItemType);
194 const change = inventoryChanges.MiscItems.find(x => x.ItemType == item.ItemType);
195 195 if (change) {
196 196 change.ItemCount += invItem.ItemCount;
197 197 } else {
198 (inventoryChanges.MiscItems as IMiscItem[]).push(invItem);
198 inventoryChanges.MiscItems.push(invItem);
199 199 }
200 200 }
201 201 };
@@ -251,7 +251,7 @@ export const handleStoreItemAcquisition = async (
251 251 }
252 252 switch (storeCategory) {
253 253 default: {
254 purchaseResponse = await addItem(inventory, internalName, quantity);
254 purchaseResponse = await addItem(inventory, internalName, quantity, true);
255 255 break;
256 256 }
257 257 case "Types":
@@ -300,16 +300,14 @@ const handleSlotPurchase = (
300 300
301 301 logger.debug(`added ${slotsPurchased} slot ${slotName}`);
302 302
303 return {
304 InventoryChanges: {
305 [slotName]: {
306 count: 0,
307 platinum: 1,
308 Slots: slotsPurchased,
309 Extra: slotsPurchased
310 }
311 }
303 const inventoryChanges: IInventoryChanges = {};
304 inventoryChanges[slotName] = {
305 count: 0,
306 platinum: 1,
307 Slots: slotsPurchased,
308 Extra: slotsPurchased
312 309 };
310 return { InventoryChanges: inventoryChanges };
313 311 };
314 312
315 313 const handleBoosterPackPurchase = async (
Modified src/types/purchaseTypes.ts +39 -25
@@ -1,5 +1,5 @@
1 1 import { IEquipmentClient } from "./inventoryTypes/commonInventoryTypes";
2 import { IDroneClient, IInfestedFoundryClient, TEquipmentKey } from "./inventoryTypes/inventoryTypes";
2 import { IDroneClient, IInfestedFoundryClient, IMiscItem, TEquipmentKey } from "./inventoryTypes/inventoryTypes";
3 3
4 4 export interface IPurchaseRequest {
5 5 PurchaseParams: IPurchaseParams;
@@ -22,20 +22,31 @@ export interface IPurchaseParams {
22 22 IsWeekly?: boolean; // for Source 7
23 23 }
24 24
25 export interface ICurrencyChanges {
26 RegularCredits?: number;
27 PremiumCredits?: number;
28 PremiumCreditsFree?: number;
29 }
30
31 25 export type IInventoryChanges = {
32 26 [_ in SlotNames]?: IBinChanges;
33 27 } & {
34 28 [_ in TEquipmentKey]?: IEquipmentClient[];
35 } & ICurrencyChanges & {
36 InfestedFoundry?: IInfestedFoundryClient;
37 Drones?: IDroneClient[];
38 } & Record<string, IBinChanges | number | object[] | IInfestedFoundryClient>;
29 } & {
30 RegularCredits?: number;
31 PremiumCredits?: number;
32 PremiumCreditsFree?: number;
33 InfestedFoundry?: IInfestedFoundryClient;
34 Drones?: IDroneClient[];
35 MiscItems?: IMiscItem[];
36 } & Record<
37 Exclude<
38 string,
39 | SlotNames
40 | TEquipmentKey
41 | "RegularCredits"
42 | "PremiumCredits"
43 | "PremiumCreditsFree"
44 | "InfestedFoundry"
45 | "Drones"
46 | "MiscItems"
47 >,
48 number | object[]
49 >;
39 50
40 51 export interface IAffiliationMods {
41 52 Tag: string;
@@ -51,8 +62,8 @@ export interface IPurchaseResponse {
51 62 }
52 63
53 64 export type IBinChanges = {
54 count: number;
55 platinum: number;
65 count?: number;
66 platinum?: number;
56 67 Slots: number;
57 68 Extra?: number;
58 69 };
@@ -69,18 +80,21 @@ export type SlotPurchaseName =
69 80 | "TwoCrewShipSalvageSlotItem"
70 81 | "CrewMemberSlotItem";
71 82
72 export type SlotNames =
73 | "SuitBin"
74 | "WeaponBin"
75 | "MechBin"
76 | "PveBonusLoadoutBin"
77 | "SentinelBin"
78 | "SpaceSuitBin"
79 | "SpaceWeaponBin"
80 | "OperatorAmpBin"
81 | "RandomModBin"
82 | "CrewShipSalvageBin"
83 | "CrewMemberBin";
83 export const slotNames = [
84 "SuitBin",
85 "WeaponBin",
86 "MechBin",
87 "PveBonusLoadoutBin",
88 "SentinelBin",
89 "SpaceSuitBin",
90 "SpaceWeaponBin",
91 "OperatorAmpBin",
92 "RandomModBin",
93 "CrewShipSalvageBin",
94 "CrewMemberBin"
95 ] as const;
96
97 export type SlotNames = (typeof slotNames)[number];
84 98
85 99 export type SlotPurchase = {
86 100 [P in SlotPurchaseName]: { name: SlotNames; slotsPerPurchase: number };