Fix hot reload: prevent duplicate event handlers and timer leaks
Unsubscribe all event handlers and stop/dispose timers at the start of Startup() before re-creating objects. On first load the -= calls are no-ops; on hot reload they remove stale handlers that would otherwise compound with each reload. Also adds LoginComplete unsubscription to Shutdown() for completeness. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
1ffa163501
commit
aed74984c6
2 changed files with 37 additions and 0 deletions
|
|
@ -163,6 +163,42 @@ namespace MosswartMassacre
|
||||||
var isCharacterLoaded = CoreManager.Current.CharacterFilter.LoginStatus == 3;
|
var isCharacterLoaded = CoreManager.Current.CharacterFilter.LoginStatus == 3;
|
||||||
var needsHotReload = IsHotReload || isCharacterLoaded;
|
var needsHotReload = IsHotReload || isCharacterLoaded;
|
||||||
|
|
||||||
|
// Clean up old event subscriptions to prevent duplicates on hot reload.
|
||||||
|
// C# -= with a non-subscribed handler is a no-op, so safe on first load.
|
||||||
|
if (_chatEventRouter != null)
|
||||||
|
CoreManager.Current.ChatBoxMessage -= new EventHandler<ChatTextInterceptEventArgs>(_chatEventRouter.OnChatText);
|
||||||
|
CoreManager.Current.ChatBoxMessage -= new EventHandler<ChatTextInterceptEventArgs>(ChatEventRouter.AllChatText);
|
||||||
|
CoreManager.Current.CommandLineText -= OnChatCommand;
|
||||||
|
CoreManager.Current.CharacterFilter.LoginComplete -= CharacterFilter_LoginComplete;
|
||||||
|
CoreManager.Current.CharacterFilter.Death -= OnCharacterDeath;
|
||||||
|
CoreManager.Current.WorldFilter.CreateObject -= OnSpawn;
|
||||||
|
CoreManager.Current.WorldFilter.CreateObject -= OnPortalDetected;
|
||||||
|
CoreManager.Current.WorldFilter.ReleaseObject -= OnDespawn;
|
||||||
|
if (_inventoryMonitor != null)
|
||||||
|
{
|
||||||
|
CoreManager.Current.WorldFilter.CreateObject -= _inventoryMonitor.OnInventoryCreate;
|
||||||
|
CoreManager.Current.WorldFilter.ReleaseObject -= _inventoryMonitor.OnInventoryRelease;
|
||||||
|
CoreManager.Current.WorldFilter.ChangeObject -= _inventoryMonitor.OnInventoryChange;
|
||||||
|
}
|
||||||
|
if (_gameEventRouter != null)
|
||||||
|
CoreManager.Current.EchoFilter.ServerDispatch -= _gameEventRouter.OnServerDispatch;
|
||||||
|
WebSocket.OnServerCommand -= HandleServerCommand;
|
||||||
|
|
||||||
|
// Stop old timers before recreating (prevents timer leaks on hot reload)
|
||||||
|
_killTracker?.Stop();
|
||||||
|
if (vitalsTimer != null)
|
||||||
|
{
|
||||||
|
vitalsTimer.Stop();
|
||||||
|
vitalsTimer.Dispose();
|
||||||
|
vitalsTimer = null;
|
||||||
|
}
|
||||||
|
if (commandTimer != null)
|
||||||
|
{
|
||||||
|
commandTimer.Stop();
|
||||||
|
commandTimer.Dispose();
|
||||||
|
commandTimer = null;
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize kill tracker (owns the 1-sec stats timer)
|
// Initialize kill tracker (owns the 1-sec stats timer)
|
||||||
_killTracker = new KillTracker(
|
_killTracker = new KillTracker(
|
||||||
this,
|
this,
|
||||||
|
|
@ -280,6 +316,7 @@ namespace MosswartMassacre
|
||||||
CoreManager.Current.ChatBoxMessage -= new EventHandler<ChatTextInterceptEventArgs>(_chatEventRouter.OnChatText);
|
CoreManager.Current.ChatBoxMessage -= new EventHandler<ChatTextInterceptEventArgs>(_chatEventRouter.OnChatText);
|
||||||
CoreManager.Current.CommandLineText -= OnChatCommand;
|
CoreManager.Current.CommandLineText -= OnChatCommand;
|
||||||
CoreManager.Current.ChatBoxMessage -= new EventHandler<ChatTextInterceptEventArgs>(ChatEventRouter.AllChatText);
|
CoreManager.Current.ChatBoxMessage -= new EventHandler<ChatTextInterceptEventArgs>(ChatEventRouter.AllChatText);
|
||||||
|
CoreManager.Current.CharacterFilter.LoginComplete -= CharacterFilter_LoginComplete;
|
||||||
CoreManager.Current.CharacterFilter.Death -= OnCharacterDeath;
|
CoreManager.Current.CharacterFilter.Death -= OnCharacterDeath;
|
||||||
CoreManager.Current.WorldFilter.CreateObject -= OnSpawn;
|
CoreManager.Current.WorldFilter.CreateObject -= OnSpawn;
|
||||||
CoreManager.Current.WorldFilter.CreateObject -= OnPortalDetected;
|
CoreManager.Current.WorldFilter.CreateObject -= OnPortalDetected;
|
||||||
|
|
|
||||||
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue