Repository navigation
fix(npc): don't respawn an NPC which was disposed while waiting to respawn - #1249
Merged
Merged
Conversation
…spawn A killed NPC schedules its respawn after the respawn delay. When it got disposed in the meantime (e.g. its spawn area was deleted, or the map or mini game was torn down), the pending respawn still initialized it and put it back into the area of interest manager of the map. The respawn is now skipped when the NPC is disposed or disposing. For this check to work, AsyncDisposable.DisposeAsync now marks the instance as disposed, too - before, IsDisposed stayed false after DisposeAsync, so a second DisposeAsync released the resources again.
Member
|
Review: looks good. You found and fixed the Verified locally (head
Notes:
Merging. Generated by Claude Code |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A killed NPC schedules its respawn (
Task.Delay(RespawnDelay)→RespawnAsync). When the NPC is disposed while it waits — e.g. its spawn area is deleted in the admin panel (theMapInitializerdelete handler disposes every NPC of the area, dead ones included), or its map/mini game is torn down — the pending task still callsInitialize()andGameMap.RespawnAsync, putting the disposed object back into the map's area of interest manager. In game it shows up as a monster which can't be attacked and stays until the server restarts; its object id may already be reused.The check needed for this didn't work either:
AsyncDisposable.DisposeAsynccalledDispose(true)directly, soIsDisposedstayedfalseafter an async dispose (and a secondDisposeAsyncreleased the resources again).Changes
AttackableNpcBase.RespawnAsyncreturns early when the NPC is disposed or disposing.AsyncDisposable.DisposeAsynccallsDispose(), which disposes the managed resources and setsIsDisposed.IsDisposedis set afterDisposeAsync, and a secondDisposeAsyncdoesn't dispose again.Note: since
IsDisposedis now true afterDisposeAsync, existingIsDisposedchecks onAsyncDisposablesubclasses (e.g. inMiniGameManager,BotManager) now see disposed instances, which seems to be what they intended.Testing
MUnique.OpenMU.Tests1897, Persistence.Initialization, Network, Web, PlugIns, ...).