using OpenTK.Mathematics; using VoxelEngine.World; using VoxelEngine.World.Blocks; using VoxelEngine.World.Persistence; using Xunit; using VoxelChunk = VoxelEngine.World.Chunk.Chunk; namespace VoxelEngine.Tests; public class WorldTests { private static (IWorld, BlockRegistry, IChunkModificationStore) Create() { var registry = new BlockRegistry(); var store = new InMemoryChunkModificationStore(); IWorld world = new World.World(registry, store); return (world, registry, store); } [Fact] public void SetBlock_LoadedChunk_WritesBlockAndRecordsDiff() { var (world, registry, store) = Create(); var chunkPos = new Vector3i(0, 0, 0); world.SetChunk(chunkPos, new VoxelChunk()); bool result = world.SetBlock(2, 3, 4, registry.Stone.Id); Assert.True(result); Assert.Equal(registry.Stone.Id, world.GetBlock(2, 3, 4).Id); Assert.True(store.HasDiff(chunkPos)); Assert.True(store.TryGetDiff(chunkPos, out var diff)); int expectedIndex = (2 * VoxelChunk.Size + 3) * VoxelChunk.Size + 4; Assert.Equal(registry.Stone.Id, diff![expectedIndex]); } [Fact] public void SetBlock_UnloadedChunk_RecordsDiffButReturnsFalse() { var (world, registry, store) = Create(); var chunkPos = new Vector3i(5, 0, 0); bool result = world.SetBlock(5 * VoxelChunk.Size, 0, 0, registry.Stone.Id); Assert.False(result); Assert.True(store.HasDiff(chunkPos)); } [Fact] public void GetBlock_UnloadedChunk_ReturnsAir() { var (world, registry, _) = Create(); Assert.Same(registry.Air, world.GetBlock(0, 0, 0)); } [Fact] public void SetBlock_NegativeCoords_FloorsToCorrectChunk() { var (world, registry, store) = Create(); var chunkPos = new Vector3i(-1, 0, 0); world.SetChunk(chunkPos, new VoxelChunk()); bool result = world.SetBlock(-1, 0, 0, registry.Stone.Id); Assert.True(result); Assert.Equal(registry.Stone.Id, world.GetBlock(-1, 0, 0).Id); Assert.True(store.HasDiff(chunkPos)); } [Fact] public void RemoveChunk_RemovesAndGetBlockReturnsAir() { var (world, registry, _) = Create(); var chunkPos = new Vector3i(0, 0, 0); world.SetChunk(chunkPos, new VoxelChunk()); world.RemoveChunk(chunkPos); Assert.Null(world.GetChunk(chunkPos)); Assert.Same(registry.Air, world.GetBlock(0, 0, 0)); } [Fact] public void ModificationStore_AccessorReturnsConstructorInjectedStore() { var (world, _, store) = Create(); Assert.Same(store, world.ModificationStore); } }