diff --git a/CSync/CSync/Lib/ConfigSyncBehaviour.cs b/CSync/CSync/Lib/ConfigSyncBehaviour.cs index 29b123a..3fe5fb5 100644 --- a/CSync/CSync/Lib/ConfigSyncBehaviour.cs +++ b/CSync/CSync/Lib/ConfigSyncBehaviour.cs @@ -1,6 +1,8 @@ +using BepInEx.Configuration; using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.Linq; using Unity.Netcode; using UnityEngine; using LogLevel = BepInEx.Logging.LogLevel; @@ -36,7 +38,9 @@ public bool SyncEnabled } private readonly NetworkVariable _syncEnabled = new(); - private NetworkList _deltas = null!; + private readonly NetworkList _deltas = new(); + private readonly List<(ConfigFile, EventHandler)> _settingChangedListeners = new(); + private readonly List<(SyncedEntryBase, EventHandler)> _entrySyncEnabledChangedListeners = new(); [MemberNotNull(nameof(EntryContainer))] private void EnsureEntryContainer() @@ -48,7 +52,6 @@ private void EnsureEntryContainer() private void Awake() { EnsureEntryContainer(); - _deltas = new NetworkList(); } public override void OnNetworkSpawn() @@ -59,28 +62,32 @@ public override void OnNetworkSpawn() { _syncEnabled.Value = true; + var index = 0; foreach (var syncedEntryBase in EntryContainer.Values) { - var currentIndex = _deltas.Count; _deltas.Add(syncedEntryBase.ToDelta()); - syncedEntryBase.BoxedEntry.ConfigFile.SettingChanged += (_, args) => + void onSettingChanged(object sender, SettingChangedEventArgs args) { if (!ReferenceEquals(syncedEntryBase.BoxedEntry, args.ChangedSetting)) return; - _deltas[currentIndex] = syncedEntryBase.ToDelta(); - }; + _deltas[index] = syncedEntryBase.ToDelta(); + } + var configFile = syncedEntryBase.BoxedEntry.ConfigFile; + configFile.SettingChanged += onSettingChanged; + _settingChangedListeners.Add((configFile, onSettingChanged)); - syncedEntryBase.SyncEnabledChanged += (_, args) => + void onEntrySyncEnabledChanged(object sender, EventArgs args) { - _deltas[currentIndex] = syncedEntryBase.ToDelta(); - }; + _deltas[index] = syncedEntryBase.ToDelta(); + } + syncedEntryBase.SyncEnabledChanged += onEntrySyncEnabledChanged; + _entrySyncEnabledChangedListeners.Add((syncedEntryBase, onEntrySyncEnabledChanged)); + index++; } InitialSyncCompletedHandler?.Invoke(this, EventArgs.Empty); - return; } - - if (IsClient) + else if (IsClient) { _syncEnabled.OnValueChanged += OnSyncEnabledChanged; _deltas.OnListChanged += OnClientDeltaListChanged; @@ -94,6 +101,48 @@ public override void OnNetworkSpawn() InitialSyncCompletedHandler?.Invoke(this, EventArgs.Empty); } + + base.OnNetworkSpawn(); + } + + public override void OnNetworkDespawn() + { + EnsureEntryContainer(); + + if (IsServer) + { + foreach (var (configFile, onSettingChanged) in _settingChangedListeners) + { + configFile.SettingChanged -= onSettingChanged; + } + + foreach (var (syncedEntryBase, onEntrySyncEnabledChanged) in _entrySyncEnabledChangedListeners) + { + syncedEntryBase.SyncEnabledChanged -= onEntrySyncEnabledChanged; + } + + _settingChangedListeners.Clear(); + _entrySyncEnabledChangedListeners.Clear(); + // NetworkList and NetworkVariable can not be modified now because the network manager has already shut down. + // See https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/pull/3502 + // Should not be needed anyway, since this component isn't being reused between network sessions. + // _deltas.Clear(); + // _syncEnabled.Value = false; + } + else if (IsClient) + { + DisableOverrides(); + + foreach (var delta in _deltas) + { + ResetOverrideValue(delta); + } + + _deltas.OnListChanged -= OnClientDeltaListChanged; + _syncEnabled.OnValueChanged -= OnSyncEnabledChanged; + } + + base.OnNetworkDespawn(); } public override void OnDestroy()