Skip to content

Commit

Permalink
Fix issue where insurance messages would appear as received if you on…
Browse files Browse the repository at this point in the history
…ly lost gear you were wearing

- Insurance messages each need a unique "stash" ID, properly handle this as part of the processing side of insurance
- Remove handling of parent IDs from the insurance storing side of insurance, as we don't need to do that processing twice
- Add a new step to the profileFixer service that resolves any already broken trader messages with attached insurance items
  • Loading branch information
DrakiaXYZ committed Dec 23, 2024
1 parent 45c3df6 commit ad155c7
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 34 deletions.
4 changes: 4 additions & 0 deletions project/src/controllers/GameController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@ export class GameController {
fullProfile.characters.scav.WishList = {};
}

if (fullProfile.dialogues) {
this.profileFixerService.checkForAndFixDialogueAttachments(fullProfile);
}

this.logger.debug(`Started game with sessionId: ${sessionID} ${fullProfile.info.username}`);

const pmcProfile = fullProfile.characters.pmc;
Expand Down
12 changes: 6 additions & 6 deletions project/src/controllers/InsuranceController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,14 @@ export class InsuranceController {
)} items, in profile ${sessionID}`,
);

// Fetch the root Item parentId property value that should be used for insurance packages.
const rootItemParentID = this.insuranceService.getRootItemParentID(sessionID);

// Iterate over each of the insurance packages.
for (const insured of insuranceDetails) {
// Create a new root parent ID for the message we'll be sending the player
const rootItemParentID = this.hashUtil.generate();

// Update the insured items to have the new root parent ID for root items
insured.items = this.itemHelper.adoptOrphanedItems(rootItemParentID, insured.items);

const simulateItemsBeingTaken = this.insuranceConfig.simulateItemsBeingTaken;
if (simulateItemsBeingTaken) {
// Find items that could be taken by another player off the players body
Expand All @@ -137,9 +140,6 @@ export class InsuranceController {
this.removeItemsFromInsurance(insured, itemsToDelete);
}

// Ensure that all items have a valid parent.
insured.items = this.itemHelper.adoptOrphanedItems(rootItemParentID, insured.items);

// Send the mail to the player.
this.sendMail(sessionID, insured);

Expand Down
28 changes: 0 additions & 28 deletions project/src/services/InsuranceService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,21 +176,6 @@ export class InsuranceService {
return this.timeUtil.getTimestamp() + finalReturnTimeSeconds;
}

/**
* Take the insurance item packages within a profile session and ensure that each of the items in that package are
* not orphaned from their parent ID.
*
* @param sessionID The session ID to update insurance equipment packages in.
* @returns void
*/
protected adoptOrphanedInsEquipment(sessionID: string): void {
const rootID = this.getRootItemParentID(sessionID);
const insuranceData = this.getInsurance(sessionID);
for (const [traderId, items] of Object.entries(insuranceData)) {
this.insured[sessionID][traderId] = this.itemHelper.adoptOrphanedItems(rootID, items);
}
}

protected getMaxInsuranceStorageTime(traderBase: ITraderBase): number {
if (this.insuranceConfig.storageTimeOverrideSeconds > 0) {
// Override exists, use instead of traders value
Expand All @@ -209,9 +194,6 @@ export class InsuranceService {
for (const gear of equipmentPkg) {
this.addGearToSend(gear);
}

// Items are separated into their individual trader packages, now we can ensure that they all have valid parents
this.adoptOrphanedInsEquipment(sessionID);
}

/**
Expand Down Expand Up @@ -347,14 +329,4 @@ export class InsuranceService {

return Math.ceil(price);
}

/**
* Returns the ID that should be used for a root-level Item's parentId property value within in the context of insurance.
* @param sessionID Players id
* @returns The root item Id.
*/
public getRootItemParentID(sessionID: string): string {
// Try to use the equipment id from the profile. I'm not sure this is strictly required, but it feels neat.
return this.saveServer.getProfile(sessionID)?.characters?.pmc?.Inventory?.equipment ?? this.hashUtil.generate();
}
}
32 changes: 32 additions & 0 deletions project/src/services/ProfileFixerService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,38 @@ export class ProfileFixerService {
}
}

/**
* Resolve any dialogue attachments that were accidentally created using the player's equipment ID as
* the stash root object ID
* @param fullProfile
*/
public checkForAndFixDialogueAttachments(fullProfile: ISptProfile): void {
for (const traderDialogues of Object.values(fullProfile.dialogues)) {
for (const message of traderDialogues?.messages) {
// Skip any messages without attached items
if (!message.items?.data || !message.items?.stash) {
continue;
}

// Skip any messages that don't have a stashId collision with the player's equipment ID
if (message.items?.stash !== fullProfile.characters?.pmc?.Inventory?.equipment) {
continue;
}

// Otherwise we need to generate a new unique stash ID for this message's attachments
message.items.stash = this.hashUtil.generate();
message.items.data = this.itemHelper.adoptOrphanedItems(message.items.stash, message.items.data);

// Because `adoptOrphanedItems` sets the slotId to `hideout`, we need to re-set it to `main` to work with mail
for (const item of message.items.data) {
if (item.slotId === "hideout") {
item.slotId = "main";
}
}
}
}
}

/**
* Find issues in the scav profile data that may cause issues
* @param scavProfile profile to check and fix
Expand Down

0 comments on commit ad155c7

Please sign in to comment.