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

chore: switch purchaseService to take inventory document (#848)

5649c5bf
Sainan <sainan@calamity.inc>
提交于

代码差异

5 个文件 +42 -61
Modified src/controllers/api/getVoidProjectionRewardsController.ts +3 -4
@@ -27,18 +27,17 @@ export const getVoidProjectionRewardsController: RequestHandler = async (req, re
27 27 logger.debug(`relic rolled`, reward);
28 28 response.ParticipantInfo.Reward = reward.type;
29 29
30 // Remove relic
31 30 const inventory = await getInventory(accountId);
31 // Remove relic
32 32 addMiscItems(inventory, [
33 33 {
34 34 ItemType: data.ParticipantInfo.VoidProjection,
35 35 ItemCount: -1
36 36 }
37 37 ]);
38 await inventory.save();
39
40 38 // Give reward
41 await handleStoreItemAcquisition(reward.type, accountId, reward.itemCount);
39 await handleStoreItemAcquisition(reward.type, inventory, reward.itemCount);
40 await inventory.save();
42 41 }
43 42 res.json(response);
44 43 };
Modified src/controllers/api/purchaseController.ts +4 -1
@@ -2,10 +2,13 @@ import { RequestHandler } from "express";
2 2 import { getAccountIdForRequest } from "@/src/services/loginService";
3 3 import { IPurchaseRequest } from "@/src/types/purchaseTypes";
4 4 import { handlePurchase } from "@/src/services/purchaseService";
5 import { getInventory } from "@/src/services/inventoryService";
5 6
6 7 export const purchaseController: RequestHandler = async (req, res) => {
7 8 const purchaseRequest = JSON.parse(String(req.body)) as IPurchaseRequest;
8 9 const accountId = await getAccountIdForRequest(req);
9 const response = await handlePurchase(purchaseRequest, accountId);
10 const inventory = await getInventory(accountId);
11 const response = await handlePurchase(purchaseRequest, inventory);
12 await inventory.save();
10 13 res.json(response);
11 14 };
Modified src/controllers/api/syndicateSacrificeController.ts +3 -3
@@ -57,15 +57,15 @@ export const syndicateSacrificeController: RequestHandler = async (request, resp
57 57 }
58 58 }
59 59
60 await inventory.save();
61
62 60 if (reward) {
63 61 combineInventoryChanges(
64 62 res.InventoryChanges,
65 (await handleStoreItemAcquisition(reward, accountId)).InventoryChanges
63 (await handleStoreItemAcquisition(reward, inventory)).InventoryChanges
66 64 );
67 65 }
68 66
67 await inventory.save();
68
69 69 response.json(res);
70 70 };
71 71
Modified src/services/inventoryService.ts +1 -4
@@ -949,10 +949,9 @@ export const addMissionComplete = (inventory: TInventoryDatabaseDocument, { Tag,
949 949 }
950 950 };
951 951
952 export const addBooster = async (ItemType: string, time: number, accountId: string): Promise<void> => {
952 export const addBooster = (ItemType: string, time: number, inventory: TInventoryDatabaseDocument): void => {
953 953 const currentTime = Math.floor(Date.now() / 1000) - 129600; // Value is wrong without 129600. Figure out why, please. :)
954 954
955 const inventory = await getInventory(accountId);
956 955 const { Boosters } = inventory;
957 956
958 957 const itemIndex = Boosters.findIndex(booster => booster.ItemType === ItemType);
@@ -964,8 +963,6 @@ export const addBooster = async (ItemType: string, time: number, accountId: stri
964 963 } else {
965 964 Boosters.push({ ItemType, ExpiryDate: currentTime + time });
966 965 }
967
968 await inventory.save();
969 966 };
970 967
971 968 export const updateSyndicate = (
Modified src/services/purchaseService.ts +31 -49
@@ -5,8 +5,7 @@ import {
5 5 addItem,
6 6 addMiscItems,
7 7 combineInventoryChanges,
8 getInventory,
9 updateCurrencyByAccountId,
8 updateCurrency,
10 9 updateSlots
11 10 } from "@/src/services/inventoryService";
12 11 import { getRandomWeightedReward } from "@/src/services/rngService";
@@ -25,6 +24,7 @@ import {
25 24 TRarity
26 25 } from "warframe-public-export-plus";
27 26 import { config } from "./configService";
27 import { TInventoryDatabaseDocument } from "../models/inventoryModels/inventoryModel";
28 28
29 29 export const getStoreItemCategory = (storeItem: string): string => {
30 30 const storeItemString = getSubstringFromKeyword(storeItem, "StoreItems/");
@@ -43,7 +43,7 @@ export const getStoreItemTypesCategory = (typesItem: string): string => {
43 43
44 44 export const handlePurchase = async (
45 45 purchaseRequest: IPurchaseRequest,
46 accountId: string
46 inventory: TInventoryDatabaseDocument
47 47 ): Promise<IPurchaseResponse> => {
48 48 logger.debug("purchase request", purchaseRequest);
49 49
@@ -58,8 +58,8 @@ export const handlePurchase = async (
58 58 throw new Error(`unknown vendor offer: ${ItemId}`);
59 59 }
60 60 if (offer.ItemPrices) {
61 await handleItemPrices(
62 accountId,
61 handleItemPrices(
62 inventory,
63 63 offer.ItemPrices,
64 64 purchaseRequest.PurchaseParams.Quantity,
65 65 inventoryChanges
@@ -73,17 +73,17 @@ export const handlePurchase = async (
73 73
74 74 const purchaseResponse = await handleStoreItemAcquisition(
75 75 purchaseRequest.PurchaseParams.StoreItem,
76 accountId,
76 inventory,
77 77 purchaseRequest.PurchaseParams.Quantity
78 78 );
79 79 combineInventoryChanges(purchaseResponse.InventoryChanges, inventoryChanges);
80 80
81 81 if (!purchaseResponse) throw new Error("purchase response was undefined");
82 82
83 const currencyChanges = await updateCurrencyByAccountId(
83 const currencyChanges = updateCurrency(
84 inventory,
84 85 purchaseRequest.PurchaseParams.ExpectedPrice,
85 purchaseRequest.PurchaseParams.UsePremium,
86 accountId
86 purchaseRequest.PurchaseParams.UsePremium
87 87 );
88 88 purchaseResponse.InventoryChanges = {
89 89 ...currencyChanges,
@@ -95,7 +95,6 @@ export const handlePurchase = async (
95 95 {
96 96 const syndicateTag = purchaseRequest.PurchaseParams.SyndicateTag!;
97 97 if (purchaseRequest.PurchaseParams.UseFreeFavor!) {
98 const inventory = await getInventory(accountId);
99 98 const affiliation = inventory.Affiliations.find(x => x.Tag == syndicateTag)!;
100 99 affiliation.FreeFavorsUsed ??= [];
101 100 const lastTitle = affiliation.FreeFavorsEarned![affiliation.FreeFavorsUsed.length];
@@ -106,7 +105,6 @@ export const handlePurchase = async (
106 105 Title: lastTitle
107 106 }
108 107 ];
109 await inventory.save();
110 108 } else {
111 109 const syndicate = ExportSyndicates[syndicateTag];
112 110 if (syndicate) {
@@ -114,7 +112,6 @@ export const handlePurchase = async (
114 112 x => x.storeItem == purchaseRequest.PurchaseParams.StoreItem
115 113 );
116 114 if (favour) {
117 const inventory = await getInventory(accountId);
118 115 const affiliation = inventory.Affiliations.find(x => x.Tag == syndicateTag);
119 116 if (affiliation) {
120 117 purchaseResponse.Standing = [
@@ -124,7 +121,6 @@ export const handlePurchase = async (
124 121 }
125 122 ];
126 123 affiliation.Standing -= favour.standingCost;
127 await inventory.save();
128 124 }
129 125 }
130 126 }
@@ -136,8 +132,8 @@ export const handlePurchase = async (
136 132 const vendor = ExportVendors[purchaseRequest.PurchaseParams.SourceId!];
137 133 const offer = vendor.items.find(x => x.storeItem == purchaseRequest.PurchaseParams.StoreItem);
138 134 if (offer && offer.itemPrices) {
139 await handleItemPrices(
140 accountId,
135 handleItemPrices(
136 inventory,
141 137 offer.itemPrices,
142 138 purchaseRequest.PurchaseParams.Quantity,
143 139 purchaseResponse.InventoryChanges
@@ -157,7 +153,6 @@ export const handlePurchase = async (
157 153 x => x.ItemType == purchaseRequest.PurchaseParams.StoreItem
158 154 );
159 155 if (offer) {
160 const inventory = await getInventory(accountId);
161 156 if (offer.RegularPrice) {
162 157 const invItem: IMiscItem = {
163 158 ItemType: "/Lotus/Types/Items/MiscItems/SchismKey",
@@ -171,7 +166,6 @@ export const handlePurchase = async (
171 166 } else if (!config.infiniteRegalAya) {
172 167 inventory.PrimeTokens -= offer.PrimePrice! * purchaseRequest.PurchaseParams.Quantity;
173 168 }
174 await inventory.save();
175 169 }
176 170 break;
177 171 }
@@ -180,13 +174,12 @@ export const handlePurchase = async (
180 174 return purchaseResponse;
181 175 };
182 176
183 const handleItemPrices = async (
184 accountId: string,
177 const handleItemPrices = (
178 inventory: TInventoryDatabaseDocument,
185 179 itemPrices: IMiscItem[],
186 180 purchaseQuantity: number,
187 181 inventoryChanges: IInventoryChanges
188 ): Promise<void> => {
189 const inventory = await getInventory(accountId);
182 ): void => {
190 183 for (const item of itemPrices) {
191 184 const invItem: IMiscItem = {
192 185 ItemType: item.ItemType,
@@ -203,12 +196,11 @@ const handleItemPrices = async (
203 196 (inventoryChanges.MiscItems as IMiscItem[]).push(invItem);
204 197 }
205 198 }
206 await inventory.save();
207 199 };
208 200
209 201 export const handleStoreItemAcquisition = async (
210 202 storeItemName: string,
211 accountId: string,
203 inventory: TInventoryDatabaseDocument,
212 204 quantity: number = 1,
213 205 durability: TRarity = "COMMON",
214 206 ignorePurchaseQuantity: boolean = false
@@ -226,7 +218,7 @@ export const handleStoreItemAcquisition = async (
226 218 (
227 219 await handleStoreItemAcquisition(
228 220 component.typeName,
229 accountId,
221 inventory,
230 222 component.purchaseQuantity * quantity,
231 223 component.durability,
232 224 true
@@ -247,16 +239,14 @@ export const handleStoreItemAcquisition = async (
247 239 }
248 240 switch (storeCategory) {
249 241 default: {
250 const inventory = await getInventory(accountId);
251 242 purchaseResponse = await addItem(inventory, internalName, quantity);
252 await inventory.save();
253 243 break;
254 244 }
255 245 case "Types":
256 purchaseResponse = await handleTypesPurchase(internalName, accountId, quantity);
246 purchaseResponse = await handleTypesPurchase(internalName, inventory, quantity);
257 247 break;
258 248 case "Boosters":
259 purchaseResponse = await handleBoostersPurchase(internalName, accountId, durability);
249 purchaseResponse = handleBoostersPurchase(internalName, inventory, durability);
260 250 break;
261 251 }
262 252 }
@@ -280,11 +270,11 @@ export const slotPurchaseNameToSlotName: SlotPurchase = {
280 270 // // new slot above base = extra + 1 and slots +1
281 271 // // new frame = slots -1
282 272 // // number of frames = extra - slots + 2
283 const handleSlotPurchase = async (
273 const handleSlotPurchase = (
284 274 slotPurchaseNameFull: string,
285 accountId: string,
275 inventory: TInventoryDatabaseDocument,
286 276 quantity: number
287 ): Promise<IPurchaseResponse> => {
277 ): IPurchaseResponse => {
288 278 logger.debug(`slot name ${slotPurchaseNameFull}`);
289 279 const slotPurchaseName = parseSlotPurchaseName(
290 280 slotPurchaseNameFull.substring(slotPurchaseNameFull.lastIndexOf("/") + 1)
@@ -294,9 +284,7 @@ const handleSlotPurchase = async (
294 284 const slotName = slotPurchaseNameToSlotName[slotPurchaseName].name;
295 285 const slotsPurchased = slotPurchaseNameToSlotName[slotPurchaseName].slotsPerPurchase * quantity;
296 286
297 const inventory = await getInventory(accountId);
298 287 updateSlots(inventory, slotName, slotsPurchased, slotsPurchased);
299 await inventory.save();
300 288
301 289 logger.debug(`added ${slotsPurchased} slot ${slotName}`);
302 290
@@ -314,7 +302,7 @@ const handleSlotPurchase = async (
314 302
315 303 const handleBoosterPackPurchase = async (
316 304 typeName: string,
317 accountId: string,
305 inventory: TInventoryDatabaseDocument,
318 306 quantity: number
319 307 ): Promise<IPurchaseResponse> => {
320 308 const pack = ExportBoosterPacks[typeName];
@@ -325,7 +313,6 @@ const handleBoosterPackPurchase = async (
325 313 BoosterPackItems: "",
326 314 InventoryChanges: {}
327 315 };
328 const inventory = await getInventory(accountId);
329 316 for (let i = 0; i != quantity; ++i) {
330 317 for (const weights of pack.rarityWeightsPerRoll) {
331 318 const result = getRandomWeightedReward(pack.components, weights);
@@ -340,29 +327,24 @@ const handleBoosterPackPurchase = async (
340 327 }
341 328 }
342 329 }
343 await inventory.save();
344 330 return purchaseResponse;
345 331 };
346 332
347 333 //TODO: change to getInventory, apply changes then save at the end
348 334 const handleTypesPurchase = async (
349 335 typesName: string,
350 accountId: string,
336 inventory: TInventoryDatabaseDocument,
351 337 quantity: number
352 338 ): Promise<IPurchaseResponse> => {
353 339 const typeCategory = getStoreItemTypesCategory(typesName);
354 340 logger.debug(`type category ${typeCategory}`);
355 341 switch (typeCategory) {
356 default: {
357 const inventory = await getInventory(accountId);
358 const resp = await addItem(inventory, typesName, quantity);
359 await inventory.save();
360 return resp;
361 }
342 default:
343 return await addItem(inventory, typesName, quantity);
362 344 case "BoosterPacks":
363 return await handleBoosterPackPurchase(typesName, accountId, quantity);
345 return handleBoosterPackPurchase(typesName, inventory, quantity);
364 346 case "SlotItems":
365 return await handleSlotPurchase(typesName, accountId, quantity);
347 return handleSlotPurchase(typesName, inventory, quantity);
366 348 }
367 349 };
368 350
@@ -380,11 +362,11 @@ const boosterDuration: Record<TRarity, number> = {
380 362 LEGENDARY: 90 * 86400
381 363 };
382 364
383 const handleBoostersPurchase = async (
365 const handleBoostersPurchase = (
384 366 boosterStoreName: string,
385 accountId: string,
367 inventory: TInventoryDatabaseDocument,
386 368 durability: TRarity
387 ): Promise<{ InventoryChanges: IInventoryChanges }> => {
369 ): { InventoryChanges: IInventoryChanges } => {
388 370 const ItemType = boosterStoreName.replace("StoreItem", "");
389 371 if (!boosterCollection.find(x => x == ItemType)) {
390 372 logger.error(`unknown booster type: ${ItemType}`);
@@ -393,7 +375,7 @@ const handleBoostersPurchase = async (
393 375
394 376 const ExpiryDate = boosterDuration[durability];
395 377
396 await addBooster(ItemType, ExpiryDate, accountId);
378 addBooster(ItemType, ExpiryDate, inventory);
397 379
398 380 return {
399 381 InventoryChanges: {