-
Notifications
You must be signed in to change notification settings - Fork 453
Prevent temporary storage item loss on forced disconnect #670
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Co-authored-by: sven-n <5238610+sven-n@users.noreply.github.com>
Co-authored-by: sven-n <5238610+sven-n@users.noreply.github.com>
…ve null safety Co-authored-by: sven-n <5238610+sven-n@users.noreply.github.com>
Co-authored-by: sven-n <5238610+sven-n@users.noreply.github.com>
|
@copilot That's a good approach, but it needs some refinement. There is already a Additionally, I noticed a bug in the |
sven-n
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like mentioned, it needs some refinements.
…dd null check in SkillList Co-authored-by: sven-n <5238610+sven-n@users.noreply.github.com>
Updated in commit 5df99bd:
|
Could you clarify what refinements are still needed? I've already added:
I'm wondering if the concern is that my code in |
Merged and moved the item restore directly before saving to the database to prevent saving invalid states.
|
Good point, I merged your logic and the logic of |
|
/gemini review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces a crucial fix to prevent item loss from temporary storage upon a forced disconnect. The implementation is well-structured, centralizing the restoration logic within the Player class and ensuring it's called at the correct point in the disconnection process. The related changes in other classes, such as nulling out the BackupInventory during crafting and fixing a null reference in SkillList, are logical and support the main fix. I've identified one critical issue in the new fallback logic that could still lead to item loss and have provided a suggestion to address it. Overall, this is a valuable improvement for data integrity.
| foreach (var item in items) | ||
| { | ||
| await this.TemporaryStorage.RemoveItemAsync(item).ConfigureAwait(false); | ||
| if (!await this.Inventory.AddItemAsync(item).ConfigureAwait(false)) | ||
| { | ||
| this.Logger.LogError("Failed to return item {item} to inventory. Item is lost. id: {itemid}", item, item.GetId()); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current implementation of the fallback logic for restoring items has a potential race condition that could lead to item loss. An item is removed from TemporaryStorage before attempting to add it to the player's Inventory. If AddItemAsync fails (e.g., due to a full inventory), the item is lost permanently because it has already been removed from its original location.
To prevent this, the order of operations should be reversed: first, attempt to add the item to the inventory, and only upon success, remove it from the temporary storage. This ensures that items are not lost if the inventory operation fails, even in this fallback scenario.
foreach (var item in items)
{
if (await this.Inventory.AddItemAsync(item).ConfigureAwait(false))
{
await this.TemporaryStorage.RemoveItemAsync(item).ConfigureAwait(false);
}
else
{
this.Logger.LogError("Failed to return item {item} to inventory. Item is lost. id: {itemid}", item, item.GetId());
}
}
Temporary Storage Item Loss on Forced Disconnect - Fix
Issue Fixed: Items placed in temporary storage (Chaos Goblin, Pet Trainer, etc.) are lost when the client is forcibly closed or connection is interrupted.
Implementation
Changes Made:
ReturnTemporaryStorageItemsAsync()method that safely returns items from temporary storage to inventoryBackupInventoryexists first - if it does,GameServer.SaveSessionOfPlayerAsynchandles restorationRemoveFromGameAsync()before character is unselectedSkillList.AddItemSkillAsync()- added null check forSelectedCharacterto prevent exceptions during disconnect cleanupKey Features:
BackupInventoryis presentTryTakeAllAsync()which has built-in rollback if inventory is fullTesting:
Root Cause
TemporaryStorageis created fresh on each character selection and not persisted. When a player disconnects with items in temporary storage, those items are lost because cleanup didn't occur before character unselection.Solution Quality
Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.