From 825db77b1f54956ccd381a710ac031b3d6b86eca Mon Sep 17 00:00:00 2001 From: Dev Date: Mon, 15 Jan 2024 14:25:17 +0000 Subject: [PATCH] Move trader purchases over to new system Fix callback errors not being propigated into client error message FIx incorrect offer id being passed into `buyItem` Update callbacks to accept a `buyCount` parameter - solves trader purchase limits being exeeded prematurely Exit addItemToStash early if warning/error found in output --- project/src/controllers/TradeController.ts | 2 +- project/src/helpers/InventoryHelper.ts | 6 +- project/src/helpers/TradeHelper.ts | 139 ++++++++++-------- project/src/helpers/TraderHelper.ts | 13 +- .../eft/inventory/IAddItemDirectRequest.ts | 2 +- 5 files changed, 87 insertions(+), 75 deletions(-) diff --git a/project/src/controllers/TradeController.ts b/project/src/controllers/TradeController.ts index 1a62a682..a081d78b 100644 --- a/project/src/controllers/TradeController.ts +++ b/project/src/controllers/TradeController.ts @@ -115,7 +115,7 @@ export class TradeController type: "buy_from_trader", tid: (sellerIsTrader) ? fleaOffer.user.id : "ragfair", // eslint-disable-next-line @typescript-eslint/naming-convention - item_id: fleaOffer._id, // Store ragfair offerId in buyRequestData.item_id + item_id: (sellerIsTrader) ? fleaOffer.root : fleaOffer._id, // Store ragfair offerId in buyRequestData.item_id count: offer.count, // eslint-disable-next-line @typescript-eslint/naming-convention scheme_id: 0, diff --git a/project/src/helpers/InventoryHelper.ts b/project/src/helpers/InventoryHelper.ts index d73305a9..c91d4799 100644 --- a/project/src/helpers/InventoryHelper.ts +++ b/project/src/helpers/InventoryHelper.ts @@ -109,14 +109,14 @@ export class InventoryHelper { if (typeof request.callback === "function") { - request.callback(); + request.callback(itemWithModsToAddClone[0].upd.StackObjectsCount); } } catch (err) { // Callback failed - const message = typeof err === "string" - ? err + const message = typeof err?.message === "string" + ? err.message : this.localisationService.getText("http-unknown_error"); return this.httpResponse.appendErrorToOutput(output, message); diff --git a/project/src/helpers/TradeHelper.ts b/project/src/helpers/TradeHelper.ts index 32f7e0af..89f02e04 100644 --- a/project/src/helpers/TradeHelper.ts +++ b/project/src/helpers/TradeHelper.ts @@ -2,6 +2,7 @@ import { inject, injectable } from "tsyringe"; import { InventoryHelper } from "@spt-aki/helpers/InventoryHelper"; import { ItemHelper } from "@spt-aki/helpers/ItemHelper"; +import { TraderAssortHelper } from "@spt-aki/helpers/TraderAssortHelper"; import { TraderHelper } from "@spt-aki/helpers/TraderHelper"; import { IPmcData } from "@spt-aki/models/eft/common/IPmcData"; import { Item, Upd } from "@spt-aki/models/eft/common/tables/IItem"; @@ -41,6 +42,7 @@ export class TradeHelper @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, @inject("InventoryHelper") protected inventoryHelper: InventoryHelper, @inject("RagfairServer") protected ragfairServer: RagfairServer, + @inject("TraderAssortHelper") protected traderAssortHelper: TraderAssortHelper, @inject("ConfigServer") protected configServer: ConfigServer, ) { @@ -67,62 +69,11 @@ export class TradeHelper { let output = this.eventOutputHolder.getOutput(sessionID); - const newReq = { - items: [{ - // eslint-disable-next-line @typescript-eslint/naming-convention - item_id: buyRequestData.item_id, - count: buyRequestData.count, - }], - tid: buyRequestData.tid, - }; - - const callback = () => - { - // Update assort/flea item values - const traderAssorts = this.traderHelper.getTraderAssortsByTraderId(buyRequestData.tid).items; - const itemPurchased = traderAssorts.find((x) => x._id === buyRequestData.item_id); - - - // Ensure purchase does not exceed trader item limit - const hasBuyRestrictions = this.itemHelper.hasBuyRestrictions(itemPurchased); - if (hasBuyRestrictions) - { - this.checkPurchaseIsWithinTraderItemLimit(itemPurchased, buyRequestData.item_id, buyRequestData.count); - } - - // Decrement trader item count - itemPurchased.upd.StackObjectsCount -= buyRequestData.count; - - if (this.traderConfig.persistPurchaseDataInProfile && hasBuyRestrictions) - { - this.traderHelper.addTraderPurchasesToPlayerProfile(sessionID, newReq); - } - - /// Pay for item - output = this.paymentService.payMoney(pmcData, buyRequestData, sessionID, output); - if (output.warnings.length > 0) - { - throw new Error(`Transaction failed: ${output.warnings[0].errmsg}`); - } - - if (hasBuyRestrictions) - { - // Increment non-fence trader item buy count - this.incrementAssortBuyCount(itemPurchased, buyRequestData.count); - } - }; - - // Handle normal traders old way...for now - if (buyRequestData.tid.toLocaleLowerCase() !== "ragfair" && buyRequestData.tid.toLocaleLowerCase() !== Traders.FENCE) - { - return this.inventoryHelper.addItem(pmcData, newReq, output, sessionID, callback, foundInRaid, upd); - } - let offerItems: Item[] = []; - let buyCallback; + let buyCallback: { (buyCount: number) }; if (buyRequestData.tid.toLocaleLowerCase() === "ragfair") { - buyCallback = () => + buyCallback = (buyCount: number) => { const allOffers = this.ragfairServer.getOffers(); @@ -131,17 +82,23 @@ export class TradeHelper const itemPurchased = offerWithItem.items[0]; // Ensure purchase does not exceed trader item limit - const hasBuyRestrictions = this.itemHelper.hasBuyRestrictions(itemPurchased); - if (hasBuyRestrictions) + const assortHasBuyRestrictions = this.itemHelper.hasBuyRestrictions(itemPurchased); + if (assortHasBuyRestrictions) { - this.checkPurchaseIsWithinTraderItemLimit(itemPurchased, buyRequestData.item_id, buyRequestData.count); + this.checkPurchaseIsWithinTraderItemLimit(itemPurchased, buyRequestData.item_id, buyCount); } // Decrement trader item count - - if (this.traderConfig.persistPurchaseDataInProfile && hasBuyRestrictions) + if (this.traderConfig.persistPurchaseDataInProfile && assortHasBuyRestrictions) { - this.traderHelper.addTraderPurchasesToPlayerProfile(sessionID, newReq); + const itemPurchaseDat = { + items: [{ + itemId: buyRequestData.item_id, + count: buyCount + }], + traderId: buyRequestData.tid + }; + this.traderHelper.addTraderPurchasesToPlayerProfile(sessionID, itemPurchaseDat); } /// Pay for item @@ -151,10 +108,10 @@ export class TradeHelper throw new Error(`Transaction failed: ${output.warnings[0].errmsg}`); } - if (hasBuyRestrictions) + if (assortHasBuyRestrictions) { // Increment non-fence trader item buy count - this.incrementAssortBuyCount(itemPurchased, buyRequestData.count); + this.incrementAssortBuyCount(itemPurchased, buyCount); } }; @@ -165,7 +122,7 @@ export class TradeHelper } else if (buyRequestData.tid === Traders.FENCE) { - buyCallback = () => + buyCallback = (buyCount: number) => { // Update assort/flea item values const traderAssorts = this.traderHelper.getTraderAssortsByTraderId(buyRequestData.tid).items; @@ -195,6 +152,59 @@ export class TradeHelper offerItems = this.itemHelper.findAndReturnChildrenAsItems(fenceItems, buyRequestData.item_id); } + else + { + // Non-fence trader + buyCallback = (buyCount: number) => + { + // Update assort/flea item values + const traderAssorts = this.traderHelper.getTraderAssortsByTraderId(buyRequestData.tid).items; + const itemPurchased = traderAssorts.find((x) => x._id === buyRequestData.item_id); + + + // Ensure purchase does not exceed trader item limit + const assortHasBuyRestrictions = this.itemHelper.hasBuyRestrictions(itemPurchased); + if (assortHasBuyRestrictions) + { + this.checkPurchaseIsWithinTraderItemLimit(itemPurchased, buyRequestData.item_id, buyCount); + } + + // Decrement trader item count + itemPurchased.upd.StackObjectsCount -= buyCount; + + if (this.traderConfig.persistPurchaseDataInProfile && assortHasBuyRestrictions) + { + const itemPurchaseDat = { + items: [{ + itemId: buyRequestData.item_id, + count: buyCount + }], + traderId: buyRequestData.tid + }; + this.traderHelper.addTraderPurchasesToPlayerProfile(sessionID, itemPurchaseDat); + } + + /// Pay for item + output = this.paymentService.payMoney(pmcData, buyRequestData, sessionID, output); + if (output.warnings.length > 0) + { + throw new Error(`Transaction failed: ${output.warnings[0].errmsg}`); + } + + if (assortHasBuyRestrictions) + { + // Increment non-fence trader item buy count + this.incrementAssortBuyCount(itemPurchased, buyCount); + } + }; + + // Get all trader assort items + const traderItems = this.traderAssortHelper.getAssort(sessionID, buyRequestData.tid).items; + + // Get item + children for purchase + const relevantItems = this.itemHelper.findAndReturnChildrenAsItems(traderItems, buyRequestData.item_id); + offerItems.push(...relevantItems); + } // Get item details from db const itemDbDetails = this.itemHelper.getItem(offerItems[0]._tpl)[1]; @@ -220,7 +230,10 @@ export class TradeHelper // Add item + children to stash this.inventoryHelper.addItemToStash(sessionID, request, pmcData, output); - + if (output.warnings.length > 0) + { + return output; + } // Remove amount of items added to player stash itemsToSendRemaining -= itemCountToSend; } diff --git a/project/src/helpers/TraderHelper.ts b/project/src/helpers/TraderHelper.ts index b91ab08e..0c52718e 100644 --- a/project/src/helpers/TraderHelper.ts +++ b/project/src/helpers/TraderHelper.ts @@ -308,12 +308,11 @@ export class TraderHelper */ public addTraderPurchasesToPlayerProfile( sessionID: string, - // eslint-disable-next-line @typescript-eslint/naming-convention - newPurchaseDetails: { items: { item_id: string; count: number; }[]; tid: string; }, + newPurchaseDetails: { items: { itemId: string; count: number; }[]; traderId: string; }, ): void { const profile = this.profileHelper.getFullProfile(sessionID); - const traderId = newPurchaseDetails.tid; + const traderId = newPurchaseDetails.traderId; // Iterate over assorts bought and add to profile for (const purchasedItem of newPurchaseDetails.items) @@ -330,9 +329,9 @@ export class TraderHelper // Null guard when dict doesnt exist const currentTime = this.timeUtil.getTimestamp(); - if (!profile.traderPurchases[traderId][purchasedItem.item_id]) + if (!profile.traderPurchases[traderId][purchasedItem.itemId]) { - profile.traderPurchases[traderId][purchasedItem.item_id] = { + profile.traderPurchases[traderId][purchasedItem.itemId] = { count: purchasedItem.count, purchaseTimestamp: currentTime, }; @@ -340,8 +339,8 @@ export class TraderHelper continue; } - profile.traderPurchases[traderId][purchasedItem.item_id].count += purchasedItem.count; - profile.traderPurchases[traderId][purchasedItem.item_id].purchaseTimestamp = currentTime; + profile.traderPurchases[traderId][purchasedItem.itemId].count += purchasedItem.count; + profile.traderPurchases[traderId][purchasedItem.itemId].purchaseTimestamp = currentTime; } } diff --git a/project/src/models/eft/inventory/IAddItemDirectRequest.ts b/project/src/models/eft/inventory/IAddItemDirectRequest.ts index c02ea1e3..ed8af4d9 100644 --- a/project/src/models/eft/inventory/IAddItemDirectRequest.ts +++ b/project/src/models/eft/inventory/IAddItemDirectRequest.ts @@ -5,6 +5,6 @@ export interface IAddItemDirectRequest /** Item and child mods to add to player inventory */ itemWithModsToAdd: Item[]; foundInRaid: boolean; - callback: () => void; + callback: (buyCount: number) => void; useSortingTable: boolean; } \ No newline at end of file