0
0
mirror of https://github.com/sp-tarkov/server.git synced 2025-02-13 09:50:43 -05:00

Removed all null references in favor of undefined (!354)

Co-authored-by: clodan <clodan@clodan.com>
Reviewed-on: SPT/Server#354
Co-authored-by: Alex <clodan@noreply.dev.sp-tarkov.com>
Co-committed-by: Alex <clodan@noreply.dev.sp-tarkov.com>
This commit is contained in:
Alex 2024-05-27 20:06:07 +00:00 committed by chomp
parent d5496dcc34
commit 173a726f33
57 changed files with 357 additions and 354 deletions

View File

@ -91,12 +91,12 @@ export class ProfileCallbacks
if (output === "taken") if (output === "taken")
{ {
return this.httpResponse.getBody(null, 255, "The nickname is already in use"); return this.httpResponse.getBody(undefined, 255, "The nickname is already in use");
} }
if (output === "tooshort") if (output === "tooshort")
{ {
return this.httpResponse.getBody(null, 1, "The nickname is too short"); return this.httpResponse.getBody(undefined, 1, "The nickname is too short");
} }
return this.httpResponse.getBody({ status: 0, nicknamechangedate: this.timeUtil.getTimestamp() }); return this.httpResponse.getBody({ status: 0, nicknamechangedate: this.timeUtil.getTimestamp() });
@ -115,12 +115,12 @@ export class ProfileCallbacks
if (output === "taken") if (output === "taken")
{ {
return this.httpResponse.getBody(null, 255, "225 - "); return this.httpResponse.getBody(undefined, 255, "225 - ");
} }
if (output === "tooshort") if (output === "tooshort")
{ {
return this.httpResponse.getBody(null, 256, "256 - "); return this.httpResponse.getBody(undefined, 256, "256 - ");
} }
return this.httpResponse.getBody({ status: "ok" }); return this.httpResponse.getBody({ status: "ok" });

View File

@ -529,7 +529,7 @@ export class HideoutController
const request: IAddItemDirectRequest = { const request: IAddItemDirectRequest = {
itemWithModsToAdd: [itemToReturn], itemWithModsToAdd: [itemToReturn],
foundInRaid: !!itemToReturn.upd?.SpawnedInSession, foundInRaid: !!itemToReturn.upd?.SpawnedInSession,
callback: null, callback: undefined,
useSortingTable: false, useSortingTable: false,
}; };
@ -824,7 +824,7 @@ export class HideoutController
let prodId: string; let prodId: string;
for (const [productionId, production] of productionDict) for (const [productionId, production] of productionDict)
{ {
// Skip null production objects // Skip undefined production objects
if (!production) if (!production)
{ {
continue; continue;
@ -981,7 +981,7 @@ export class HideoutController
itemsWithModsToAdd: [toolItem], itemsWithModsToAdd: [toolItem],
foundInRaid: toolItem[0].upd?.SpawnedInSession ?? false, foundInRaid: toolItem[0].upd?.SpawnedInSession ?? false,
useSortingTable: false, useSortingTable: false,
callback: null, callback: undefined,
}; };
this.inventoryHelper.addItemsToStash(sessionID, addToolsRequest, pmcData, output); this.inventoryHelper.addItemsToStash(sessionID, addToolsRequest, pmcData, output);
@ -996,7 +996,7 @@ export class HideoutController
itemsWithModsToAdd: itemAndChildrenToSendToPlayer, itemsWithModsToAdd: itemAndChildrenToSendToPlayer,
foundInRaid: true, foundInRaid: true,
useSortingTable: false, useSortingTable: false,
callback: null, callback: undefined,
}; };
this.inventoryHelper.addItemsToStash(sessionID, addItemsRequest, pmcData, output); this.inventoryHelper.addItemsToStash(sessionID, addItemsRequest, pmcData, output);
if (output.warnings.length > 0) if (output.warnings.length > 0)
@ -1118,7 +1118,7 @@ export class HideoutController
const addItemsRequest: IAddItemsDirectRequest = { const addItemsRequest: IAddItemsDirectRequest = {
itemsWithModsToAdd: scavCaseRewards, itemsWithModsToAdd: scavCaseRewards,
foundInRaid: true, foundInRaid: true,
callback: null, callback: undefined,
useSortingTable: false, useSortingTable: false,
}; };
@ -1320,7 +1320,7 @@ export class HideoutController
} }
// Null out production data so client gets informed when response send back // Null out production data so client gets informed when response send back
pmcData.Hideout.Production[request.recipeId] = null; pmcData.Hideout.Production[request.recipeId] = undefined;
// TODO - handle timestamp somehow? // TODO - handle timestamp somehow?

View File

