2024-05-27 22:06:07 +02:00
|
|
|
import { ProfileHelper } from "@spt/helpers/ProfileHelper";
|
2024-05-21 19:59:04 +02:00
|
|
|
import { RagfairServerHelper } from "@spt/helpers/RagfairServerHelper";
|
|
|
|
import { IRagfairOffer } from "@spt/models/eft/ragfair/IRagfairOffer";
|
2023-03-03 16:23:46 +01:00
|
|
|
|
|
|
|
export class RagfairOfferHolder
|
|
|
|
{
|
2023-07-15 11:45:33 +02:00
|
|
|
protected offersById: Map<string, IRagfairOffer>;
|
|
|
|
protected offersByTemplate: Map<string, Map<string, IRagfairOffer>>;
|
|
|
|
protected offersByTrader: Map<string, Map<string, IRagfairOffer>>;
|
2023-03-03 16:23:46 +01:00
|
|
|
|
2024-05-17 21:32:41 +02:00
|
|
|
constructor(
|
|
|
|
protected maxOffersPerTemplate: number,
|
|
|
|
protected ragfairServerHelper: RagfairServerHelper,
|
2024-05-27 22:06:07 +02:00
|
|
|
protected profileHelper: ProfileHelper,
|
2024-05-17 21:32:41 +02:00
|
|
|
)
|
2023-03-03 16:23:46 +01:00
|
|
|
{
|
|
|
|
this.offersById = new Map();
|
|
|
|
this.offersByTemplate = new Map();
|
|
|
|
this.offersByTrader = new Map();
|
|
|
|
}
|
|
|
|
|
2024-05-27 18:05:16 +02:00
|
|
|
public getOfferById(id: string): IRagfairOffer | undefined
|
2023-03-03 16:23:46 +01:00
|
|
|
{
|
|
|
|
if (this.offersById.has(id))
|
|
|
|
{
|
2024-05-27 18:05:16 +02:00
|
|
|
return this.offersById.get(id)!;
|
2023-03-03 16:23:46 +01:00
|
|
|
}
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
|
2024-05-27 18:05:16 +02:00
|
|
|
public getOffersByTemplate(templateId: string): Array<IRagfairOffer> | undefined
|
2023-03-03 16:23:46 +01:00
|
|
|
{
|
|
|
|
if (this.offersByTemplate.has(templateId))
|
|
|
|
{
|
2024-05-27 18:05:16 +02:00
|
|
|
return [...this.offersByTemplate.get(templateId)!.values()];
|
2023-03-03 16:23:46 +01:00
|
|
|
}
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
|
2024-05-27 18:05:16 +02:00
|
|
|
public getOffersByTrader(traderId: string): Array<IRagfairOffer> | undefined
|
2023-03-03 16:23:46 +01:00
|
|
|
{
|
|
|
|
if (this.offersByTrader.has(traderId))
|
|
|
|
{
|
2024-05-27 18:05:16 +02:00
|
|
|
return [...this.offersByTrader.get(traderId)!.values()];
|
2023-03-03 16:23:46 +01:00
|
|
|
}
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
public getOffers(): Array<IRagfairOffer>
|
|
|
|
{
|
|
|
|
if (this.offersById.size > 0)
|
|
|
|
{
|
|
|
|
return [...this.offersById.values()];
|
|
|
|
}
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
|
|
|
public addOffers(offers: Array<IRagfairOffer>): void
|
|
|
|
{
|
2023-10-31 18:46:14 +01:00
|
|
|
for (const offer of offers)
|
|
|
|
{
|
|
|
|
this.addOffer(offer);
|
|
|
|
}
|
2023-03-03 16:23:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public addOffer(offer: IRagfairOffer): void
|
|
|
|
{
|
|
|
|
const trader = offer.user.id;
|
|
|
|
const offerId = offer._id;
|
2024-01-14 11:09:43 +01:00
|
|
|
const itemTpl = offer.items[0]._tpl;
|
2024-05-02 10:56:40 +02:00
|
|
|
// If its an NPC PMC offer AND we have already reached the maximum amount of possible offers
|
|
|
|
// for this template, just dont add in more
|
|
|
|
if (
|
2024-05-27 22:06:07 +02:00
|
|
|
!(this.ragfairServerHelper.isTrader(trader) || this.profileHelper.isPlayer(trader))
|
2024-05-27 18:05:16 +02:00
|
|
|
&& (this.getOffersByTemplate(itemTpl)?.length ?? 0) >= this.maxOffersPerTemplate
|
2024-05-02 10:56:40 +02:00
|
|
|
)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2023-03-03 16:23:46 +01:00
|
|
|
this.offersById.set(offerId, offer);
|
|
|
|
this.addOfferByTrader(trader, offer);
|
2024-01-14 11:09:43 +01:00
|
|
|
this.addOfferByTemplates(itemTpl, offer);
|
2023-03-03 16:23:46 +01:00
|
|
|
}
|
|
|
|
|
2024-01-26 11:49:06 +01:00
|
|
|
/**
|
|
|
|
* Purge offer from offer cache
|
|
|
|
* @param offer Offer to remove
|
|
|
|
*/
|
2023-03-03 16:23:46 +01:00
|
|
|
public removeOffer(offer: IRagfairOffer): void
|
|
|
|
{
|
|
|
|
if (this.offersById.has(offer._id))
|
|
|
|
{
|
|
|
|
this.offersById.delete(offer._id);
|
2024-05-27 18:05:16 +02:00
|
|
|
if (this.offersByTrader.has(offer.user.id))
|
2024-05-02 15:18:34 +02:00
|
|
|
{
|
2024-05-27 18:05:16 +02:00
|
|
|
this.offersByTrader.get(offer.user.id)!.delete(offer._id);
|
|
|
|
// This was causing a memory leak, we need to make sure that we remove
|
|
|
|
// the user ID from the cached offers after they dont have anything else
|
|
|
|
// on the flea placed. We regenerate the ID for the NPC users, making it
|
|
|
|
// continously grow otherwise
|
|
|
|
if (this.offersByTrader.get(offer.user.id)!.size === 0)
|
|
|
|
{
|
|
|
|
this.offersByTrader.delete(offer.user.id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.offersByTemplate.has(offer.items[0]._tpl))
|
|
|
|
{
|
|
|
|
this.offersByTemplate.get(offer.items[0]._tpl)!.delete(offer._id);
|
2024-05-02 15:18:34 +02:00
|
|
|
}
|
2023-03-03 16:23:46 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public removeOffers(offers: Array<IRagfairOffer>): void
|
|
|
|
{
|
2023-10-31 18:46:14 +01:00
|
|
|
for (const offer of offers)
|
|
|
|
{
|
|
|
|
this.removeOffer(offer);
|
|
|
|
}
|
2023-03-03 16:23:46 +01:00
|
|
|
}
|
2023-11-13 17:14:58 +01:00
|
|
|
|
2024-01-26 11:49:06 +01:00
|
|
|
public removeAllOffersByTrader(traderId: string): void
|
2023-03-03 16:23:46 +01:00
|
|
|
{
|
|
|
|
if (this.offersByTrader.has(traderId))
|
|
|
|
{
|
2024-05-27 18:05:16 +02:00
|
|
|
this.removeOffers([...this.offersByTrader.get(traderId)!.values()]);
|
2023-03-03 16:23:46 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get an array of stale offers that are still shown to player
|
|
|
|
* @returns IRagfairOffer array
|
|
|
|
*/
|
|
|
|
public getStaleOffers(time: number): Array<IRagfairOffer>
|
|
|
|
{
|
2024-05-17 21:32:41 +02:00
|
|
|
return this.getOffers().filter((o) => this.isStale(o, time));
|
2023-03-03 16:23:46 +01:00
|
|
|
}
|
|
|
|
|
2023-07-15 11:45:33 +02:00
|
|
|
protected addOfferByTemplates(template: string, offer: IRagfairOffer): void
|
2023-03-03 16:23:46 +01:00
|
|
|
{
|
|
|
|
if (this.offersByTemplate.has(template))
|
|
|
|
{
|
2024-05-27 18:05:16 +02:00
|
|
|
this.offersByTemplate.get(template)!.set(offer._id, offer);
|
2023-03-03 16:23:46 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const valueMapped = new Map<string, IRagfairOffer>();
|
|
|
|
valueMapped.set(offer._id, offer);
|
|
|
|
this.offersByTemplate.set(template, valueMapped);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-15 11:45:33 +02:00
|
|
|
protected addOfferByTrader(trader: string, offer: IRagfairOffer): void
|
2023-03-03 16:23:46 +01:00
|
|
|
{
|
|
|
|
if (this.offersByTrader.has(trader))
|
|
|
|
{
|
2024-05-27 18:05:16 +02:00
|
|
|
this.offersByTrader.get(trader)!.set(offer._id, offer);
|
2023-03-03 16:23:46 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const valueMapped = new Map<string, IRagfairOffer>();
|
|
|
|
valueMapped.set(offer._id, offer);
|
|
|
|
this.offersByTrader.set(trader, valueMapped);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected isStale(offer: IRagfairOffer, time: number): boolean
|
|
|
|
{
|
2024-05-27 18:05:16 +02:00
|
|
|
return offer.endTime < time || (offer.items[0].upd?.StackObjectsCount ?? 0) < 1;
|
2023-03-03 16:23:46 +01:00
|
|
|
}
|
2023-11-13 17:14:58 +01:00
|
|
|
}
|