SyncDictionary: Add oldValue to AddOperation (#3790)

This is preparation for Actions coming in subsequent PR.
This commit is contained in:
MrGadget 2024-03-22 00:49:01 -04:00
parent 877067af76
commit 5c96c81e35

View File

@ -65,12 +65,10 @@ public SyncIDictionary(IDictionary<TKey, TValue> objects)
this.objects = objects; this.objects = objects;
} }
void AddOperation(Operation op, TKey key, TValue item, bool checkAccess) void AddOperation(Operation op, TKey key, TValue item, TValue oldItem, bool checkAccess)
{ {
if (checkAccess && IsReadOnly) if (checkAccess && IsReadOnly)
{ throw new InvalidOperationException("SyncDictionaries can only be modified by the owner.");
throw new System.InvalidOperationException("SyncDictionaries can only be modified by the owner.");
}
Change change = new Change Change change = new Change
{ {
@ -179,15 +177,15 @@ public override void OnDeserializeDelta(NetworkReader reader)
// ClientToServer needs to set dirty in server OnDeserialize. // ClientToServer needs to set dirty in server OnDeserialize.
// no access check: server OnDeserialize can always // no access check: server OnDeserialize can always
// write, even for ClientToServer (for broadcasting). // write, even for ClientToServer (for broadcasting).
if (ContainsKey(key)) if (objects.TryGetValue(key, out TValue oldItem))
{ {
objects[key] = item; // assign after ContainsKey check objects[key] = item; // assign after TryGetValue
AddOperation(Operation.OP_SET, key, item, false); AddOperation(Operation.OP_SET, key, item, oldItem, false);
} }
else else
{ {
objects[key] = item; // assign after ContainsKey check objects[key] = item; // assign after TryGetValue
AddOperation(Operation.OP_ADD, key, item, false); AddOperation(Operation.OP_ADD, key, item, default, false);
} }
} }
break; break;
@ -199,7 +197,7 @@ public override void OnDeserializeDelta(NetworkReader reader)
// ClientToServer needs to set dirty in server OnDeserialize. // ClientToServer needs to set dirty in server OnDeserialize.
// no access check: server OnDeserialize can always // no access check: server OnDeserialize can always
// write, even for ClientToServer (for broadcasting). // write, even for ClientToServer (for broadcasting).
AddOperation(Operation.OP_CLEAR, default, default, false); AddOperation(Operation.OP_CLEAR, default, default, default, false);
// clear after invoking the callback so users can iterate the dictionary // clear after invoking the callback so users can iterate the dictionary
// and take appropriate action on the items before they are wiped. // and take appropriate action on the items before they are wiped.
objects.Clear(); objects.Clear();
@ -210,14 +208,14 @@ public override void OnDeserializeDelta(NetworkReader reader)
key = reader.Read<TKey>(); key = reader.Read<TKey>();
if (apply) if (apply)
{ {
if (objects.TryGetValue(key, out item)) if (objects.TryGetValue(key, out TValue oldItem))
{ {
// add dirty + changes. // add dirty + changes.
// ClientToServer needs to set dirty in server OnDeserialize. // ClientToServer needs to set dirty in server OnDeserialize.
// no access check: server OnDeserialize can always // no access check: server OnDeserialize can always
// write, even for ClientToServer (for broadcasting). // write, even for ClientToServer (for broadcasting).
objects.Remove(key); objects.Remove(key);
AddOperation(Operation.OP_REMOVE, key, item, false); AddOperation(Operation.OP_REMOVE, key, oldItem, oldItem, false);
} }
} }
break; break;
@ -233,7 +231,7 @@ public override void OnDeserializeDelta(NetworkReader reader)
public void Clear() public void Clear()
{ {
AddOperation(Operation.OP_CLEAR, default, default, true); AddOperation(Operation.OP_CLEAR, default, default, default, true);
// clear after invoking the callback so users can iterate the dictionary // clear after invoking the callback so users can iterate the dictionary
// and take appropriate action on the items before they are wiped. // and take appropriate action on the items before they are wiped.
objects.Clear(); objects.Clear();
@ -243,9 +241,9 @@ public void Clear()
public bool Remove(TKey key) public bool Remove(TKey key)
{ {
if (objects.TryGetValue(key, out TValue item) && objects.Remove(key)) if (objects.TryGetValue(key, out TValue oldItem) && objects.Remove(key))
{ {
AddOperation(Operation.OP_REMOVE, key, item, true); AddOperation(Operation.OP_REMOVE, key, oldItem, oldItem, true);
return true; return true;
} }
return false; return false;
@ -258,13 +256,14 @@ public TValue this[TKey i]
{ {
if (ContainsKey(i)) if (ContainsKey(i))
{ {
TValue oldItem = objects[i];
objects[i] = value; objects[i] = value;
AddOperation(Operation.OP_SET, i, value, true); AddOperation(Operation.OP_SET, i, value, oldItem, true);
} }
else else
{ {
objects[i] = value; objects[i] = value;
AddOperation(Operation.OP_ADD, i, value, true); AddOperation(Operation.OP_ADD, i, value, default, true);
} }
} }
} }
@ -274,7 +273,7 @@ public TValue this[TKey i]
public void Add(TKey key, TValue value) public void Add(TKey key, TValue value)
{ {
objects.Add(key, value); objects.Add(key, value);
AddOperation(Operation.OP_ADD, key, value, true); AddOperation(Operation.OP_ADD, key, value, default, true);
} }
public void Add(KeyValuePair<TKey, TValue> item) => Add(item.Key, item.Value); public void Add(KeyValuePair<TKey, TValue> item) => Add(item.Key, item.Value);
@ -301,7 +300,7 @@ public bool Remove(KeyValuePair<TKey, TValue> item)
{ {
bool result = objects.Remove(item.Key); bool result = objects.Remove(item.Key);
if (result) if (result)
AddOperation(Operation.OP_REMOVE, item.Key, item.Value, true); AddOperation(Operation.OP_REMOVE, item.Key, item.Value, item.Value, true);
return result; return result;
} }