完善snapshot
This commit is contained in:
1 parent
5cf62f91cd
commit
af72792875
6 files changed
+181
-38
No files matched your search
@@ -9,6 +9,8 @@ namespace GameCore.LowLevel
|
||||
[NativeDisableUnsafePtrRestriction]
|
||||
internal UnsafeDataContainer* m_UnsafeDataPtr;
|
||||
internal AllocatorManager.AllocatorHandle m_Allocator;
|
||||
|
||||
public int Length => m_UnsafeDataPtr->Length;
|
||||
|
||||
public bool IsCreated => m_UnsafeDataPtr != null;
|
||||
|
||||
@@ -56,5 +58,10 @@ namespace GameCore.LowLevel
|
||||
{
|
||||
m_UnsafeDataPtr->Clear();
|
||||
}
|
||||
|
||||
public void CopyFrom(NativeDataContainer<T> other)
|
||||
{
|
||||
m_UnsafeDataPtr->CopyFrom(*other.m_UnsafeDataPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
using Unity.Collections;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Assertions;
|
||||
|
||||
namespace GameCore.LowLevel
|
||||
{
|
||||
@@ -19,21 +20,23 @@ namespace GameCore.LowLevel
|
||||
ClearNew = 1,
|
||||
ClearAll = 2,
|
||||
}
|
||||
|
||||
|
||||
public readonly int elementSize;
|
||||
private UnsafeList<FreeNode> m_Buffer;
|
||||
private readonly int m_NodeNumPerElement;
|
||||
|
||||
public int Length => m_Buffer.Length;
|
||||
|
||||
public bool IsCreated => m_Buffer.IsCreated;
|
||||
|
||||
|
||||
public UnsafeDataContainer(int elementSize, AllocatorManager.AllocatorHandle allocator)
|
||||
{
|
||||
if (elementSize <= 0)
|
||||
throw new ArgumentException(nameof(elementSize));
|
||||
|
||||
|
||||
this.elementSize = elementSize;
|
||||
m_NodeNumPerElement = ComputeNodeNumPerElement(elementSize);
|
||||
|
||||
|
||||
m_Buffer = new UnsafeList<FreeNode>(0, allocator);
|
||||
m_Buffer.Resize(m_NodeNumPerElement, NativeArrayOptions.ClearMemory);
|
||||
}
|
||||
@@ -54,7 +57,7 @@ namespace GameCore.LowLevel
|
||||
ref var node = ref m_Buffer.ElementAt(index * m_NodeNumPerElement);
|
||||
if (node.next >= 0)
|
||||
return false;
|
||||
|
||||
|
||||
ref var head = ref m_Buffer.ElementAt(0);
|
||||
node.next = head.next;
|
||||
head.next = index;
|
||||
@@ -68,11 +71,14 @@ namespace GameCore.LowLevel
|
||||
if (index == 0)
|
||||
{
|
||||
index = m_Buffer.Length / m_NodeNumPerElement;
|
||||
m_Buffer.Resize(m_Buffer.Length + m_NodeNumPerElement, options == AllocOptions.None ? NativeArrayOptions.UninitializedMemory : NativeArrayOptions.ClearMemory);
|
||||
m_Buffer.Resize(m_Buffer.Length + m_NodeNumPerElement,
|
||||
options == AllocOptions.None
|
||||
? NativeArrayOptions.UninitializedMemory
|
||||
: NativeArrayOptions.ClearMemory);
|
||||
m_Buffer.ElementAt(index * m_NodeNumPerElement).next = -1;
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
ref var node = ref m_Buffer.ElementAt(index * m_NodeNumPerElement);
|
||||
if (options == AllocOptions.ClearAll)
|
||||
{
|
||||
@@ -89,8 +95,8 @@ namespace GameCore.LowLevel
|
||||
{
|
||||
ref var node = ref m_Buffer.ElementAt(index * m_NodeNumPerElement);
|
||||
if (node.next >= 0)
|
||||
throw new Exception("Index out of range");
|
||||
|
||||
throw new IndexOutOfRangeException();
|
||||
|
||||
return ref UnsafeUtility.As<FreeNode, T>(ref m_Buffer.ElementAt(index * m_NodeNumPerElement + 1));
|
||||
}
|
||||
|
||||
@@ -100,6 +106,16 @@ namespace GameCore.LowLevel
|
||||
m_Buffer.ElementAt(0).next = 0;
|
||||
}
|
||||
|
||||
public void CopyFrom(UnsafeDataContainer other)
|
||||
{
|
||||
if (elementSize != other.elementSize)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
m_Buffer.CopyFrom(other.m_Buffer);
|
||||
}
|
||||
|
||||
internal static int ComputeNodeNumPerElement(int elementSize)
|
||||
{
|
||||
return (elementSize + UnsafeUtility.SizeOf<FreeNode>() - 1) / UnsafeUtility.SizeOf<FreeNode>() + 1;
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
using System;
|
||||
using Unity.Collections;
|
||||
|
||||
namespace GameCore.Network
|
||||
{
|
||||
public struct ClientAgent : IDisposable
|
||||
{
|
||||
private NativeList<int> dirtySet;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
public void UpdateDirtySet(NetDatabase.Snapshot netDatabase, int frameId)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -1,14 +1,100 @@
|
||||
using System;
|
||||
using GameCore.LowLevel;
|
||||
using Unity.Collections;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
|
||||
namespace GameCore.Network
|
||||
{
|
||||
public partial struct NetDatabase
|
||||
{
|
||||
public readonly struct Snapshot : IDisposable
|
||||
public struct Snapshot : IDisposable
|
||||
{
|
||||
private NativeDataContainer<Entry> entries;
|
||||
private NativeArray<UnsafeDataContainer> dataContainers;
|
||||
private NativeList<FrameHistoryItem> frameHistoryList;
|
||||
private NativeList<UnsafeList<int>> childrenList;
|
||||
|
||||
private readonly int maxHistoryCount;
|
||||
|
||||
public Snapshot(TypeMetaDatabase typeMetaDatabase, int maxHistoryCount,
|
||||
AllocatorManager.AllocatorHandle allocator)
|
||||
{
|
||||
entries = new(allocator);
|
||||
|
||||
var typeCount = typeMetaDatabase.GetTotalTypeCount();
|
||||
dataContainers = new NativeArray<UnsafeDataContainer>(typeCount, allocator.ToAllocator);
|
||||
for (var i = 0; i < typeCount; i++)
|
||||
{
|
||||
if (typeMetaDatabase.IsValid(i))
|
||||
{
|
||||
dataContainers[i] = new UnsafeDataContainer(typeMetaDatabase.GetTypeSize(i), allocator);
|
||||
}
|
||||
}
|
||||
|
||||
frameHistoryList = new NativeList<FrameHistoryItem>(allocator);
|
||||
|
||||
childrenList = new NativeList<UnsafeList<int>>(allocator);
|
||||
|
||||
this.maxHistoryCount = maxHistoryCount;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
entries.Dispose();
|
||||
|
||||
var typeCount = dataContainers.Length;
|
||||
for (var i = 0; i < typeCount; i++)
|
||||
{
|
||||
if (dataContainers[i].IsCreated)
|
||||
dataContainers[i].Dispose();
|
||||
}
|
||||
dataContainers.Dispose();
|
||||
frameHistoryList.Dispose();
|
||||
|
||||
for (int i = 0, len = childrenList.Length; i < len; i++)
|
||||
{
|
||||
childrenList[i].Dispose();
|
||||
}
|
||||
childrenList.Dispose();
|
||||
}
|
||||
|
||||
public void GatherNetDataIndex(NativeList<int> list)
|
||||
{
|
||||
for (int i = 1, len = entries.Length; i < len; ++i)
|
||||
{
|
||||
if (entries.HasValue(i))
|
||||
list.Add(i);
|
||||
}
|
||||
}
|
||||
|
||||
public void CopyFrom(NetDatabase database)
|
||||
{
|
||||
entries.CopyFrom(database.entries);
|
||||
|
||||
var typeCount = dataContainers.Length;
|
||||
for (var i = 0; i < typeCount; i++)
|
||||
{
|
||||
ref var dataContainer = ref dataContainers.GetRef(i);
|
||||
if (dataContainer.IsCreated)
|
||||
dataContainer.CopyFrom(database.dataContainers[i]);
|
||||
}
|
||||
|
||||
frameHistoryList.CopyFrom(database.frameHistoryList);
|
||||
|
||||
var newLength = database.childrenList.Length;
|
||||
var oldLength = childrenList.Length;
|
||||
if (oldLength < newLength)
|
||||
{
|
||||
childrenList.Resize(newLength, NativeArrayOptions.UninitializedMemory);
|
||||
for (var i = oldLength; i < newLength; ++i)
|
||||
{
|
||||
childrenList.ElementAt(i) = new UnsafeList<int>(0, database.allocator);
|
||||
}
|
||||
}
|
||||
for (int i = 0, len = database.childrenList.Length; i < len; ++i)
|
||||
{
|
||||
childrenList.ElementAt(i).CopyFrom(database.childrenList[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,12 +16,14 @@ namespace GameCore.Network
|
||||
public ushort historyOffset;
|
||||
public ushort historyCount;
|
||||
public int parentIndex;
|
||||
public int childrenListIndex;
|
||||
}
|
||||
|
||||
private NativeDataContainer<Entry> entries;
|
||||
private NativeHashMap<int, UnsafeList<int>> childrenIndexMap;
|
||||
private NativeArray<UnsafeDataContainer> dataContainers;
|
||||
private NativeList<FrameHistoryItem> frameHistoryList;
|
||||
private NativeList<UnsafeList<int>> childrenList;
|
||||
private NativeList<int> freeChildrenListIndexStack;
|
||||
|
||||
private readonly int maxHistoryCount;
|
||||
private readonly AllocatorManager.AllocatorHandle allocator;
|
||||
@@ -30,7 +32,6 @@ namespace GameCore.Network
|
||||
AllocatorManager.AllocatorHandle allocator)
|
||||
{
|
||||
entries = new(allocator);
|
||||
childrenIndexMap = new(8, allocator);
|
||||
|
||||
var typeCount = typeMetaDatabase.GetTotalTypeCount();
|
||||
dataContainers = new NativeArray<UnsafeDataContainer>(typeCount, allocator.ToAllocator);
|
||||
@@ -44,6 +45,9 @@ namespace GameCore.Network
|
||||
|
||||
frameHistoryList = new NativeList<FrameHistoryItem>(allocator);
|
||||
|
||||
childrenList = new NativeList<UnsafeList<int>>(allocator) {default};
|
||||
freeChildrenListIndexStack = new NativeList<int>(allocator);
|
||||
|
||||
this.maxHistoryCount = maxHistoryCount;
|
||||
this.allocator = allocator;
|
||||
}
|
||||
@@ -52,20 +56,22 @@ namespace GameCore.Network
|
||||
{
|
||||
entries.Dispose();
|
||||
|
||||
foreach (var kvp in childrenIndexMap)
|
||||
{
|
||||
kvp.Value.Dispose();
|
||||
}
|
||||
childrenIndexMap.Dispose();
|
||||
|
||||
var typeCount = dataContainers.Length;
|
||||
for (var i = 0; i < typeCount; i++)
|
||||
{
|
||||
if (dataContainers[i].IsCreated)
|
||||
dataContainers[i].Dispose();
|
||||
}
|
||||
|
||||
dataContainers.Dispose();
|
||||
frameHistoryList.Dispose();
|
||||
|
||||
for (int i = 0, len = childrenList.Length; i < len; i++)
|
||||
{
|
||||
childrenList[i].Dispose();
|
||||
}
|
||||
childrenList.Dispose();
|
||||
freeChildrenListIndexStack.Dispose();
|
||||
}
|
||||
|
||||
public int Add<T>(T data, int frameId, int parentIndex, out int generation,
|
||||
@@ -87,14 +93,26 @@ namespace GameCore.Network
|
||||
dataContainer.ElementAt<T>(dataIndex) = data;
|
||||
|
||||
entry.parentIndex = parentIndex;
|
||||
entry.childrenListIndex = 0;
|
||||
if (parentIndex > 0)
|
||||
{
|
||||
if (!childrenIndexMap.TryGetValue(parentIndex, out var list))
|
||||
ref var parentEntry = ref entries.ElementAt(parentIndex);
|
||||
if (parentEntry.childrenListIndex == 0)
|
||||
{
|
||||
list = new UnsafeList<int>(4, allocator);
|
||||
if (freeChildrenListIndexStack.Length > 0)
|
||||
{
|
||||
parentEntry.childrenListIndex = freeChildrenListIndexStack[^1];
|
||||
freeChildrenListIndexStack.RemoveAt(freeChildrenListIndexStack.Length - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
parentEntry.childrenListIndex = childrenList.Length;
|
||||
childrenList.Add(new UnsafeList<int>(4, allocator));
|
||||
}
|
||||
}
|
||||
|
||||
ref var list = ref childrenList.ElementAt(parentEntry.childrenListIndex);
|
||||
list.Add(entryIndex);
|
||||
childrenIndexMap[parentIndex] = list;
|
||||
}
|
||||
|
||||
entry.historyOffset = 0;
|
||||
@@ -178,25 +196,26 @@ namespace GameCore.Network
|
||||
|
||||
if (entry.parentIndex > 0)
|
||||
{
|
||||
if (removeFromParent && childrenIndexMap.TryGetValue(entry.parentIndex, out var list))
|
||||
if (removeFromParent)
|
||||
{
|
||||
var i = list.IndexOf(index);
|
||||
list.RemoveAtSwapBack(i);
|
||||
childrenIndexMap[entry.parentIndex] = list;
|
||||
var parentEntry = entries.ElementAt(entry.parentIndex);
|
||||
ref var list = ref childrenList.ElementAt(parentEntry.childrenListIndex);
|
||||
|
||||
var selfIndex = list.IndexOf(index);
|
||||
list.RemoveAtSwapBack(selfIndex);
|
||||
}
|
||||
}
|
||||
|
||||
if (entry.childrenListIndex > 0)
|
||||
{
|
||||
if (childrenIndexMap.TryGetValue(index, out var list))
|
||||
ref var list = ref childrenList.ElementAt(entry.childrenListIndex);
|
||||
for (int i = 0, len = list.Length; i < len; ++i)
|
||||
{
|
||||
for (int i = 0, len = list.Length; i < len; ++i)
|
||||
{
|
||||
RemoveInternal(list[i], false);
|
||||
}
|
||||
|
||||
list.Dispose();
|
||||
childrenIndexMap.Remove(index);
|
||||
RemoveInternal(list[i], false);
|
||||
}
|
||||
|
||||
list.Clear();
|
||||
freeChildrenListIndexStack.Add(entry.childrenListIndex);
|
||||
}
|
||||
|
||||
entries.Free(index);
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace GameCore.Network.Test
|
||||
|
||||
private TypeMetaDatabase typeMetaDatabase;
|
||||
private NetDatabase netDatabase;
|
||||
private NetDatabase.Snapshot snapshot;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
@@ -30,11 +31,13 @@ namespace GameCore.Network.Test
|
||||
typeMetaDatabase.RegisterType<Soldier>();
|
||||
|
||||
netDatabase = new NetDatabase(typeMetaDatabase, 16, Allocator.Persistent);
|
||||
snapshot = new NetDatabase.Snapshot(typeMetaDatabase, 16, Allocator.Persistent);
|
||||
|
||||
var handle = new UpdateJob()
|
||||
{
|
||||
typeMetaDatabase = typeMetaDatabase,
|
||||
netDatabase = netDatabase,
|
||||
snapshot = snapshot,
|
||||
frameId = 1,
|
||||
}.Schedule();
|
||||
handle.Complete();
|
||||
@@ -44,6 +47,7 @@ namespace GameCore.Network.Test
|
||||
{
|
||||
typeMetaDatabase.Dispose();
|
||||
netDatabase.Dispose();
|
||||
snapshot.Dispose();
|
||||
}
|
||||
|
||||
[BurstCompile]
|
||||
@@ -51,6 +55,7 @@ namespace GameCore.Network.Test
|
||||
{
|
||||
public TypeMetaDatabase typeMetaDatabase;
|
||||
public NetDatabase netDatabase;
|
||||
public NetDatabase.Snapshot snapshot;
|
||||
public int frameId;
|
||||
|
||||
public void Execute()
|
||||
@@ -69,11 +74,13 @@ namespace GameCore.Network.Test
|
||||
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}");
|
||||
// ok = netDatabase.Remove(troopIndex);
|
||||
// Debug.Log($"Troop removed: {ok}");
|
||||
//
|
||||
// ok = netDatabase.Remove(soldierIndex);
|
||||
// Debug.Log($"Solider removed: {ok}");
|
||||
|
||||
snapshot.CopyFrom(netDatabase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user