85 lines
2.9 KiB
C#
85 lines
2.9 KiB
C#
using OpenTK.Mathematics;
|
|
using VoxelEngine.Core;
|
|
using VoxelEngine.World;
|
|
using VoxelEngine.World.Blocks;
|
|
using VoxelEngine.World.Chunk;
|
|
using VoxelEngine.World.Persistence;
|
|
using VoxelEngine.World.Streaming;
|
|
using VoxelEngine.World.WorldGen;
|
|
using Xunit;
|
|
|
|
namespace VoxelEngine.Tests.Streaming;
|
|
|
|
public class StreamingIntegrationTests
|
|
{
|
|
private static (ChunkStreamer streamer, World.World world, InMemoryChunkModificationStore store)
|
|
BuildRealStack(Configuration cfg)
|
|
{
|
|
var registry = new BlockRegistry();
|
|
var store = new InMemoryChunkModificationStore();
|
|
var world = new World.World(registry, store);
|
|
var gen = new WorldGenerator(seed: 1337, blocks: registry, cfg: new Configuration());
|
|
var mesher = new ChunkMesher(atlasWidthPixels: 128, atlasHeightPixels: 32);
|
|
var executor = new SynchronousJobExecutor();
|
|
Func<float[], IChunkRenderer> factory = m => new FakeRenderer(m);
|
|
var streamer = new ChunkStreamer(cfg, world, gen.Generate, gen.SurfaceHeightAt, mesher, registry, executor, factory);
|
|
return (streamer, world, store);
|
|
}
|
|
|
|
[Fact]
|
|
public void PlayerWalksAcrossWorld_LoadBoxFollowsPlayer()
|
|
{
|
|
var cfg = new Configuration
|
|
{
|
|
RenderDistanceHorizontal = 1,
|
|
RenderDistanceVertical = 0,
|
|
MaxGenerateJobsInFlight = 100,
|
|
MaxMeshUploadsPerFrame = 100,
|
|
};
|
|
var (streamer, world, _) = BuildRealStack(cfg);
|
|
|
|
for (int step = 0; step < 5; step++)
|
|
{
|
|
streamer.Tick(new Vector3i(step, 0, 0));
|
|
|
|
for (int dx = -1; dx <= 1; dx++)
|
|
for (int dz = -1; dz <= 1; dz++)
|
|
{
|
|
var pos = new Vector3i(step + dx, 0, dz);
|
|
Assert.NotNull(world.GetChunk(pos));
|
|
Assert.True(streamer.IsReady(pos));
|
|
}
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void ModificationStore_SurvivesUnloadReload()
|
|
{
|
|
var cfg = new Configuration
|
|
{
|
|
RenderDistanceHorizontal = 0,
|
|
RenderDistanceVertical = 0,
|
|
MaxGenerateJobsInFlight = 100,
|
|
MaxMeshUploadsPerFrame = 100,
|
|
};
|
|
var (streamer, world, store) = BuildRealStack(cfg);
|
|
|
|
// Use a block id that differs from what WorldGenerator places at
|
|
// world (0,0,0). At y=0 every biome's "Under" block is Stone (id 1),
|
|
// so SetBlock(..., Stone) would hit World.SetBlock's no-op guard and
|
|
// skip the diff record. Dirt (id 2) is always a real change.
|
|
var pos = new Vector3i(0, 0, 0);
|
|
streamer.Tick(pos);
|
|
Assert.True(streamer.IsReady(pos));
|
|
Assert.True(world.SetBlock(0, 0, 0, /*Dirt*/ (ushort)2));
|
|
|
|
streamer.Tick(new Vector3i(50, 0, 0));
|
|
Assert.Null(world.GetChunk(pos));
|
|
Assert.True(store.HasDiff(pos));
|
|
|
|
streamer.Tick(pos);
|
|
Assert.NotNull(world.GetChunk(pos));
|
|
Assert.Equal((ushort)2, world.GetBlock(0, 0, 0).Id);
|
|
}
|
|
}
|