Introduced a new ICloner interface with 3 implementations, one of them being a recursive cloner which is faster and more efficient than its counterparts by more than 50%
This commit is contained in:
parent
ba1ac09b0b
commit
793d884293
@ -24,6 +24,7 @@ import { BotGenerationCacheService } from "@spt-aki/services/BotGenerationCacheS
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { MatchBotDetailsCacheService } from "@spt-aki/services/MatchBotDetailsCacheService";
|
||||
import { SeasonalEventService } from "@spt-aki/services/SeasonalEventService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
|
||||
|
||||
@ -48,6 +49,7 @@ export class BotController
|
||||
@inject("ApplicationContext") protected applicationContext: ApplicationContext,
|
||||
@inject("RandomUtil") protected randomUtil: RandomUtil,
|
||||
@inject("JsonUtil") protected jsonUtil: JsonUtil,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.botConfig = this.configServer.getConfig(ConfigTypes.BOT);
|
||||
@ -281,7 +283,7 @@ export class BotController
|
||||
const botPromises: Promise<void>[] = [];
|
||||
for (let i = 0; i < botGenerationDetails.botCountToGenerate; i++)
|
||||
{
|
||||
const detailsClone = this.jsonUtil.clone(botGenerationDetails);
|
||||
const detailsClone = this.cloner.clone(botGenerationDetails);
|
||||
botPromises.push(this.generateSingleBotAndStoreInCache(detailsClone, sessionId, cacheKey));
|
||||
}
|
||||
return Promise.all(botPromises).then(() =>
|
||||
|
@ -10,6 +10,7 @@ import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { EventOutputHolder } from "@spt-aki/routers/EventOutputHolder";
|
||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { SaveServer } from "@spt-aki/servers/SaveServer";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
|
||||
@ -25,6 +26,7 @@ export class BuildController
|
||||
@inject("ProfileHelper") protected profileHelper: ProfileHelper,
|
||||
@inject("ItemHelper") protected itemHelper: ItemHelper,
|
||||
@inject("SaveServer") protected saveServer: SaveServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{}
|
||||
|
||||
@ -39,7 +41,7 @@ export class BuildController
|
||||
}
|
||||
|
||||
// Ensure the secure container in the default presets match what the player has equipped
|
||||
const defaultEquipmentPresetsClone = this.jsonUtil.clone(
|
||||
const defaultEquipmentPresetsClone = this.cloner.clone(
|
||||
this.databaseServer.getTables().templates.defaultEquipmentPresets,
|
||||
);
|
||||
const playerSecureContainer = profile.characters.pmc.Inventory.items?.find(x =>
|
||||
@ -63,7 +65,7 @@ export class BuildController
|
||||
}
|
||||
|
||||
// Clone player build data from profile and append the above defaults onto end
|
||||
const userBuildsClone = this.jsonUtil.clone(profile.userbuilds);
|
||||
const userBuildsClone = this.cloner.clone(profile.userbuilds);
|
||||
userBuildsClone.equipmentBuilds.push(...defaultEquipmentPresetsClone);
|
||||
|
||||
return userBuildsClone;
|
||||
|
@ -44,6 +44,7 @@ import { ProfileActivityService } from "@spt-aki/services/ProfileActivityService
|
||||
import { ProfileFixerService } from "@spt-aki/services/ProfileFixerService";
|
||||
import { RaidTimeAdjustmentService } from "@spt-aki/services/RaidTimeAdjustmentService";
|
||||
import { SeasonalEventService } from "@spt-aki/services/SeasonalEventService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
|
||||
@ -83,6 +84,7 @@ export class GameController
|
||||
@inject("ProfileActivityService") protected profileActivityService: ProfileActivityService,
|
||||
@inject("ApplicationContext") protected applicationContext: ApplicationContext,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.httpConfig = this.configServer.getConfig(ConfigTypes.HTTP);
|
||||
@ -321,7 +323,7 @@ export class GameController
|
||||
this.logger.warning(
|
||||
`Trader ${trader.base._id} ${trader.base.nickname} is missing a repair object, adding in default values`,
|
||||
);
|
||||
trader.base.repair = this.jsonUtil.clone(this.databaseServer.getTables().traders.ragfair.base.repair);
|
||||
trader.base.repair = this.cloner.clone(this.databaseServer.getTables().traders.ragfair.base.repair);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -331,7 +333,7 @@ export class GameController
|
||||
this.logger.warning(
|
||||
`Trader ${trader.base._id} ${trader.base.nickname} is missing a repair quality value, adding in default value`,
|
||||
);
|
||||
trader.base.repair.quality = this.jsonUtil.clone(
|
||||
trader.base.repair.quality = this.cloner.clone(
|
||||
this.databaseServer.getTables().traders.ragfair.base.repair.quality,
|
||||
);
|
||||
trader.base.repair.quality = this.databaseServer.getTables().traders.ragfair.base.repair.quality;
|
||||
@ -791,7 +793,7 @@ export class GameController
|
||||
for (let index = indexOfWaveToSplit + 1; index < indexOfWaveToSplit + waveSize; index++)
|
||||
{
|
||||
// Clone wave ready to insert into array
|
||||
const waveToAddClone = this.jsonUtil.clone(wave);
|
||||
const waveToAddClone = this.cloner.clone(wave);
|
||||
|
||||
// Some waves have value of 0 for some reason, preserve
|
||||
if (waveToAddClone.number !== 0)
|
||||
|
@ -15,6 +15,7 @@ import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { EventOutputHolder } from "@spt-aki/routers/EventOutputHolder";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { PaymentService } from "@spt-aki/services/PaymentService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { HttpResponseUtil } from "@spt-aki/utils/HttpResponseUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
|
||||
@ -31,6 +32,7 @@ export class HealthController
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||
@inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil,
|
||||
@inject("HealthHelper") protected healthHelper: HealthHelper,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{}
|
||||
|
||||
@ -215,7 +217,7 @@ export class HealthController
|
||||
}
|
||||
|
||||
// Inform client of new post-raid, post-therapist heal values
|
||||
output.profileChanges[sessionID].health = this.jsonUtil.clone(pmcData.Health);
|
||||
output.profileChanges[sessionID].health = this.cloner.clone(pmcData.Health);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
@ -48,6 +48,7 @@ import { FenceService } from "@spt-aki/services/FenceService";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { PlayerService } from "@spt-aki/services/PlayerService";
|
||||
import { ProfileActivityService } from "@spt-aki/services/ProfileActivityService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
import { HttpResponseUtil } from "@spt-aki/utils/HttpResponseUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
@ -83,6 +84,7 @@ export class HideoutController
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("JsonUtil") protected jsonUtil: JsonUtil,
|
||||
@inject("FenceService") protected fenceService: FenceService,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.hideoutConfig = this.configServer.getConfig(ConfigTypes.HIDEOUT);
|
||||
@ -594,7 +596,7 @@ export class HideoutController
|
||||
const recipe = this.databaseServer.getTables().hideout.production.find(p => p._id === body.recipeId);
|
||||
|
||||
// Find the actual amount of items we need to remove because body can send weird data
|
||||
const recipeRequirementsClone = this.jsonUtil.clone(
|
||||
const recipeRequirementsClone = this.cloner.clone(
|
||||
recipe.requirements.filter(i => i.type === "Item" || i.type === "Tool"),
|
||||
);
|
||||
|
||||
|
@ -56,6 +56,7 @@ export class InsuranceController
|
||||
@inject("MailSendService") protected mailSendService: MailSendService,
|
||||
@inject("RagfairPriceService") protected ragfairPriceService: RagfairPriceService,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.insuranceConfig = this.configServer.getConfig(ConfigTypes.INSURANCE);
|
||||
@ -458,7 +459,7 @@ export class InsuranceController
|
||||
const countOfAttachmentsToRemove = this.getAttachmentCountToRemove(weightedAttachmentByPrice, traderId);
|
||||
|
||||
// Create prob array and add all attachments with rouble price as the weight
|
||||
const attachmentsProbabilityArray = new ProbabilityObjectArray<string, number>(this.mathUtil, this.jsonUtil);
|
||||
const attachmentsProbabilityArray = new ProbabilityObjectArray<string, number>(this.mathUtil, this.cloner);
|
||||
for (const attachmentTpl of Object.keys(weightedAttachmentByPrice))
|
||||
{
|
||||
attachmentsProbabilityArray.push(
|
||||
|
@ -41,6 +41,7 @@ import { FenceService } from "@spt-aki/services/FenceService";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { PlayerService } from "@spt-aki/services/PlayerService";
|
||||
import { RagfairOfferService } from "@spt-aki/services/RagfairOfferService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
import { HttpResponseUtil } from "@spt-aki/utils/HttpResponseUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
@ -69,6 +70,7 @@ export class InventoryController
|
||||
@inject("LootGenerator") protected lootGenerator: LootGenerator,
|
||||
@inject("EventOutputHolder") protected eventOutputHolder: EventOutputHolder,
|
||||
@inject("HttpResponseUtil") protected httpResponseUtil: HttpResponseUtil,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{}
|
||||
|
||||
@ -212,7 +214,7 @@ export class InventoryController
|
||||
}
|
||||
|
||||
// Create new upd object that retains properties of original upd + new stack count size
|
||||
const updatedUpd = this.jsonUtil.clone(itemToSplit.upd);
|
||||
const updatedUpd = this.cloner.clone(itemToSplit.upd);
|
||||
updatedUpd.StackObjectsCount = request.count;
|
||||
|
||||
// Remove split item count from source stack
|
||||
|
@ -23,6 +23,7 @@ import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { ItemFilterService } from "@spt-aki/services/ItemFilterService";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { RaidTimeAdjustmentService } from "@spt-aki/services/RaidTimeAdjustmentService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
|
||||
@ -49,6 +50,7 @@ export class LocationController
|
||||
@inject("TimeUtil") protected timeUtil: TimeUtil,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("ApplicationContext") protected applicationContext: ApplicationContext,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.airdropConfig = this.configServer.getConfig(ConfigTypes.AIRDROP);
|
||||
@ -80,7 +82,7 @@ export class LocationController
|
||||
{
|
||||
const db = this.databaseServer.getTables();
|
||||
const location: ILocation = db.locations[name];
|
||||
const locationBaseClone: ILocationBase = this.jsonUtil.clone(location.base);
|
||||
const locationBaseClone: ILocationBase = this.cloner.clone(location.base);
|
||||
|
||||
locationBaseClone.UnixDateTime = this.timeUtil.getTimestamp();
|
||||
|
||||
@ -97,18 +99,18 @@ export class LocationController
|
||||
>();
|
||||
if (raidAdjustments)
|
||||
{
|
||||
locationConfigCopy = this.jsonUtil.clone(this.locationConfig); // Clone values so they can be used to reset originals later
|
||||
locationConfigCopy = this.cloner.clone(this.locationConfig); // Clone values so they can be used to reset originals later
|
||||
this.raidTimeAdjustmentService.makeAdjustmentsToMap(raidAdjustments, locationBaseClone);
|
||||
}
|
||||
|
||||
const staticAmmoDist = this.jsonUtil.clone(location.staticAmmo);
|
||||
const staticAmmoDist = this.cloner.clone(location.staticAmmo);
|
||||
|
||||
// Create containers and add loot to them
|
||||
const staticLoot = this.locationGenerator.generateStaticContainers(locationBaseClone, staticAmmoDist);
|
||||
locationBaseClone.Loot.push(...staticLoot);
|
||||
|
||||
// Add dynamic loot to output loot
|
||||
const dynamicLootDistClone: ILooseLoot = this.jsonUtil.clone(location.looseLoot);
|
||||
const dynamicLootDistClone: ILooseLoot = this.cloner.clone(location.looseLoot);
|
||||
const dynamicSpawnPoints: SpawnpointTemplate[] = this.locationGenerator.generateDynamicLoot(
|
||||
dynamicLootDistClone,
|
||||
staticAmmoDist,
|
||||
|
@ -29,6 +29,7 @@ import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { MailSendService } from "@spt-aki/services/MailSendService";
|
||||
import { PlayerService } from "@spt-aki/services/PlayerService";
|
||||
import { SeasonalEventService } from "@spt-aki/services/SeasonalEventService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { HttpResponseUtil } from "@spt-aki/utils/HttpResponseUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { TimeUtil } from "@spt-aki/utils/TimeUtil";
|
||||
@ -57,6 +58,7 @@ export class QuestController
|
||||
@inject("SeasonalEventService") protected seasonalEventService: SeasonalEventService,
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.questConfig = this.configServer.getConfig(ConfigTypes.QUEST);
|
||||
@ -466,10 +468,10 @@ export class QuestController
|
||||
const completeQuestResponse = this.eventOutputHolder.getOutput(sessionID);
|
||||
|
||||
const completedQuest = this.questHelper.getQuestFromDb(body.qid, pmcData);
|
||||
const preCompleteProfileQuests = this.jsonUtil.clone(pmcData.Quests);
|
||||
const preCompleteProfileQuests = this.cloner.clone(pmcData.Quests);
|
||||
|
||||
const completedQuestId = body.qid;
|
||||
const clientQuestsClone = this.jsonUtil.clone(this.getClientQuests(sessionID)); // Must be gathered prior to applyQuestReward() & failQuests()
|
||||
const clientQuestsClone = this.cloner.clone(this.getClientQuests(sessionID)); // Must be gathered prior to applyQuestReward() & failQuests()
|
||||
|
||||
const newQuestState = QuestStatus.Success;
|
||||
this.questHelper.updateQuestState(pmcData, newQuestState, completedQuestId);
|
||||
|
@ -26,6 +26,7 @@ import { ConfigServer } from "@spt-aki/servers/ConfigServer";
|
||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { PaymentService } from "@spt-aki/services/PaymentService";
|
||||
import { ProfileFixerService } from "@spt-aki/services/ProfileFixerService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { HttpResponseUtil } from "@spt-aki/utils/HttpResponseUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { ObjectId } from "@spt-aki/utils/ObjectId";
|
||||
@ -53,6 +54,7 @@ export class RepeatableQuestController
|
||||
@inject("RepeatableQuestHelper") protected repeatableQuestHelper: RepeatableQuestHelper,
|
||||
@inject("QuestHelper") protected questHelper: QuestHelper,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.questConfig = this.configServer.getConfig(ConfigTypes.QUEST);
|
||||
@ -458,7 +460,7 @@ export class RepeatableQuestController
|
||||
);
|
||||
|
||||
// Get cost to replace existing quest
|
||||
changeRequirement = this.jsonUtil.clone(currentRepeatablePool.changeRequirement[changeRequest.qid]);
|
||||
changeRequirement = this.cloner.clone(currentRepeatablePool.changeRequirement[changeRequest.qid]);
|
||||
delete currentRepeatablePool.changeRequirement[changeRequest.qid];
|
||||
// TODO: somehow we need to reduce the questPool by the currently active quests (for all repeatables)
|
||||
|
||||
@ -490,7 +492,7 @@ export class RepeatableQuestController
|
||||
}
|
||||
|
||||
// Found and replaced the quest in current repeatable
|
||||
repeatableToChange = this.jsonUtil.clone(currentRepeatablePool);
|
||||
repeatableToChange = this.cloner.clone(currentRepeatablePool);
|
||||
delete repeatableToChange.inactiveQuests;
|
||||
|
||||
break;
|
||||
|
@ -13,6 +13,7 @@ import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { FenceService } from "@spt-aki/services/FenceService";
|
||||
import { TraderAssortService } from "@spt-aki/services/TraderAssortService";
|
||||
import { TraderPurchasePersisterService } from "@spt-aki/services/TraderPurchasePersisterService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { TimeUtil } from "@spt-aki/utils/TimeUtil";
|
||||
|
||||
@ -34,6 +35,7 @@ export class TraderController
|
||||
@inject("FenceBaseAssortGenerator") protected fenceBaseAssortGenerator: FenceBaseAssortGenerator,
|
||||
@inject("JsonUtil") protected jsonUtil: JsonUtil,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.traderConfig = this.configServer.getConfig(ConfigTypes.TRADER);
|
||||
@ -67,7 +69,7 @@ export class TraderController
|
||||
// Create dict of trader assorts on server start
|
||||
if (!this.traderAssortService.getPristineTraderAssort(traderId))
|
||||
{
|
||||
const assortsClone = this.jsonUtil.clone(trader.assort);
|
||||
const assortsClone = this.cloner.clone(trader.assort);
|
||||
this.traderAssortService.setPristineTraderAssort(traderId, assortsClone);
|
||||
}
|
||||
|
||||
|
@ -240,6 +240,10 @@ import { TraderPurchasePersisterService } from "@spt-aki/services/TraderPurchase
|
||||
import { TraderServicesService } from "@spt-aki/services/TraderServicesService";
|
||||
import { App } from "@spt-aki/utils/App";
|
||||
import { AsyncQueue } from "@spt-aki/utils/AsyncQueue";
|
||||
import type { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { JsonCloner } from "@spt-aki/utils/cloners/JsonCloner";
|
||||
import { RecursiveCloner } from "@spt-aki/utils/cloners/RecursiveCloner";
|
||||
import { StructuredCloner } from "@spt-aki/utils/cloners/StructuredCloner";
|
||||
import { CompareUtil } from "@spt-aki/utils/CompareUtil";
|
||||
import { DatabaseImporter } from "@spt-aki/utils/DatabaseImporter";
|
||||
import { EncodingUtil } from "@spt-aki/utils/EncodingUtil";
|
||||
@ -411,6 +415,9 @@ export class Container
|
||||
depContainer.register<ModLoadOrder>("ModLoadOrder", ModLoadOrder, { lifecycle: Lifecycle.Singleton });
|
||||
depContainer.register<ModTypeCheck>("ModTypeCheck", ModTypeCheck, { lifecycle: Lifecycle.Singleton });
|
||||
depContainer.register<CompareUtil>("CompareUtil", CompareUtil, { lifecycle: Lifecycle.Singleton });
|
||||
depContainer.register<ICloner>("StructuredCloner", StructuredCloner, { lifecycle: Lifecycle.Singleton });
|
||||
depContainer.register<ICloner>("JsonCloner", JsonCloner, { lifecycle: Lifecycle.Singleton });
|
||||
depContainer.register<ICloner>("RecursiveCloner", RecursiveCloner, { lifecycle: Lifecycle.Singleton });
|
||||
}
|
||||
|
||||
private static registerRouters(depContainer: DependencyContainer): void
|
||||
|
@ -25,6 +25,7 @@ import { BotEquipmentModPoolService } from "@spt-aki/services/BotEquipmentModPoo
|
||||
import { BotModLimits, BotWeaponModLimitService } from "@spt-aki/services/BotWeaponModLimitService";
|
||||
import { ItemFilterService } from "@spt-aki/services/ItemFilterService";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
|
||||
@ -56,6 +57,7 @@ export class BotEquipmentModGenerator
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||
@inject("BotEquipmentModPoolService") protected botEquipmentModPoolService: BotEquipmentModPoolService,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.botConfig = this.configServer.getConfig(ConfigTypes.BOT);
|
||||
@ -157,7 +159,7 @@ export class BotEquipmentModGenerator
|
||||
// Find random mod and check its compatible
|
||||
let modTpl: string;
|
||||
let found = false;
|
||||
const exhaustableModPool = new ExhaustableArray(modPoolToChooseFrom, this.randomUtil, this.jsonUtil);
|
||||
const exhaustableModPool = new ExhaustableArray(modPoolToChooseFrom, this.randomUtil, this.cloner);
|
||||
while (exhaustableModPool.hasValues())
|
||||
{
|
||||
modTpl = exhaustableModPool.getRandomValue();
|
||||
@ -857,7 +859,7 @@ export class BotEquipmentModGenerator
|
||||
): IChooseRandomCompatibleModResult
|
||||
{
|
||||
let chosenTpl: string;
|
||||
const exhaustableModPool = new ExhaustableArray(modPool, this.randomUtil, this.jsonUtil);
|
||||
const exhaustableModPool = new ExhaustableArray(modPool, this.randomUtil, this.cloner);
|
||||
let chosenModResult: IChooseRandomCompatibleModResult = { incompatible: true, found: false, reason: "unknown" };
|
||||
const modParentFilterList = parentSlot._props.filters[0].Filter;
|
||||
|
||||
@ -1091,7 +1093,7 @@ export class BotEquipmentModGenerator
|
||||
const allowedItems = parentSlot._props.filters[0].Filter;
|
||||
|
||||
// Find mod item that fits slot from sorted mod array
|
||||
const exhaustableModPool = new ExhaustableArray(allowedItems, this.randomUtil, this.jsonUtil);
|
||||
const exhaustableModPool = new ExhaustableArray(allowedItems, this.randomUtil, this.cloner);
|
||||
let tmpModTpl = modTpl;
|
||||
while (exhaustableModPool.hasValues())
|
||||
{
|
||||
@ -1221,7 +1223,7 @@ export class BotEquipmentModGenerator
|
||||
botEquipBlacklist: EquipmentFilterDetails,
|
||||
): string[]
|
||||
{
|
||||
const modsFromDynamicPool = this.jsonUtil.clone(
|
||||
const modsFromDynamicPool = this.cloner.clone(
|
||||
this.botEquipmentModPoolService.getCompatibleModsForWeaponSlot(parentItemId, modSlot),
|
||||
);
|
||||
|
||||
@ -1303,7 +1305,7 @@ export class BotEquipmentModGenerator
|
||||
const camoraFirstSlot = "camora_000";
|
||||
if (modSlot in itemModPool)
|
||||
{
|
||||
exhaustableModPool = new ExhaustableArray(itemModPool[modSlot], this.randomUtil, this.jsonUtil);
|
||||
exhaustableModPool = new ExhaustableArray(itemModPool[modSlot], this.randomUtil, this.cloner);
|
||||
}
|
||||
else if (camoraFirstSlot in itemModPool)
|
||||
{
|
||||
@ -1311,7 +1313,7 @@ export class BotEquipmentModGenerator
|
||||
exhaustableModPool = new ExhaustableArray(
|
||||
this.mergeCamoraPoolsTogether(itemModPool),
|
||||
this.randomUtil,
|
||||
this.jsonUtil,
|
||||
this.cloner,
|
||||
);
|
||||
}
|
||||
else
|
||||
|
@ -29,6 +29,7 @@ import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { BotEquipmentFilterService } from "@spt-aki/services/BotEquipmentFilterService";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { SeasonalEventService } from "@spt-aki/services/SeasonalEventService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
|
||||
@ -57,6 +58,7 @@ export class BotGenerator
|
||||
@inject("SeasonalEventService") protected seasonalEventService: SeasonalEventService,
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.botConfig = this.configServer.getConfig(ConfigTypes.BOT);
|
||||
@ -109,7 +111,7 @@ export class BotGenerator
|
||||
bot.Info.Settings.BotDifficulty = botGenerationDetails.botDifficulty;
|
||||
|
||||
// Get raw json data for bot (Cloned)
|
||||
const botJsonTemplateClone = this.jsonUtil.clone(
|
||||
const botJsonTemplateClone = this.cloner.clone(
|
||||
this.botHelper.getBotTemplate(botGenerationDetails.isPmc ? bot.Info.Side : botGenerationDetails.role),
|
||||
);
|
||||
|
||||
@ -124,7 +126,7 @@ export class BotGenerator
|
||||
*/
|
||||
protected getCloneOfBotBase(): IBotBase
|
||||
{
|
||||
return this.jsonUtil.clone(this.databaseServer.getTables().bots.base);
|
||||
return this.cloner.clone(this.databaseServer.getTables().bots.base);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -23,6 +23,7 @@ import { ConfigServer } from "@spt-aki/servers/ConfigServer";
|
||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { BotLootCacheService } from "@spt-aki/services/BotLootCacheService";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
|
||||
@ -49,6 +50,7 @@ export class BotLootGenerator
|
||||
@inject("BotLootCacheService") protected botLootCacheService: BotLootCacheService,
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.botConfig = this.configServer.getConfig(ConfigTypes.BOT);
|
||||
@ -459,7 +461,7 @@ export class BotLootGenerator
|
||||
|
||||
// Check if all the chosen currency items fit into wallet
|
||||
const canAddToContainer = this.inventoryHelper.canPlaceItemsInContainer(
|
||||
this.jsonUtil.clone(containerGrid), // MUST clone grid before passing in as function modifies grid
|
||||
this.cloner.clone(containerGrid), // MUST clone grid before passing in as function modifies grid
|
||||
itemsToAdd,
|
||||
);
|
||||
if (canAddToContainer)
|
||||
|
@ -23,6 +23,7 @@ import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { BotWeaponModLimitService } from "@spt-aki/services/BotWeaponModLimitService";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { RepairService } from "@spt-aki/services/RepairService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
|
||||
@ -51,6 +52,7 @@ export class BotWeaponGenerator
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||
@inject("RepairService") protected repairService: RepairService,
|
||||
@injectAll("InventoryMagGen") protected inventoryMagGenComponents: IInventoryMagGen[],
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.botConfig = this.configServer.getConfig(ConfigTypes.BOT);
|
||||
@ -323,7 +325,7 @@ export class BotWeaponGenerator
|
||||
{
|
||||
if (presetObj._items[0]._tpl === weaponTpl)
|
||||
{
|
||||
preset = this.jsonUtil.clone(presetObj);
|
||||
preset = this.cloner.clone(presetObj);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -582,7 +584,7 @@ export class BotWeaponGenerator
|
||||
{
|
||||
const desiredCaliber = this.getWeaponCaliber(weaponTemplate);
|
||||
|
||||
const compatibleCartridges = this.jsonUtil.clone(ammo[desiredCaliber]);
|
||||
const compatibleCartridges = this.cloner.clone(ammo[desiredCaliber]);
|
||||
if (!compatibleCartridges || compatibleCartridges?.length === 0)
|
||||
{
|
||||
this.logger.debug(
|
||||
|
@ -23,6 +23,7 @@ import { ConfigServer } from "@spt-aki/servers/ConfigServer";
|
||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { SeasonalEventService } from "@spt-aki/services/SeasonalEventService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { MathUtil } from "@spt-aki/utils/MathUtil";
|
||||
import { ObjectId } from "@spt-aki/utils/ObjectId";
|
||||
@ -61,6 +62,7 @@ export class LocationGenerator
|
||||
@inject("PresetHelper") protected presetHelper: PresetHelper,
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.locationConfig = this.configServer.getConfig(ConfigTypes.LOCATION);
|
||||
@ -84,7 +86,8 @@ export class LocationGenerator
|
||||
const db = this.databaseServer.getTables();
|
||||
const mapData: ILocation = db.locations[locationId];
|
||||
|
||||
const staticWeaponsOnMapClone = this.jsonUtil.clone(mapData.staticContainers.staticWeapons);
|
||||
const staticWeaponsOnMapClone = this.cloner.clone(mapData.staticContainers.staticWeapons);
|
||||
|
||||
if (!staticWeaponsOnMapClone)
|
||||
{
|
||||
this.logger.error(`Unable to find static weapon data for map: ${locationBase.Name}`);
|
||||
@ -93,7 +96,8 @@ export class LocationGenerator
|
||||
// Add mounted weapons to output loot
|
||||
result.push(...staticWeaponsOnMapClone ?? []);
|
||||
|
||||
const allStaticContainersOnMapClone = this.jsonUtil.clone(mapData.staticContainers.staticContainers);
|
||||
const allStaticContainersOnMapClone = this.cloner.clone(mapData.staticContainers.staticContainers);
|
||||
|
||||
if (!allStaticContainersOnMapClone)
|
||||
{
|
||||
this.logger.error(`Unable to find static container data for map: ${locationBase.Name}`);
|
||||
@ -101,7 +105,8 @@ export class LocationGenerator
|
||||
const staticRandomisableContainersOnMap = this.getRandomisableContainersOnMap(allStaticContainersOnMapClone);
|
||||
|
||||
// Containers that MUST be added to map (quest containers etc)
|
||||
const staticForcedOnMapClone = this.jsonUtil.clone(mapData.staticContainers.staticForced);
|
||||
const staticForcedOnMapClone = this.cloner.clone(mapData.staticContainers.staticForced);
|
||||
|
||||
if (!staticForcedOnMapClone)
|
||||
{
|
||||
this.logger.error(`Unable to find forced static data for map: ${locationBase.Name}`);
|
||||
@ -192,7 +197,7 @@ export class LocationGenerator
|
||||
// EDGE CASE: These are containers without a group and have a probability < 100%
|
||||
if (groupId === "")
|
||||
{
|
||||
const containerIdsCopy = this.jsonUtil.clone(data.containerIdsWithProbability);
|
||||
const containerIdsCopy = this.cloner.clone(data.containerIdsWithProbability);
|
||||
// Roll each containers probability, if it passes, it gets added
|
||||
data.containerIdsWithProbability = {};
|
||||
for (const containerId in containerIdsCopy)
|
||||
@ -305,7 +310,7 @@ export class LocationGenerator
|
||||
}
|
||||
|
||||
// Create probability array with all possible container ids in this group and their relataive probability of spawning
|
||||
const containerDistribution = new ProbabilityObjectArray<string>(this.mathUtil, this.jsonUtil);
|
||||
const containerDistribution = new ProbabilityObjectArray<string>(this.mathUtil, this.cloner);
|
||||
for (const x of containerIds)
|
||||
{
|
||||
containerDistribution.push(new ProbabilityObject(x, containerData.containerIdsWithProbability[x]));
|
||||
@ -395,7 +400,7 @@ export class LocationGenerator
|
||||
locationName: string,
|
||||
): IStaticContainerData
|
||||
{
|
||||
const containerClone = this.jsonUtil.clone(staticContainer);
|
||||
const containerClone = this.cloner.clone(staticContainer);
|
||||
const containerTpl = containerClone.template.Items[0]._tpl;
|
||||
|
||||
// Create new unique parent id to prevent any collisions
|
||||
@ -509,7 +514,7 @@ export class LocationGenerator
|
||||
): number
|
||||
{
|
||||
// Create probability array to calcualte the total count of lootable items inside container
|
||||
const itemCountArray = new ProbabilityObjectArray<number>(this.mathUtil, this.jsonUtil);
|
||||
const itemCountArray = new ProbabilityObjectArray<number>(this.mathUtil, this.cloner);
|
||||
const countDistribution = staticLootDist[containerTypeId]?.itemcountDistribution;
|
||||
if (!countDistribution)
|
||||
{
|
||||
@ -546,7 +551,7 @@ export class LocationGenerator
|
||||
const seasonalEventActive = this.seasonalEventService.seasonalEventEnabled();
|
||||
const seasonalItemTplBlacklist = this.seasonalEventService.getInactiveSeasonalEventItems();
|
||||
|
||||
const itemDistribution = new ProbabilityObjectArray<string>(this.mathUtil, this.jsonUtil);
|
||||
const itemDistribution = new ProbabilityObjectArray<string>(this.mathUtil, this.cloner);
|
||||
|
||||
const itemContainerDistribution = staticLootDist[containerTypeId]?.itemDistribution;
|
||||
if (!itemContainerDistribution)
|
||||
@ -617,7 +622,7 @@ export class LocationGenerator
|
||||
const guaranteedLoosePoints: Spawnpoint[] = [];
|
||||
|
||||
const blacklistedSpawnpoints = this.locationConfig.looseLootBlacklist[locationName];
|
||||
const spawnpointArray = new ProbabilityObjectArray<string, Spawnpoint>(this.mathUtil, this.jsonUtil);
|
||||
const spawnpointArray = new ProbabilityObjectArray<string, Spawnpoint>(this.mathUtil, this.cloner);
|
||||
|
||||
for (const spawnpoint of allDynamicSpawnpoints)
|
||||
{
|
||||
@ -699,7 +704,7 @@ export class LocationGenerator
|
||||
continue;
|
||||
}
|
||||
|
||||
const itemArray = new ProbabilityObjectArray<string>(this.mathUtil, this.jsonUtil);
|
||||
const itemArray = new ProbabilityObjectArray<string>(this.mathUtil, this.cloner);
|
||||
for (const itemDist of spawnPoint.itemDistribution)
|
||||
{
|
||||
if (
|
||||
@ -769,7 +774,7 @@ export class LocationGenerator
|
||||
// Create probability array of all spawn positions for this spawn id
|
||||
const spawnpointArray = new ProbabilityObjectArray<string, SpawnpointsForced>(
|
||||
this.mathUtil,
|
||||
this.jsonUtil,
|
||||
this.cloner,
|
||||
);
|
||||
for (const si of items)
|
||||
{
|
||||
@ -986,7 +991,7 @@ export class LocationGenerator
|
||||
else if (this.itemHelper.isOfBaseclass(chosenTpl, BaseClasses.WEAPON))
|
||||
{
|
||||
let children: Item[] = [];
|
||||
const defaultPreset = this.jsonUtil.clone(this.presetHelper.getDefaultPreset(chosenTpl));
|
||||
const defaultPreset = this.cloner.clone(this.presetHelper.getDefaultPreset(chosenTpl));
|
||||
if (defaultPreset)
|
||||
{
|
||||
try
|
||||
|
@ -22,6 +22,7 @@ import { SaveServer } from "@spt-aki/servers/SaveServer";
|
||||
import { BotLootCacheService } from "@spt-aki/services/BotLootCacheService";
|
||||
import { FenceService } from "@spt-aki/services/FenceService";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
|
||||
@ -47,6 +48,7 @@ export class PlayerScavGenerator
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||
@inject("BotGenerator") protected botGenerator: BotGenerator,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.playerScavConfig = this.configServer.getConfig(ConfigTypes.PLAYERSCAV);
|
||||
@ -61,8 +63,8 @@ export class PlayerScavGenerator
|
||||
{
|
||||
// get karma level from profile
|
||||
const profile = this.saveServer.getProfile(sessionID);
|
||||
const pmcDataClone = this.jsonUtil.clone(profile.characters.pmc);
|
||||
const existingScavDataClone = this.jsonUtil.clone(profile.characters.scav);
|
||||
const pmcDataClone = this.cloner.clone(profile.characters.pmc);
|
||||
const existingScavDataClone = this.cloner.clone(profile.characters.scav);
|
||||
|
||||
const scavKarmaLevel = this.getScavKarmaLevel(pmcDataClone);
|
||||
|
||||
@ -219,7 +221,7 @@ export class PlayerScavGenerator
|
||||
protected constructBotBaseTemplate(botTypeForLoot: string): IBotType
|
||||
{
|
||||
const baseScavType = "assault";
|
||||
const assaultBase = this.jsonUtil.clone(this.botHelper.getBotTemplate(baseScavType));
|
||||
const assaultBase = this.cloner.clone(this.botHelper.getBotTemplate(baseScavType));
|
||||
|
||||
// Loot bot is same as base bot, return base with no modification
|
||||
if (botTypeForLoot === baseScavType)
|
||||
@ -227,7 +229,7 @@ export class PlayerScavGenerator
|
||||
return assaultBase;
|
||||
}
|
||||
|
||||
const lootBase = this.jsonUtil.clone(this.botHelper.getBotTemplate(botTypeForLoot));
|
||||
const lootBase = this.cloner.clone(this.botHelper.getBotTemplate(botTypeForLoot));
|
||||
assaultBase.inventory = lootBase.inventory;
|
||||
assaultBase.chances = lootBase.chances;
|
||||
assaultBase.generation = lootBase.generation;
|
||||
|
@ -27,6 +27,7 @@ import { FenceService } from "@spt-aki/services/FenceService";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { RagfairOfferService } from "@spt-aki/services/RagfairOfferService";
|
||||
import { RagfairPriceService } from "@spt-aki/services/RagfairPriceService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
|
||||
@ -60,6 +61,7 @@ export class RagfairOfferGenerator
|
||||
@inject("FenceService") protected fenceService: FenceService,
|
||||
@inject("ItemHelper") protected itemHelper: ItemHelper,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR);
|
||||
@ -123,7 +125,7 @@ export class RagfairOfferGenerator
|
||||
offerRequirements.push(requirement);
|
||||
}
|
||||
|
||||
const itemsClone = this.jsonUtil.clone(items);
|
||||
const itemsClone = this.cloner.clone(items);
|
||||
|
||||
// Add cartridges to offers for ammo boxes
|
||||
if (this.itemHelper.isOfBaseclass(itemsClone[0]._tpl, BaseClasses.AMMO_BOX))
|
||||
@ -380,7 +382,7 @@ export class RagfairOfferGenerator
|
||||
for (let index = 0; index < offerCount; index++)
|
||||
{
|
||||
// Clone the item so we don't have shared references and generate new item IDs
|
||||
const clonedAssort = this.jsonUtil.clone(assortItemWithChildren);
|
||||
const clonedAssort = this.cloner.clone(assortItemWithChildren);
|
||||
this.itemHelper.reparentItemAndChildren(clonedAssort[0], clonedAssort);
|
||||
|
||||
// Clear unnecessary properties
|
||||
|
@ -20,6 +20,7 @@ import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { ConfigServer } from "@spt-aki/servers/ConfigServer";
|
||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { MathUtil } from "@spt-aki/utils/MathUtil";
|
||||
import { ObjectId } from "@spt-aki/utils/ObjectId";
|
||||
@ -43,6 +44,7 @@ export class RepeatableQuestGenerator
|
||||
@inject("RepeatableQuestRewardGenerator") protected repeatableQuestRewardGenerator:
|
||||
RepeatableQuestRewardGenerator,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.questConfig = this.configServer.getConfig(ConfigTypes.QUEST);
|
||||
@ -873,7 +875,7 @@ export class RepeatableQuestGenerator
|
||||
// @Incomplete: define Type for "type".
|
||||
protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest
|
||||
{
|
||||
const questClone = this.jsonUtil.clone<IRepeatableQuest>(
|
||||
const questClone = this.cloner.clone<IRepeatableQuest>(
|
||||
this.databaseServer.getTables().templates.repeatableQuests.templates[type],
|
||||
);
|
||||
questClone._id = this.objectId.generate();
|
||||
|
@ -19,6 +19,7 @@ import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { ItemFilterService } from "@spt-aki/services/ItemFilterService";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { SeasonalEventService } from "@spt-aki/services/SeasonalEventService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { MathUtil } from "@spt-aki/utils/MathUtil";
|
||||
import { ObjectId } from "@spt-aki/utils/ObjectId";
|
||||
@ -43,6 +44,7 @@ export class RepeatableQuestRewardGenerator
|
||||
@inject("ItemFilterService") protected itemFilterService: ItemFilterService,
|
||||
@inject("SeasonalEventService") protected seasonalEventService: SeasonalEventService,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.questConfig = this.configServer.getConfig(ConfigTypes.QUEST);
|
||||
@ -144,7 +146,7 @@ export class RepeatableQuestRewardGenerator
|
||||
const defaultPresetPool = new ExhaustableArray(
|
||||
Object.values(this.presetHelper.getDefaultWeaponPresets()),
|
||||
this.randomUtil,
|
||||
this.jsonUtil,
|
||||
this.cloner,
|
||||
);
|
||||
let chosenPreset: IPreset;
|
||||
while (defaultPresetPool.hasValues())
|
||||
@ -156,7 +158,7 @@ export class RepeatableQuestRewardGenerator
|
||||
{
|
||||
this.logger.debug(` Added weapon ${tpls[0]} with price ${presetPrice}`);
|
||||
roublesBudget -= presetPrice;
|
||||
chosenPreset = this.jsonUtil.clone(randomPreset);
|
||||
chosenPreset = this.cloner.clone(randomPreset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { ConfigServer } from "@spt-aki/servers/ConfigServer";
|
||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
|
||||
|
||||
@ -23,6 +24,7 @@ export class BotDifficultyHelper
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||
@inject("BotHelper") protected botHelper: BotHelper,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.pmcConfig = this.configServer.getConfig(ConfigTypes.PMC);
|
||||
@ -61,7 +63,7 @@ export class BotDifficultyHelper
|
||||
{
|
||||
// get fallback
|
||||
this.logger.warning(this.localisationService.getText("bot-unable_to_get_bot_fallback_to_assault", type));
|
||||
this.databaseServer.getTables().bots.types[type] = this.jsonUtil.clone(
|
||||
this.databaseServer.getTables().bots.types[type] = this.cloner.clone(
|
||||
this.databaseServer.getTables().bots.types.assault,
|
||||
);
|
||||
}
|
||||
@ -75,12 +77,12 @@ export class BotDifficultyHelper
|
||||
difficulty: difficulty,
|
||||
}),
|
||||
);
|
||||
this.databaseServer.getTables().bots.types[type].difficulty[difficulty] = this.jsonUtil.clone(
|
||||
this.databaseServer.getTables().bots.types[type].difficulty[difficulty] = this.cloner.clone(
|
||||
this.databaseServer.getTables().bots.types.assault.difficulty[difficulty],
|
||||
);
|
||||
}
|
||||
|
||||
return this.jsonUtil.clone(difficultySettings);
|
||||
return this.cloner.clone(difficultySettings);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -97,7 +99,7 @@ export class BotDifficultyHelper
|
||||
|
||||
difficultySetting = this.convertBotDifficultyDropdownToBotDifficulty(difficultySetting);
|
||||
|
||||
return this.jsonUtil.clone(this.databaseServer.getTables().bots.types[type].difficulty[difficultySetting]);
|
||||
return this.cloner.clone(this.databaseServer.getTables().bots.types[type].difficulty[difficultySetting]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -14,6 +14,7 @@ import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { ItemFilterService } from "@spt-aki/services/ItemFilterService";
|
||||
import { LocaleService } from "@spt-aki/services/LocaleService";
|
||||
import { MailSendService } from "@spt-aki/services/MailSendService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
|
||||
@ -43,6 +44,7 @@ export class GiveSptCommand implements ISptCommand
|
||||
@inject("LocaleService") protected localeService: LocaleService,
|
||||
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
|
||||
@inject("ItemFilterService") protected itemFilterService: ItemFilterService,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
}
|
||||
@ -229,7 +231,7 @@ export class GiveSptCommand implements ISptCommand
|
||||
}
|
||||
for (let i = 0; i < quantity; i++)
|
||||
{
|
||||
let items = this.jsonUtil.clone(preset._items);
|
||||
let items = this.cloner.clone(preset._items);
|
||||
items = this.itemHelper.replaceIDs(items);
|
||||
itemsToSend.push(...items);
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import { Money } from "@spt-aki/models/enums/Money";
|
||||
import { IItemConfig } from "@spt-aki/models/spt/config/IItemConfig";
|
||||
import { ConfigServer } from "@spt-aki/servers/ConfigServer";
|
||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
|
||||
class LookupItem<T, I>
|
||||
@ -43,6 +44,7 @@ export class HandbookHelper
|
||||
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
|
||||
@inject("JsonUtil") protected jsonUtil: JsonUtil,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.itemConfig = this.configServer.getConfig(ConfigTypes.ITEM);
|
||||
@ -74,7 +76,7 @@ export class HandbookHelper
|
||||
itemToUpdate.Price = this.itemConfig.handbookPriceOverride[itemTpl];
|
||||
}
|
||||
|
||||
const handbookDbClone = this.jsonUtil.clone(this.databaseServer.getTables().templates.handbook);
|
||||
const handbookDbClone = this.cloner.clone(this.databaseServer.getTables().templates.handbook);
|
||||
for (const handbookItem of handbookDbClone.Items)
|
||||
{
|
||||
this.handbookPriceCache.items.byId.set(handbookItem.Id, handbookItem.Price);
|
||||
|
@ -7,6 +7,7 @@ import { IHealthConfig } from "@spt-aki/models/spt/config/IHealthConfig";
|
||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { ConfigServer } from "@spt-aki/servers/ConfigServer";
|
||||
import { SaveServer } from "@spt-aki/servers/SaveServer";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { TimeUtil } from "@spt-aki/utils/TimeUtil";
|
||||
|
||||
@ -21,6 +22,7 @@ export class HealthHelper
|
||||
@inject("TimeUtil") protected timeUtil: TimeUtil,
|
||||
@inject("SaveServer") protected saveServer: SaveServer,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.healthConfig = this.configServer.getConfig(ConfigTypes.HEALTH);
|
||||
@ -115,7 +117,7 @@ export class HealthHelper
|
||||
this.saveEffects(
|
||||
pmcData,
|
||||
sessionID,
|
||||
this.jsonUtil.clone(this.saveServer.getProfile(sessionID).vitality.effects),
|
||||
this.cloner.clone(this.saveServer.getProfile(sessionID).vitality.effects),
|
||||
deleteExistingEffects,
|
||||
);
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import { ConfigServer } from "@spt-aki/servers/ConfigServer";
|
||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { PlayerService } from "@spt-aki/services/PlayerService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
import { HttpResponseUtil } from "@spt-aki/utils/HttpResponseUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
@ -54,6 +55,7 @@ export class HideoutHelper
|
||||
@inject("ItemHelper") protected itemHelper: ItemHelper,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("JsonUtil") protected jsonUtil: JsonUtil,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.hideoutConfig = this.configServer.getConfig(ConfigTypes.HIDEOUT);
|
||||
@ -106,7 +108,7 @@ export class HideoutHelper
|
||||
|
||||
for (const tool of bodyAsSingle.tools)
|
||||
{
|
||||
const toolItem = this.jsonUtil.clone(pmcData.Inventory.items.find(x => x._id === tool.id));
|
||||
const toolItem = this.cloner.clone(pmcData.Inventory.items.find(x => x._id === tool.id));
|
||||
|
||||
// Make sure we only return as many as we took
|
||||
this.itemHelper.addUpdObjectToItem(toolItem);
|
||||
|
@ -19,6 +19,7 @@ import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { SaveServer } from "@spt-aki/servers/SaveServer";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { ProfileFixerService } from "@spt-aki/services/ProfileFixerService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
|
||||
import { TimeUtil } from "@spt-aki/utils/TimeUtil";
|
||||
@ -45,6 +46,7 @@ export class InRaidHelper
|
||||
@inject("ProfileFixerService") protected profileFixerService: ProfileFixerService,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RandomUtil") protected randomUtil: RandomUtil,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.lostOnDeathConfig = this.configServer.getConfig(ConfigTypes.LOST_ON_DEATH);
|
||||
@ -480,7 +482,7 @@ export class InRaidHelper
|
||||
public setInventory(sessionID: string, serverProfile: IPmcData, postRaidProfile: IPmcData): void
|
||||
{
|
||||
// Store insurance (as removeItem() removes insurance also)
|
||||
const insured = this.jsonUtil.clone(serverProfile.InsuredItems);
|
||||
const insured = this.cloner.clone(serverProfile.InsuredItems);
|
||||
|
||||
// Remove possible equipped items from before the raid
|
||||
this.inventoryHelper.removeItem(serverProfile, serverProfile.Inventory.equipment, sessionID);
|
||||
|
@ -30,6 +30,7 @@ import { ConfigServer } from "@spt-aki/servers/ConfigServer";
|
||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { FenceService } from "@spt-aki/services/FenceService";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
import { HttpResponseUtil } from "@spt-aki/utils/HttpResponseUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
@ -65,6 +66,7 @@ export class InventoryHelper
|
||||
@inject("PresetHelper") protected presetHelper: PresetHelper,
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.inventoryConfig = this.configServer.getConfig(ConfigTypes.INVENTORY);
|
||||
@ -129,7 +131,7 @@ export class InventoryHelper
|
||||
output: IItemEventRouterResponse,
|
||||
): void
|
||||
{
|
||||
const itemWithModsToAddClone = this.jsonUtil.clone(request.itemWithModsToAdd);
|
||||
const itemWithModsToAddClone = this.cloner.clone(request.itemWithModsToAdd);
|
||||
|
||||
// Get stash layouts ready for use
|
||||
const stashFS2D = this.getStashSlotMap(pmcData, sessionId);
|
||||
@ -245,7 +247,7 @@ export class InventoryHelper
|
||||
{
|
||||
const pmcData = this.profileHelper.getPmcProfile(sessionId);
|
||||
|
||||
const stashFS2D = this.jsonUtil.clone(this.getStashSlotMap(pmcData, sessionId));
|
||||
const stashFS2D = this.cloner.clone(this.getStashSlotMap(pmcData, sessionId));
|
||||
for (const itemWithChildren of itemsWithChildren)
|
||||
{
|
||||
if (this.canPlaceItemInContainer(stashFS2D, itemWithChildren))
|
||||
@ -534,7 +536,7 @@ export class InventoryHelper
|
||||
// Keep splitting items into stacks until none left
|
||||
if (remainingCountOfItemToAdd > 0)
|
||||
{
|
||||
const newChildItemToAdd = this.jsonUtil.clone(itemToAdd);
|
||||
const newChildItemToAdd = this.cloner.clone(itemToAdd);
|
||||
if (remainingCountOfItemToAdd > itemDetails._props.StackMaxSize)
|
||||
{
|
||||
// Reduce total count of item purchased by stack size we're going to add to inventory
|
||||
|
@ -13,6 +13,7 @@ import { ItemBaseClassService } from "@spt-aki/services/ItemBaseClassService";
|
||||
import { ItemFilterService } from "@spt-aki/services/ItemFilterService";
|
||||
import { LocaleService } from "@spt-aki/services/LocaleService";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { CompareUtil } from "@spt-aki/utils/CompareUtil";
|
||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
@ -47,6 +48,7 @@ export class ItemHelper
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||
@inject("LocaleService") protected localeService: LocaleService,
|
||||
@inject("CompareUtil") protected compareUtil: CompareUtil,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{}
|
||||
|
||||
@ -428,7 +430,7 @@ export class ItemHelper
|
||||
*/
|
||||
public getItems(): ITemplateItem[]
|
||||
{
|
||||
return this.jsonUtil.clone(Object.values(this.databaseServer.getTables().templates.items));
|
||||
return this.cloner.clone(Object.values(this.databaseServer.getTables().templates.items));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -734,7 +736,7 @@ export class ItemHelper
|
||||
// return the item as is.
|
||||
if (remainingCount <= maxStackSize)
|
||||
{
|
||||
rootAndChildren.push(this.jsonUtil.clone(itemToSplit));
|
||||
rootAndChildren.push(this.cloner.clone(itemToSplit));
|
||||
|
||||
return rootAndChildren;
|
||||
}
|
||||
@ -742,7 +744,7 @@ export class ItemHelper
|
||||
while (remainingCount)
|
||||
{
|
||||
const amount = Math.min(remainingCount, maxStackSize);
|
||||
const newStackClone = this.jsonUtil.clone(itemToSplit);
|
||||
const newStackClone = this.cloner.clone(itemToSplit);
|
||||
|
||||
newStackClone._id = this.hashUtil.generate();
|
||||
newStackClone.upd.StackObjectsCount = amount;
|
||||
@ -775,7 +777,7 @@ export class ItemHelper
|
||||
while (remainingCount)
|
||||
{
|
||||
const amount = Math.min(remainingCount, itemMaxStackSize);
|
||||
const newItemClone = this.jsonUtil.clone(itemToSplit);
|
||||
const newItemClone = this.cloner.clone(itemToSplit);
|
||||
|
||||
newItemClone._id = this.hashUtil.generate();
|
||||
newItemClone.upd.StackObjectsCount = amount;
|
||||
@ -836,7 +838,7 @@ export class ItemHelper
|
||||
fastPanel = null,
|
||||
): Item[]
|
||||
{
|
||||
let items = this.jsonUtil.clone(originalItems); // Deep-clone the items to avoid mutation.
|
||||
let items = this.cloner.clone(originalItems); // Deep-clone the items to avoid mutation.
|
||||
let serialisedInventory = this.jsonUtil.serialize(items);
|
||||
|
||||
for (const item of items)
|
||||
|
@ -2,6 +2,7 @@ import { inject, injectable } from "tsyringe";
|
||||
import { IPreset } from "@spt-aki/models/eft/common/IGlobals";
|
||||
import { BaseClasses } from "@spt-aki/models/enums/BaseClasses";
|
||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { ItemHelper } from "./ItemHelper";
|
||||
|
||||
@ -16,6 +17,7 @@ export class PresetHelper
|
||||
@inject("JsonUtil") protected jsonUtil: JsonUtil,
|
||||
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
|
||||
@inject("ItemHelper") protected itemHelper: ItemHelper,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{}
|
||||
|
||||
@ -70,8 +72,10 @@ export class PresetHelper
|
||||
{
|
||||
if (!this.defaultEquipmentPresets)
|
||||
{
|
||||
this.defaultEquipmentPresets = Object.values(this.databaseServer.getTables().globals.ItemPresets).filter(preset => preset._encyclopedia !== undefined && this.itemHelper.armorItemCanHoldMods(preset._encyclopedia))
|
||||
.reduce((acc, cur) =>
|
||||
this.defaultEquipmentPresets = Object.values(this.databaseServer.getTables().globals.ItemPresets)
|
||||
.filter(preset => preset._encyclopedia !== undefined
|
||||
&& this.itemHelper.armorItemCanHoldMods(preset._encyclopedia),
|
||||
).reduce((acc, cur) =>
|
||||
{
|
||||
acc[cur._id] = cur;
|
||||
return acc;
|
||||
@ -104,12 +108,12 @@ export class PresetHelper
|
||||
|
||||
public getPreset(id: string): IPreset
|
||||
{
|
||||
return this.jsonUtil.clone(this.databaseServer.getTables().globals.ItemPresets[id]);
|
||||
return this.cloner.clone(this.databaseServer.getTables().globals.ItemPresets[id]);
|
||||
}
|
||||
|
||||
public getAllPresets(): IPreset[]
|
||||
{
|
||||
return this.jsonUtil.clone(Object.values(this.databaseServer.getTables().globals.ItemPresets));
|
||||
return this.cloner.clone(Object.values(this.databaseServer.getTables().globals.ItemPresets));
|
||||
}
|
||||
|
||||
public getPresets(templateId: string): IPreset[]
|
||||
|
@ -15,6 +15,7 @@ import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { SaveServer } from "@spt-aki/servers/SaveServer";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { ProfileSnapshotService } from "@spt-aki/services/ProfileSnapshotService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { TimeUtil } from "@spt-aki/utils/TimeUtil";
|
||||
@ -37,6 +38,7 @@ export class ProfileHelper
|
||||
@inject("ProfileSnapshotService") protected profileSnapshotService: ProfileSnapshotService,
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.inventoryConfig = this.configServer.getConfig(ConfigTypes.INVENTORY);
|
||||
@ -120,8 +122,8 @@ export class ProfileHelper
|
||||
scavProfile: IPmcData,
|
||||
): IPmcData[]
|
||||
{
|
||||
const clonedPmc = this.jsonUtil.clone(pmcProfile);
|
||||
const clonedScav = this.jsonUtil.clone(scavProfile);
|
||||
const clonedPmc = this.cloner.clone(pmcProfile);
|
||||
const clonedScav = this.cloner.clone(scavProfile);
|
||||
|
||||
const profileSnapshot = this.profileSnapshotService.getProfileSnapshot(sessionId);
|
||||
clonedPmc.Info.Level = profileSnapshot.characters.pmc.Info.Level;
|
||||
|
@ -28,6 +28,7 @@ import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { LocaleService } from "@spt-aki/services/LocaleService";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { MailSendService } from "@spt-aki/services/MailSendService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { TimeUtil } from "@spt-aki/utils/TimeUtil";
|
||||
@ -56,6 +57,7 @@ export class QuestHelper
|
||||
@inject("PresetHelper") protected presetHelper: PresetHelper,
|
||||
@inject("MailSendService") protected mailSendService: MailSendService,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.questConfig = this.configServer.getConfig(ConfigTypes.QUEST);
|
||||
@ -320,13 +322,13 @@ export class QuestHelper
|
||||
for (const target of targets)
|
||||
{
|
||||
// This has all the original id relations since we reset the id to the original after the splitStack
|
||||
const itemsClone = [this.jsonUtil.clone(target)];
|
||||
const itemsClone = [this.cloner.clone(target)];
|
||||
// Here we generate a new id for the root item
|
||||
target._id = this.hashUtil.generate();
|
||||
|
||||
for (const mod of mods)
|
||||
{
|
||||
itemsClone.push(this.jsonUtil.clone(mod));
|
||||
itemsClone.push(this.cloner.clone(mod));
|
||||
}
|
||||
|
||||
rewardItems = rewardItems.concat(this.itemHelper.reparentItemAndChildren(target, itemsClone));
|
||||
@ -691,7 +693,7 @@ export class QuestHelper
|
||||
*/
|
||||
public getQuestWithOnlyLevelRequirementStartCondition(quest: IQuest): IQuest
|
||||
{
|
||||
const updatedQuest = this.jsonUtil.clone(quest);
|
||||
const updatedQuest = this.cloner.clone(quest);
|
||||
updatedQuest.conditions.AvailableForStart = updatedQuest.conditions.AvailableForStart.filter(q =>
|
||||
q.conditionType === "Level",
|
||||
);
|
||||
|
@ -13,6 +13,7 @@ import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { ConfigServer } from "@spt-aki/servers/ConfigServer";
|
||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { RagfairLinkedItemService } from "@spt-aki/services/RagfairLinkedItemService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
|
||||
@injectable()
|
||||
@ -30,6 +31,7 @@ export class RagfairHelper
|
||||
@inject("RagfairLinkedItemService") protected ragfairLinkedItemService: RagfairLinkedItemService,
|
||||
@inject("UtilityHelper") protected utilityHelper: UtilityHelper,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR);
|
||||
@ -162,7 +164,7 @@ export class RagfairHelper
|
||||
{
|
||||
if (!rootItem)
|
||||
{
|
||||
rootItem = this.jsonUtil.clone(item);
|
||||
rootItem = this.cloner.clone(item);
|
||||
rootItem.upd.OriginalStackObjectsCount = rootItem.upd.StackObjectsCount;
|
||||
}
|
||||
else
|
||||
|
@ -19,6 +19,7 @@ import { SaveServer } from "@spt-aki/servers/SaveServer";
|
||||
import { ItemFilterService } from "@spt-aki/services/ItemFilterService";
|
||||
import { LocaleService } from "@spt-aki/services/LocaleService";
|
||||
import { MailSendService } from "@spt-aki/services/MailSendService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
|
||||
@ -50,6 +51,7 @@ export class RagfairServerHelper
|
||||
@inject("MailSendService") protected mailSendService: MailSendService,
|
||||
@inject("ItemFilterService") protected itemFilterService: ItemFilterService,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR);
|
||||
@ -291,7 +293,7 @@ export class RagfairServerHelper
|
||||
*/
|
||||
public getPresetItems(item: Item): Item[]
|
||||
{
|
||||
const preset = this.jsonUtil.clone(this.databaseServer.getTables().globals.ItemPresets[item._id]._items);
|
||||
const preset = this.cloner.clone(this.databaseServer.getTables().globals.ItemPresets[item._id]._items);
|
||||
return this.itemHelper.reparentItemAndChildren(item, preset);
|
||||
}
|
||||
|
||||
@ -307,7 +309,7 @@ export class RagfairServerHelper
|
||||
{
|
||||
if (this.databaseServer.getTables().globals.ItemPresets[itemId]._items[0]._tpl === item._tpl)
|
||||
{
|
||||
const presetItems = this.jsonUtil.clone(
|
||||
const presetItems = this.cloner.clone(
|
||||
this.databaseServer.getTables().globals.ItemPresets[itemId]._items,
|
||||
);
|
||||
presets.push(this.itemHelper.reparentItemAndChildren(item, presetItems));
|
||||
|
@ -7,6 +7,7 @@ import { IRepairConfig } from "@spt-aki/models/spt/config/IRepairConfig";
|
||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { ConfigServer } from "@spt-aki/servers/ConfigServer";
|
||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
|
||||
|
||||
@ -21,6 +22,7 @@ export class RepairHelper
|
||||
@inject("RandomUtil") protected randomUtil: RandomUtil,
|
||||
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.repairConfig = this.configServer.getConfig(ConfigTypes.REPAIR);
|
||||
@ -48,9 +50,9 @@ export class RepairHelper
|
||||
{
|
||||
this.logger.debug(`Adding ${amountToRepair} to ${itemToRepairDetails._name} using kit: ${useRepairKit}`);
|
||||
|
||||
const itemMaxDurability = this.jsonUtil.clone(itemToRepair.upd.Repairable.MaxDurability);
|
||||
const itemCurrentDurability = this.jsonUtil.clone(itemToRepair.upd.Repairable.Durability);
|
||||
const itemCurrentMaxDurability = this.jsonUtil.clone(itemToRepair.upd.Repairable.MaxDurability);
|
||||
const itemMaxDurability = this.cloner.clone(itemToRepair.upd.Repairable.MaxDurability);
|
||||
const itemCurrentDurability = this.cloner.clone(itemToRepair.upd.Repairable.Durability);
|
||||
const itemCurrentMaxDurability = this.cloner.clone(itemToRepair.upd.Repairable.MaxDurability);
|
||||
|
||||
let newCurrentDurability = itemCurrentDurability + amountToRepair;
|
||||
let newCurrentMaxDurability = itemCurrentMaxDurability + amountToRepair;
|
||||
|
@ -2,6 +2,7 @@ import { inject, injectable } from "tsyringe";
|
||||
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
|
||||
import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "@spt-aki/models/spt/config/IQuestConfig";
|
||||
import { ConfigServer } from "@spt-aki/servers/ConfigServer";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { MathUtil } from "@spt-aki/utils/MathUtil";
|
||||
import { ProbabilityObject, ProbabilityObjectArray } from "@spt-aki/utils/RandomUtil";
|
||||
@ -15,6 +16,7 @@ export class RepeatableQuestHelper
|
||||
@inject("MathUtil") protected mathUtil: MathUtil,
|
||||
@inject("JsonUtil") protected jsonUtil: JsonUtil,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.questConfig = this.configServer.getConfig(ConfigTypes.QUEST);
|
||||
@ -38,8 +40,8 @@ export class RepeatableQuestHelper
|
||||
|
||||
public probabilityObjectArray<K, V>(configArrayInput: ProbabilityObject<K, V>[]): ProbabilityObjectArray<K, V>
|
||||
{
|
||||
const configArray = this.jsonUtil.clone(configArrayInput);
|
||||
const probabilityArray = new ProbabilityObjectArray<K, V>(this.mathUtil, this.jsonUtil);
|
||||
const configArray = this.cloner.clone(configArrayInput);
|
||||
const probabilityArray = new ProbabilityObjectArray<K, V>(this.mathUtil, this.cloner);
|
||||
for (const configObject of configArray)
|
||||
{
|
||||
probabilityArray.push(
|
||||
|
@ -22,6 +22,7 @@ import { FenceService } from "@spt-aki/services/FenceService";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { PaymentService } from "@spt-aki/services/PaymentService";
|
||||
import { TraderPurchasePersisterService } from "@spt-aki/services/TraderPurchasePersisterService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { HttpResponseUtil } from "@spt-aki/utils/HttpResponseUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
|
||||
@ -47,6 +48,7 @@ export class TradeHelper
|
||||
@inject("TraderPurchasePersisterService") protected traderPurchasePersisterService:
|
||||
TraderPurchasePersisterService,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.traderConfig = this.configServer.getConfig(ConfigTypes.TRADER);
|
||||
@ -105,7 +107,7 @@ export class TradeHelper
|
||||
|
||||
// Get raw offer from ragfair, clone to prevent altering offer itself
|
||||
const allOffers = this.ragfairServer.getOffers();
|
||||
const offerWithItemCloned = this.jsonUtil.clone(allOffers.find(x => x._id === buyRequestData.item_id));
|
||||
const offerWithItemCloned = this.cloner.clone(allOffers.find(x => x._id === buyRequestData.item_id));
|
||||
offerItems = offerWithItemCloned.items;
|
||||
}
|
||||
else if (buyRequestData.tid === Traders.FENCE)
|
||||
@ -196,7 +198,7 @@ export class TradeHelper
|
||||
const itemsToSendToPlayer: Item[][] = [];
|
||||
while (itemsToSendRemaining > 0)
|
||||
{
|
||||
const offerClone = this.jsonUtil.clone(offerItems);
|
||||
const offerClone = this.cloner.clone(offerItems);
|
||||
// Handle stackable items that have a max stack size limit
|
||||
const itemCountToSend = Math.min(itemMaxStackSize, itemsToSendRemaining);
|
||||
offerClone[0].upd.StackObjectsCount = itemCountToSend;
|
||||
|
@ -17,6 +17,7 @@ import { FenceService } from "@spt-aki/services/FenceService";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { TraderAssortService } from "@spt-aki/services/TraderAssortService";
|
||||
import { TraderPurchasePersisterService } from "@spt-aki/services/TraderPurchasePersisterService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { MathUtil } from "@spt-aki/utils/MathUtil";
|
||||
import { TimeUtil } from "@spt-aki/utils/TimeUtil";
|
||||
@ -46,6 +47,7 @@ export class TraderAssortHelper
|
||||
@inject("TraderHelper") protected traderHelper: TraderHelper,
|
||||
@inject("FenceService") protected fenceService: FenceService,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.traderConfig = this.configServer.getConfig(ConfigTypes.TRADER);
|
||||
@ -68,7 +70,7 @@ export class TraderAssortHelper
|
||||
return this.getRagfairDataAsTraderAssort();
|
||||
}
|
||||
|
||||
const traderClone = this.jsonUtil.clone(this.databaseServer.getTables().traders[traderId]);
|
||||
const traderClone = this.cloner.clone(this.databaseServer.getTables().traders[traderId]);
|
||||
const pmcProfile = this.profileHelper.getPmcProfile(sessionId);
|
||||
|
||||
if (traderId === Traders.FENCE)
|
||||
@ -250,7 +252,7 @@ export class TraderAssortHelper
|
||||
*/
|
||||
protected getPristineTraderAssorts(traderId: string): Item[]
|
||||
{
|
||||
return this.jsonUtil.clone(this.traderAssortService.getPristineTraderAssort(traderId).items);
|
||||
return this.cloner.clone(this.traderAssortService.getPristineTraderAssort(traderId).items);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2,6 +2,7 @@ import path from "node:path";
|
||||
import { inject, injectable } from "tsyringe";
|
||||
import { HttpServerHelper } from "@spt-aki/helpers/HttpServerHelper";
|
||||
import { BundleHashCacheService } from "@spt-aki/services/cache/BundleHashCacheService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { VFS } from "@spt-aki/utils/VFS";
|
||||
|
||||
@ -31,6 +32,7 @@ export class BundleLoader
|
||||
@inject("VFS") protected vfs: VFS,
|
||||
@inject("JsonUtil") protected jsonUtil: JsonUtil,
|
||||
@inject("BundleHashCacheService") protected bundleHashCacheService: BundleHashCacheService,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{}
|
||||
|
||||
@ -51,7 +53,7 @@ export class BundleLoader
|
||||
|
||||
public getBundle(key: string): BundleInfo
|
||||
{
|
||||
return this.jsonUtil.clone(this.bundles[key]);
|
||||
return this.cloner.clone(this.bundles[key]);
|
||||
}
|
||||
|
||||
public addBundles(modpath: string): void
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
|
||||
|
||||
@ -5,9 +6,9 @@ export class ExhaustableArray<T> implements IExhaustableArray<T>
|
||||
{
|
||||
private pool: T[];
|
||||
|
||||
constructor(private itemPool: T[], private randomUtil: RandomUtil, private jsonUtil: JsonUtil)
|
||||
constructor(private itemPool: T[], private randomUtil: RandomUtil, private cloner: ICloner)
|
||||
{
|
||||
this.pool = this.jsonUtil.clone(itemPool);
|
||||
this.pool = this.cloner.clone(itemPool);
|
||||
}
|
||||
|
||||
public getRandomValue(): T
|
||||
@ -18,7 +19,7 @@ export class ExhaustableArray<T> implements IExhaustableArray<T>
|
||||
}
|
||||
|
||||
const index = this.randomUtil.getInt(0, this.pool.length - 1);
|
||||
const toReturn = this.jsonUtil.clone(this.pool[index]);
|
||||
const toReturn = this.cloner.clone(this.pool[index]);
|
||||
this.pool.splice(index, 1);
|
||||
return toReturn;
|
||||
}
|
||||
@ -30,7 +31,7 @@ export class ExhaustableArray<T> implements IExhaustableArray<T>
|
||||
return null;
|
||||
}
|
||||
|
||||
const toReturn = this.jsonUtil.clone(this.pool[0]);
|
||||
const toReturn = this.cloner.clone(this.pool[0]);
|
||||
this.pool.splice(0, 1);
|
||||
return toReturn;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import { IPmcData } from "@spt-aki/models/eft/common/IPmcData";
|
||||
import { IHideoutImprovement, Productive, TraderInfo } from "@spt-aki/models/eft/common/tables/IBotBase";
|
||||
import { ProfileChange, TraderData } from "@spt-aki/models/eft/itemEvent/IItemEventRouterBase";
|
||||
import { IItemEventRouterResponse } from "@spt-aki/models/eft/itemEvent/IItemEventRouterResponse";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { TimeUtil } from "@spt-aki/utils/TimeUtil";
|
||||
|
||||
@ -17,6 +18,7 @@ export class EventOutputHolder
|
||||
@inject("JsonUtil") protected jsonUtil: JsonUtil,
|
||||
@inject("ProfileHelper") protected profileHelper: ProfileHelper,
|
||||
@inject("TimeUtil") protected timeUtil: TimeUtil,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{}
|
||||
|
||||
@ -54,7 +56,7 @@ export class EventOutputHolder
|
||||
production: {},
|
||||
improvements: {},
|
||||
skills: { Common: [], Mastering: [], Points: 0 },
|
||||
health: this.jsonUtil.clone(pmcData.Health),
|
||||
health: this.cloner.clone(pmcData.Health),
|
||||
traderRelations: {},
|
||||
// changedHideoutStashes: {},
|
||||
recipeUnlocked: {},
|
||||
@ -72,15 +74,15 @@ export class EventOutputHolder
|
||||
const profileChanges: ProfileChange = this.output.profileChanges[sessionId];
|
||||
|
||||
profileChanges.experience = pmcData.Info.Experience;
|
||||
profileChanges.health = this.jsonUtil.clone(pmcData.Health);
|
||||
profileChanges.skills.Common = this.jsonUtil.clone(pmcData.Skills.Common); // Always send skills for Item event route response
|
||||
profileChanges.skills.Mastering = this.jsonUtil.clone(pmcData.Skills.Mastering);
|
||||
profileChanges.health = this.cloner.clone(pmcData.Health);
|
||||
profileChanges.skills.Common = this.cloner.clone(pmcData.Skills.Common); // Always send skills for Item event route response
|
||||
profileChanges.skills.Mastering = this.cloner.clone(pmcData.Skills.Mastering);
|
||||
|
||||
// Clone productions to ensure we preseve the profile jsons data
|
||||
profileChanges.production = this.getProductionsFromProfileAndFlagComplete(
|
||||
this.jsonUtil.clone(pmcData.Hideout.Production),
|
||||
this.cloner.clone(pmcData.Hideout.Production),
|
||||
);
|
||||
profileChanges.improvements = this.jsonUtil.clone(this.getImprovementsFromProfileAndFlagComplete(pmcData));
|
||||
profileChanges.improvements = this.cloner.clone(this.getImprovementsFromProfileAndFlagComplete(pmcData));
|
||||
profileChanges.traderRelations = this.constructTraderRelations(pmcData.TradersInfo);
|
||||
|
||||
// Fixes container craft from water collector not resetting after collection + removed completed normal crafts
|
||||
|
@ -6,6 +6,7 @@ import { IItemEventRouterResponse } from "@spt-aki/models/eft/itemEvent/IItemEve
|
||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { EventOutputHolder } from "@spt-aki/routers/EventOutputHolder";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
|
||||
@injectable()
|
||||
@ -18,6 +19,7 @@ export class ItemEventRouter
|
||||
@injectAll("IERouters") protected itemEventRouters: ItemEventRouterDefinition[],
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||
@inject("EventOutputHolder") protected eventOutputHolder: EventOutputHolder,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{}
|
||||
|
||||
@ -54,7 +56,7 @@ export class ItemEventRouter
|
||||
this.eventOutputHolder.updateOutputProperties(sessionID);
|
||||
|
||||
// Clone output before resetting the output object ready for use next time
|
||||
const outputClone = this.jsonUtil.clone(output);
|
||||
const outputClone = this.cloner.clone(output);
|
||||
this.eventOutputHolder.resetOutput(sessionID);
|
||||
|
||||
return outputClone;
|
||||
|
@ -9,6 +9,7 @@ import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { RagfairPriceService } from "@spt-aki/services/RagfairPriceService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
|
||||
@injectable()
|
||||
@ -24,6 +25,7 @@ export class BotLootCacheService
|
||||
@inject("PMCLootGenerator") protected pmcLootGenerator: PMCLootGenerator,
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||
@inject("RagfairPriceService") protected ragfairPriceService: RagfairPriceService,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.clearCache();
|
||||
@ -111,7 +113,7 @@ export class BotLootCacheService
|
||||
break;
|
||||
}
|
||||
|
||||
return this.jsonUtil.clone(result);
|
||||
return this.cloner.clone(result);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -136,9 +138,9 @@ export class BotLootCacheService
|
||||
if (isPmc)
|
||||
{
|
||||
// Replace lootPool from bot json with our own generated list for PMCs
|
||||
lootPool.Backpack = this.jsonUtil.clone(this.pmcLootGenerator.generatePMCBackpackLootPool(botRole));
|
||||
lootPool.Pockets = this.jsonUtil.clone(this.pmcLootGenerator.generatePMCPocketLootPool(botRole));
|
||||
lootPool.TacticalVest = this.jsonUtil.clone(this.pmcLootGenerator.generatePMCVestLootPool(botRole));
|
||||
lootPool.Backpack = this.cloner.clone(this.pmcLootGenerator.generatePMCBackpackLootPool(botRole));
|
||||
lootPool.Pockets = this.cloner.clone(this.pmcLootGenerator.generatePMCPocketLootPool(botRole));
|
||||
lootPool.TacticalVest = this.cloner.clone(this.pmcLootGenerator.generatePMCVestLootPool(botRole));
|
||||
}
|
||||
|
||||
// Backpack/Pockets etc
|
||||
|
@ -21,6 +21,7 @@ import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { ConfigServer } from "@spt-aki/servers/ConfigServer";
|
||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
|
||||
import { TimeUtil } from "@spt-aki/utils/TimeUtil";
|
||||
@ -69,6 +70,7 @@ export class FenceService
|
||||
@inject("PresetHelper") protected presetHelper: PresetHelper,
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.traderConfig = this.configServer.getConfig(ConfigTypes.TRADER);
|
||||
@ -134,13 +136,13 @@ export class FenceService
|
||||
}
|
||||
|
||||
// Clone assorts so we can adjust prices before sending to client
|
||||
const assort = this.jsonUtil.clone(this.fenceAssort);
|
||||
const assort = this.cloner.clone(this.fenceAssort);
|
||||
this.adjustAssortItemPricesByConfigMultiplier(assort, 1, this.traderConfig.fence.presetPriceMult);
|
||||
|
||||
// merge normal fence assorts + discount assorts if player standing is large enough
|
||||
if (pmcProfile.TradersInfo[Traders.FENCE].standing >= 6)
|
||||
{
|
||||
const discountAssort = this.jsonUtil.clone(this.fenceDiscountAssort);
|
||||
const discountAssort = this.cloner.clone(this.fenceDiscountAssort);
|
||||
this.adjustAssortItemPricesByConfigMultiplier(
|
||||
discountAssort,
|
||||
this.traderConfig.fence.discountOptions.itemPriceMult,
|
||||
@ -163,7 +165,7 @@ export class FenceService
|
||||
{
|
||||
// HUGE THANKS TO LACYWAY AND LEAVES FOR PROVIDING THIS SOLUTION FOR SPT TO IMPLEMENT!!
|
||||
// Copy the item and its children
|
||||
let clonedItems = this.jsonUtil.clone(this.itemHelper.findAndReturnChildrenAsItems(items, mainItem._id));
|
||||
let clonedItems = this.cloner.clone(this.itemHelper.findAndReturnChildrenAsItems(items, mainItem._id));
|
||||
const root = clonedItems[0];
|
||||
|
||||
const cost = this.getItemPrice(root._tpl, clonedItems);
|
||||
@ -310,7 +312,7 @@ export class FenceService
|
||||
*/
|
||||
public getRawFenceAssorts(): ITraderAssort
|
||||
{
|
||||
return this.mergeAssorts(this.jsonUtil.clone(this.fenceAssort), this.jsonUtil.clone(this.fenceDiscountAssort));
|
||||
return this.mergeAssorts(this.cloner.clone(this.fenceAssort), this.cloner.clone(this.fenceDiscountAssort));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -682,7 +684,7 @@ export class FenceService
|
||||
{
|
||||
const result: ICreateFenceAssortsResult = { sptItems: [], barter_scheme: {}, loyal_level_items: {} };
|
||||
|
||||
const baseFenceAssortClone = this.jsonUtil.clone(this.databaseServer.getTables().traders[Traders.FENCE].assort);
|
||||
const baseFenceAssortClone = this.cloner.clone(this.databaseServer.getTables().traders[Traders.FENCE].assort);
|
||||
const itemTypeLimitCounts = this.initItemLimitCounter(this.traderConfig.fence.itemTypeLimits);
|
||||
|
||||
if (itemCounts.item > 0)
|
||||
@ -743,7 +745,7 @@ export class FenceService
|
||||
|
||||
continue;
|
||||
}
|
||||
let desiredAssortItemAndChildrenClone = this.jsonUtil.clone(
|
||||
let desiredAssortItemAndChildrenClone = this.cloner.clone(
|
||||
this.itemHelper.findAndReturnChildrenAsItems(baseFenceAssortClone.items, chosenBaseAssortRoot._id),
|
||||
);
|
||||
|
||||
@ -814,7 +816,7 @@ export class FenceService
|
||||
|
||||
assorts.sptItems.push(desiredAssortItemAndChildrenClone);
|
||||
|
||||
assorts.barter_scheme[rootItemBeingAdded._id] = this.jsonUtil.clone(
|
||||
assorts.barter_scheme[rootItemBeingAdded._id] = this.cloner.clone(
|
||||
baseFenceAssortClone.barter_scheme[chosenBaseAssortRoot._id],
|
||||
);
|
||||
|
||||
@ -1004,7 +1006,7 @@ export class FenceService
|
||||
|
||||
const rootItemDb = this.itemHelper.getItem(randomPresetRoot._tpl)[1];
|
||||
|
||||
const presetWithChildrenClone = this.jsonUtil.clone(
|
||||
const presetWithChildrenClone = this.cloner.clone(
|
||||
this.itemHelper.findAndReturnChildrenAsItems(baseFenceAssort.items, randomPresetRoot._id),
|
||||
);
|
||||
|
||||
@ -1060,7 +1062,7 @@ export class FenceService
|
||||
const randomPresetRoot = this.randomUtil.getArrayValue(equipmentPresetRootItems);
|
||||
const rootItemDb = this.itemHelper.getItem(randomPresetRoot._tpl)[1];
|
||||
|
||||
const presetWithChildrenClone = this.jsonUtil.clone(
|
||||
const presetWithChildrenClone = this.cloner.clone(
|
||||
this.itemHelper.findAndReturnChildrenAsItems(baseFenceAssort.items, randomPresetRoot._id),
|
||||
);
|
||||
|
||||
|
@ -12,7 +12,6 @@ import { ISaveProgressRequestData } from "@spt-aki/models/eft/inRaid/ISaveProgre
|
||||
import { BonusType } from "@spt-aki/models/enums/BonusType";
|
||||
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
|
||||
import { MessageType } from "@spt-aki/models/enums/MessageType";
|
||||
import { Traders } from "@spt-aki/models/enums/Traders";
|
||||
import { IInsuranceConfig } from "@spt-aki/models/spt/config/IInsuranceConfig";
|
||||
import { ILostOnDeathConfig } from "@spt-aki/models/spt/config/ILostOnDeathConfig";
|
||||
import { IInsuranceEquipmentPkg } from "@spt-aki/models/spt/services/IInsuranceEquipmentPkg";
|
||||
@ -23,6 +22,7 @@ import { SaveServer } from "@spt-aki/servers/SaveServer";
|
||||
import { LocaleService } from "@spt-aki/services/LocaleService";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { MailSendService } from "@spt-aki/services/MailSendService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
|
||||
@ -52,6 +52,7 @@ export class InsuranceService
|
||||
@inject("LocaleService") protected localeService: LocaleService,
|
||||
@inject("MailSendService") protected mailSendService: MailSendService,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.insuranceConfig = this.configServer.getConfig(ConfigTypes.INSURANCE);
|
||||
|
@ -21,6 +21,7 @@ import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { ConfigServer } from "@spt-aki/servers/ConfigServer";
|
||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { TimeUtil } from "@spt-aki/utils/TimeUtil";
|
||||
@ -46,6 +47,7 @@ export class ProfileFixerService
|
||||
@inject("HashUtil") protected hashUtil: HashUtil,
|
||||
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.coreConfig = this.configServer.getConfig(ConfigTypes.CORE);
|
||||
@ -1322,7 +1324,7 @@ export class ProfileFixerService
|
||||
if ("OverallCounters" in fullProfile.characters.pmc.Stats)
|
||||
{
|
||||
this.logger.debug("Migrating stats object into new structure");
|
||||
const statsCopy = this.jsonUtil.clone(fullProfile.characters.pmc.Stats);
|
||||
const statsCopy = this.cloner.clone(fullProfile.characters.pmc.Stats);
|
||||
|
||||
// Clear stats object
|
||||
fullProfile.characters.pmc.Stats = { Eft: null };
|
||||
@ -1400,7 +1402,7 @@ export class ProfileFixerService
|
||||
if ("Improvements" in pmcProfile.Hideout)
|
||||
{
|
||||
const improvements = pmcProfile.Hideout.Improvements as Record<string, IHideoutImprovement>;
|
||||
pmcProfile.Hideout.Improvement = this.jsonUtil.clone(improvements);
|
||||
pmcProfile.Hideout.Improvement = this.cloner.clone(improvements);
|
||||
delete pmcProfile.Hideout.Improvements;
|
||||
this.logger.success("Successfully migrated hideout Improvements data to new location, deleted old data");
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
import { IAkiProfile } from "@spt-aki/models/eft/profile/IAkiProfile";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
|
||||
@injectable()
|
||||
@ -7,7 +8,7 @@ export class ProfileSnapshotService
|
||||
{
|
||||
protected storedProfileSnapshots: Record<string, IAkiProfile> = {};
|
||||
|
||||
constructor(@inject("JsonUtil") protected jsonUtil: JsonUtil)
|
||||
constructor(@inject("JsonUtil") protected jsonUtil: JsonUtil, @inject("RecursiveCloner") protected cloner: ICloner)
|
||||
{}
|
||||
|
||||
/**
|
||||
@ -17,7 +18,7 @@ export class ProfileSnapshotService
|
||||
*/
|
||||
public storeProfileSnapshot(sessionID: string, profile: IAkiProfile): void
|
||||
{
|
||||
this.storedProfileSnapshots[sessionID] = this.jsonUtil.clone(profile);
|
||||
this.storedProfileSnapshots[sessionID] = this.cloner.clone(profile);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4,6 +4,7 @@ import { QuestStatus } from "@spt-aki/models/enums/QuestStatus";
|
||||
import { ITraderServiceModel } from "@spt-aki/models/spt/services/ITraderServiceModel";
|
||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
|
||||
@injectable()
|
||||
@ -14,13 +15,14 @@ export class TraderServicesService
|
||||
@inject("JsonUtil") protected jsonUtil: JsonUtil,
|
||||
@inject("WinstonLogger") protected logger: ILogger,
|
||||
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{}
|
||||
|
||||
public getTraderServices(sessionId: string, traderId: string): ITraderServiceModel[]
|
||||
{
|
||||
const pmcData = this.profileHelper.getPmcProfile(sessionId);
|
||||
let traderServices = this.jsonUtil.clone(this.databaseServer.getTables().traders[traderId]?.services);
|
||||
let traderServices = this.cloner.clone(this.databaseServer.getTables().traders[traderId]?.services);
|
||||
if (!traderServices)
|
||||
{
|
||||
return [];
|
||||
|
@ -12,6 +12,7 @@ import { IDatabaseTables } from "@spt-aki/models/spt/server/IDatabaseTables";
|
||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { ItemBaseClassService } from "@spt-aki/services/ItemBaseClassService";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
|
||||
@ -27,6 +28,7 @@ export class CustomItemService
|
||||
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
|
||||
@inject("ItemHelper") protected itemHelper: ItemHelper,
|
||||
@inject("ItemBaseClassService") protected itemBaseClassService: ItemBaseClassService,
|
||||
@inject("RecursiveCloner") protected cloner: ICloner,
|
||||
)
|
||||
{
|
||||
this.tables = this.databaseServer.getTables();
|
||||
@ -61,7 +63,7 @@ export class CustomItemService
|
||||
}
|
||||
|
||||
// Clone existing item
|
||||
const itemClone = this.jsonUtil.clone(tables.templates.items[newItemDetails.itemTplToClone]);
|
||||
const itemClone = this.cloner.clone(tables.templates.items[newItemDetails.itemTplToClone]);
|
||||
|
||||
// Update id and parentId of item
|
||||
itemClone._id = newItemId;
|
||||
|
@ -242,6 +242,7 @@ export class JsonUtil
|
||||
* Convert into string and back into object to clone object
|
||||
* @param objectToClone Item to clone
|
||||
* @returns Cloned parameter
|
||||
* @deprecated Use ICloner implementations, such as RecursiveCloner or StructuredCloner
|
||||
*/
|
||||
public clone<T>(objectToClone: T): T
|
||||
{
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { MathUtil } from "@spt-aki/utils/MathUtil";
|
||||
|
||||
@ -20,7 +21,7 @@ import { MathUtil } from "@spt-aki/utils/MathUtil";
|
||||
*/
|
||||
export class ProbabilityObjectArray<K, V = undefined> extends Array<ProbabilityObject<K, V>>
|
||||
{
|
||||
constructor(private mathUtil: MathUtil, private jsonUtil: JsonUtil, ...items: ProbabilityObject<K, V>[])
|
||||
constructor(private mathUtil: MathUtil, private cloner: ICloner, ...items: ProbabilityObject<K, V>[])
|
||||
{
|
||||
super();
|
||||
this.push(...items);
|
||||
@ -30,7 +31,7 @@ export class ProbabilityObjectArray<K, V = undefined> extends Array<ProbabilityO
|
||||
callbackfn: (value: ProbabilityObject<K, V>, index: number, array: ProbabilityObject<K, V>[]) => any,
|
||||
): ProbabilityObjectArray<K, V>
|
||||
{
|
||||
return new ProbabilityObjectArray(this.mathUtil, this.jsonUtil, ...super.filter(callbackfn));
|
||||
return new ProbabilityObjectArray(this.mathUtil, this.cloner, ...super.filter(callbackfn));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -52,8 +53,8 @@ export class ProbabilityObjectArray<K, V = undefined> extends Array<ProbabilityO
|
||||
*/
|
||||
clone(): ProbabilityObjectArray<K, V>
|
||||
{
|
||||
const clone = this.jsonUtil.clone(this);
|
||||
const probabliltyObjects = new ProbabilityObjectArray<K, V>(this.mathUtil, this.jsonUtil);
|
||||
const clone = this.cloner.clone(this);
|
||||
const probabliltyObjects = new ProbabilityObjectArray<K, V>(this.mathUtil, this.cloner);
|
||||
for (const ci of clone)
|
||||
{
|
||||
probabliltyObjects.push(new ProbabilityObject(ci.key, ci.relativeProbability, ci.data));
|
||||
@ -204,7 +205,7 @@ export class ProbabilityObject<K, V = undefined>
|
||||
@injectable()
|
||||
export class RandomUtil
|
||||
{
|
||||
constructor(@inject("JsonUtil") protected jsonUtil: JsonUtil, @inject("WinstonLogger") protected logger: ILogger)
|
||||
constructor(@inject("RecursiveCloner") protected cloner: ICloner, @inject("WinstonLogger") protected logger: ILogger)
|
||||
{
|
||||
}
|
||||
|
||||
@ -342,7 +343,7 @@ export class RandomUtil
|
||||
let list = originalList;
|
||||
if (!replacement)
|
||||
{
|
||||
list = this.jsonUtil.clone(originalList);
|
||||
list = this.cloner.clone(originalList);
|
||||
}
|
||||
|
||||
const results = [];
|
||||
|
4
project/src/utils/cloners/ICloner.ts
Normal file
4
project/src/utils/cloners/ICloner.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export interface ICloner
|
||||
{
|
||||
clone<T>(obj: T): T
|
||||
}
|
11
project/src/utils/cloners/JsonCloner.ts
Normal file
11
project/src/utils/cloners/JsonCloner.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { injectable } from "tsyringe";
|
||||
import type { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
|
||||
@injectable()
|
||||
export class JsonCloner implements ICloner
|
||||
{
|
||||
public clone<T>(obj: T): T
|
||||
{
|
||||
return JSON.parse(JSON.stringify(obj));
|
||||
}
|
||||
}
|
45
project/src/utils/cloners/RecursiveCloner.ts
Normal file
45
project/src/utils/cloners/RecursiveCloner.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import { injectable } from "tsyringe";
|
||||
import type { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
|
||||
@injectable()
|
||||
export class RecursiveCloner implements ICloner
|
||||
{
|
||||
private static primitives = new Set<string>([
|
||||
"string",
|
||||
"number",
|
||||
"boolean",
|
||||
"bigint",
|
||||
"symbol",
|
||||
"undefined",
|
||||
"null",
|
||||
]);
|
||||
|
||||
public clone<T>(obj: T): T
|
||||
{
|
||||
const typeOfObj = typeof obj;
|
||||
// no need to clone these types, they are primitives
|
||||
if (RecursiveCloner.primitives.has(typeOfObj))
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
// clone the object types
|
||||
if (typeOfObj === "object")
|
||||
{
|
||||
if (Array.isArray(obj))
|
||||
{
|
||||
// biome-ignore lint/suspicious/noExplicitAny: used for clone
|
||||
const objArr = obj as Array<any>;
|
||||
return objArr.map(v => this.clone(v)) as T;
|
||||
}
|
||||
|
||||
const newObj = {};
|
||||
for (const propOf1 in obj)
|
||||
{
|
||||
newObj[propOf1.toString()] = this.clone(obj[propOf1]);
|
||||
}
|
||||
return newObj as T;
|
||||
}
|
||||
|
||||
throw new Error(`Cant clone ${JSON.stringify(obj)}`);
|
||||
}
|
||||
}
|
11
project/src/utils/cloners/StructuredCloner.ts
Normal file
11
project/src/utils/cloners/StructuredCloner.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { injectable } from "tsyringe";
|
||||
import type { ICloner } from "@spt-aki/utils/cloners/ICloner";
|
||||
|
||||
@injectable()
|
||||
export class StructuredCloner implements ICloner
|
||||
{
|
||||
public clone<T>(obj: T): T
|
||||
{
|
||||
return structuredClone(obj);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user