diff --git a/LocalPackages/com.nimin.lowlevel/Runtime/NativeDataContainer.cs b/LocalPackages/com.nimin.lowlevel/Runtime/NativeDataContainer.cs index 2df49dc..c99eb4e 100644 --- a/LocalPackages/com.nimin.lowlevel/Runtime/NativeDataContainer.cs +++ b/LocalPackages/com.nimin.lowlevel/Runtime/NativeDataContainer.cs @@ -32,6 +32,11 @@ namespace GameCore.LowLevel m_UnsafeDataPtr = null; } + public bool HasValue(int index) + { + return m_UnsafeDataPtr->HasValue(index); + } + public bool Free(int index) { return m_UnsafeDataPtr->Free(index); diff --git a/LocalPackages/com.nimin.lowlevel/Runtime/UnsafeDataContainer.cs b/LocalPackages/com.nimin.lowlevel/Runtime/UnsafeDataContainer.cs index 0012686..6d6ad98 100644 --- a/LocalPackages/com.nimin.lowlevel/Runtime/UnsafeDataContainer.cs +++ b/LocalPackages/com.nimin.lowlevel/Runtime/UnsafeDataContainer.cs @@ -43,6 +43,12 @@ namespace GameCore.LowLevel m_Buffer.Dispose(); } + public bool HasValue(int index) + { + var node = m_Buffer[index * m_NodeNumPerElement]; + return node.next < 0; + } + public bool Free(int index) { ref var node = ref m_Buffer.ElementAt(index * m_NodeNumPerElement); @@ -83,7 +89,7 @@ namespace GameCore.LowLevel { ref var node = ref m_Buffer.ElementAt(index * m_NodeNumPerElement); if (node.next >= 0) - throw new IndexOutOfRangeException(); + throw new Exception("Index out of range"); return ref UnsafeUtility.As(ref m_Buffer.ElementAt(index * m_NodeNumPerElement + 1)); } diff --git a/LocalPackages/com.nimin.network/Runtime/ClientAgent.cs b/LocalPackages/com.nimin.network/Runtime/ClientAgent.cs new file mode 100644 index 0000000..536251d --- /dev/null +++ b/LocalPackages/com.nimin.network/Runtime/ClientAgent.cs @@ -0,0 +1,12 @@ +using System; + +namespace GameCore.Network +{ + public struct ClientAgent : IDisposable + { + public void Dispose() + { + + } + } +} \ No newline at end of file diff --git a/LocalPackages/com.nimin.network/Runtime/ClientAgent.cs.meta b/LocalPackages/com.nimin.network/Runtime/ClientAgent.cs.meta new file mode 100644 index 0000000..5f44b1e --- /dev/null +++ b/LocalPackages/com.nimin.network/Runtime/ClientAgent.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6e15dc0c921b45ec98b8428a748fee1e +timeCreated: 1767301633 \ No newline at end of file diff --git a/LocalPackages/com.nimin.network/Runtime/NetDatabase.cs b/LocalPackages/com.nimin.network/Runtime/NetDatabase.cs index d87d91f..05c06cf 100644 --- a/LocalPackages/com.nimin.network/Runtime/NetDatabase.cs +++ b/LocalPackages/com.nimin.network/Runtime/NetDatabase.cs @@ -16,10 +16,10 @@ namespace GameCore.Network public ushort historyOffset; public ushort historyCount; public int parentIndex; - public int childrenIndex; } private NativeDataContainer entries; + private NativeHashMap> childrenIndexMap; private NativeArray dataContainers; private NativeList frameHistoryList; @@ -30,6 +30,7 @@ namespace GameCore.Network AllocatorManager.AllocatorHandle allocator) { entries = new(allocator); + childrenIndexMap = new(8, allocator); var typeCount = typeMetaDatabase.GetTotalTypeCount(); dataContainers = new NativeArray(typeCount, allocator.ToAllocator); @@ -50,7 +51,13 @@ namespace GameCore.Network public void Dispose() { entries.Dispose(); - + + foreach (var kvp in childrenIndexMap) + { + kvp.Value.Dispose(); + } + childrenIndexMap.Dispose(); + var typeCount = dataContainers.Length; for (var i = 0; i < typeCount; i++) { @@ -66,23 +73,7 @@ namespace GameCore.Network { var typeIndex = typeMetaDatabase.TypeIndexOf(); - var childrenIndex = 0; generation = 0; - // if (parentIndex > 0) - // { - // if (parentIndex >= entryList.Length) - // return 0; - // - // ref var parentEntry = ref entryList.ElementAt(parentIndex); - // if (parentEntry.childrenIndex > 0) - // { - // childrenIndex = parentEntry.childrenIndex; - // } - // else - // { - // //TODO - // } - // } var entryIndex = entries.Alloc(UnsafeDataContainer.AllocOptions.ClearNew); ref var entry = ref entries.ElementAt(entryIndex); @@ -94,9 +85,17 @@ namespace GameCore.Network var dataIndex = dataContainer.Alloc(); entry.dataIndex = dataIndex; dataContainer.ElementAt(dataIndex) = data; - - //TODO - //entry.parentIndex = parentIndex; + + entry.parentIndex = parentIndex; + if (parentIndex > 0) + { + if (!childrenIndexMap.TryGetValue(parentIndex, out var list)) + { + list = new UnsafeList(4, allocator); + } + list.Add(entryIndex); + childrenIndexMap[parentIndex] = list; + } entry.historyOffset = 0; var fieldSizeArray = typeMetaDatabase.GetFieldSizeArray(typeIndex); @@ -164,16 +163,43 @@ namespace GameCore.Network public bool Remove(int index) { - if (!entries.Free(index)) + return RemoveInternal(index, true); + } + + private bool RemoveInternal(int index, bool removeFromParent) + { + if (!entries.HasValue(index)) return false; ref var entry = ref entries.ElementAt(index); - ref var dataContainer = ref dataContainers.GetRef(entry.dataIndex); + ref var dataContainer = ref dataContainers.GetRef(entry.typeIndex); if (!dataContainer.Free(entry.dataIndex)) throw new Exception("Data mismatch"); - //TODO - + if (entry.parentIndex > 0) + { + if (removeFromParent && childrenIndexMap.TryGetValue(entry.parentIndex, out var list)) + { + var i = list.IndexOf(index); + list.RemoveAtSwapBack(i); + childrenIndexMap[entry.parentIndex] = list; + } + } + + { + if (childrenIndexMap.TryGetValue(index, out var list)) + { + for (int i = 0, len = list.Length; i < len; ++i) + { + RemoveInternal(list[i], false); + } + + list.Dispose(); + childrenIndexMap.Remove(index); + } + } + + entries.Free(index); return true; } diff --git a/LocalPackages/com.nimin.network/Runtime/Test/TestNetDatabase.cs b/LocalPackages/com.nimin.network/Runtime/Test/TestNetDatabase.cs index ccb907d..709e7b8 100644 --- a/LocalPackages/com.nimin.network/Runtime/Test/TestNetDatabase.cs +++ b/LocalPackages/com.nimin.network/Runtime/Test/TestNetDatabase.cs @@ -60,7 +60,7 @@ namespace GameCore.Network.Test Debug.Log($"Troop {troopIndex} added, generation {gen0}"); var soldier = new Soldier() {id = 1, coord = new int2(1, 1)}; - var soldierIndex = netDatabase.Add(soldier, frameId, 0, out var gen1, typeMetaDatabase); + var soldierIndex = netDatabase.Add(soldier, frameId, troopIndex, out var gen1, typeMetaDatabase); Debug.Log($"Soldier {soldierIndex} added, generation {gen1}"); ref readonly var soldierData = ref netDatabase.Get(soldierIndex, typeMetaDatabase); @@ -68,6 +68,12 @@ namespace GameCore.Network.Test soldier.coord = new int2(2, 2); var ok = netDatabase.Update(soldierIndex, soldier, frameId, typeMetaDatabase); Debug.Log($"Soldier update: {ok}, id: {soldierData.id}, coord: {soldierData.coord}"); + + ok = netDatabase.Remove(troopIndex); + Debug.Log($"Troop removed: {ok}"); + + ok = netDatabase.Remove(soldierIndex); + Debug.Log($"Solider removed: {ok}"); } } }