From 877067af76521bc92f5c33fc11d02c4962f31fb3 Mon Sep 17 00:00:00 2001 From: MrGadget <9826063+MrGadget1024@users.noreply.github.com> Date: Thu, 21 Mar 2024 23:02:54 -0400 Subject: [PATCH] fix(SyncDictionary): Clear after Callback (#3789) --- Assets/Mirror/Core/SyncDictionary.cs | 8 ++++++-- .../Tests/Editor/SyncCollections/SyncDictionaryTest.cs | 10 ++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Assets/Mirror/Core/SyncDictionary.cs b/Assets/Mirror/Core/SyncDictionary.cs index cbfc670e8..4de1994a9 100644 --- a/Assets/Mirror/Core/SyncDictionary.cs +++ b/Assets/Mirror/Core/SyncDictionary.cs @@ -195,12 +195,14 @@ public override void OnDeserializeDelta(NetworkReader reader) case Operation.OP_CLEAR: if (apply) { - objects.Clear(); // add dirty + changes. // ClientToServer needs to set dirty in server OnDeserialize. // no access check: server OnDeserialize can always // write, even for ClientToServer (for broadcasting). AddOperation(Operation.OP_CLEAR, default, default, false); + // clear after invoking the callback so users can iterate the dictionary + // and take appropriate action on the items before they are wiped. + objects.Clear(); } break; @@ -231,8 +233,10 @@ public override void OnDeserializeDelta(NetworkReader reader) public void Clear() { - objects.Clear(); AddOperation(Operation.OP_CLEAR, default, default, true); + // clear after invoking the callback so users can iterate the dictionary + // and take appropriate action on the items before they are wiped. + objects.Clear(); } public bool ContainsKey(TKey key) => objects.ContainsKey(key); diff --git a/Assets/Mirror/Tests/Editor/SyncCollections/SyncDictionaryTest.cs b/Assets/Mirror/Tests/Editor/SyncCollections/SyncDictionaryTest.cs index 15b81d9e6..aa7bb0e71 100644 --- a/Assets/Mirror/Tests/Editor/SyncCollections/SyncDictionaryTest.cs +++ b/Assets/Mirror/Tests/Editor/SyncCollections/SyncDictionaryTest.cs @@ -89,9 +89,19 @@ public void TestAdd() [Test] public void TestClear() { + // Verifies that the clear method works and that the data is still present for the Callback. + bool called = false; + clientSyncDictionary.Callback = (op, index, item) => + { + called = true; + + Assert.That(op, Is.EqualTo(SyncDictionary.Operation.OP_CLEAR)); + Assert.That(clientSyncDictionary.Count, Is.EqualTo(3)); + }; serverSyncDictionary.Clear(); SerializeDeltaTo(serverSyncDictionary, clientSyncDictionary); Assert.That(serverSyncDictionary, Is.EquivalentTo(new SyncDictionary())); + Assert.That(called, Is.True); } [Test]