feat(SyncList): Add individual Actions for operations (#3794)

This commit is contained in:
MrGadget 2024-03-23 14:54:38 -04:00
parent 1919e61856
commit 824712df9c
3 changed files with 154 additions and 6 deletions

View File

@ -15,6 +15,23 @@ public enum Operation : byte
OP_CLEAR
}
/// <summary>This is called after the item is added with index</summary>
public Action<int> OnAdd;
/// <summary>This is called after the item is inserted with inedx</summary>
public Action<int> OnInsert;
/// <summary>This is called after the item is set with index and OLD Value</summary>
public Action<int, T> OnSet;
/// <summary>This is called after the item is removed with index and OLD Value</summary>
public Action<int, T> OnRemove;
/// <summary>This is called before the list is cleared so the list can be iterated</summary>
public Action OnClear;
// Deprecated 2024-03-23
[Obsolete("Use individual Actions, which pass OLD values where appropriate, instead.")]
public Action<Operation, int, T, T> Callback;
readonly IList<T> objects;
@ -85,7 +102,28 @@ void AddOperation(Operation op, int itemIndex, T oldItem, T newItem, bool checkA
OnDirty?.Invoke();
}
switch (op)
{
case Operation.OP_ADD:
OnAdd?.Invoke(itemIndex);
break;
case Operation.OP_INSERT:
OnInsert?.Invoke(itemIndex);
break;
case Operation.OP_SET:
OnSet?.Invoke(itemIndex, oldItem);
break;
case Operation.OP_REMOVEAT:
OnRemove?.Invoke(itemIndex, oldItem);
break;
case Operation.OP_CLEAR:
OnClear?.Invoke();
break;
}
#pragma warning disable CS0618 // Type or member is obsolete
Callback?.Invoke(op, itemIndex, oldItem, newItem);
#pragma warning restore CS0618 // Type or member is obsolete
}
public override void OnSerializeAll(NetworkWriter writer)

View File

@ -47,6 +47,7 @@ public void OldValueShouldNotBeNewValue()
player.item.price = 15;
serverList[0] = player;
#pragma warning disable 618 // Type or member is obsolete
bool callbackCalled = false;
clientList.Callback = (SyncList<TestPlayer>.Operation op, int itemIndex, TestPlayer oldItem, TestPlayer newItem) =>
{
@ -56,6 +57,7 @@ public void OldValueShouldNotBeNewValue()
Assert.That(newItem.item.price, Is.EqualTo(15));
callbackCalled = true;
};
#pragma warning restore 618 // Type or member is obsolete
SyncListTest.SerializeDeltaTo(serverList, clientList);
Assert.IsTrue(callbackCalled);

View File

