diff --git a/Assets/Scripts/Core/DataManagement/CreateEvent.cs b/Assets/Scripts/Core/DataManagement/CreateEvent.cs new file mode 100644 index 00000000..36e23b31 --- /dev/null +++ b/Assets/Scripts/Core/DataManagement/CreateEvent.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; + +namespace Core.DataManagement +{ + public class CreateEvent + { + public delegate void CreateCallback(TDataElement subject) + where TDataElement : struct, IDataWithId; + + private Dictionary> invocationLists = new Dictionary>(); + + public void AddCallback(CreateCallback callback) + where TDataElement : struct, IDataWithId + { + Type type = typeof(TDataElement); + + if (!invocationLists.TryGetValue(type, out List invocationList)) + { + invocationList = new List(); + invocationLists.Add(type, invocationList); + } + + invocationList.Add(callback); + } + + public void RemoveCallback(CreateCallback callback) + where TDataElement : struct, IDataWithId + { + Type type = typeof(TDataElement); + + if (!invocationLists.TryGetValue(type, out List invocationList)) + return; + + invocationList.Remove(callback); + + if (invocationList.Count == 0) + invocationLists.Remove(type); + } + + public void Invoke(TDataElement data) + where TDataElement : struct, IDataWithId + { + Type type = typeof(TDataElement); + + if (!invocationLists.TryGetValue(type, out List invocationList)) + return; + + foreach (object invocation in invocationList) + { + if (invocation is CreateCallback callback) + callback(data); + } + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Core/DataManagement/CreateEvent.cs.meta b/Assets/Scripts/Core/DataManagement/CreateEvent.cs.meta new file mode 100644 index 00000000..9e35d4e0 --- /dev/null +++ b/Assets/Scripts/Core/DataManagement/CreateEvent.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 495862aaa58f4f9d957f43e26ba8c98e +timeCreated: 1677703541 \ No newline at end of file diff --git a/Assets/Scripts/Core/DataManagement/DataCallbacks.cs b/Assets/Scripts/Core/DataManagement/DataCallbacks.cs new file mode 100644 index 00000000..9151793d --- /dev/null +++ b/Assets/Scripts/Core/DataManagement/DataCallbacks.cs @@ -0,0 +1,48 @@ +namespace Core.DataManagement +{ + public class DataCallbacks + { + private readonly DataEventDispatcher eventDispatcher; + + public DataCallbacks(DataEventDispatcher eventDispatcher) + { + this.eventDispatcher = eventDispatcher; + } + + public void AddCreateCallback(CreateEvent.CreateCallback callback) + where TDataElement : struct, IDataWithId + { + eventDispatcher.Create.AddCallback(callback); + } + + public void RemoveCreateCallback(CreateEvent.CreateCallback callback) + where TDataElement : struct, IDataWithId + { + eventDispatcher.Create.RemoveCallback(callback); + } + + public void AddDeleteCallback(DeleteEvent.DeleteCallback callback) + where TDataElement : struct, IDataWithId + { + eventDispatcher.Delete.AddCallback(callback); + } + + public void RemoveDeleteCallback(DeleteEvent.DeleteCallback callback) + where TDataElement : struct, IDataWithId + { + eventDispatcher.Delete.RemoveCallback(callback); + } + + public void AddModifyCallback(ModifyEvent.ModifyCallback callback) + where TDataElement : struct, IDataWithId + { + eventDispatcher.Modify.AddCallback(callback); + } + + public void RemoveModifyCallback(ModifyEvent.ModifyCallback callback) + where TDataElement : struct, IDataWithId + { + eventDispatcher.Modify.RemoveCallback(callback); + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Core/DataManagement/DataCallbacks.cs.meta b/Assets/Scripts/Core/DataManagement/DataCallbacks.cs.meta new file mode 100644 index 00000000..414c7db7 --- /dev/null +++ b/Assets/Scripts/Core/DataManagement/DataCallbacks.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 89d5f9a513ce4caf927d5a9647d715af +timeCreated: 1677703541 \ No newline at end of file diff --git a/Assets/Scripts/Core/DataManagement/DataEventDispatcher.cs b/Assets/Scripts/Core/DataManagement/DataEventDispatcher.cs new file mode 100644 index 00000000..24b873fc --- /dev/null +++ b/Assets/Scripts/Core/DataManagement/DataEventDispatcher.cs @@ -0,0 +1,13 @@ +namespace Core.DataManagement +{ + public class DataEventDispatcher + { + private readonly CreateEvent createEvent = new CreateEvent(); + private readonly DeleteEvent deleteEvent = new DeleteEvent(); + private readonly ModifyEvent modifyEvent = new ModifyEvent(); + + public CreateEvent Create => createEvent; + public DeleteEvent Delete => deleteEvent; + public ModifyEvent Modify => modifyEvent; + } +} \ No newline at end of file diff --git a/Assets/Scripts/Core/DataManagement/DataEventDispatcher.cs.meta b/Assets/Scripts/Core/DataManagement/DataEventDispatcher.cs.meta new file mode 100644 index 00000000..d9bb2687 --- /dev/null +++ b/Assets/Scripts/Core/DataManagement/DataEventDispatcher.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c9d98f982b6a4fdba2c4e406cdac0412 +timeCreated: 1677703541 \ No newline at end of file diff --git a/Assets/Scripts/Core/DataManagement/DataTable.cs b/Assets/Scripts/Core/DataManagement/DataTable.cs index 3150c753..36ea837f 100644 --- a/Assets/Scripts/Core/DataManagement/DataTable.cs +++ b/Assets/Scripts/Core/DataManagement/DataTable.cs @@ -12,6 +12,7 @@ namespace Core.DataManagement private UniqueIntGenerator instanceIdGenerator; private List dataElements = new List(); private Dictionary dataIndexMap = new Dictionary(); + private readonly DataEventDispatcher eventDispatcher; public TDataElement this[ObjectId instanceId] { @@ -24,9 +25,10 @@ namespace Core.DataManagement } } - public DataTable(UniqueIntGenerator instanceIdgenerator) + public DataTable(UniqueIntGenerator instanceIdgenerator, DataEventDispatcher eventDispatcher) { this.instanceIdGenerator = instanceIdgenerator; + this.eventDispatcher = eventDispatcher; } public void Add(TDataElement data) @@ -39,6 +41,8 @@ namespace Core.DataManagement dataIndexMap.Add(data.InstanceId, dataElements.Count); dataElements.Add(data); + + eventDispatcher.Create.Invoke(data); } public void Remove(TDataElement data) @@ -48,6 +52,7 @@ namespace Core.DataManagement dataElements.RemoveAt(index); dataIndexMap.Remove(data.InstanceId); + eventDispatcher.Delete.Invoke(data); } public void Modify(TDataElement data) @@ -55,11 +60,12 @@ namespace Core.DataManagement if (!dataIndexMap.TryGetValue(data.InstanceId, out int index)) throw new InvalidOperationException($"Instance ID not found: {data.InstanceId.Id}"); + TDataElement previous = dataElements[index]; dataElements[index] = data; instanceIdGenerator.DeclareUnused(data.InstanceId.Id); + eventDispatcher.Modify.Invoke(previous, data); } - /// public void Serialize(IRevisionedSerializer serializer, TRevision revision) { // How many elements do we have in the data table? diff --git a/Assets/Scripts/Core/DataManagement/DeleteEvent.cs b/Assets/Scripts/Core/DataManagement/DeleteEvent.cs new file mode 100644 index 00000000..70047d3f --- /dev/null +++ b/Assets/Scripts/Core/DataManagement/DeleteEvent.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; + +namespace Core.DataManagement +{ + public class DeleteEvent + { + public delegate void DeleteCallback(TDataElement subject) + where TDataElement : struct, IDataWithId; + + private Dictionary> invocationLists = new Dictionary>(); + + public void AddCallback(DeleteCallback callback) + where TDataElement : struct, IDataWithId + { + Type type = typeof(TDataElement); + + if (!invocationLists.TryGetValue(type, out List invocationList)) + { + invocationList = new List(); + invocationLists.Add(type, invocationList); + } + + invocationList.Add(callback); + } + + public void RemoveCallback(DeleteCallback callback) + where TDataElement : struct, IDataWithId + { + Type type = typeof(TDataElement); + + if (!invocationLists.TryGetValue(type, out List invocationList)) + return; + + invocationList.Remove(callback); + + if (invocationList.Count == 0) + invocationLists.Remove(type); + } + + public void Invoke(TDataElement data) + where TDataElement : struct, IDataWithId + { + Type type = typeof(TDataElement); + + if (!invocationLists.TryGetValue(type, out List invocationList)) + return; + + foreach (object invocation in invocationList) + { + if (invocation is DeleteCallback callback) + callback(data); + } + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Core/DataManagement/DeleteEvent.cs.meta b/Assets/Scripts/Core/DataManagement/DeleteEvent.cs.meta new file mode 100644 index 00000000..15099ebe --- /dev/null +++ b/Assets/Scripts/Core/DataManagement/DeleteEvent.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 92c99810b07e4bec8f19ddd342508e05 +timeCreated: 1677703541 \ No newline at end of file diff --git a/Assets/Scripts/Core/DataManagement/ModifyEvent.cs b/Assets/Scripts/Core/DataManagement/ModifyEvent.cs new file mode 100644 index 00000000..28645bee --- /dev/null +++ b/Assets/Scripts/Core/DataManagement/ModifyEvent.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; + +namespace Core.DataManagement +{ + public class ModifyEvent + { + public delegate void ModifyCallback(TDataElement subjectPrevious, TDataElement subjectNew) + where TDataElement : struct, IDataWithId; + + private Dictionary> invocationLists = new Dictionary>(); + + public void AddCallback(ModifyCallback callback) + where TDataElement : struct, IDataWithId + { + Type type = typeof(TDataElement); + + if (!invocationLists.TryGetValue(type, out List invocationList)) + { + invocationList = new List(); + invocationLists.Add(type, invocationList); + } + + invocationList.Add(callback); + } + + public void RemoveCallback(ModifyCallback callback) + where TDataElement : struct, IDataWithId + { + Type type = typeof(TDataElement); + + if (!invocationLists.TryGetValue(type, out List invocationList)) + return; + + invocationList.Remove(callback); + + if (invocationList.Count == 0) + invocationLists.Remove(type); + } + + public void Invoke(TDataElement subjectPrevious, TDataElement subjectNew) + where TDataElement : struct, IDataWithId + { + Type type = typeof(TDataElement); + + if (!invocationLists.TryGetValue(type, out List invocationList)) + return; + + foreach (object invocation in invocationList) + { + if (invocation is ModifyCallback callback) + callback(subjectPrevious, subjectNew); + } + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Core/DataManagement/ModifyEvent.cs.meta b/Assets/Scripts/Core/DataManagement/ModifyEvent.cs.meta new file mode 100644 index 00000000..65ab3ce9 --- /dev/null +++ b/Assets/Scripts/Core/DataManagement/ModifyEvent.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b4125ec3ea934168ac29c381ba8662db +timeCreated: 1677703739 \ No newline at end of file diff --git a/Assets/Scripts/Core/WorldData/World.cs b/Assets/Scripts/Core/WorldData/World.cs index 26338abe..80a2d208 100644 --- a/Assets/Scripts/Core/WorldData/World.cs +++ b/Assets/Scripts/Core/WorldData/World.cs @@ -11,9 +11,9 @@ namespace Core.WorldData { public readonly DataTable Computers; - public World(UniqueIntGenerator instanceIdGenerator) + public World(UniqueIntGenerator instanceIdGenerator, DataEventDispatcher eventDispatcher) { - Computers = new DataTable(instanceIdGenerator); + Computers = new DataTable(instanceIdGenerator, eventDispatcher); } public void Serialize(IRevisionedSerializer serializer) diff --git a/Assets/Scripts/Core/WorldManager.cs b/Assets/Scripts/Core/WorldManager.cs index 96acc5ea..071534d8 100644 --- a/Assets/Scripts/Core/WorldManager.cs +++ b/Assets/Scripts/Core/WorldManager.cs @@ -10,13 +10,19 @@ namespace Core { private World world; private UniqueIntGenerator instanceIdGenerator; + private DataEventDispatcher eventDispatcher; + private DataCallbacks dataCallbacks; public World World => world; - + public DataCallbacks Callbacks => dataCallbacks; + public WorldManager() { + eventDispatcher = new DataEventDispatcher(); instanceIdGenerator = new UniqueIntGenerator(); - world = new World(instanceIdGenerator); + dataCallbacks = new DataCallbacks(eventDispatcher); + + world = new World(instanceIdGenerator, eventDispatcher); } public ObjectId GetNextObjectId()