feat: add IChunkModificationStore and in-memory implementation
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
using OpenTK.Mathematics;
|
||||
using VoxelEngine.World.Persistence;
|
||||
using Xunit;
|
||||
|
||||
namespace VoxelEngine.Tests.Persistence;
|
||||
|
||||
public class InMemoryChunkModificationStoreTests
|
||||
{
|
||||
[Fact]
|
||||
public void NewStore_HasNoDiffs()
|
||||
{
|
||||
var s = new InMemoryChunkModificationStore();
|
||||
Assert.False(s.HasDiff(new Vector3i(0, 0, 0)));
|
||||
Assert.False(s.TryGetDiff(new Vector3i(0, 0, 0), out _));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RecordEdit_StoresAndIsRetrievable()
|
||||
{
|
||||
var s = new InMemoryChunkModificationStore();
|
||||
Vector3i pos = new(1, 2, 3);
|
||||
s.RecordEdit(pos, 42, 7);
|
||||
|
||||
Assert.True(s.HasDiff(pos));
|
||||
Assert.True(s.TryGetDiff(pos, out var diff));
|
||||
Assert.Single(diff!);
|
||||
Assert.Equal((ushort)7, diff![42]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RecordEdit_OverwritesSameLocalIndex()
|
||||
{
|
||||
var s = new InMemoryChunkModificationStore();
|
||||
Vector3i pos = new(0, 0, 0);
|
||||
s.RecordEdit(pos, 10, 1);
|
||||
s.RecordEdit(pos, 10, 2);
|
||||
|
||||
Assert.True(s.TryGetDiff(pos, out var diff));
|
||||
Assert.Single(diff!);
|
||||
Assert.Equal((ushort)2, diff![10]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RecordEdit_MultipleChunks_AreIndependent()
|
||||
{
|
||||
var s = new InMemoryChunkModificationStore();
|
||||
s.RecordEdit(new Vector3i(0, 0, 0), 0, 1);
|
||||
s.RecordEdit(new Vector3i(1, 0, 0), 0, 2);
|
||||
|
||||
Assert.True(s.TryGetDiff(new Vector3i(0, 0, 0), out var a));
|
||||
Assert.True(s.TryGetDiff(new Vector3i(1, 0, 0), out var b));
|
||||
Assert.Equal((ushort)1, a![0]);
|
||||
Assert.Equal((ushort)2, b![0]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ClearDiff_RemovesChunk()
|
||||
{
|
||||
var s = new InMemoryChunkModificationStore();
|
||||
Vector3i pos = new(5, 5, 5);
|
||||
s.RecordEdit(pos, 0, 1);
|
||||
s.ClearDiff(pos);
|
||||
Assert.False(s.HasDiff(pos));
|
||||
}
|
||||
}
|
||||
11
World/Persistence/IChunkModificationStore.cs
Normal file
11
World/Persistence/IChunkModificationStore.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace VoxelEngine.World.Persistence;
|
||||
|
||||
public interface IChunkModificationStore
|
||||
{
|
||||
bool TryGetDiff(Vector3i chunkPos, out IReadOnlyDictionary<int, ushort>? diff);
|
||||
void RecordEdit(Vector3i chunkPos, int localIndex, ushort blockId);
|
||||
void ClearDiff(Vector3i chunkPos);
|
||||
bool HasDiff(Vector3i chunkPos);
|
||||
}
|
||||
33
World/Persistence/InMemoryChunkModificationStore.cs
Normal file
33
World/Persistence/InMemoryChunkModificationStore.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace VoxelEngine.World.Persistence;
|
||||
|
||||
public sealed class InMemoryChunkModificationStore : IChunkModificationStore
|
||||
{
|
||||
private readonly Dictionary<Vector3i, Dictionary<int, ushort>> _diffs = new();
|
||||
|
||||
public bool TryGetDiff(Vector3i chunkPos, out IReadOnlyDictionary<int, ushort>? diff)
|
||||
{
|
||||
if (this._diffs.TryGetValue(chunkPos, out Dictionary<int, ushort>? d))
|
||||
{
|
||||
diff = d;
|
||||
return true;
|
||||
}
|
||||
diff = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void RecordEdit(Vector3i chunkPos, int localIndex, ushort blockId)
|
||||
{
|
||||
if (!this._diffs.TryGetValue(chunkPos, out Dictionary<int, ushort>? d))
|
||||
{
|
||||
d = new Dictionary<int, ushort>();
|
||||
this._diffs[chunkPos] = d;
|
||||
}
|
||||
d[localIndex] = blockId;
|
||||
}
|
||||
|
||||
public void ClearDiff(Vector3i chunkPos) => this._diffs.Remove(chunkPos);
|
||||
|
||||
public bool HasDiff(Vector3i chunkPos) => this._diffs.ContainsKey(chunkPos);
|
||||
}
|
||||
Reference in New Issue
Block a user