Fix issues around ragfair and handbook caching (!334)

- Make `PenetrationDamageMod` optional in ITemplateItem
- Cache handbook values if they're found after initial cache generation
- Refactor how caching in RagfairPriceService is handled
-- Rename `generate` methods to `refresh` to better indicate their purpose
-- If item price isn't found in cache, try to find it and add it
-- Refresh caches prior to returning all flea prices (This is only triggered via a route call, so shouldn't happen often)
-- Remove storage of whether we've generated cache, it should always be done on load, and we dynamically add to it, so it's not necessary to keep track of

Co-authored-by: DrakiaXYZ <565558+TheDgtl@users.noreply.github.com>
Reviewed-on: https://dev.sp-tarkov.com/SPT-AKI/Server/pulls/334
Co-authored-by: DrakiaXYZ <drakiaxyz@noreply.dev.sp-tarkov.com>
Co-committed-by: DrakiaXYZ <drakiaxyz@noreply.dev.sp-tarkov.com>
This commit is contained in:
DrakiaXYZ 2024-05-20 07:58:13 +00:00 committed by chomp
parent 66cac910c3
commit fcabd68dfc
3 changed files with 30 additions and 27 deletions

View File

@ -101,7 +101,7 @@ export class HandbookHelper
/**
* Get price from internal cache, if cache empty look up price directly in handbook (expensive)
* If no values found, return 1
* If no values found, return 0
* @param tpl item tpl to look up price for
* @returns price in roubles
*/
@ -127,6 +127,7 @@ export class HandbookHelper
return newValue;
}
this.handbookPriceCache.items.byId.set(tpl, handbookItem.Price);
return handbookItem.Price;
}

View File

@ -358,7 +358,7 @@ export interface Props
casingSounds?: string
ProjectileCount?: number
PenetrationChanceObstacle?: number
PenetrationDamageMod: number
PenetrationDamageMod?: number
RicochetChance?: number
FragmentationChance?: number
Deterioration?: number

View File

@ -27,8 +27,6 @@ import { RandomUtil } from "@spt-aki/utils/RandomUtil";
export class RagfairPriceService implements OnLoad
{
protected ragfairConfig: IRagfairConfig;
protected generatedDynamicPrices: boolean;
protected generatedStaticPrices: boolean;
protected prices: IRagfairServerPrices = { static: {}, dynamic: {} };
@ -52,15 +50,8 @@ export class RagfairPriceService implements OnLoad
*/
public async onLoad(): Promise<void>
{
if (!this.generatedStaticPrices)
{
this.generateStaticPrices();
}
if (!this.generatedDynamicPrices)
{
this.generateDynamicPrices();
}
this.refreshStaticPrices();
this.refreshDynamicPrices();
}
public getRoute(): string
@ -71,7 +62,7 @@ export class RagfairPriceService implements OnLoad
/**
* Iterate over all items of type "Item" in db and get template price, store in cache
*/
public generateStaticPrices(): void
public refreshStaticPrices(): void
{
for (const item of Object.values(this.databaseServer.getTables().templates.items).filter(
(x) => x._type === "Item",
@ -79,18 +70,15 @@ export class RagfairPriceService implements OnLoad
{
this.prices.static[item._id] = Math.round(this.handbookHelper.getTemplatePrice(item._id));
}
this.generatedStaticPrices = true;
}
/**
* Create a dictionary and store prices from prices.json in it
* Copy the prices.json data into our dynamic price dictionary
*/
public generateDynamicPrices(): void
public refreshDynamicPrices(): void
{
Object.assign(this.prices.dynamic, this.databaseServer.getTables().templates.prices);
this.generatedDynamicPrices = true;
const pricesTable = this.databaseServer.getTables().templates.prices;
this.prices.dynamic = { ...this.prices.dynamic, ...pricesTable };
}
/**
@ -140,15 +128,15 @@ export class RagfairPriceService implements OnLoad
/**
* get the dynamic (flea) price for an item
* Grabs prices from prices.json and stores in class if none currently exist
* @param itemTpl item template id to look up
* @returns price in roubles
*/
public getDynamicPriceForItem(itemTpl: string): number
{
if (!this.generatedDynamicPrices)
// If the price doesn't exist in the cache yet, try to find it
if (!this.prices.dynamic[itemTpl])
{
this.generateDynamicPrices();
this.prices.dynamic[itemTpl] = this.databaseServer.getTables().templates.prices[itemTpl];
}
return this.prices.dynamic[itemTpl];
@ -161,9 +149,15 @@ export class RagfairPriceService implements OnLoad
*/
public getStaticPriceForItem(itemTpl: string): number
{
if (!this.generatedStaticPrices)
// If the price doesn't exist in the cache yet, try to find it
if (!this.prices.static[itemTpl])
{
this.generateStaticPrices();
// Store the price in the cache only if it exists
const itemPrice = Math.round(this.handbookHelper.getTemplatePrice(itemTpl));
if (itemPrice !== 0)
{
this.prices.static[itemTpl] = itemPrice;
}
}
return this.prices.static[itemTpl];
@ -171,10 +165,15 @@ export class RagfairPriceService implements OnLoad
/**
* Get prices for all items on flea, prioritize handbook prices first, use prices from prices.json if missing
* This will refresh the caches prior to building the output
* @returns Dictionary of item tpls and rouble cost
*/
public getAllFleaPrices(): Record<string, number>
{
// Refresh the caches so we include any newly added custom items
this.refreshDynamicPrices();
this.refreshStaticPrices();
// assign dynamic (prices.json) values first, then overwrite them with static (handbook.json)
// any values not stored in static data will be covered by dynamic data
return { ...this.prices.dynamic, ...this.prices.static };
@ -182,6 +181,9 @@ export class RagfairPriceService implements OnLoad
public getAllStaticPrices(): Record<string, number>
{
// Refresh the cache so we include any newly added custom items
this.refreshStaticPrices();
return { ...this.prices.static };
}
@ -207,7 +209,7 @@ export class RagfairPriceService implements OnLoad
for (const item of barterScheme)
{
price += this.prices.static[item._tpl] * item.count;
price += this.getStaticPriceForItem(item._tpl) * item.count;
}
return Math.round(price);