@ -628,14 +628,14 @@ export class InsuranceController
* *
* @param traderId The ID of the trader who insured the item. * @param traderId The ID of the trader who insured the item.
* @param insuredItem Optional. The item to roll for. Only used for logging. * @param insuredItem Optional. The item to roll for. Only used for logging.
* @returns true if the insured item should be removed from inventory, false otherwise, or null on error. * @returns true if the insured item should be removed from inventory, false otherwise, or undefined on error.
*/ */
protected rollForDelete(traderId: string, insuredItem?: Item): boolean | null protected rollForDelete(traderId: string, insuredItem?: Item): boolean | undefined
{ {
const trader = this.traderHelper.getTraderById(traderId); const trader = this.traderHelper.getTraderById(traderId);
if (!trader) if (!trader)
{ {
return null; return undefined;
} }
const maxRoll = 9999; const maxRoll = 9999;

View File

@ -345,7 +345,7 @@ export class InventoryController
const sourceItem = inventoryItems.from.find((item) => item._id === body.item); const sourceItem = inventoryItems.from.find((item) => item._id === body.item);
const destinationItem = inventoryItems.to.find((item) => item._id === body.with); const destinationItem = inventoryItems.to.find((item) => item._id === body.with);
if (sourceItem === null) if (!sourceItem)
{ {
const errorMessage = `Unable to transfer stack, cannot find source: ${body.item}`; const errorMessage = `Unable to transfer stack, cannot find source: ${body.item}`;
this.logger.error(errorMessage); this.logger.error(errorMessage);
@ -355,7 +355,7 @@ export class InventoryController
return output; return output;
} }
if (destinationItem === null) if (!destinationItem)
{ {
const errorMessage = `Unable to transfer stack, cannot find destination: ${body.with} `; const errorMessage = `Unable to transfer stack, cannot find destination: ${body.with} `;
this.logger.error(errorMessage); this.logger.error(errorMessage);
@ -939,7 +939,7 @@ export class InventoryController
const addItemsRequest: IAddItemsDirectRequest = { const addItemsRequest: IAddItemsDirectRequest = {
itemsWithModsToAdd: rewards, itemsWithModsToAdd: rewards,
foundInRaid: foundInRaid, foundInRaid: foundInRaid,
callback: null, callback: undefined,
useSortingTable: true, useSortingTable: true,
}; };
this.inventoryHelper.addItemsToStash(sessionID, addItemsRequest, pmcData, output); this.inventoryHelper.addItemsToStash(sessionID, addItemsRequest, pmcData, output);

View File

@ -92,9 +92,9 @@ export class MatchController
location: "TODO get location", location: "TODO get location",
raidMode: "Online", raidMode: "Online",
mode: "deathmatch", mode: "deathmatch",
shortId: null, shortId: undefined,
// eslint-disable-next-line @typescript-eslint/naming-convention // eslint-disable-next-line @typescript-eslint/naming-convention
additional_info: null, additional_info: undefined,
}); });
return output; return output;
@ -268,7 +268,7 @@ export class MatchController
*/ */
protected extractWasViaCar(extractName: string): boolean protected extractWasViaCar(extractName: string): boolean
{ {
// exit name is null on death // exit name is undefined on death
if (!extractName) if (!extractName)
{ {
return false; return false;

View File

@ -167,7 +167,7 @@ export class ProfileController
pmcData.Inventory.items = this.itemHelper.replaceIDs( pmcData.Inventory.items = this.itemHelper.replaceIDs(
pmcData.Inventory.items, pmcData.Inventory.items,
pmcData, pmcData,
null, undefined,
pmcData.Inventory.fastPanel, pmcData.Inventory.fastPanel,
); );
pmcData.Inventory.hideoutAreaStashes = {}; pmcData.Inventory.hideoutAreaStashes = {};
@ -419,10 +419,10 @@ export class ProfileController
const response: GetProfileStatusResponseData = { const response: GetProfileStatusResponseData = {
maxPveCountExceeded: false, maxPveCountExceeded: false,
profiles: [ profiles: [
{ profileid: account.scavId, profileToken: null, status: "Free", sid: "", ip: "", port: 0 }, { profileid: account.scavId, profileToken: undefined, status: "Free", sid: "", ip: "", port: 0 },
{ {
profileid: account.id, profileid: account.id,
profileToken: null, profileToken: undefined,
status: "Free", status: "Free",
sid: "", sid: "",
ip: "", ip: "",

View File

@ -602,7 +602,7 @@ export class QuestController
protected getQuestsWithDifferentStatuses( protected getQuestsWithDifferentStatuses(
preQuestStatusus: IQuestStatus[], preQuestStatusus: IQuestStatus[],
postQuestStatuses: IQuestStatus[], postQuestStatuses: IQuestStatus[],
): IQuestStatus[] ): IQuestStatus[] | undefined
{ {
const result: IQuestStatus[] = []; const result: IQuestStatus[] = [];
@ -618,7 +618,7 @@ export class QuestController
if (result.length === 0) if (result.length === 0)
{ {
return null; return undefined;
} }
return result; return result;

View File

@ -620,10 +620,10 @@ export class RagfairController
protected getItemsToListOnFleaFromInventory( protected getItemsToListOnFleaFromInventory(
pmcData: IPmcData, pmcData: IPmcData,
itemIdsFromFleaOfferRequest: string[], itemIdsFromFleaOfferRequest: string[],
): { items: Item[] | null, errorMessage: string | null } ): { items: Item[] | undefined, errorMessage: string | undefined }
{ {
const itemsToReturn = []; const itemsToReturn = [];
let errorMessage: string | null = null; let errorMessage: string | undefined = undefined;
// Count how many items are being sold and multiply the requested amount accordingly // Count how many items are being sold and multiply the requested amount accordingly
for (const itemId of itemIdsFromFleaOfferRequest) for (const itemId of itemIdsFromFleaOfferRequest)
@ -636,7 +636,7 @@ export class RagfairController
}); });
this.logger.error(errorMessage); this.logger.error(errorMessage);
return { items: null, errorMessage }; return { items: undefined, errorMessage };
} }
item = this.itemHelper.fixItemStackCount(item); item = this.itemHelper.fixItemStackCount(item);
@ -648,7 +648,7 @@ export class RagfairController
errorMessage = this.localisationService.getText("ragfair-unable_to_find_requested_items_in_inventory"); errorMessage = this.localisationService.getText("ragfair-unable_to_find_requested_items_in_inventory");
this.logger.error(errorMessage); this.logger.error(errorMessage);
return { items: null, errorMessage }; return { items: undefined, errorMessage };
} }
return { items: itemsToReturn, errorMessage }; return { items: itemsToReturn, errorMessage };

View File

@ -147,7 +147,7 @@ export class RepeatableQuestController
// Add daily quests // Add daily quests
for (let i = 0; i < this.getQuestCount(repeatableConfig, pmcData); i++) for (let i = 0; i < this.getQuestCount(repeatableConfig, pmcData); i++)
{ {
let quest = null; let quest: IRepeatableQuest | undefined = undefined;
let lifeline = 0; let lifeline = 0;
while (!quest && questTypePool.types.length > 0) while (!quest && questTypePool.types.length > 0)
{ {
@ -535,7 +535,7 @@ export class RepeatableQuestController
repeatableConfig: IRepeatableQuestConfig, repeatableConfig: IRepeatableQuestConfig,
): IRepeatableQuest ): IRepeatableQuest
{ {
let newRepeatableQuest: IRepeatableQuest = null; let newRepeatableQuest: IRepeatableQuest = undefined;
let attemptsToGenerateQuest = 0; let attemptsToGenerateQuest = 0;
while (!newRepeatableQuest && questTypePool.types.length > 0) while (!newRepeatableQuest && questTypePool.types.length > 0)
{ {

View File

@ -23,7 +23,7 @@ export class WeatherController
/** Handle client/weather */ /** Handle client/weather */
public generate(): IWeatherData public generate(): IWeatherData
{ {
let result: IWeatherData = { acceleration: 0, time: "", date: "", weather: null, season: 1 }; // defaults, hydrated below let result: IWeatherData = { acceleration: 0, time: "", date: "", weather: undefined, season: 1 }; // defaults, hydrated below
result = this.weatherGenerator.calculateGameTime(result); result = this.weatherGenerator.calculateGameTime(result);
result.weather = this.weatherGenerator.generateWeather(); result.weather = this.weatherGenerator.generateWeather();

View File

@ -223,7 +223,7 @@ export class BotEquipmentModGenerator
armorItem: ITemplateItem, armorItem: ITemplateItem,
): IFilterPlateModsForSlotByLevelResult ): IFilterPlateModsForSlotByLevelResult
{ {
const result: IFilterPlateModsForSlotByLevelResult = { result: Result.UNKNOWN_FAILURE, plateModTpls: null }; const result: IFilterPlateModsForSlotByLevelResult = { result: Result.UNKNOWN_FAILURE, plateModTpls: undefined };
// Not pmc or not a plate slot, return original mod pool array // Not pmc or not a plate slot, return original mod pool array
if (!this.itemHelper.isRemovablePlateSlot(modSlot)) if (!this.itemHelper.isRemovablePlateSlot(modSlot))
@ -796,7 +796,7 @@ export class BotEquipmentModGenerator
{ {
// Nothing in mod pool + item not required // Nothing in mod pool + item not required
this.logger.debug(`Mod pool for slot: ${request.modSlot} on item: ${request.parentTemplate._name} was empty, skipping mod`); this.logger.debug(`Mod pool for slot: ${request.modSlot} on item: ${request.parentTemplate._name} was empty, skipping mod`);
return null; return undefined;
} }
// Filter out non-whitelisted scopes, use full modpool if filtered pool would have no elements // Filter out non-whitelisted scopes, use full modpool if filtered pool would have no elements
@ -844,7 +844,7 @@ export class BotEquipmentModGenerator
if (chosenModResult.slotBlocked && !parentSlot._required) if (chosenModResult.slotBlocked && !parentSlot._required)
{ {
// Don't bother trying to fit mod, slot is completely blocked // Don't bother trying to fit mod, slot is completely blocked
return null; return undefined;
} }
// Log if mod chosen was incompatible // Log if mod chosen was incompatible
@ -864,7 +864,7 @@ export class BotEquipmentModGenerator
// Compatible item not found + not required // Compatible item not found + not required
if (!chosenModResult.found && parentSlot !== undefined && !parentSlot._required) if (!chosenModResult.found && parentSlot !== undefined && !parentSlot._required)
{ {
return null; return undefined;
} }
if (!chosenModResult.found && parentSlot !== undefined) if (!chosenModResult.found && parentSlot !== undefined)
@ -876,7 +876,7 @@ export class BotEquipmentModGenerator
); );
} }
return null; return undefined;
} }
return this.itemHelper.getItem(chosenModResult.chosenTpl); return this.itemHelper.getItem(chosenModResult.chosenTpl);
@ -1141,7 +1141,7 @@ export class BotEquipmentModGenerator
} }
// No mod found // No mod found
return null; return undefined;
} }
/** /**
@ -1336,7 +1336,7 @@ export class BotEquipmentModGenerator
itemModPool = modPool[parentTemplate._id]; itemModPool = modPool[parentTemplate._id];
} }
let exhaustableModPool = null; let exhaustableModPool = undefined;
let modSlot = "cartridges"; let modSlot = "cartridges";
const camoraFirstSlot = "camora_000"; const camoraFirstSlot = "camora_000";
if (modSlot in itemModPool) if (modSlot in itemModPool)

View File

@ -176,7 +176,7 @@ export class BotGenerator
// Remove hideout data if bot is not a PMC or pscav // Remove hideout data if bot is not a PMC or pscav
if (!(botGenerationDetails.isPmc || botGenerationDetails.isPlayerScav)) if (!(botGenerationDetails.isPmc || botGenerationDetails.isPlayerScav))
{ {
bot.Hideout = null; bot.Hideout = undefined;
} }
bot.Info.Experience = botLevel.exp; bot.Info.Experience = botLevel.exp;
@ -436,7 +436,7 @@ export class BotGenerator
const skill = skills[skillKey]; const skill = skills[skillKey];
if (!skill) if (!skill)
{ {
return null; return undefined;
} }
// All skills have id and progress props // All skills have id and progress props
@ -451,7 +451,7 @@ export class BotGenerator
return skillToAdd; return skillToAdd;
}) })
.filter((x) => x !== null); .filter((x) => x !== undefined);
} }
/** /**

View File

@ -170,7 +170,7 @@ export class BotLootGenerator
healingItemCount, healingItemCount,
botInventory, botInventory,
botRole, botRole,
null, undefined,
0, 0,
isPmc, isPmc,
containersIdFull, containersIdFull,
@ -183,7 +183,7 @@ export class BotLootGenerator
drugItemCount, drugItemCount,
botInventory, botInventory,
botRole, botRole,
null, undefined,
0, 0,
isPmc, isPmc,
containersIdFull, containersIdFull,
@ -196,7 +196,7 @@ export class BotLootGenerator
foodItemCount, foodItemCount,
botInventory, botInventory,
botRole, botRole,
null, undefined,
0, 0,
isPmc, isPmc,
containersIdFull, containersIdFull,
@ -209,7 +209,7 @@ export class BotLootGenerator
drinkItemCount, drinkItemCount,
botInventory, botInventory,
botRole, botRole,
null, undefined,
0, 0,
isPmc, isPmc,
containersIdFull, containersIdFull,
@ -222,7 +222,7 @@ export class BotLootGenerator
currencyItemCount, currencyItemCount,
botInventory, botInventory,
botRole, botRole,
null, undefined,
0, 0,
isPmc, isPmc,
containersIdFull, containersIdFull,
@ -248,7 +248,7 @@ export class BotLootGenerator
grenadeCount, grenadeCount,
botInventory, botInventory,
botRole, botRole,
null, undefined,
0, 0,
isPmc, isPmc,
containersIdFull, containersIdFull,
@ -327,7 +327,7 @@ export class BotLootGenerator
50, 50,
botInventory, botInventory,
botRole, botRole,
null, undefined,
-1, -1,
isPmc, isPmc,
containersIdFull, containersIdFull,
@ -372,7 +372,7 @@ export class BotLootGenerator
1, 1,
botInventory, botInventory,
botRole, botRole,
null, undefined,
0, 0,
true, true,
); );
@ -385,7 +385,7 @@ export class BotLootGenerator
10, 10,
botInventory, botInventory,
botRole, botRole,
null, undefined,
0, 0,
true, true,
); );
@ -421,7 +421,7 @@ export class BotLootGenerator
totalItemCount: number, totalItemCount: number,
inventoryToAddItemsTo: PmcInventory, inventoryToAddItemsTo: PmcInventory,
botRole: string, botRole: string,
itemSpawnLimits: IItemSpawnLimitSettings = null, itemSpawnLimits: IItemSpawnLimitSettings = undefined,
totalValueLimitRub = 0, totalValueLimitRub = 0,
isPmc = false, isPmc = false,
containersIdFull = new Set<string>(), containersIdFull = new Set<string>(),
@ -628,7 +628,7 @@ export class BotLootGenerator
// Must add soft inserts/plates // Must add soft inserts/plates
else if (this.itemHelper.itemRequiresSoftInserts(itemToAddTemplate._id)) else if (this.itemHelper.itemRequiresSoftInserts(itemToAddTemplate._id))
{ {
this.itemHelper.addChildSlotItems(itemToAddChildrenTo, itemToAddTemplate, null, false); this.itemHelper.addChildSlotItems(itemToAddChildrenTo, itemToAddTemplate, undefined, false);
} }
} }

View File

@ -199,7 +199,7 @@ export class FenceBaseAssortGenerator
protected isAmmoAbovePenetrationLimit(rootItemDb: ITemplateItem): boolean protected isAmmoAbovePenetrationLimit(rootItemDb: ITemplateItem): boolean
{ {
const ammoPenetrationPower = this.getAmmoPenetrationPower(rootItemDb); const ammoPenetrationPower = this.getAmmoPenetrationPower(rootItemDb);
if (ammoPenetrationPower === null) if (ammoPenetrationPower === undefined)
{ {
this.logger.warning(this.localisationService.getText("fence-unable_to_get_ammo_penetration_value", rootItemDb._id)); this.logger.warning(this.localisationService.getText("fence-unable_to_get_ammo_penetration_value", rootItemDb._id));
@ -212,9 +212,9 @@ export class FenceBaseAssortGenerator
/** /**
* Get the penetration power value of an ammo, works with ammo boxes and raw ammos * Get the penetration power value of an ammo, works with ammo boxes and raw ammos
* @param rootItemDb Ammo box or ammo item from items.db * @param rootItemDb Ammo box or ammo item from items.db
* @returns Penetration power of passed in item, null if it doesnt have a power * @returns Penetration power of passed in item, undefined if it doesnt have a power
*/ */
protected getAmmoPenetrationPower(rootItemDb: ITemplateItem): number protected getAmmoPenetrationPower(rootItemDb: ITemplateItem): number | undefined
{ {
if (this.itemHelper.isOfBaseclass(rootItemDb._id, BaseClasses.AMMO_BOX)) if (this.itemHelper.isOfBaseclass(rootItemDb._id, BaseClasses.AMMO_BOX))
{ {
@ -227,7 +227,7 @@ export class FenceBaseAssortGenerator
{ {
this.logger.warning(this.localisationService.getText("fence-ammo_not_found_in_db", cartridgeTplInBox)); this.logger.warning(this.localisationService.getText("fence-ammo_not_found_in_db", cartridgeTplInBox));
return null; return undefined;
} }
return ammoItemDb[1]._props.PenetrationPower; return ammoItemDb[1]._props.PenetrationPower;
@ -240,7 +240,7 @@ export class FenceBaseAssortGenerator
} }
// Not an ammobox or ammo // Not an ammobox or ammo
return null; return undefined;
} }
/** /**

View File

@ -896,7 +896,7 @@ export class LocationGenerator
magazineItem, magazineItem,
itemTemplate, // Magazine template itemTemplate, // Magazine template
staticAmmoDist, staticAmmoDist,
null, undefined,
this.locationConfig.minFillLooseMagazinePercent / 100, this.locationConfig.minFillLooseMagazinePercent / 100,
); );
} }
@ -1108,7 +1108,7 @@ export class LocationGenerator
magazineWithCartridges, magazineWithCartridges,
itemTemplate, itemTemplate,
staticAmmoDist, staticAmmoDist,
null, undefined,
this.locationConfig.minFillStaticMagazinePercent / 100, this.locationConfig.minFillStaticMagazinePercent / 100,
); );

View File

@ -90,7 +90,7 @@ export class PlayerScavGenerator
this.botLootCacheService.clearCache(); this.botLootCacheService.clearCache();
// Add scav metadata // Add scav metadata
scavData.savage = null; scavData.savage = undefined;
scavData.aid = pmcDataClone.aid; scavData.aid = pmcDataClone.aid;
scavData.TradersInfo = pmcDataClone.TradersInfo; scavData.TradersInfo = pmcDataClone.TradersInfo;
scavData.Info.Settings = {} as Settings; scavData.Info.Settings = {} as Settings;
@ -311,7 +311,7 @@ export class PlayerScavGenerator
protected getScavLevel(scavProfile: IPmcData): number protected getScavLevel(scavProfile: IPmcData): number
{ {
// Info can be null on initial account creation // Info can be undefined on initial account creation
if (!scavProfile.Info?.Level) if (!scavProfile.Info?.Level)
{ {
return 1; return 1;
@ -322,7 +322,7 @@ export class PlayerScavGenerator
protected getScavExperience(scavProfile: IPmcData): number protected getScavExperience(scavProfile: IPmcData): number
{ {
// Info can be null on initial account creation // Info can be undefined on initial account creation
if (!scavProfile.Info?.Experience) if (!scavProfile.Info?.Experience)
{ {
return 0; return 0;

View File

@ -185,17 +185,17 @@ export class RagfairOfferGenerator
}; };
} }
const isPlayerOffer = this.ragfairServerHelper.isPlayer(userID); const isPlayerOffer = this.profileHelper.isPlayer(userID);
if (isPlayerOffer) if (isPlayerOffer)
{ {
const playerProfile = this.profileHelper.getPmcProfile(userID); const playerProfile = this.profileHelper.getPmcProfile(userID)!;
return { return {
id: playerProfile._id, id: playerProfile._id,
memberType: MemberCategory.DEFAULT, memberType: MemberCategory.DEFAULT,
nickname: playerProfile.Info.Nickname, nickname: playerProfile.Info.Nickname,
rating: playerProfile.RagfairInfo.rating, rating: playerProfile.RagfairInfo.rating,
isRatingGrowing: playerProfile.RagfairInfo.isRatingGrowing, isRatingGrowing: playerProfile.RagfairInfo.isRatingGrowing,
avatar: null, avatar: undefined,
aid: playerProfile.aid, aid: playerProfile.aid,
}; };
} }
@ -209,7 +209,7 @@ export class RagfairOfferGenerator
this.ragfairConfig.dynamic.rating.min, this.ragfairConfig.dynamic.rating.min,
this.ragfairConfig.dynamic.rating.max), this.ragfairConfig.dynamic.rating.max),
isRatingGrowing: this.randomUtil.getBool(), isRatingGrowing: this.randomUtil.getBool(),
avatar: null, avatar: undefined,
aid: this.hashUtil.generateAccountId(), aid: this.hashUtil.generateAccountId(),
}; };
} }
@ -271,7 +271,7 @@ export class RagfairOfferGenerator
*/ */
protected getTraderId(userId: string): string protected getTraderId(userId: string): string
{ {
if (this.ragfairServerHelper.isPlayer(userId)) if (this.profileHelper.isPlayer(userId))
{ {
return this.saveServer.getProfile(userId).characters.pmc._id; return this.saveServer.getProfile(userId).characters.pmc._id;
} }
@ -286,7 +286,7 @@ export class RagfairOfferGenerator
*/ */
protected getRating(userId: string): number protected getRating(userId: string): number
{ {
if (this.ragfairServerHelper.isPlayer(userId)) if (this.profileHelper.isPlayer(userId))
{ {
// Player offer // Player offer
return this.saveServer.getProfile(userId).characters.pmc.RagfairInfo.rating; return this.saveServer.getProfile(userId).characters.pmc.RagfairInfo.rating;
@ -309,7 +309,7 @@ export class RagfairOfferGenerator
*/ */
protected getRatingGrowing(userID: string): boolean protected getRatingGrowing(userID: string): boolean
{ {
if (this.ragfairServerHelper.isPlayer(userID)) if (this.profileHelper.isPlayer(userID))
{ {
// player offer // player offer
return this.saveServer.getProfile(userID).characters.pmc.RagfairInfo.isRatingGrowing; return this.saveServer.getProfile(userID).characters.pmc.RagfairInfo.isRatingGrowing;
@ -334,18 +334,18 @@ export class RagfairOfferGenerator
*/ */
protected getOfferEndTime(userID: string, time: number): number protected getOfferEndTime(userID: string, time: number): number
{ {
if (this.ragfairServerHelper.isPlayer(userID)) if (this.profileHelper.isPlayer(userID))
{ {
// Player offer = current time + offerDurationTimeInHour; // Player offer = current time + offerDurationTimeInHour;
const offerDurationTimeHours const offerDurationTimeHours
= this.databaseServer.getTables().globals.config.RagFair.offerDurationTimeInHour; = this.databaseServer.getTables().globals!.config.RagFair.offerDurationTimeInHour;
return this.timeUtil.getTimestamp() + Math.round(offerDurationTimeHours * TimeUtil.ONE_HOUR_AS_SECONDS); return this.timeUtil.getTimestamp() + Math.round(offerDurationTimeHours * TimeUtil.ONE_HOUR_AS_SECONDS);
} }
if (this.ragfairServerHelper.isTrader(userID)) if (this.ragfairServerHelper.isTrader(userID))
{ {
// Trader offer // Trader offer
return this.databaseServer.getTables().traders[userID].base.nextResupply; return this.databaseServer.getTables().traders![userID].base.nextResupply;
} }
// Generated fake-player offer // Generated fake-player offer
@ -362,14 +362,14 @@ export class RagfairOfferGenerator
* Create multiple offers for items by using a unique list of items we've generated previously * Create multiple offers for items by using a unique list of items we've generated previously
* @param expiredOffers optional, expired offers to regenerate * @param expiredOffers optional, expired offers to regenerate
*/ */
public async generateDynamicOffers(expiredOffers: Item[][] = null): Promise<void> public async generateDynamicOffers(expiredOffers?: Item[][]): Promise<void>
{ {
const replacingExpiredOffers = expiredOffers?.length > 0; const replacingExpiredOffers = (expiredOffers?.length ?? 0) > 0;
const config = this.ragfairConfig.dynamic; const config = this.ragfairConfig.dynamic;
// get assort items from param if they exist, otherwise grab freshly generated assorts // get assort items from param if they exist, otherwise grab freshly generated assorts
const assortItemsToProcess: Item[][] = replacingExpiredOffers const assortItemsToProcess: Item[][] = replacingExpiredOffers
? expiredOffers ? expiredOffers!
: this.ragfairAssortGenerator.getAssortItems(); : this.ragfairAssortGenerator.getAssortItems();
// Store all functions to create an offer for every item and pass into Promise.all to run async // Store all functions to create an offer for every item and pass into Promise.all to run async
@ -658,7 +658,7 @@ export class RagfairOfferGenerator
// Add any missing properties to first item in array // Add any missing properties to first item in array
this.addMissingConditions(itemWithMods[0]); this.addMissingConditions(itemWithMods[0]);
if (!(this.ragfairServerHelper.isPlayer(userID) || this.ragfairServerHelper.isTrader(userID))) if (!(this.profileHelper.isPlayer(userID) || this.ragfairServerHelper.isTrader(userID)))
{ {
const parentId = this.getDynamicConditionIdForTpl(itemDetails._id); const parentId = this.getDynamicConditionIdForTpl(itemDetails._id);
if (!parentId) if (!parentId)

View File

@ -153,7 +153,7 @@ export class RepeatableQuestGenerator
dist: number, dist: number,
kill: number, kill: number,
weaponRequirement: number, weaponRequirement: number,
): number ): number | undefined
{ {
return Math.sqrt(Math.sqrt(target) + bodyPart + dist + weaponRequirement) * kill; return Math.sqrt(Math.sqrt(target) + bodyPart + dist + weaponRequirement) * kill;
} }
@ -167,7 +167,7 @@ export class RepeatableQuestGenerator
// also if only bosses are left we need to leave otherwise it's a guaranteed boss elimination // also if only bosses are left we need to leave otherwise it's a guaranteed boss elimination
// -> then it would not be a quest with low probability anymore // -> then it would not be a quest with low probability anymore
questTypePool.types = questTypePool.types.filter((t) => t !== "Elimination"); questTypePool.types = questTypePool.types.filter((t) => t !== "Elimination");
return null; return undefined;
} }
const targetKey = targetsConfig.draw()[0]; const targetKey = targetsConfig.draw()[0];
@ -208,7 +208,7 @@ export class RepeatableQuestGenerator
} }
// draw the target body part and calculate the difficulty factor // draw the target body part and calculate the difficulty factor
let bodyPartsToClient = null; let bodyPartsToClient = undefined;
let bodyPartDifficulty = 0; let bodyPartDifficulty = 0;
if (eliminationConfig.bodyPartProb > Math.random()) if (eliminationConfig.bodyPartProb > Math.random())
{ {
@ -231,7 +231,7 @@ export class RepeatableQuestGenerator
} }
// Draw a distance condition // Draw a distance condition
let distance = null; let distance = undefined;
let distanceDifficulty = 0; let distanceDifficulty = 0;
let isDistanceRequirementAllowed = !eliminationConfig.distLocationBlacklist.includes(locationKey); let isDistanceRequirementAllowed = !eliminationConfig.distLocationBlacklist.includes(locationKey);
@ -555,7 +555,7 @@ export class RepeatableQuestGenerator
), ),
); );
return null; return undefined;
} }
// Draw items to ask player to retrieve // Draw items to ask player to retrieve
@ -698,7 +698,7 @@ export class RepeatableQuestGenerator
{ {
// there are no more locations left for exploration; delete it as a possible quest type // there are no more locations left for exploration; delete it as a possible quest type
questTypePool.types = questTypePool.types.filter((t) => t !== "Exploration"); questTypePool.types = questTypePool.types.filter((t) => t !== "Exploration");
return null; return undefined;
} }
// If location drawn is factory, it's possible to either get factory4_day and factory4_night or only one // If location drawn is factory, it's possible to either get factory4_day and factory4_night or only one

View File

@ -391,7 +391,7 @@ export class RepeatableQuestRewardGenerator
* @param {integer} index All rewards will be appended to a list, for unknown reasons the client wants the index * @param {integer} index All rewards will be appended to a list, for unknown reasons the client wants the index
* @returns {object} Object of "Reward"-item-type * @returns {object} Object of "Reward"-item-type
*/ */
protected generateRewardItem(tpl: string, value: number, index: number, preset: Item[] = null): IQuestReward protected generateRewardItem(tpl: string, value: number, index: number, preset?: Item[]): IQuestReward
{ {
const id = this.objectId.generate(); const id = this.objectId.generate();
const rewardItem: IQuestReward = { target: id, value: value, type: QuestRewardType.ITEM, index: index }; const rewardItem: IQuestReward = { target: id, value: value, type: QuestRewardType.ITEM, index: index };

View File

@ -150,13 +150,13 @@ export class ExternalInventoryMagGen implements IInventoryMagGen
protected getRandomExternalMagazineForInternalMagazineGun( protected getRandomExternalMagazineForInternalMagazineGun(
weaponTpl: string, weaponTpl: string,
magazineBlacklist: string[], magazineBlacklist: string[],
): ITemplateItem ): ITemplateItem | undefined
{ {
// The mag Slot data for the weapon // The mag Slot data for the weapon
const magSlot = this.itemHelper.getItem(weaponTpl)[1]._props.Slots.find((x) => x._name === "mod_magazine"); const magSlot = this.itemHelper.getItem(weaponTpl)[1]._props.Slots.find((x) => x._name === "mod_magazine");
if (!magSlot) if (!magSlot)
{ {
return null; return undefined;
} }
// All possible mags that fit into the weapon excluding blacklisted // All possible mags that fit into the weapon excluding blacklisted
@ -165,14 +165,14 @@ export class ExternalInventoryMagGen implements IInventoryMagGen
); );
if (!magazinePool) if (!magazinePool)
{ {
return null; return undefined;
} }
// Non-internal magazines that fit into the weapon // Non-internal magazines that fit into the weapon
const externalMagazineOnlyPool = magazinePool.filter((x) => x._props.ReloadMagType !== "InternalMagazine"); const externalMagazineOnlyPool = magazinePool.filter((x) => x._props.ReloadMagType !== "InternalMagazine");
if (!externalMagazineOnlyPool || externalMagazineOnlyPool?.length === 0) if (!externalMagazineOnlyPool || externalMagazineOnlyPool?.length === 0)
{ {
return null; return undefined;
} }
// Randomly chosen external magazine // Randomly chosen external magazine

View File

@ -194,7 +194,7 @@ export class BotGeneratorHelper
* Get the chance for the weapon attachment or helmet equipment to be set as activated * Get the chance for the weapon attachment or helmet equipment to be set as activated
* @param botRole role of bot with weapon/helmet * @param botRole role of bot with weapon/helmet
* @param setting the setting of the weapon attachment/helmet equipment to be activated * @param setting the setting of the weapon attachment/helmet equipment to be activated
* @param defaultValue default value for the chance of activation if the botrole or bot equipment role is null * @param defaultValue default value for the chance of activation if the botrole or bot equipment role is undefined
* @returns Percent chance to be active * @returns Percent chance to be active
*/ */
protected getBotEquipmentSettingFromConfig( protected getBotEquipmentSettingFromConfig(

View File

@ -152,12 +152,15 @@ export class BotHelper
* @param botEquipConfig bot equipment json * @param botEquipConfig bot equipment json
* @returns RandomisationDetails * @returns RandomisationDetails
*/ */
public getBotRandomizationDetails(botLevel: number, botEquipConfig: EquipmentFilters): RandomisationDetails public getBotRandomizationDetails(
botLevel: number,
botEquipConfig: EquipmentFilters,
): RandomisationDetails | undefined
{ {
// No randomisation details found, skip // No randomisation details found, skip
if (!botEquipConfig || Object.keys(botEquipConfig).length === 0 || !botEquipConfig.randomisation) if (!botEquipConfig || Object.keys(botEquipConfig).length === 0 || !botEquipConfig.randomisation)
{ {
return null; return undefined;
} }
return botEquipConfig.randomisation.find((x) => botLevel >= x.levelRange.min && botLevel <= x.levelRange.max); return botEquipConfig.randomisation.find((x) => botLevel >= x.levelRange.min && botLevel <= x.levelRange.max);

View File

@ -2,17 +2,8 @@ import { injectable } from "tsyringe";
export class FindSlotResult export class FindSlotResult
{ {
success: boolean; constructor(public success = false, public x?: number, public y?: number, public rotation = false)
x: any; {}
y: any;
rotation: boolean;
constructor(success = false, x = null, y = null, rotation = false)
{
this.success = success;
this.x = x;
this.y = y;
this.rotation = rotation;
}
} }
@injectable() @injectable()

View File

@ -155,7 +155,7 @@ export class ProfileSptCommand implements ISptCommand
_id: this.hashUtil.generate(), _id: this.hashUtil.generate(),
Type: ProfileChangeEventType.PROFILE_LEVEL, Type: ProfileChangeEventType.PROFILE_LEVEL,
value: exp, value: exp,
entity: null, entity: undefined,
}; };
return event; return event;
} }

View File

@ -56,25 +56,28 @@ export class HandbookHelper
// Add handbook overrides found in items.json config into db // Add handbook overrides found in items.json config into db
for (const itemTpl in this.itemConfig.handbookPriceOverride) for (const itemTpl in this.itemConfig.handbookPriceOverride)
{ {
let itemToUpdate = this.databaseServer let itemToUpdate = this.databaseServer.getTables()
.getTables() .templates!
.templates.handbook.Items.find((item) => item.Id === itemTpl); .handbook
.Items.find((item) => item.Id === itemTpl);
if (!itemToUpdate) if (!itemToUpdate)
{ {
this.databaseServer.getTables().templates.handbook.Items.push({ this.databaseServer.getTables().templates!.handbook.Items.push({
Id: itemTpl, Id: itemTpl,
ParentId: this.databaseServer.getTables().templates.items[itemTpl]._parent, ParentId: this.databaseServer.getTables().templates!.items[itemTpl]._parent,
Price: this.itemConfig.handbookPriceOverride[itemTpl], Price: this.itemConfig.handbookPriceOverride[itemTpl],
}); });
itemToUpdate = this.databaseServer itemToUpdate = this.databaseServer
.getTables() .getTables()
.templates.handbook.Items.find((item) => item.Id === itemTpl); .templates!
.handbook
.Items.find((item) => item.Id === itemTpl);
} }
itemToUpdate.Price = this.itemConfig.handbookPriceOverride[itemTpl]; itemToUpdate.Price = this.itemConfig.handbookPriceOverride[itemTpl];
} }
const handbookDbClone = this.cloner.clone(this.databaseServer.getTables().templates.handbook); const handbookDbClone = this.cloner.clone(this.databaseServer.getTables().templates!.handbook);
for (const handbookItem of handbookDbClone.Items) for (const handbookItem of handbookDbClone.Items)
{ {
this.handbookPriceCache.items.byId.set(handbookItem.Id, handbookItem.Price); this.handbookPriceCache.items.byId.set(handbookItem.Id, handbookItem.Price);
@ -87,7 +90,7 @@ export class HandbookHelper
for (const handbookCategory of handbookDbClone.Categories) for (const handbookCategory of handbookDbClone.Categories)
{ {
this.handbookPriceCache.categories.byId.set(handbookCategory.Id, handbookCategory.ParentId || null); this.handbookPriceCache.categories.byId.set(handbookCategory.Id, handbookCategory.ParentId || undefined);
if (handbookCategory.ParentId) if (handbookCategory.ParentId)
{ {
if (!this.handbookPriceCache.categories.byParent.has(handbookCategory.ParentId)) if (!this.handbookPriceCache.categories.byParent.has(handbookCategory.ParentId))
@ -118,7 +121,7 @@ export class HandbookHelper
return this.handbookPriceCache.items.byId.get(tpl); return this.handbookPriceCache.items.byId.get(tpl);
} }
const handbookItem = this.databaseServer.getTables().templates.handbook.Items.find((x) => x.Id === tpl); const handbookItem = this.databaseServer.getTables().templates!.handbook.Items.find((x) => x.Id === tpl);
if (!handbookItem) if (!handbookItem)
{ {
const newValue = 0; const newValue = 0;

View File

@ -38,7 +38,7 @@ export class HealthHelper
if (!profile.vitality) if (!profile.vitality)
{ {
// Occurs on newly created profiles // Occurs on newly created profiles
profile.vitality = { health: null, effects: null }; profile.vitality = { health: undefined!, effects: undefined! };
} }
profile.vitality.health = { profile.vitality.health = {
Hydration: 0, Hydration: 0,
@ -87,9 +87,9 @@ export class HealthHelper
const profileHealth = profile.vitality.health; const profileHealth = profile.vitality.health;
const profileEffects = profile.vitality.effects; const profileEffects = profile.vitality.effects;
profileHealth.Hydration = request.Hydration; profileHealth.Hydration = request.Hydration!;
profileHealth.Energy = request.Energy; profileHealth.Energy = request.Energy!;
profileHealth.Temperature = request.Temperature; profileHealth.Temperature = request.Temperature!;
// Transfer properties from request to profile // Transfer properties from request to profile
for (const bodyPart in postRaidBodyParts) for (const bodyPart in postRaidBodyParts)

View File

@ -266,13 +266,13 @@ export class HideoutHelper
const craft = pmcData.Hideout.Production[prodId]; const craft = pmcData.Hideout.Production[prodId];
if (!craft) if (!craft)
{ {
// Craft value is null, get rid of it (could be from cancelling craft that needs cleaning up) // Craft value is undefined, get rid of it (could be from cancelling craft that needs cleaning up)
delete pmcData.Hideout.Production[prodId]; delete pmcData.Hideout.Production[prodId];
continue; continue;
} }
if (craft.Progress === undefined || craft.Progress === null) if (craft.Progress === undefined)
{ {
this.logger.warning(this.localisationService.getText("hideout-craft_has_undefined_progress_value_defaulting", prodId)); this.logger.warning(this.localisationService.getText("hideout-craft_has_undefined_progress_value_defaulting", prodId));
craft.Progress = 0; craft.Progress = 0;
@ -692,7 +692,7 @@ export class HideoutHelper
// How many units of filter are left // How many units of filter are left
let resourceValue = waterFilterItemInSlot.upd?.Resource let resourceValue = waterFilterItemInSlot.upd?.Resource
? waterFilterItemInSlot.upd.Resource.Value ? waterFilterItemInSlot.upd.Resource.Value
: null; : undefined;
if (!resourceValue) if (!resourceValue)
{ {
// Missing, is new filter, add default and subtract usage // Missing, is new filter, add default and subtract usage
@ -853,7 +853,7 @@ export class HideoutHelper
{ {
let resourceValue = airFilterArea.slots[i].item[0].upd?.Resource let resourceValue = airFilterArea.slots[i].item[0].upd?.Resource
? airFilterArea.slots[i].item[0].upd.Resource.Value ? airFilterArea.slots[i].item[0].upd.Resource.Value
: null; : undefined;
if (!resourceValue) if (!resourceValue)
{ {
resourceValue = 300 - filterDrainRate; resourceValue = 300 - filterDrainRate;
@ -891,12 +891,13 @@ export class HideoutHelper
} }
} }
protected updateBitcoinFarm(pmcData: IPmcData, btcFarmCGs: number, isGeneratorOn: boolean): Production protected updateBitcoinFarm(pmcData: IPmcData, btcFarmCGs: number, isGeneratorOn: boolean): Production | undefined
{ {
const btcProd = pmcData.Hideout.Production[HideoutHelper.bitcoinFarm]; const btcProd = pmcData.Hideout.Production[HideoutHelper.bitcoinFarm];
const bitcoinProdData = this.databaseServer const bitcoinProdData = this.databaseServer
.getTables() .getTables()
.hideout.production.find((production) => production._id === HideoutHelper.bitcoinProductionId); .hideout!
.production.find((production) => production._id === HideoutHelper.bitcoinProductionId);
const coinSlotCount = this.getBTCSlots(pmcData); const coinSlotCount = this.getBTCSlots(pmcData);
// Full on bitcoins, halt progress // Full on bitcoins, halt progress
@ -973,7 +974,7 @@ export class HideoutHelper
return btcProd; return btcProd;
} }
return null; return undefined;
} }
/** /**
@ -1003,7 +1004,7 @@ export class HideoutHelper
protected getTimeElapsedSinceLastServerTick( protected getTimeElapsedSinceLastServerTick(
pmcData: IPmcData, pmcData: IPmcData,
isGeneratorOn: boolean, isGeneratorOn: boolean,
recipe: IHideoutProduction = null, recipe?: IHideoutProduction,
): number ): number
{ {
// Reduce time elapsed (and progress) when generator is off // Reduce time elapsed (and progress) when generator is off
@ -1017,7 +1018,7 @@ export class HideoutHelper
if (!isGeneratorOn) if (!isGeneratorOn)
{ {
timeElapsed *= this.databaseServer.getTables().hideout.settings.generatorSpeedWithoutFuel; timeElapsed *= this.databaseServer.getTables().hideout!.settings.generatorSpeedWithoutFuel;
} }
return timeElapsed; return timeElapsed;
@ -1169,7 +1170,7 @@ export class HideoutHelper
itemsWithModsToAdd: itemsToAdd, itemsWithModsToAdd: itemsToAdd,
foundInRaid: true, foundInRaid: true,
useSortingTable: false, useSortingTable: false,
callback: null, callback: undefined,
}; };
// Add FiR coins to player inventory // Add FiR coins to player inventory

View File

@ -184,7 +184,7 @@ export class ItemHelper
* @param {string} tpl the template id / tpl * @param {string} tpl the template id / tpl
* @returns boolean; true for items that may be in player possession and not quest items * @returns boolean; true for items that may be in player possession and not quest items
*/ */
public isValidItem(tpl: string, invalidBaseTypes: string[] = null): boolean public isValidItem(tpl: string, invalidBaseTypes?: string[]): boolean
{ {
const baseTypes = invalidBaseTypes || this.defaultInvalidBaseTypes; const baseTypes = invalidBaseTypes || this.defaultInvalidBaseTypes;
const itemDetails = this.getItem(tpl); const itemDetails = this.getItem(tpl);
@ -496,12 +496,12 @@ export class ItemHelper
if (item.upd) if (item.upd)
{ {
const medkit = item.upd.MedKit ? item.upd.MedKit : null; const medkit = item.upd.MedKit ? item.upd.MedKit : undefined;
const repairable = item.upd.Repairable ? item.upd.Repairable : null; const repairable = item.upd.Repairable ? item.upd.Repairable : undefined;
const foodDrink = item.upd.FoodDrink ? item.upd.FoodDrink : null; const foodDrink = item.upd.FoodDrink ? item.upd.FoodDrink : undefined;
const key = item.upd.Key ? item.upd.Key : null; const key = item.upd.Key ? item.upd.Key : undefined;
const resource = item.upd.Resource ? item.upd.Resource : null; const resource = item.upd.Resource ? item.upd.Resource : undefined;
const repairKit = item.upd.RepairKit ? item.upd.RepairKit : null; const repairKit = item.upd.RepairKit ? item.upd.RepairKit : undefined;
const itemDetails = this.getItem(item._tpl)[1]; const itemDetails = this.getItem(item._tpl)[1];
@ -725,7 +725,7 @@ export class ItemHelper
*/ */
public splitStack(itemToSplit: Item): Item[] public splitStack(itemToSplit: Item): Item[]
{ {
if (!(itemToSplit?.upd?.StackObjectsCount != null)) if (itemToSplit?.upd?.StackObjectsCount === undefined)
{ {
return [itemToSplit]; return [itemToSplit];
} }
@ -834,9 +834,9 @@ export class ItemHelper
*/ */
public replaceIDs( public replaceIDs(
originalItems: Item[], originalItems: Item[],
pmcData: IPmcData | null = null, pmcData?: IPmcData,
insuredItems: InsuredItem[] | null = null, insuredItems?: InsuredItem[],
fastPanel = null, fastPanel?: any,
): Item[] ): Item[]
{ {
let items = this.cloner.clone(originalItems); // Deep-clone the items to avoid mutation. let items = this.cloner.clone(originalItems); // Deep-clone the items to avoid mutation.
@ -844,7 +844,7 @@ export class ItemHelper
for (const item of items) for (const item of items)
{ {
if (pmcData !== null) if (pmcData)
{ {
// Insured items should not be renamed. Only works for PMCs. // Insured items should not be renamed. Only works for PMCs.
if (insuredItems?.find((insuredItem) => insuredItem.itemId === item._id)) if (insuredItems?.find((insuredItem) => insuredItem.itemId === item._id))
@ -871,7 +871,7 @@ export class ItemHelper
serialisedInventory = serialisedInventory.replace(new RegExp(oldId, "g"), newId); serialisedInventory = serialisedInventory.replace(new RegExp(oldId, "g"), newId);
// Also replace in quick slot if the old ID exists. // Also replace in quick slot if the old ID exists.
if (fastPanel !== null) if (fastPanel)
{ {
for (const itemSlot in fastPanel) for (const itemSlot in fastPanel)
{ {
@ -1031,14 +1031,14 @@ export class ItemHelper
* *
* @param item The item to be checked * @param item The item to be checked
* @param parent The parent of the item to be checked * @param parent The parent of the item to be checked
* @returns True if the item is actually moddable, false if it is not, and null if the check cannot be performed. * @returns True if the item is actually moddable, false if it is not, and undefined if the check cannot be performed.
*/ */
public isRaidModdable(item: Item, parent: Item): boolean | null public isRaidModdable(item: Item, parent: Item): boolean | undefined
{ {
// This check requires the item to have the slotId property populated. // This check requires the item to have the slotId property populated.
if (!item.slotId) if (!item.slotId)
{ {
return null; return undefined;
} }
const itemTemplate = this.getItem(item._tpl); const itemTemplate = this.getItem(item._tpl);
@ -1077,9 +1077,9 @@ export class ItemHelper
* *
* @param itemId - The unique identifier of the item for which to find the main parent. * @param itemId - The unique identifier of the item for which to find the main parent.
* @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup. * @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup.
* @returns The Item object representing the top-most parent of the given item, or `null` if no such parent exists. * @returns The Item object representing the top-most parent of the given item, or `undefined` if no such parent exists.
*/ */
public getAttachmentMainParent(itemId: string, itemsMap: Map<string, Item>): Item | null public getAttachmentMainParent(itemId: string, itemsMap: Map<string, Item>): Item | undefined
{ {
let currentItem = itemsMap.get(itemId); let currentItem = itemsMap.get(itemId);
while (currentItem && this.isAttachmentAttached(currentItem)) while (currentItem && this.isAttachmentAttached(currentItem))
@ -1087,7 +1087,7 @@ export class ItemHelper
currentItem = itemsMap.get(currentItem.parentId); currentItem = itemsMap.get(currentItem.parentId);
if (!currentItem) if (!currentItem)
{ {
return null; return undefined;
} }
} }
return currentItem; return currentItem;
@ -1123,9 +1123,9 @@ export class ItemHelper
* *
* @param itemId - The unique identifier of the item for which to find the equipment parent. * @param itemId - The unique identifier of the item for which to find the equipment parent.
* @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup. * @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup.
* @returns The Item object representing the equipment parent of the given item, or `null` if no such parent exists. * @returns The Item object representing the equipment parent of the given item, or `undefined` if no such parent exists.
*/ */
public getEquipmentParent(itemId: string, itemsMap: Map<string, Item>): Item | null public getEquipmentParent(itemId: string, itemsMap: Map<string, Item>): Item | undefined
{ {
let currentItem = itemsMap.get(itemId); let currentItem = itemsMap.get(itemId);
const equipmentSlots = Object.values(EquipmentSlots).map((value) => value as string); const equipmentSlots = Object.values(EquipmentSlots).map((value) => value as string);
@ -1135,7 +1135,7 @@ export class ItemHelper
currentItem = itemsMap.get(currentItem.parentId); currentItem = itemsMap.get(currentItem.parentId);
if (!currentItem) if (!currentItem)
{ {
return null; return undefined;
} }
} }
return currentItem; return currentItem;
@ -1197,14 +1197,14 @@ export class ItemHelper
* @param item Db item template to look up Cartridge filter values from * @param item Db item template to look up Cartridge filter values from
* @returns Caliber of cartridge * @returns Caliber of cartridge
*/ */
public getRandomCompatibleCaliberTemplateId(item: ITemplateItem): string | null public getRandomCompatibleCaliberTemplateId(item: ITemplateItem): string | undefined
{ {
const cartridges = item?._props?.Cartridges[0]?._props?.filters[0]?.Filter; const cartridges = item?._props?.Cartridges[0]?._props?.filters[0]?.Filter;
if (!cartridges) if (!cartridges)
{ {
this.logger.warning(`Failed to find cartridge for item: ${item?._id} ${item?._name}`); this.logger.warning(`Failed to find cartridge for item: ${item?._id} ${item?._name}`);
return null; return undefined;
} }
return this.randomUtil.getArrayValue(cartridges); return this.randomUtil.getArrayValue(cartridges);
@ -1467,8 +1467,8 @@ export class ItemHelper
caliber: string, caliber: string,
staticAmmoDist: Record<string, IStaticAmmoDetails[]>, staticAmmoDist: Record<string, IStaticAmmoDetails[]>,
fallbackCartridgeTpl: string, fallbackCartridgeTpl: string,
cartridgeWhitelist: string[] = null, cartridgeWhitelist?: string[],
): string ): string | undefined
{ {
const ammos = staticAmmoDist[caliber]; const ammos = staticAmmoDist[caliber];
if (!ammos && fallbackCartridgeTpl) if (!ammos && fallbackCartridgeTpl)
@ -1581,7 +1581,7 @@ export class ItemHelper
public addChildSlotItems( public addChildSlotItems(
itemToAdd: Item[], itemToAdd: Item[],
itemToAddTemplate: ITemplateItem, itemToAddTemplate: ITemplateItem,
modSpawnChanceDict: Record<string, number> = null, modSpawnChanceDict?: Record<string, number>,
requiredOnly = false, requiredOnly = false,
): Item[] ): Item[]
{ {
@ -1641,16 +1641,16 @@ export class ItemHelper
* Get a compatible tpl from the array provided where it is not found in the provided incompatible mod tpls parameter * Get a compatible tpl from the array provided where it is not found in the provided incompatible mod tpls parameter
* @param possibleTpls Tpls to randomly choose from * @param possibleTpls Tpls to randomly choose from
* @param incompatibleModTpls Incompatible tpls to not allow * @param incompatibleModTpls Incompatible tpls to not allow
* @returns Chosen tpl or null * @returns Chosen tpl or undefined
*/ */
public getCompatibleTplFromArray(possibleTpls: string[], incompatibleModTpls: Set<string>): string public getCompatibleTplFromArray(possibleTpls: string[], incompatibleModTpls: Set<string>): string | undefined
{ {
if (possibleTpls.length === 0) if (possibleTpls.length === 0)
{ {
return null; return undefined;
} }
let chosenTpl = null; let chosenTpl: string | undefined = undefined;
let count = 0; let count = 0;
while (!chosenTpl) while (!chosenTpl)
{ {
@ -1662,7 +1662,7 @@ export class ItemHelper
count++; count++;
if (count >= possibleTpls.length) if (count >= possibleTpls.length)
{ {
return null; return undefined;
} }
continue; continue;
} }
@ -1818,7 +1818,7 @@ export class ItemHelper
* @param warningMessageWhenMissing text to write to log when upd object was not found * @param warningMessageWhenMissing text to write to log when upd object was not found
* @returns True when upd object was added * @returns True when upd object was added
*/ */
public addUpdObjectToItem(item: Item, warningMessageWhenMissing: string = null): boolean public addUpdObjectToItem(item: Item, warningMessageWhenMissing?: string): boolean
{ {
if (!item.upd) if (!item.upd)
{ {

View File

@ -138,11 +138,11 @@ export class PresetHelper
* @param templateId Item id to get preset for * @param templateId Item id to get preset for
* @returns Null if no default preset, otherwise IPreset * @returns Null if no default preset, otherwise IPreset
*/ */
public getDefaultPreset(templateId: string): IPreset public getDefaultPreset(templateId: string): IPreset | undefined
{ {
if (!this.hasPreset(templateId)) if (!this.hasPreset(templateId))
{ {
return null; return undefined;
} }
const allPresets = this.getPresets(templateId); const allPresets = this.getPresets(templateId);

View File

@ -218,7 +218,7 @@ export class ProfileHelper
public getExperience(level: number): number public getExperience(level: number): number
{ {
let playerLevel = level; let playerLevel = level;
const expTable = this.databaseServer.getTables().globals.config.exp.level.exp_table; const expTable = this.databaseServer.getTables().globals!.config.exp.level.exp_table;
let exp = 0; let exp = 0;
if (playerLevel >= expTable.length) if (playerLevel >= expTable.length)
@ -241,7 +241,7 @@ export class ProfileHelper
*/ */
public getMaxLevel(): number public getMaxLevel(): number
{ {
return this.databaseServer.getTables().globals.config.exp.level.exp_table.length - 1; return this.databaseServer.getTables().globals!.config.exp.level.exp_table.length - 1;
} }
public getDefaultSptDataObject(): any public getDefaultSptDataObject(): any
@ -254,14 +254,11 @@ export class ProfileHelper
* @param sessionID Profile id to get * @param sessionID Profile id to get
* @returns ISptProfile object * @returns ISptProfile object
*/ */
public getFullProfile(sessionID: string): ISptProfile public getFullProfile(sessionID: string): ISptProfile | undefined
{ {
if (this.saveServer.getProfile(sessionID) === undefined) return this.saveServer.profileExists(sessionID)
{ ? this.saveServer.getProfile(sessionID)
return undefined; : undefined;
}
return this.saveServer.getProfile(sessionID);
} }
/** /**
@ -269,10 +266,10 @@ export class ProfileHelper
* @param sessionID Profile id to return * @param sessionID Profile id to return
* @returns IPmcData object * @returns IPmcData object
*/ */
public getPmcProfile(sessionID: string): IPmcData public getPmcProfile(sessionID: string): IPmcData | undefined
{ {
const fullProfile = this.getFullProfile(sessionID); const fullProfile = this.getFullProfile(sessionID);
if (fullProfile === undefined || fullProfile.characters.pmc === undefined) if (!fullProfile?.characters?.pmc)
{ {
return undefined; return undefined;
} }
@ -280,6 +277,16 @@ export class ProfileHelper
return this.saveServer.getProfile(sessionID).characters.pmc; return this.saveServer.getProfile(sessionID).characters.pmc;
} }
/**
* Is this user id the logged in player
* @param userId Id to test
* @returns True is the current player
*/
public isPlayer(userId: string): boolean
{
return this.saveServer.profileExists(userId);
}
/** /**
* Get a full profiles scav-specific sub-profile * Get a full profiles scav-specific sub-profile
* @param sessionID Profiles id * @param sessionID Profiles id
@ -299,7 +306,7 @@ export class ProfileHelper
return { return {
Eft: { Eft: {
CarriedQuestItems: [], CarriedQuestItems: [],
DamageHistory: { LethalDamagePart: "Head", LethalDamage: undefined, BodyParts: <any>[] }, DamageHistory: { LethalDamagePart: "Head", LethalDamage: undefined!, BodyParts: <any>[] },
DroppedItems: [], DroppedItems: [],
ExperienceBonusMult: 0, ExperienceBonusMult: 0,
FoundInRaidItems: [], FoundInRaidItems: [],

View File

@ -6,7 +6,7 @@ export class QuestConditionHelper
{ {
public getQuestConditions( public getQuestConditions(
q: IQuestCondition[], q: IQuestCondition[],
furtherFilter: (a: IQuestCondition) => IQuestCondition[] = null, furtherFilter?: (a: IQuestCondition) => IQuestCondition[],
): IQuestCondition[] ): IQuestCondition[]
{ {
return this.filterConditions(q, "Quest", furtherFilter); return this.filterConditions(q, "Quest", furtherFilter);
@ -14,7 +14,7 @@ export class QuestConditionHelper
public getLevelConditions( public getLevelConditions(
q: IQuestCondition[], q: IQuestCondition[],
furtherFilter: (a: IQuestCondition) => IQuestCondition[] = null, furtherFilter?: (a: IQuestCondition) => IQuestCondition[],
): IQuestCondition[] ): IQuestCondition[]
{ {
return this.filterConditions(q, "Level", furtherFilter); return this.filterConditions(q, "Level", furtherFilter);
@ -22,7 +22,7 @@ export class QuestConditionHelper
public getLoyaltyConditions( public getLoyaltyConditions(
q: IQuestCondition[], q: IQuestCondition[],
furtherFilter: (a: IQuestCondition) => IQuestCondition[] = null, furtherFilter?: (a: IQuestCondition) => IQuestCondition[],
): IQuestCondition[] ): IQuestCondition[]
{ {
return this.filterConditions(q, "TraderLoyalty", furtherFilter); return this.filterConditions(q, "TraderLoyalty", furtherFilter);
@ -30,7 +30,7 @@ export class QuestConditionHelper
public getStandingConditions( public getStandingConditions(
q: IQuestCondition[], q: IQuestCondition[],
furtherFilter: (a: IQuestCondition) => IQuestCondition[] = null, furtherFilter?: (a: IQuestCondition) => IQuestCondition[],
): IQuestCondition[] ): IQuestCondition[]
{ {
return this.filterConditions(q, "TraderStanding", furtherFilter); return this.filterConditions(q, "TraderStanding", furtherFilter);
@ -39,7 +39,7 @@ export class QuestConditionHelper
protected filterConditions( protected filterConditions(
q: IQuestCondition[], q: IQuestCondition[],
questType: string, questType: string,
furtherFilter: (a: IQuestCondition) => IQuestCondition[] = null, furtherFilter?: (a: IQuestCondition) => IQuestCondition[],
): IQuestCondition[] ): IQuestCondition[]
{ {
const filteredQuests = q.filter((c) => const filteredQuests = q.filter((c) =>

View File

@ -374,7 +374,7 @@ export class QuestHelper
const itemDbData = this.itemHelper.getItem(originalRewardRootItem._tpl)[1]; const itemDbData = this.itemHelper.getItem(originalRewardRootItem._tpl)[1];
// Hydrate reward with only 'required' mods - necessary for things like helmets otherwise you end up with nvgs/visors etc // Hydrate reward with only 'required' mods - necessary for things like helmets otherwise you end up with nvgs/visors etc
questReward.items = this.itemHelper.addChildSlotItems(questReward.items, itemDbData, null, true); questReward.items = this.itemHelper.addChildSlotItems(questReward.items, itemDbData, undefined, true);
} }
/** /**
@ -716,7 +716,7 @@ export class QuestHelper
pmcData: IPmcData, pmcData: IPmcData,
failRequest: IFailQuestRequestData, failRequest: IFailQuestRequestData,
sessionID: string, sessionID: string,
output: IItemEventRouterResponse = null, output?: IItemEventRouterResponse,
): void ): void
{ {
let updatedOutput = output; let updatedOutput = output;
@ -751,7 +751,7 @@ export class QuestHelper
{ {
this.mailSendService.sendLocalisedNpcMessageToPlayer( this.mailSendService.sendLocalisedNpcMessageToPlayer(
sessionID, sessionID,
this.traderHelper.getTraderById(quest?.traderId ?? matchingRepeatableQuest?.traderId), // Can be null when repeatable quest has been moved to inactiveQuests this.traderHelper.getTraderById(quest?.traderId ?? matchingRepeatableQuest?.traderId), // Can be undefined when repeatable quest has been moved to inactiveQuests
MessageType.QUEST_FAIL, MessageType.QUEST_FAIL,
quest.failMessageText, quest.failMessageText,
questRewards, questRewards,

View File

@ -151,7 +151,7 @@ export class RagfairHelper
public mergeStackable(items: Item[]): Item[] public mergeStackable(items: Item[]): Item[]
{ {
const list = []; const list = [];
let rootItem = null; let rootItem = undefined;
for (let item of items) for (let item of items)
{ {

View File

@ -510,7 +510,7 @@ export class RagfairOfferHelper
itemsToSend, itemsToSend,
this.timeUtil.getHoursAsSeconds( this.timeUtil.getHoursAsSeconds(
this.questHelper.getMailItemRedeemTimeHoursForProfile(this.profileHelper.getPmcProfile(sessionID))), this.questHelper.getMailItemRedeemTimeHoursForProfile(this.profileHelper.getPmcProfile(sessionID))),
null, undefined,
ragfairDetails, ragfairDetails,
); );
@ -755,7 +755,7 @@ export class RagfairOfferHelper
if (Number.isNaN(offer.requirementsCost)) if (Number.isNaN(offer.requirementsCost))
{ {
// don't include offers with null or NaN in it // don't include offers with undefined or NaN in it
return false; return false;
} }

View File

@ -147,20 +147,6 @@ export class RagfairServerHelper
return traderId in this.databaseServer.getTables().traders; return traderId in this.databaseServer.getTables().traders;
} }
/**
* Is this user id the logged in player
* @param userId Id to test
* @returns True is the current player
*/
public isPlayer(userId: string): boolean
{
if (this.profileHelper.getPmcProfile(userId) !== undefined)
{
return true;
}
return false;
}
/** /**
* Send items back to player * Send items back to player
* @param sessionID Player to send items to * @param sessionID Player to send items to

View File

@ -292,7 +292,7 @@ export class TraderAssortHelper
items: this.ragfairAssortGenerator.getAssortItems().flat(), items: this.ragfairAssortGenerator.getAssortItems().flat(),
barter_scheme: {}, barter_scheme: {},
loyal_level_items: {}, loyal_level_items: {},
nextResupply: null, nextResupply: undefined,
}; };
} }
} }

View File

@ -116,9 +116,9 @@ export class ModLoadOrder
// Additional info to help debug // Additional info to help debug
this.logger.debug(this.localisationService.getText("modloader-checking_mod", mod)); this.logger.debug(this.localisationService.getText("modloader-checking_mod", mod));
this.logger.debug(`${this.localisationService.getText("modloader-checked")}:`); this.logger.debug(`${this.localisationService.getText("modloader-checked")}:`);
this.logger.debug(JSON.stringify(this.loadOrder, null, "\t")); this.logger.debug(JSON.stringify(this.loadOrder, undefined, "\t"));
this.logger.debug(`${this.localisationService.getText("modloader-visited")}:`); this.logger.debug(`${this.localisationService.getText("modloader-visited")}:`);
this.logger.debug(JSON.stringify(visited, null, "\t")); this.logger.debug(JSON.stringify(visited, undefined, "\t"));
throw new Error(this.localisationService.getText("modloader-cyclic_dependency")); throw new Error(this.localisationService.getText("modloader-cyclic_dependency"));
} }

View File

@ -136,7 +136,7 @@ export class PreSptModLoader implements IModLoader
this.logger.info(this.localisationService.getText("modloader-mod_order_missing")); this.logger.info(this.localisationService.getText("modloader-mod_order_missing"));
// Write file with empty order array to disk // Write file with empty order array to disk
this.vfs.writeFile(this.modOrderPath, this.jsonUtil.serializeAdvanced({ order: [] }, null, 4)); this.vfs.writeFile(this.modOrderPath, this.jsonUtil.serializeAdvanced({ order: [] }, undefined, 4));
} }
else else
{ {

View File

@ -1,4 +1,4 @@
export interface IGameModeRequestData export interface IGameModeRequestData
{ {
sessionMode: string | null sessionMode: string | undefined
} }

View File

@ -2,5 +2,5 @@ export interface INullResponseData
{ {
err: number err: number
errmsg: any errmsg: any
data: null data: undefined
} }

View File

@ -14,11 +14,11 @@ export class ExhaustableArray<T> implements IExhaustableArray<T>
this.pool = this.cloner.clone(itemPool); this.pool = this.cloner.clone(itemPool);
} }
public getRandomValue(): T public getRandomValue(): T | undefined
{ {
if (!this.pool?.length) if (!this.pool?.length)
{ {
return null; return undefined;
} }
const index = this.randomUtil.getInt(0, this.pool.length - 1); const index = this.randomUtil.getInt(0, this.pool.length - 1);
@ -27,11 +27,11 @@ export class ExhaustableArray<T> implements IExhaustableArray<T>
return toReturn; return toReturn;
} }
public getFirstValue(): T public getFirstValue(): T | undefined
{ {
if (!this.pool?.length) if (!this.pool?.length)
{ {
return null; return undefined;
} }
const toReturn = this.cloner.clone(this.pool[0]); const toReturn = this.cloner.clone(this.pool[0]);
@ -52,7 +52,7 @@ export class ExhaustableArray<T> implements IExhaustableArray<T>
export interface IExhaustableArray<T> export interface IExhaustableArray<T>
{ {
getRandomValue(): T getRandomValue(): T | undefined
getFirstValue(): T getFirstValue(): T | undefined
hasValues(): boolean hasValues(): boolean
} }

View File

@ -144,7 +144,7 @@ export class EventOutputHolder
*/ */
protected getProductionsFromProfileAndFlagComplete( protected getProductionsFromProfileAndFlagComplete(
productions: Record<string, Productive>, productions: Record<string, Productive>,
): Record<string, Productive> ): Record<string, Productive> | undefined
{ {
for (const productionKey in productions) for (const productionKey in productions)
{ {
@ -182,8 +182,8 @@ export class EventOutputHolder
} }
} }
// Return null if there's no crafts to send to client to match live behaviour // Return undefined if there's no crafts to send to client to match live behaviour
return Object.keys(productions).length > 0 ? productions : null; return Object.keys(productions).length > 0 ? productions : undefined;
} }
/** /**

View File

@ -15,7 +15,7 @@ export class HealthSaveLoadRouter extends SaveLoadRouter
if (!profile.vitality) if (!profile.vitality)
{ {
// Occurs on newly created profiles // Occurs on newly created profiles
profile.vitality = { health: null, effects: null }; profile.vitality = { health: undefined!, effects: undefined! };
} }
profile.vitality.health = { profile.vitality.health = {
Hydration: 0, Hydration: 0,

View File

@ -13,7 +13,7 @@ export class ProfileSaveLoadRouter extends SaveLoadRouter
public override handleLoad(profile: ISptProfile): ISptProfile public override handleLoad(profile: ISptProfile): ISptProfile
{ {
if (profile.characters === null) if (!profile.characters)
{ {
profile.characters = { pmc: {} as IPmcData, scav: {} as IPmcData }; profile.characters = { pmc: {} as IPmcData, scav: {} as IPmcData };
} }

View File

@ -46,7 +46,7 @@ export class SaveServer
*/ */
public removeBeforeSaveCallback(id: string): void public removeBeforeSaveCallback(id: string): void
{ {
this.onBeforeSaveCallbacks[id] = null; this.onBeforeSaveCallbacks[id] = undefined;
} }
/** /**
@ -102,12 +102,12 @@ export class SaveServer
throw new Error("session id provided was empty, did you restart the server while the game was running?"); throw new Error("session id provided was empty, did you restart the server while the game was running?");
} }
if (this.profiles === null) if (!this.profiles)
{ {
throw new Error(`no profiles found in saveServer with id: ${sessionId}`); throw new Error(`no profiles found in saveServer with id: ${sessionId}`);
} }
if (this.profiles[sessionId] === null) if (!this.profiles[sessionId])
{ {
throw new Error(`no profile found for sessionId: ${sessionId}`); throw new Error(`no profile found for sessionId: ${sessionId}`);
} }
@ -115,6 +115,11 @@ export class SaveServer
return this.profiles[sessionId]; return this.profiles[sessionId];
} }
public profileExists(id: string): boolean
{
return !!this.profiles[id];
}
/** /**
* Get all profiles from memory * Get all profiles from memory
* @returns Dictionary of ISptProfile * @returns Dictionary of ISptProfile
@ -131,7 +136,7 @@ export class SaveServer
*/ */
public deleteProfileById(sessionID: string): boolean public deleteProfileById(sessionID: string): boolean
{ {
if (this.profiles[sessionID] != null) if (this.profiles[sessionID])
{ {
delete this.profiles[sessionID]; delete this.profiles[sessionID];
return true; return true;
@ -146,7 +151,7 @@ export class SaveServer
*/ */
public createProfile(profileInfo: Info): void public createProfile(profileInfo: Info): void
{ {
if (this.profiles[profileInfo.id] != null) if (this.profiles[profileInfo.id])
{ {
throw new Error(`profile already exists for sessionId: ${profileInfo.id}`); throw new Error(`profile already exists for sessionId: ${profileInfo.id}`);
} }

View File

@ -34,8 +34,8 @@ export class SptHttpListener implements IHttpListener
{ {
case "GET": case "GET":
{ {
const response = await this.getResponse(sessionId, req, null); const response = await this.getResponse(sessionId, req, undefined);
this.sendResponse(sessionId, req, resp, null, response); this.sendResponse(sessionId, req, resp, undefined, response);
break; break;
} }
// these are handled almost identically. // these are handled almost identically.
@ -152,12 +152,12 @@ export class SptHttpListener implements IHttpListener
{ {
this.logger.error(this.localisationService.getText("unhandled_response", req.url)); this.logger.error(this.localisationService.getText("unhandled_response", req.url));
this.logger.info(info); this.logger.info(info);
output = <string>(<unknown> this.httpResponse.getBody(null, 404, `UNHANDLED RESPONSE: ${req.url}`)); output = <string>(<unknown> this.httpResponse.getBody(undefined, 404, `UNHANDLED RESPONSE: ${req.url}`));
} }
return output; return output;
} }
protected getBodyInfo(body: Buffer, requestUrl = null): any protected getBodyInfo(body: Buffer, requestUrl = undefined): any
{ {
const text = body ? body.toString() : "{}"; const text = body ? body.toString() : "{}";
const info = text ? this.jsonUtil.deserialize<any>(text, requestUrl) : {}; const info = text ? this.jsonUtil.deserialize<any>(text, requestUrl) : {};

View File

@ -20,7 +20,7 @@ export class SptWebSocketConnectionHandler implements IWebSocketConnectionHandle
protected webSockets: Map<string, WebSocket> = new Map<string, WebSocket>(); protected webSockets: Map<string, WebSocket> = new Map<string, WebSocket>();
protected defaultNotification: IWsNotificationEvent = { type: NotificationEventType.PING, eventId: "ping" }; protected defaultNotification: IWsNotificationEvent = { type: NotificationEventType.PING, eventId: "ping" };
protected websocketPingHandler = null; protected websocketPingHandler: NodeJS.Timeout | undefined;
constructor( constructor(
@inject("WinstonLogger") protected logger: ILogger, @inject("WinstonLogger") protected logger: ILogger,
@inject("ProfileHelper") protected profileHelper: ProfileHelper, @inject("ProfileHelper") protected profileHelper: ProfileHelper,

View File

@ -152,13 +152,13 @@ export class BotEquipmentFilterService
* @param botEquipmentRole equipment role of bot to look up * @param botEquipmentRole equipment role of bot to look up
* @returns Dictionary of weapon type and their whitelisted scope types * @returns Dictionary of weapon type and their whitelisted scope types
*/ */
public getBotWeaponSightWhitelist(botEquipmentRole: string): Record<string, string[]> public getBotWeaponSightWhitelist(botEquipmentRole: string): Record<string, string[]> | undefined
{ {
const botEquipmentSettings = this.botEquipmentConfig[botEquipmentRole]; const botEquipmentSettings = this.botEquipmentConfig[botEquipmentRole];
if (!botEquipmentSettings) if (!botEquipmentSettings)
{ {
return null; return undefined;
} }
return botEquipmentSettings.weaponSightWhitelist; return botEquipmentSettings.weaponSightWhitelist;
@ -170,7 +170,7 @@ export class BotEquipmentFilterService
* @param playerLevel Level of the player * @param playerLevel Level of the player
* @returns EquipmentBlacklistDetails object * @returns EquipmentBlacklistDetails object
*/ */
public getBotEquipmentBlacklist(botRole: string, playerLevel: number): EquipmentFilterDetails public getBotEquipmentBlacklist(botRole: string, playerLevel: number): EquipmentFilterDetails | undefined
{ {
const blacklistDetailsForBot = this.botEquipmentConfig[botRole]; const blacklistDetailsForBot = this.botEquipmentConfig[botRole];
@ -181,7 +181,7 @@ export class BotEquipmentFilterService
|| !blacklistDetailsForBot.blacklist || !blacklistDetailsForBot.blacklist
) )
{ {
return null; return undefined;
} }
return blacklistDetailsForBot.blacklist.find( return blacklistDetailsForBot.blacklist.find(
@ -195,14 +195,14 @@ export class BotEquipmentFilterService
* @param playerLevel Players level * @param playerLevel Players level
* @returns EquipmentFilterDetails object * @returns EquipmentFilterDetails object
*/ */
protected getBotEquipmentWhitelist(botRole: string, playerLevel: number): EquipmentFilterDetails protected getBotEquipmentWhitelist(botRole: string, playerLevel: number): EquipmentFilterDetails | undefined
{ {
const botEquipmentConfig = this.botEquipmentConfig[botRole]; const botEquipmentConfig = this.botEquipmentConfig[botRole];
// No equipment blacklist found, skip // No equipment blacklist found, skip
if (!botEquipmentConfig || Object.keys(botEquipmentConfig).length === 0 || !botEquipmentConfig.whitelist) if (!botEquipmentConfig || Object.keys(botEquipmentConfig).length === 0 || !botEquipmentConfig.whitelist)
{ {
return null; return undefined;
} }
return botEquipmentConfig.whitelist.find( return botEquipmentConfig.whitelist.find(
@ -216,7 +216,7 @@ export class BotEquipmentFilterService
* @param botLevel Level of bot * @param botLevel Level of bot
* @returns Weighting adjustments for bot items * @returns Weighting adjustments for bot items
*/ */
protected getBotWeightingAdjustments(botRole: string, botLevel: number): WeightingAdjustmentDetails protected getBotWeightingAdjustments(botRole: string, botLevel: number): WeightingAdjustmentDetails | undefined
{ {
const botEquipmentConfig = this.botEquipmentConfig[botRole]; const botEquipmentConfig = this.botEquipmentConfig[botRole];
@ -227,7 +227,7 @@ export class BotEquipmentFilterService
|| !botEquipmentConfig.weightingAdjustmentsByBotLevel || !botEquipmentConfig.weightingAdjustmentsByBotLevel
) )
{ {
return null; return undefined;
} }
return botEquipmentConfig.weightingAdjustmentsByBotLevel.find( return botEquipmentConfig.weightingAdjustmentsByBotLevel.find(
@ -244,7 +244,7 @@ export class BotEquipmentFilterService
protected getBotWeightingAdjustmentsByPlayerLevel( protected getBotWeightingAdjustmentsByPlayerLevel(
botRole: string, botRole: string,
playerlevel: number, playerlevel: number,
): WeightingAdjustmentDetails ): WeightingAdjustmentDetails | undefined
{ {
const botEquipmentConfig = this.botEquipmentConfig[botRole]; const botEquipmentConfig = this.botEquipmentConfig[botRole];
@ -255,7 +255,7 @@ export class BotEquipmentFilterService
|| !botEquipmentConfig.weightingAdjustmentsByPlayerLevel || !botEquipmentConfig.weightingAdjustmentsByPlayerLevel
) )
{ {
return null; return undefined;
} }
return botEquipmentConfig.weightingAdjustmentsByPlayerLevel.find( return botEquipmentConfig.weightingAdjustmentsByPlayerLevel.find(

View File

@ -532,7 +532,7 @@ export class BotLootCacheService
} }
/** /**
* If lootcache is null, init with empty property arrays * If lootcache is undefined, init with empty property arrays
* @param botRole Bot role to hydrate * @param botRole Bot role to hydrate
*/ */
protected initCacheForBotRole(botRole: string): void protected initCacheForBotRole(botRole: string): void

View File

@ -38,10 +38,10 @@ export class FenceService
protected nextPartialRefreshTimestamp: number; protected nextPartialRefreshTimestamp: number;
/** Main assorts you see at all rep levels */ /** Main assorts you see at all rep levels */
protected fenceAssort: ITraderAssort = undefined; protected fenceAssort?: ITraderAssort = undefined;
/** Assorts shown on a separate tab when you max out fence rep */ /** Assorts shown on a separate tab when you max out fence rep */
protected fenceDiscountAssort: ITraderAssort = undefined; protected fenceDiscountAssort?: ITraderAssort = undefined;
/** Desired baseline counts - Hydrated on initial assort generation as part of generateFenceAssorts() */ /** Desired baseline counts - Hydrated on initial assort generation as part of generateFenceAssorts() */
protected desiredAssortCounts: IFenceAssortGenerationValues; protected desiredAssortCounts: IFenceAssortGenerationValues;
@ -96,7 +96,7 @@ export class FenceService
* Get main fence assort * Get main fence assort
* @return ITraderAssort * @return ITraderAssort
*/ */
public getMainFenceAssort(): ITraderAssort public getMainFenceAssort(): ITraderAssort | undefined
{ {
return this.fenceAssort; return this.fenceAssort;
} }
@ -105,7 +105,7 @@ export class FenceService
* Get discount fence assort * Get discount fence assort
* @return ITraderAssort * @return ITraderAssort
*/ */
public getDiscountFenceAssort(): ITraderAssort public getDiscountFenceAssort(): ITraderAssort | undefined
{ {
return this.fenceDiscountAssort; return this.fenceDiscountAssort;
} }
@ -135,23 +135,23 @@ export class FenceService
// Clone assorts so we can adjust prices before sending to client // Clone assorts so we can adjust prices before sending to client
const assort = this.cloner.clone(this.fenceAssort); const assort = this.cloner.clone(this.fenceAssort);
this.adjustAssortItemPricesByConfigMultiplier(assort, 1, this.traderConfig.fence.presetPriceMult); this.adjustAssortItemPricesByConfigMultiplier(assort!, 1, this.traderConfig.fence.presetPriceMult);
// merge normal fence assorts + discount assorts if player standing is large enough // merge normal fence assorts + discount assorts if player standing is large enough
if (pmcProfile.TradersInfo[Traders.FENCE].standing >= 6) if (pmcProfile.TradersInfo[Traders.FENCE].standing >= 6)
{ {
const discountAssort = this.cloner.clone(this.fenceDiscountAssort); const discountAssort = this.cloner.clone(this.fenceDiscountAssort);
this.adjustAssortItemPricesByConfigMultiplier( this.adjustAssortItemPricesByConfigMultiplier(
discountAssort, discountAssort!,
this.traderConfig.fence.discountOptions.itemPriceMult, this.traderConfig.fence.discountOptions.itemPriceMult,
this.traderConfig.fence.discountOptions.presetPriceMult, this.traderConfig.fence.discountOptions.presetPriceMult,
); );
const mergedAssorts = this.mergeAssorts(assort, discountAssort); const mergedAssorts = this.mergeAssorts(assort!, discountAssort!);
return mergedAssorts; return mergedAssorts;
} }
return assort; return assort!;
} }
/** /**
@ -184,7 +184,7 @@ export class FenceService
createAssort.sptItems.push(clonedItems); createAssort.sptItems.push(clonedItems);
createAssort.loyal_level_items[root._id] = 1; createAssort.loyal_level_items[root._id] = 1;
this.updateFenceAssorts(createAssort, this.fenceAssort); this.updateFenceAssorts(createAssort, this.fenceAssort!);
} }
/** /**
@ -213,7 +213,7 @@ export class FenceService
{ {
if (this.itemHelper.isOfBaseclass(item._tpl, BaseClasses.AMMO)) if (this.itemHelper.isOfBaseclass(item._tpl, BaseClasses.AMMO))
{ {
total += this.handbookHelper.getTemplatePrice(item._tpl) * (item.upd.StackObjectsCount ?? 1); total += this.handbookHelper.getTemplatePrice(item._tpl) * (item.upd?.StackObjectsCount ?? 1);
} }
} }
@ -310,7 +310,7 @@ export class FenceService
*/ */
public getRawFenceAssorts(): ITraderAssort public getRawFenceAssorts(): ITraderAssort
{ {
return this.mergeAssorts(this.cloner.clone(this.fenceAssort), this.cloner.clone(this.fenceDiscountAssort)); return this.mergeAssorts(this.cloner.clone(this.fenceAssort!), this.cloner.clone(this.fenceDiscountAssort!));
} }
/** /**
@ -333,49 +333,49 @@ export class FenceService
); );
// Simulate players buying items // Simulate players buying items
this.deleteRandomAssorts(itemCountToReplace, this.fenceAssort); this.deleteRandomAssorts(itemCountToReplace, this.fenceAssort!);
this.deleteRandomAssorts(discountItemCountToReplace, this.fenceDiscountAssort); this.deleteRandomAssorts(discountItemCountToReplace, this.fenceDiscountAssort!);
const normalItemCountsToGenerate = this.getItemCountsToGenerate( const normalItemCountsToGenerate = this.getItemCountsToGenerate(
this.fenceAssort.items, this.fenceAssort!.items,
this.desiredAssortCounts.normal, this.desiredAssortCounts.normal,
); );
const newItems = this.createAssorts(normalItemCountsToGenerate, 1); const newItems = this.createAssorts(normalItemCountsToGenerate, 1);
// Push newly generated assorts into existing data // Push newly generated assorts into existing data
this.updateFenceAssorts(newItems, this.fenceAssort); this.updateFenceAssorts(newItems, this.fenceAssort!);
const discountItemCountsToGenerate = this.getItemCountsToGenerate( const discountItemCountsToGenerate = this.getItemCountsToGenerate(
this.fenceDiscountAssort.items, this.fenceDiscountAssort!.items,
this.desiredAssortCounts.discount, this.desiredAssortCounts.discount,
); );
const newDiscountItems = this.createAssorts(discountItemCountsToGenerate, 2); const newDiscountItems = this.createAssorts(discountItemCountsToGenerate, 2);
// Push newly generated discount assorts into existing data // Push newly generated discount assorts into existing data
this.updateFenceAssorts(newDiscountItems, this.fenceDiscountAssort); this.updateFenceAssorts(newDiscountItems, this.fenceDiscountAssort!);
// Add new barter items to fence barter scheme // Add new barter items to fence barter scheme
for (const barterItemKey in newItems.barter_scheme) for (const barterItemKey in newItems.barter_scheme)
{ {
this.fenceAssort.barter_scheme[barterItemKey] = newItems.barter_scheme[barterItemKey]; this.fenceAssort!.barter_scheme[barterItemKey] = newItems.barter_scheme[barterItemKey];
} }
// Add loyalty items to fence assorts loyalty object // Add loyalty items to fence assorts loyalty object
for (const loyaltyItemKey in newItems.loyal_level_items) for (const loyaltyItemKey in newItems.loyal_level_items)
{ {
this.fenceAssort.loyal_level_items[loyaltyItemKey] = newItems.loyal_level_items[loyaltyItemKey]; this.fenceAssort!.loyal_level_items[loyaltyItemKey] = newItems.loyal_level_items[loyaltyItemKey];
} }
// Add new barter items to fence assorts discounted barter scheme // Add new barter items to fence assorts discounted barter scheme
for (const barterItemKey in newDiscountItems.barter_scheme) for (const barterItemKey in newDiscountItems.barter_scheme)
{ {
this.fenceDiscountAssort.barter_scheme[barterItemKey] = newDiscountItems.barter_scheme[barterItemKey]; this.fenceDiscountAssort!.barter_scheme[barterItemKey] = newDiscountItems.barter_scheme[barterItemKey];
} }
// Add loyalty items to fence discount assorts loyalty object // Add loyalty items to fence discount assorts loyalty object
for (const loyaltyItemKey in newDiscountItems.loyal_level_items) for (const loyaltyItemKey in newDiscountItems.loyal_level_items)
{ {
this.fenceDiscountAssort.loyal_level_items[loyaltyItemKey] this.fenceDiscountAssort!.loyal_level_items[loyaltyItemKey]
= newDiscountItems.loyal_level_items[loyaltyItemKey]; = newDiscountItems.loyal_level_items[loyaltyItemKey];
} }
@ -428,13 +428,13 @@ export class FenceService
) )
{ {
// Guard against a missing stack count // Guard against a missing stack count
if (!existingRootItem.upd.StackObjectsCount) if (existingRootItem.upd?.StackObjectsCount === undefined)
{ {
existingRootItem.upd.StackObjectsCount = 1; existingRootItem.upd!.StackObjectsCount = 1;
} }
// Merge new items count into existing, dont add new loyalty/barter data as it already exists // Merge new items count into existing, dont add new loyalty/barter data as it already exists
existingRootItem.upd.StackObjectsCount += newRootItem?.upd?.StackObjectsCount ?? 1; existingRootItem.upd!.StackObjectsCount += newRootItem?.upd?.StackObjectsCount ?? 1;
continue; continue;
} }
@ -547,7 +547,7 @@ export class FenceService
} }
// Reduce stack to at smallest, 1 // Reduce stack to at smallest, 1
rootItemToAdjust.upd.StackObjectsCount -= Math.max(1, itemCountToRemove); rootItemToAdjust.upd!.StackObjectsCount! -= Math.max(1, itemCountToRemove);
return; return;
} }
@ -694,7 +694,7 @@ export class FenceService
{ {
const result: ICreateFenceAssortsResult = { sptItems: [], barter_scheme: {}, loyal_level_items: {} }; const result: ICreateFenceAssortsResult = { sptItems: [], barter_scheme: {}, loyal_level_items: {} };
const baseFenceAssortClone = this.cloner.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); const itemTypeLimitCounts = this.initItemLimitCounter(this.traderConfig.fence.itemTypeLimits);
if (itemCounts.item > 0) if (itemCounts.item > 0)
@ -750,7 +750,7 @@ export class FenceService
if (!chosenBaseAssortRoot) if (!chosenBaseAssortRoot)
{ {
this.logger.error( this.logger.error(
this.localisationService.getText("fence-unable_to_find_assort_by_id", chosenBaseAssortRoot._id), this.localisationService.getText("fence-unable_to_find_assort_by_id"),
); );
continue; continue;
@ -760,7 +760,7 @@ export class FenceService
); );
const itemDbDetails = this.itemHelper.getItem(chosenBaseAssortRoot._tpl)[1]; const itemDbDetails = this.itemHelper.getItem(chosenBaseAssortRoot._tpl)[1];
const itemLimitCount = this.getMatchingItemLimit(itemTypeLimits, itemDbDetails._id); const itemLimitCount = this.getMatchingItemLimit(itemTypeLimits, itemDbDetails._id)!;
if (itemLimitCount?.current >= itemLimitCount?.max) if (itemLimitCount?.current >= itemLimitCount?.max)
{ {
// Skip adding item as assort as limit reached, decrement i counter so we still get another item // Skip adding item as assort as limit reached, decrement i counter so we still get another item
@ -798,23 +798,23 @@ export class FenceService
const rootItemBeingAdded = desiredAssortItemAndChildrenClone[0]; const rootItemBeingAdded = desiredAssortItemAndChildrenClone[0];
// Set stack size based on possible overrides, e.g. ammos, otherwise set to 1 // Set stack size based on possible overrides, e.g. ammos, otherwise set to 1
rootItemBeingAdded.upd.StackObjectsCount = this.getSingleItemStackCount(itemDbDetails); rootItemBeingAdded.upd!.StackObjectsCount = this.getSingleItemStackCount(itemDbDetails);
// Only randomise upd values for single // Only randomise upd values for single
const isSingleStack = rootItemBeingAdded.upd.StackObjectsCount === 1; const isSingleStack = (rootItemBeingAdded.upd?.StackObjectsCount ?? 0) === 1;
if (isSingleStack) if (isSingleStack)
{ {
this.randomiseItemUpdProperties(itemDbDetails, rootItemBeingAdded); this.randomiseItemUpdProperties(itemDbDetails, rootItemBeingAdded);
} }
// Skip items already in the assort if it exists in the prevent duplicate list // Skip items already in the assort if it exists in the prevent duplicate list
const existingItemThatMatches = this.getMatchingItem(rootItemBeingAdded, itemDbDetails, assorts.sptItems); const existingItemThatMatches = this.getMatchingItem(rootItemBeingAdded, itemDbDetails, assorts.sptItems)!;
const shouldBeStacked = this.itemShouldBeForceStacked(existingItemThatMatches, itemDbDetails); const shouldBeStacked = this.itemShouldBeForceStacked(existingItemThatMatches, itemDbDetails);
if (shouldBeStacked && existingItemThatMatches) if (shouldBeStacked && existingItemThatMatches)
{ {
// Decrement loop counter so another items gets added // Decrement loop counter so another items gets added
i--; i--;
existingItemThatMatches.upd.StackObjectsCount++; existingItemThatMatches.upd!.StackObjectsCount!++;
continue; continue;
} }
@ -853,7 +853,7 @@ export class FenceService
rootItemBeingAdded: Item, rootItemBeingAdded: Item,
itemDbDetails: ITemplateItem, itemDbDetails: ITemplateItem,
itemsWithChildren: Item[][], itemsWithChildren: Item[][],
): Item ): Item | undefined
{ {
// Get matching root items // Get matching root items
const matchingItems = itemsWithChildren const matchingItems = itemsWithChildren
@ -864,7 +864,7 @@ export class FenceService
if (matchingItems.length === 0) if (matchingItems.length === 0)
{ {
// Nothing matches by tpl and is root item, exit early // Nothing matches by tpl and is root item, exit early
return null; return undefined;
} }
const isMedical = this.itemHelper.isOfBaseclasses(rootItemBeingAdded._tpl, [ const isMedical = this.itemHelper.isOfBaseclasses(rootItemBeingAdded._tpl, [
@ -875,7 +875,7 @@ export class FenceService
= this.itemHelper.isOfBaseclasses(rootItemBeingAdded._tpl, [ = this.itemHelper.isOfBaseclasses(rootItemBeingAdded._tpl, [
BaseClasses.ARMORED_EQUIPMENT, BaseClasses.ARMORED_EQUIPMENT,
BaseClasses.SEARCHABLE_ITEM, BaseClasses.SEARCHABLE_ITEM,
]) && itemDbDetails._props.Slots.length > 0; ]) && (itemDbDetails._props.Slots?.length ?? 0) > 0;
// Only one match and its not medical or armored gear // Only one match and its not medical or armored gear
if (matchingItems.length === 1 && !(isMedical || isGearAndHasSlots)) if (matchingItems.length === 1 && !(isMedical || isGearAndHasSlots))
@ -886,25 +886,25 @@ export class FenceService
// Items have sub properties that need to be checked against // Items have sub properties that need to be checked against
for (const item of matchingItems) for (const item of matchingItems)
{ {
if (isMedical && rootItemBeingAdded.upd.MedKit?.HpResource === item.upd.MedKit?.HpResource) if (isMedical && rootItemBeingAdded.upd!.MedKit?.HpResource === item.upd!.MedKit?.HpResource)
{ {
// e.g. bandages with multiple use // e.g. bandages with multiple use
// Both null === both max resoruce left // Both undefined === both max resoruce left
return item; return item;
} }
// Armors/helmets etc // Armors/helmets etc
if ( if (
isGearAndHasSlots isGearAndHasSlots
&& rootItemBeingAdded.upd.Repairable?.Durability === item.upd.Repairable?.Durability && rootItemBeingAdded.upd!.Repairable?.Durability === item.upd!.Repairable?.Durability
&& rootItemBeingAdded.upd.Repairable?.MaxDurability === item.upd.Repairable?.MaxDurability && rootItemBeingAdded.upd!.Repairable?.MaxDurability === item.upd!.Repairable?.MaxDurability
) )
{ {
return item; return item;
} }
} }
return null; return undefined;
} }
/** /**
@ -951,7 +951,7 @@ export class FenceService
// Healing items // Healing items
if (itemRoot.upd?.MedKit) if (itemRoot.upd?.MedKit)
{ {
const itemTotalMax = itemTemplate._props.MaxHpResource; const itemTotalMax = itemTemplate._props.MaxHpResource!;
const current = itemRoot.upd.MedKit.HpResource; const current = itemRoot.upd.MedKit.HpResource;
// Current and max match, no adjustment necessary // Current and max match, no adjustment necessary
@ -981,7 +981,7 @@ export class FenceService
protected getMatchingItemLimit( protected getMatchingItemLimit(
itemTypeLimits: Record<string, { current: number, max: number }>, itemTypeLimits: Record<string, { current: number, max: number }>,
itemTpl: string, itemTpl: string,
): { current: number, max: number } ): { current: number, max: number } | undefined
{ {
for (const baseTypeKey in itemTypeLimits) for (const baseTypeKey in itemTypeLimits)
{ {
@ -1143,20 +1143,20 @@ export class FenceService
protected randomiseArmorModDurability(armor: Item[], itemDbDetails: ITemplateItem): void protected randomiseArmorModDurability(armor: Item[], itemDbDetails: ITemplateItem): void
{ {
// Armor has no mods, make no changes // Armor has no mods, make no changes
const hasMods = itemDbDetails._props.Slots.length > 0; const hasMods = (itemDbDetails._props.Slots?.length ?? 0) > 0;
if (!hasMods) if (!hasMods)
{ {
return; return;
} }
// Check for and adjust soft insert durability values // Check for and adjust soft insert durability values
const requiredSlots = itemDbDetails._props.Slots.filter((slot) => slot._required); const requiredSlots = itemDbDetails._props.Slots?.filter((slot) => slot._required);
const hasRequiredSlots = requiredSlots.length > 0; const hasRequiredSlots = (requiredSlots?.length ?? 0) > 0;
if (hasRequiredSlots) if (hasRequiredSlots)
{ {
for (const requiredSlot of requiredSlots) for (const requiredSlot of requiredSlots!)
{ {
const modItemDbDetails = this.itemHelper.getItem(requiredSlot._props.filters[0].Plate)[1]; const modItemDbDetails = this.itemHelper.getItem(requiredSlot._props.filters[0].Plate!)[1];
const durabilityValues = this.getRandomisedArmorDurabilityValues( const durabilityValues = this.getRandomisedArmorDurabilityValues(
modItemDbDetails, modItemDbDetails,
this.traderConfig.fence.armorMaxDurabilityPercentMinMax, this.traderConfig.fence.armorMaxDurabilityPercentMinMax,
@ -1170,42 +1170,42 @@ export class FenceService
// Find items mod to apply dura changes to // Find items mod to apply dura changes to
const modItemToAdjust = armor.find( const modItemToAdjust = armor.find(
(mod) => mod.slotId.toLowerCase() === requiredSlot._name.toLowerCase(), (mod) => mod.slotId!.toLowerCase() === requiredSlot._name.toLowerCase(),
); )!;
this.itemHelper.addUpdObjectToItem(modItemToAdjust); this.itemHelper.addUpdObjectToItem(modItemToAdjust);
if (!modItemToAdjust.upd.Repairable) if (!modItemToAdjust.upd!.Repairable)
{ {
modItemToAdjust.upd.Repairable = { modItemToAdjust.upd!.Repairable = {
Durability: modItemDbDetails._props.MaxDurability, Durability: modItemDbDetails._props.MaxDurability!,
MaxDurability: modItemDbDetails._props.MaxDurability, MaxDurability: modItemDbDetails._props.MaxDurability!,
}; };
} }
modItemToAdjust.upd.Repairable.Durability = durabilityValues.Durability; modItemToAdjust.upd!.Repairable.Durability = durabilityValues.Durability;
modItemToAdjust.upd.Repairable.MaxDurability = durabilityValues.MaxDurability; modItemToAdjust.upd!.Repairable.MaxDurability = durabilityValues.MaxDurability;
// 25% chance to add shots to visor when its below max durability // 25% chance to add shots to visor when its below max durability
if ( if (
this.randomUtil.getChance100(25) this.randomUtil.getChance100(25)
&& modItemToAdjust.parentId === BaseClasses.ARMORED_EQUIPMENT && modItemToAdjust.parentId === BaseClasses.ARMORED_EQUIPMENT
&& modItemToAdjust.slotId === "mod_equipment_000" && modItemToAdjust.slotId === "mod_equipment_000"
&& modItemToAdjust.upd.Repairable.Durability < modItemDbDetails._props.MaxDurability && modItemToAdjust.upd!.Repairable.Durability < modItemDbDetails._props.MaxDurability!
) )
{ {
// Is damaged // Is damaged
modItemToAdjust.upd.FaceShield = { Hits: this.randomUtil.getInt(1, 3) }; modItemToAdjust.upd!.FaceShield = { Hits: this.randomUtil.getInt(1, 3) };
} }
} }
} }
// Check for and adjust plate durability values // Check for and adjust plate durability values
const plateSlots = itemDbDetails._props.Slots.filter((slot) => const plateSlots = itemDbDetails._props.Slots?.filter((slot) =>
this.itemHelper.isRemovablePlateSlot(slot._name), this.itemHelper.isRemovablePlateSlot(slot._name),
); );
if (plateSlots.length > 0) if ((plateSlots?.length ?? 0) > 0)
{ {
for (const plateSlot of plateSlots) for (const plateSlot of plateSlots!)
{ {
// Chance to not add plate // Chance to not add plate
if (!this.randomUtil.getChance100(this.traderConfig.fence.chancePlateExistsInArmorPercent)) if (!this.randomUtil.getChance100(this.traderConfig.fence.chancePlateExistsInArmorPercent))
@ -1226,19 +1226,19 @@ export class FenceService
); );
// Find items mod to apply dura changes to // Find items mod to apply dura changes to
const modItemToAdjust = armor.find((mod) => mod.slotId.toLowerCase() === plateSlot._name.toLowerCase()); const modItemToAdjust = armor.find((mod) => mod.slotId!.toLowerCase() === plateSlot._name.toLowerCase());
this.itemHelper.addUpdObjectToItem(modItemToAdjust); this.itemHelper.addUpdObjectToItem(modItemToAdjust!);
if (!modItemToAdjust.upd.Repairable) if (!modItemToAdjust?.upd?.Repairable)
{ {
modItemToAdjust.upd.Repairable = { modItemToAdjust!.upd!.Repairable = {
Durability: modItemDbDetails._props.MaxDurability, Durability: modItemDbDetails._props.MaxDurability!,
MaxDurability: modItemDbDetails._props.MaxDurability, MaxDurability: modItemDbDetails._props.MaxDurability!,
}; };
} }
modItemToAdjust.upd.Repairable.Durability = durabilityValues.Durability; modItemToAdjust!.upd!.Repairable.Durability = durabilityValues.Durability;
modItemToAdjust.upd.Repairable.MaxDurability = durabilityValues.MaxDurability; modItemToAdjust!.upd!.Repairable.MaxDurability = durabilityValues.MaxDurability;
} }
} }
} }
@ -1261,7 +1261,7 @@ export class FenceService
// No override, use stack max size from item db // No override, use stack max size from item db
return itemDbDetails._props.StackMaxSize === 1 return itemDbDetails._props.StackMaxSize === 1
? 1 ? 1
: this.randomUtil.getInt(itemDbDetails._props.StackMinRandom, itemDbDetails._props.StackMaxRandom); : this.randomUtil.getInt(itemDbDetails._props.StackMinRandom!, itemDbDetails._props.StackMaxRandom!);
} }
// Check for override in config, use values if exists // Check for override in config, use values if exists
@ -1326,7 +1326,7 @@ export class FenceService
protected presetModItemWillBeRemoved(weaponMod: Item, itemsBeingDeleted: string[]): boolean protected presetModItemWillBeRemoved(weaponMod: Item, itemsBeingDeleted: string[]): boolean
{ {
const slotIdsThatCanFail = this.traderConfig.fence.presetSlotsToRemoveChancePercent; const slotIdsThatCanFail = this.traderConfig.fence.presetSlotsToRemoveChancePercent;
const removalChance = slotIdsThatCanFail[weaponMod.slotId]; const removalChance = slotIdsThatCanFail[weaponMod.slotId!];
if (!removalChance) if (!removalChance)
{ {
return false; return false;
@ -1355,9 +1355,9 @@ export class FenceService
} }
// Randomise hp resource of med items // Randomise hp resource of med items
if ("MaxHpResource" in itemDetails._props && itemDetails._props.MaxHpResource > 0) if ("MaxHpResource" in itemDetails._props && (itemDetails._props.MaxHpResource ?? 0) > 0)
{ {
itemToAdjust.upd.MedKit = { HpResource: this.randomUtil.getInt(1, itemDetails._props.MaxHpResource) }; itemToAdjust.upd!.MedKit = { HpResource: this.randomUtil.getInt(1, itemDetails._props.MaxHpResource!) };
} }
// Randomise armor durability // Randomise armor durability
@ -1365,14 +1365,14 @@ export class FenceService
(itemDetails._parent === BaseClasses.ARMORED_EQUIPMENT (itemDetails._parent === BaseClasses.ARMORED_EQUIPMENT
|| itemDetails._parent === BaseClasses.FACECOVER || itemDetails._parent === BaseClasses.FACECOVER
|| itemDetails._parent === BaseClasses.ARMOR_PLATE) || itemDetails._parent === BaseClasses.ARMOR_PLATE)
&& itemDetails._props.MaxDurability > 0 && (itemDetails._props.MaxDurability ?? 0) > 0
) )
{ {
const values = this.getRandomisedArmorDurabilityValues( const values = this.getRandomisedArmorDurabilityValues(
itemDetails, itemDetails,
this.traderConfig.fence.armorMaxDurabilityPercentMinMax, this.traderConfig.fence.armorMaxDurabilityPercentMinMax,
); );
itemToAdjust.upd.Repairable = { Durability: values.Durability, MaxDurability: values.MaxDurability }; itemToAdjust.upd!.Repairable = { Durability: values.Durability, MaxDurability: values.MaxDurability };
return; return;
} }
@ -1381,25 +1381,25 @@ export class FenceService
if (this.itemHelper.isOfBaseclass(itemDetails._id, BaseClasses.WEAPON)) if (this.itemHelper.isOfBaseclass(itemDetails._id, BaseClasses.WEAPON))
{ {
const weaponDurabilityLimits = this.traderConfig.fence.weaponDurabilityPercentMinMax; const weaponDurabilityLimits = this.traderConfig.fence.weaponDurabilityPercentMinMax;
const maxDuraMin = (weaponDurabilityLimits.max.min / 100) * itemDetails._props.MaxDurability; const maxDuraMin = (weaponDurabilityLimits.max.min / 100) * itemDetails._props.MaxDurability!;
const maxDuraMax = (weaponDurabilityLimits.max.max / 100) * itemDetails._props.MaxDurability; const maxDuraMax = (weaponDurabilityLimits.max.max / 100) * itemDetails._props.MaxDurability!;
const chosenMaxDurability = this.randomUtil.getInt(maxDuraMin, maxDuraMax); const chosenMaxDurability = this.randomUtil.getInt(maxDuraMin, maxDuraMax);
const currentDuraMin = (weaponDurabilityLimits.current.min / 100) * itemDetails._props.MaxDurability; const currentDuraMin = (weaponDurabilityLimits.current.min / 100) * itemDetails._props.MaxDurability!;
const currentDuraMax = (weaponDurabilityLimits.current.max / 100) * itemDetails._props.MaxDurability; const currentDuraMax = (weaponDurabilityLimits.current.max / 100) * itemDetails._props.MaxDurability!;
const currentDurability = Math.min( const currentDurability = Math.min(
this.randomUtil.getInt(currentDuraMin, currentDuraMax), this.randomUtil.getInt(currentDuraMin, currentDuraMax),
chosenMaxDurability, chosenMaxDurability,
); );
itemToAdjust.upd.Repairable = { Durability: currentDurability, MaxDurability: chosenMaxDurability }; itemToAdjust.upd!.Repairable = { Durability: currentDurability, MaxDurability: chosenMaxDurability };
return; return;
} }
if (this.itemHelper.isOfBaseclass(itemDetails._id, BaseClasses.REPAIR_KITS)) if (this.itemHelper.isOfBaseclass(itemDetails._id, BaseClasses.REPAIR_KITS))
{ {
itemToAdjust.upd.RepairKit = { Resource: this.randomUtil.getInt(1, itemDetails._props.MaxRepairResource) }; itemToAdjust.upd!.RepairKit = { Resource: this.randomUtil.getInt(1, itemDetails._props.MaxRepairResource!) };
return; return;
} }
@ -1407,23 +1407,23 @@ export class FenceService
// Mechanical key + has limited uses // Mechanical key + has limited uses
if ( if (
this.itemHelper.isOfBaseclass(itemDetails._id, BaseClasses.KEY_MECHANICAL) this.itemHelper.isOfBaseclass(itemDetails._id, BaseClasses.KEY_MECHANICAL)
&& itemDetails._props.MaximumNumberOfUsage > 1 && (itemDetails._props.MaximumNumberOfUsage ?? 0) > 1
) )
{ {
itemToAdjust.upd.Key = { itemToAdjust.upd!.Key = {
NumberOfUsages: this.randomUtil.getInt(0, itemDetails._props.MaximumNumberOfUsage - 1), NumberOfUsages: this.randomUtil.getInt(0, itemDetails._props.MaximumNumberOfUsage! - 1),
}; };
return; return;
} }
// Randomise items that use resources (e.g. fuel) // Randomise items that use resources (e.g. fuel)
if (itemDetails._props.MaxResource > 0) if ((itemDetails._props.MaxResource ?? 0) > 0)
{ {
const resourceMax = itemDetails._props.MaxResource; const resourceMax = itemDetails._props.MaxResource!;
const resourceCurrent = this.randomUtil.getInt(1, itemDetails._props.MaxResource); const resourceCurrent = this.randomUtil.getInt(1, itemDetails._props.MaxResource!);
itemToAdjust.upd.Resource = { Value: resourceMax - resourceCurrent, UnitsConsumed: resourceCurrent }; itemToAdjust.upd!.Resource = { Value: resourceMax - resourceCurrent, UnitsConsumed: resourceCurrent };
} }
} }
@ -1438,12 +1438,12 @@ export class FenceService
equipmentDurabilityLimits: IItemDurabilityCurrentMax, equipmentDurabilityLimits: IItemDurabilityCurrentMax,
): Repairable ): Repairable
{ {
const maxDuraMin = (equipmentDurabilityLimits.max.min / 100) * itemDetails._props.MaxDurability; const maxDuraMin = (equipmentDurabilityLimits.max.min / 100) * itemDetails._props.MaxDurability!;
const maxDuraMax = (equipmentDurabilityLimits.max.max / 100) * itemDetails._props.MaxDurability; const maxDuraMax = (equipmentDurabilityLimits.max.max / 100) * itemDetails._props.MaxDurability!;
const chosenMaxDurability = this.randomUtil.getInt(maxDuraMin, maxDuraMax); const chosenMaxDurability = this.randomUtil.getInt(maxDuraMin, maxDuraMax);
const currentDuraMin = (equipmentDurabilityLimits.current.min / 100) * itemDetails._props.MaxDurability; const currentDuraMin = (equipmentDurabilityLimits.current.min / 100) * itemDetails._props.MaxDurability!;
const currentDuraMax = (equipmentDurabilityLimits.current.max / 100) * itemDetails._props.MaxDurability; const currentDuraMax = (equipmentDurabilityLimits.current.max / 100) * itemDetails._props.MaxDurability!;
const chosenCurrentDurability = Math.min( const chosenCurrentDurability = Math.min(
this.randomUtil.getInt(currentDuraMin, currentDuraMax), this.randomUtil.getInt(currentDuraMin, currentDuraMax),
chosenMaxDurability, chosenMaxDurability,
@ -1486,7 +1486,7 @@ export class FenceService
*/ */
protected getFenceRefreshTime(): number protected getFenceRefreshTime(): number
{ {
const fence = this.traderConfig.updateTime.find((x) => x.traderId === Traders.FENCE).seconds; const fence = this.traderConfig.updateTime.find((x) => x.traderId === Traders.FENCE)!.seconds;
return this.randomUtil.getInt(fence.min, fence.max); return this.randomUtil.getInt(fence.min, fence.max);
} }
@ -1498,7 +1498,7 @@ export class FenceService
*/ */
public getFenceInfo(pmcData: IPmcData): IFenceLevel public getFenceInfo(pmcData: IPmcData): IFenceLevel
{ {
const fenceSettings = this.databaseServer.getTables().globals.config.FenceSettings; const fenceSettings = this.databaseServer.getTables().globals!.config.FenceSettings;
const pmcFenceInfo = pmcData.TradersInfo[fenceSettings.FenceId]; const pmcFenceInfo = pmcData.TradersInfo[fenceSettings.FenceId];
if (!pmcFenceInfo) if (!pmcFenceInfo)
@ -1532,11 +1532,11 @@ export class FenceService
public amendOrRemoveFenceOffer(assortId: string, buyCount: number): void public amendOrRemoveFenceOffer(assortId: string, buyCount: number): void
{ {
let isNormalAssort = true; let isNormalAssort = true;
let fenceAssortItem = this.fenceAssort.items.find((item) => item._id === assortId); let fenceAssortItem = this.fenceAssort!.items.find((item) => item._id === assortId);
if (!fenceAssortItem) if (!fenceAssortItem)
{ {
// Not in main assorts, check secondary section // Not in main assorts, check secondary section
fenceAssortItem = this.fenceDiscountAssort.items.find((item) => item._id === assortId); fenceAssortItem = this.fenceDiscountAssort!.items.find((item) => item._id === assortId);
if (!fenceAssortItem) if (!fenceAssortItem)
{ {
this.logger.error(this.localisationService.getText("fence-unable_to_find_offer_by_id", assortId)); this.logger.error(this.localisationService.getText("fence-unable_to_find_offer_by_id", assortId));
@ -1547,15 +1547,15 @@ export class FenceService
} }
// Player wants to buy whole stack, delete stack // Player wants to buy whole stack, delete stack
if (fenceAssortItem.upd.StackObjectsCount === buyCount) if (fenceAssortItem.upd!.StackObjectsCount === buyCount)
{ {
this.deleteOffer(assortId, isNormalAssort ? this.fenceAssort.items : this.fenceDiscountAssort.items); this.deleteOffer(assortId, isNormalAssort ? this.fenceAssort!.items : this.fenceDiscountAssort!.items);
return; return;
} }
// Adjust stack size // Adjust stack size
fenceAssortItem.upd.StackObjectsCount -= buyCount; fenceAssortItem.upd!.StackObjectsCount! -= buyCount;
} }
protected deleteOffer(assortId: string, assorts: Item[]): void protected deleteOffer(assortId: string, assorts: Item[]): void
@ -1569,8 +1569,8 @@ export class FenceService
// No offer found in main assort, check discount items // No offer found in main assort, check discount items
if (indexToRemove === -1) if (indexToRemove === -1)
{ {
indexToRemove = this.fenceDiscountAssort.items.findIndex((item) => item._id === itemToRemove._id); indexToRemove = this.fenceDiscountAssort!.items.findIndex((item) => item._id === itemToRemove._id);
this.fenceDiscountAssort.items.splice(indexToRemove, 1); this.fenceDiscountAssort!.items.splice(indexToRemove, 1);
if (indexToRemove === -1) if (indexToRemove === -1)
{ {

View File

@ -518,9 +518,9 @@ export class ProfileFixerService
for (const traderId in pmcProfile.TradersInfo) for (const traderId in pmcProfile.TradersInfo)
{ {
const trader = pmcProfile.TradersInfo[traderId]; const trader = pmcProfile.TradersInfo[traderId];
if (trader && trader.salesSum === null) if (trader?.salesSum === undefined)
{ {
this.logger.warning(`trader ${traderId} has a null salesSum value, resetting to 0`); this.logger.warning(`trader ${traderId} has a undefined salesSum value, resetting to 0`);
trader.salesSum = 0; trader.salesSum = 0;
} }
} }
@ -1096,7 +1096,7 @@ export class ProfileFixerService
{ {
for (const item of magazineBuild.Items) for (const item of magazineBuild.Items)
{ {
// Magazine builds can have null items in them, skip those // Magazine builds can have undefined items in them, skip those
if (!item) if (!item)
{ {
continue; continue;
@ -1187,10 +1187,10 @@ export class ProfileFixerService
item.upd.Tag.Name = item.upd.Tag.Name.replace(regxp, ""); item.upd.Tag.Name = item.upd.Tag.Name.replace(regxp, "");
} }
// Check items with StackObjectsCount (null) // Check items with StackObjectsCount (undefined)
if (item.upd.StackObjectsCount === null) if (item.upd?.StackObjectsCount === undefined)
{ {
this.logger.warning(`Fixed item: ${item._id}s null StackObjectsCount value, now set to 1`); this.logger.warning(`Fixed item: ${item._id}s undefined StackObjectsCount value, now set to 1`);
item.upd.StackObjectsCount = 1; item.upd.StackObjectsCount = 1;
} }
} }
@ -1449,15 +1449,15 @@ export class ProfileFixerService
/** /**
* If someone has run a mod from pre-3.8.0, it results in an invalid `nextResupply` value * If someone has run a mod from pre-3.8.0, it results in an invalid `nextResupply` value
* Resolve this by setting the nextResupply to 0 if it's null * Resolve this by setting the nextResupply to 0 if it's undefined
*/ */
protected fixNullTraderNextResupply(pmcProfile: IPmcData): void protected fixNullTraderNextResupply(pmcProfile: IPmcData): void
{ {
for (const [traderId, trader] of Object.entries(pmcProfile.TradersInfo)) for (const [traderId, trader] of Object.entries(pmcProfile.TradersInfo))
{ {
if (trader && trader.nextResupply === null) if (trader?.nextResupply === undefined)
{ {
this.logger.warning(`trader ${traderId} has a null nextResupply value, resetting to 0`); this.logger.warning(`trader ${traderId} has a undefined nextResupply value, resetting to 0`);
trader.nextResupply = 0; trader.nextResupply = 0;
} }
} }

View File

@ -42,6 +42,7 @@ export class RagfairOfferService
this.ragfairOfferHandler = new RagfairOfferHolder( this.ragfairOfferHandler = new RagfairOfferHolder(
this.ragfairConfig.dynamic.offerItemCount.max, this.ragfairConfig.dynamic.offerItemCount.max,
ragfairServerHelper, ragfairServerHelper,
profileHelper,
); );
} }
@ -221,7 +222,7 @@ export class RagfairOfferService
{ {
const staleOfferUserId = staleOffer.user.id; const staleOfferUserId = staleOffer.user.id;
const isTrader = this.ragfairServerHelper.isTrader(staleOfferUserId); const isTrader = this.ragfairServerHelper.isTrader(staleOfferUserId);
const isPlayer = this.ragfairServerHelper.isPlayer(staleOfferUserId.replace(/^pmc/, "")); const isPlayer = this.profileHelper.isPlayer(staleOfferUserId.replace(/^pmc/, ""));
// Skip trader offers, managed by RagfairServer.update() // Skip trader offers, managed by RagfairServer.update()
if (isTrader) if (isTrader)

View File

@ -61,7 +61,7 @@ export class HttpResponseUtil
public nullResponse(): INullResponseData public nullResponse(): INullResponseData
{ {
return this.clearString(this.getUnclearedBody(null, 0, undefined)); return this.clearString(this.getUnclearedBody(undefined, 0, undefined));
} }
public emptyArrayResponse(): IGetBodyResponseData<any[]> public emptyArrayResponse(): IGetBodyResponseData<any[]>

View File

@ -31,7 +31,7 @@ export class JsonUtil
{ {
if (prettify) if (prettify)
{ {
return JSON.stringify(data, null, "\t"); return JSON.stringify(data, undefined, "\t");
} }
return JSON.stringify(data); return JSON.stringify(data);
@ -60,7 +60,11 @@ export class JsonUtil
* @param options Stringify options or a replacer. * @param options Stringify options or a replacer.
* @returns The string converted from the JavaScript value * @returns The string converted from the JavaScript value
*/ */
public serializeJsonC(data: any, filename?: string | null, options?: IStringifyOptions | Reviver): string | undefined public serializeJsonC(
data: any,
filename?: string | undefined,
options?: IStringifyOptions | Reviver,
): string | undefined
{ {
try try
{ {
@ -74,13 +78,13 @@ export class JsonUtil
} }
} }
public serializeJson5(data: any, filename?: string | null, prettify = false): string | undefined public serializeJson5(data: any, filename?: string | undefined, prettify = false): string | undefined
{ {
try try
{ {
if (prettify) if (prettify)
{ {
return stringify(data, null, "\t"); return stringify(data, undefined, "\t");
} }
return stringify(data); return stringify(data);

View File

@ -1,3 +1,4 @@
import { ProfileHelper } from "@spt/helpers/ProfileHelper";
import { RagfairServerHelper } from "@spt/helpers/RagfairServerHelper"; import { RagfairServerHelper } from "@spt/helpers/RagfairServerHelper";
import { IRagfairOffer } from "@spt/models/eft/ragfair/IRagfairOffer"; import { IRagfairOffer } from "@spt/models/eft/ragfair/IRagfairOffer";
@ -10,6 +11,7 @@ export class RagfairOfferHolder
constructor( constructor(
protected maxOffersPerTemplate: number, protected maxOffersPerTemplate: number,
protected ragfairServerHelper: RagfairServerHelper, protected ragfairServerHelper: RagfairServerHelper,
protected profileHelper: ProfileHelper,
) )
{ {
this.offersById = new Map(); this.offersById = new Map();
@ -69,7 +71,7 @@ export class RagfairOfferHolder
// If its an NPC PMC offer AND we have already reached the maximum amount of possible offers // If its an NPC PMC offer AND we have already reached the maximum amount of possible offers
// for this template, just dont add in more // for this template, just dont add in more
if ( if (
!(this.ragfairServerHelper.isTrader(trader) || this.ragfairServerHelper.isPlayer(trader)) !(this.ragfairServerHelper.isTrader(trader) || this.profileHelper.isPlayer(trader))
&& (this.getOffersByTemplate(itemTpl)?.length ?? 0) >= this.maxOffersPerTemplate && (this.getOffersByTemplate(itemTpl)?.length ?? 0) >= this.maxOffersPerTemplate
) )
{ {

View File

@ -37,9 +37,9 @@ export class RecursiveCloner implements ICloner
{ {
// If the value of the original property is null, ensure the cloned value is also null // If the value of the original property is null, ensure the cloned value is also null
// This fixes an issue where null arrays were incorrectly being converted to empty objects // This fixes an issue where null arrays were incorrectly being converted to empty objects
if (obj[propOf1] === null) if (obj[propOf1] === null || obj[propOf1] === undefined)
{ {
newObj[propOf1.toString()] = null; newObj[propOf1.toString()] = undefined;
continue; continue;
} }

View File

@ -163,7 +163,7 @@ export abstract class AbstractWinstonLogger implements ILogger
{ {
command = { command = {
uuid: crypto.randomUUID(), uuid: crypto.randomUUID(),
cmd: async () => await tmpLogger.log("custom", JSON.stringify(data, null, 4)), cmd: async () => await tmpLogger.log("custom", JSON.stringify(data, undefined, 4)),
}; };
} }