diff --git a/MosswartMassacre/PluginCore.cs b/MosswartMassacre/PluginCore.cs index 8c03124..bbd640a 100644 --- a/MosswartMassacre/PluginCore.cs +++ b/MosswartMassacre/PluginCore.cs @@ -163,6 +163,42 @@ namespace MosswartMassacre var isCharacterLoaded = CoreManager.Current.CharacterFilter.LoginStatus == 3; 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(_chatEventRouter.OnChatText); + CoreManager.Current.ChatBoxMessage -= new EventHandler(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) _killTracker = new KillTracker( this, @@ -280,6 +316,7 @@ namespace MosswartMassacre CoreManager.Current.ChatBoxMessage -= new EventHandler(_chatEventRouter.OnChatText); CoreManager.Current.CommandLineText -= OnChatCommand; CoreManager.Current.ChatBoxMessage -= new EventHandler(ChatEventRouter.AllChatText); + CoreManager.Current.CharacterFilter.LoginComplete -= CharacterFilter_LoginComplete; CoreManager.Current.CharacterFilter.Death -= OnCharacterDeath; CoreManager.Current.WorldFilter.CreateObject -= OnSpawn; CoreManager.Current.WorldFilter.CreateObject -= OnPortalDetected; diff --git a/MosswartMassacre/bin/Release/MosswartMassacre.dll b/MosswartMassacre/bin/Release/MosswartMassacre.dll index 6503adc..5e74667 100644 Binary files a/MosswartMassacre/bin/Release/MosswartMassacre.dll and b/MosswartMassacre/bin/Release/MosswartMassacre.dll differ