Refactored post-raid pmc inventory modification - Fixes dupe id error on raid end

This commit is contained in:
Dev 2024-11-01 12:08:05 +00:00
parent 922adcfb5c
commit 2c53e28e81
3 changed files with 66 additions and 42 deletions

View File

@ -61,7 +61,7 @@ export class InRaidHelper {
isSurvived: boolean,
isTransfer: boolean,
): void {
// Store insurance (as removeItem() removes insurance also)
// Store insurance (as removeItem() removes insured items)
const insured = this.cloner.clone(serverProfile.InsuredItems);
// Remove possible equipped items from before the raid
@ -69,46 +69,50 @@ export class InRaidHelper {
this.inventoryHelper.removeItem(serverProfile, serverProfile.Inventory.questRaidItems, sessionID);
this.inventoryHelper.removeItem(serverProfile, serverProfile.Inventory.sortingTable, sessionID);
// Handle Removing of FIR status if did not survive.
// Get all items that have a parent of `serverProfile.Inventory.equipment` (All items player had on them at end of raid)
const postRaidInventoryItems = this.itemHelper.findAndReturnChildrenAsItems(
postRaidProfile.Inventory.items,
postRaidProfile.Inventory.equipment,
);
// Handle Removing of FIR status if player did not survive + not transferring
// Do after above filtering code to reduce work done
if (!isSurvived && !isTransfer && !this.inRaidConfig.alwaysKeepFoundInRaidonRaidEnd) {
this.removeSpawnedInSessionPropertyFromItems(postRaidProfile);
const dbItems = this.databaseService.getItems();
const itemsToRemovePropertyFrom = postRaidProfile.Inventory.items.filter((item) => {
// Has upd object + upd.SpawnedInSession property + not a quest item
return (
item.upd?.SpawnedInSession &&
!dbItems[item._tpl]._props.QuestItem &&
!(
this.inRaidConfig.keepFiRSecureContainerOnDeath &&
this.itemHelper.itemIsInsideContainer(item, "SecuredContainer", postRaidProfile.Inventory.items)
)
);
});
this.itemHelper.removeSpawnedInSessionPropertyFromItems(itemsToRemovePropertyFrom);
}
for (const item of postRaidInventoryItems) {
// Try to find index of item to determine if we should add or replace
const existingItemIndex = serverProfile.Inventory.items.findIndex(
(inventoryItem) => inventoryItem._id === item._id,
);
if (existingItemIndex === -1) {
// Not found, add
serverProfile.Inventory.items.push(item);
} else {
// Replace item with one from client
postRaidProfile.Inventory.items.splice(existingItemIndex, 1, item);
}
}
// Add the new items
serverProfile.Inventory.items = [...postRaidProfile.Inventory.items, ...serverProfile.Inventory.items];
serverProfile.Inventory.fastPanel = postRaidProfile.Inventory.fastPanel; // Quick access items bar
serverProfile.InsuredItems = insured;
}
/**
* Iterate over inventory items and remove the property that defines an item as Found in Raid
* Only removes property if item had FiR when entering raid
* @param postRaidProfile profile to update items for
* @returns Updated profile with SpawnedInSession removed
*/
public removeSpawnedInSessionPropertyFromItems(postRaidProfile: IPmcData): IPmcData {
const dbItems = this.databaseService.getItems();
const itemsToRemovePropertyFrom = postRaidProfile.Inventory.items.filter((item) => {
// Has upd object + upd.SpawnedInSession property + not a quest item
return (
"upd" in item &&
"SpawnedInSession" in item.upd &&
!dbItems[item._tpl]._props.QuestItem &&
!(
this.inRaidConfig.keepFiRSecureContainerOnDeath &&
this.itemHelper.itemIsInsideContainer(item, "SecuredContainer", postRaidProfile.Inventory.items)
)
);
});
for (const item of itemsToRemovePropertyFrom) {
// biome-ignore lint/performance/noDelete: <explanation>
delete item.upd.SpawnedInSession;
}
return postRaidProfile;
}
/**
* Clear PMC inventory of all items except those that are exempt
* Used post-raid to remove items after death

View File

@ -450,33 +450,43 @@ export class InventoryHelper {
}
// Get children of item, they get deleted too
const itemToRemoveWithChildren = this.itemHelper.findAndReturnChildrenByItems(profile.Inventory.items, itemId);
const itemAndChildrenToRemove = this.itemHelper.findAndReturnChildrenAsItems(profile.Inventory.items, itemId);
if (itemAndChildrenToRemove.length === 0) {
this.logger.debug(
this.localisationService.getText("inventory-unable_to_remove_item_id_not_found", {
childId: itemId,
profileId: profile._id,
}),
);
return;
}
const inventoryItems = profile.Inventory.items;
const insuredItems = profile.InsuredItems;
// We have output object, inform client of item deletion
// We have output object, inform client of root item deletion, not children
if (output) {
output.profileChanges[sessionID].items.del.push({ _id: itemId });
}
for (const childId of itemToRemoveWithChildren) {
for (const item of itemAndChildrenToRemove) {
// We expect that each inventory item and each insured item has unique "_id", respective "itemId".
// Therefore we want to use a NON-Greedy function and escape the iteration as soon as we find requested item.
const inventoryIndex = inventoryItems.findIndex((item) => item._id === childId);
const inventoryIndex = inventoryItems.findIndex((inventoryItem) => inventoryItem._id === item._id);
if (inventoryIndex !== -1) {
inventoryItems.splice(inventoryIndex, 1);
} else {
this.logger.warning(
this.localisationService.getText("inventory-unable_to_remove_item_id_not_found", {
childId: childId,
childId: item._id,
profileId: profile._id,
}),
);
}
const insuredIndex = insuredItems.findIndex((item) => item.itemId === childId);
if (insuredIndex !== -1) {
insuredItems.splice(insuredIndex, 1);
const insuredItemIndex = insuredItems.findIndex((insuredItem) => insuredItem.itemId === item._id);
if (insuredItemIndex !== -1) {
insuredItems.splice(insuredItemIndex, 1);
}
}
}

View File

@ -1794,6 +1794,16 @@ export class ItemHelper {
currentItem = this.getItem(tpl)[1];
}
}
/**
* Remove FiR status from passed in items
* @param items Items to update FiR status of
*/
public removeSpawnedInSessionPropertyFromItems(items: IItem[]): void {
for (const item of items) {
delete item.upd.SpawnedInSession;
}
}
}
namespace ItemHelper {