@ -97,6 +97,7 @@ public void TestAddRange()
[Test]
public void TestClear()
{
#pragma warning disable 618 // Type or member is obsolete
bool called = false;
clientSyncList.Callback = (op, index, oldItem, newItem) =>
{
@ -105,16 +106,26 @@ public void TestClear()
Assert.That(op, Is.EqualTo(SyncList<string>.Operation.OP_CLEAR));
Assert.That(clientSyncList.Count, Is.EqualTo(3));
};
#pragma warning restore 618 // Type or member is obsolete
bool actionCalled = false;
clientSyncList.OnClear = () =>
{
actionCalled = true;
Assert.That(clientSyncList.Count, Is.EqualTo(3));
};
serverSyncList.Clear();
SerializeDeltaTo(serverSyncList, clientSyncList);
Assert.That(clientSyncList, Is.EquivalentTo(new string[] { }));
Assert.That(called, Is.True);
Assert.That(actionCalled, Is.True);
}
[Test]
public void TestInsert()
{
#pragma warning disable 618 // Type or member is obsolete
bool called = false;
clientSyncList.Callback = (op, index, oldItem, newItem) =>
{
@ -124,11 +135,20 @@ public void TestInsert()
Assert.That(index, Is.EqualTo(0));
Assert.That(newItem, Is.EqualTo("yay"));
};
#pragma warning restore 618 // Type or member is obsolete
bool actionCalled = false;
clientSyncList.OnInsert = (index) =>
{
actionCalled = true;
Assert.That(index, Is.EqualTo(0));
};
serverSyncList.Insert(0, "yay");
SerializeDeltaTo(serverSyncList, clientSyncList);
Assert.That(clientSyncList, Is.EquivalentTo(new[] { "yay", "Hello", "World", "!" }));
Assert.That(called, Is.True);
Assert.That(actionCalled, Is.True);
}
[Test]
@ -142,6 +162,7 @@ public void TestInsertRange()
[Test]
public void TestSet()
{
#pragma warning disable 618 // Type or member is obsolete
bool called = false;
clientSyncList.Callback = (op, index, oldItem, newItem) =>
{
@ -152,17 +173,28 @@ public void TestSet()
Assert.That(oldItem, Is.EqualTo("World"));
Assert.That(newItem, Is.EqualTo("yay"));
};
#pragma warning restore 618 // Type or member is obsolete
bool actionCalled = false;
clientSyncList.OnSet = (index, oldItem) =>
{
actionCalled = true;
Assert.That(index, Is.EqualTo(1));
Assert.That(oldItem, Is.EqualTo("World"));
};
serverSyncList[1] = "yay";
SerializeDeltaTo(serverSyncList, clientSyncList);
Assert.That(clientSyncList[1], Is.EqualTo("yay"));
Assert.That(clientSyncList, Is.EquivalentTo(new[] { "Hello", "yay", "!" }));
Assert.That(called, Is.True);
Assert.That(actionCalled, Is.True);
}
[Test]
public void TestSetNull()
{
#pragma warning disable 618 // Type or member is obsolete
bool called = false;
clientSyncList.Callback = (op, index, oldItem, newItem) =>
{
@ -173,15 +205,30 @@ public void TestSetNull()
Assert.That(oldItem, Is.EqualTo("World"));
Assert.That(newItem, Is.EqualTo(null));
};
#pragma warning restore 618 // Type or member is obsolete
bool actionCalled = false;
clientSyncList.OnSet = (index, oldItem) =>
{
actionCalled = true;
Assert.That(index, Is.EqualTo(1));
Assert.That(oldItem, Is.EqualTo("World"));
};
serverSyncList[1] = null;
SerializeDeltaTo(serverSyncList, clientSyncList);
Assert.That(clientSyncList[1], Is.EqualTo(null));
Assert.That(clientSyncList, Is.EquivalentTo(new[] { "Hello", null, "!" }));
Assert.That(called, Is.True);
Assert.That(actionCalled, Is.True);
#pragma warning disable 618 // Type or member is obsolete
// clear callback so we don't get called again
clientSyncList.Callback = null;
#pragma warning restore 618 // Type or member is obsolete
// clear handlers so we don't get called again
clientSyncList.OnSet = null;
serverSyncList[1] = "yay";
SerializeDeltaTo(serverSyncList, clientSyncList);
@ -191,6 +238,7 @@ public void TestSetNull()
[Test]
public void TestRemoveAll()
{
#pragma warning disable 618 // Type or member is obsolete
bool called = false;
clientSyncList.Callback = (op, index, oldItem, newItem) =>
{
@ -201,12 +249,22 @@ public void TestRemoveAll()
Assert.That(oldItem, Is.Not.EqualTo("!"));
Assert.That(newItem, Is.EqualTo(default(string)));
};
#pragma warning restore 618 // Type or member is obsolete
bool actionCalled = false;
clientSyncList.OnRemove = (index, item) =>
{
actionCalled = true;
Assert.That(index, Is.EqualTo(0));
Assert.That(item, Is.Not.EqualTo("!"));
};
// This will remove "Hello" and "World"
serverSyncList.RemoveAll(entry => entry.Contains("l"));
SerializeDeltaTo(serverSyncList, clientSyncList);
Assert.That(clientSyncList, Is.EquivalentTo(new[] { "!" }));
Assert.That(called, Is.True);
Assert.That(actionCalled, Is.True);
}
[Test]
@ -220,6 +278,7 @@ public void TestRemoveAllNone()
[Test]
public void TestRemoveAt()
{
#pragma warning disable 618 // Type or member is obsolete
bool called = false;
clientSyncList.Callback = (op, index, oldItem, newItem) =>
{
@ -230,16 +289,27 @@ public void TestRemoveAt()
Assert.That(oldItem, Is.EqualTo("World"));
Assert.That(newItem, Is.EqualTo(default(string)));
};
#pragma warning restore 618 // Type or member is obsolete
bool actionCalled = false;
clientSyncList.OnRemove = (index, oldItem) =>
{
actionCalled = true;
Assert.That(index, Is.EqualTo(1));
Assert.That(oldItem, Is.EqualTo("World"));
};
serverSyncList.RemoveAt(1);
SerializeDeltaTo(serverSyncList, clientSyncList);
Assert.That(clientSyncList, Is.EquivalentTo(new[] { "Hello", "!" }));
Assert.That(called, Is.True);
Assert.That(actionCalled, Is.True);
}
[Test]
public void TestRemove()
{
#pragma warning disable 618 // Type or member is obsolete
bool called = false;
clientSyncList.Callback = (op, index, oldItem, newItem) =>
{
@ -250,11 +320,21 @@ public void TestRemove()
Assert.That(oldItem, Is.EqualTo("World"));
Assert.That(newItem, Is.EqualTo(default(string)));
};
#pragma warning restore 618 // Type or member is obsolete
bool actionCalled = false;
clientSyncList.OnRemove = (index, oldItem) =>
{
actionCalled = true;
Assert.That(index, Is.EqualTo(1));
Assert.That(oldItem, Is.EqualTo("World"));
};
serverSyncList.Remove("World");
SerializeDeltaTo(serverSyncList, clientSyncList);
Assert.That(clientSyncList, Is.EquivalentTo(new[] { "Hello", "!" }));
Assert.That(called, Is.True);
Assert.That(actionCalled, Is.True);
}
[Test]
@ -362,8 +442,8 @@ public void SyncListFloatTest()
[Test]
public void CallbackTest()
{
#pragma warning disable 618 // Type or member is obsolete
bool called = false;
clientSyncList.Callback = (op, index, oldItem, newItem) =>
{
called = true;
@ -373,18 +453,27 @@ public void CallbackTest()
Assert.That(oldItem, Is.EqualTo(default(string)));
Assert.That(newItem, Is.EqualTo("yay"));
};
#pragma warning restore 618 // Type or member is obsolete
bool actionCalled = false;
clientSyncList.OnAdd = (index) =>
{
actionCalled = true;
Assert.That(index, Is.EqualTo(3));
Assert.That(clientSyncList[index], Is.EqualTo("yay"));
};
serverSyncList.Add("yay");
SerializeDeltaTo(serverSyncList, clientSyncList);
Assert.That(called, Is.True);
Assert.That(actionCalled, Is.True);
}
[Test]
public void CallbackRemoveTest()
{
#pragma warning disable 618 // Type or member is obsolete
bool called = false;
clientSyncList.Callback = (op, index, oldItem, newItem) =>
{
called = true;
@ -393,17 +482,27 @@ public void CallbackRemoveTest()
Assert.That(oldItem, Is.EqualTo("World"));
Assert.That(newItem, Is.EqualTo(default(string)));
};
#pragma warning restore 618 // Type or member is obsolete
bool actionCalled = false;
clientSyncList.OnRemove = (index, oldItem) =>
{
actionCalled = true;
Assert.That(index, Is.EqualTo(1));
Assert.That(oldItem, Is.EqualTo("World"));
};
serverSyncList.Remove("World");
SerializeDeltaTo(serverSyncList, clientSyncList);
Assert.That(called, Is.True);
Assert.That(actionCalled, Is.True);
}
[Test]
public void CallbackRemoveAtTest()
{
#pragma warning disable 618 // Type or member is obsolete
bool called = false;
clientSyncList.Callback = (op, index, oldItem, newItem) =>
{
called = true;
@ -413,11 +512,20 @@ public void CallbackRemoveAtTest()
Assert.That(oldItem, Is.EqualTo("World"));
Assert.That(newItem, Is.EqualTo(default(string)));
};
#pragma warning restore 618 // Type or member is obsolete
bool actionCalled = false;
clientSyncList.OnRemove = (index, oldItem) =>
{
actionCalled = true;
Assert.That(index, Is.EqualTo(1));
Assert.That(oldItem, Is.EqualTo("World"));
};
serverSyncList.RemoveAt(1);
SerializeDeltaTo(serverSyncList, clientSyncList);
Assert.That(called, Is.True);
Assert.That(actionCalled, Is.True);
}
[Test]