refactor: extract shared ChunkMath.FloorDiv helper

This commit is contained in:
2026-06-01 10:45:58 +02:00
parent 2afeee50d5
commit 39375b83ea
3 changed files with 28 additions and 34 deletions

13
Core/ChunkMath.cs Normal file
View File

@@ -0,0 +1,13 @@
namespace VoxelEngine.Core;
internal static class ChunkMath
{
// Floor division: floors toward negative infinity (not toward zero like C#'s /).
// Required for correct world-coord -> chunk-index mapping for negative coordinates.
internal static int FloorDiv(int value, int size)
{
int q = value / size;
if (value % size != 0 && value < 0) q--;
return q;
}
}

View File

@@ -20,9 +20,9 @@ public sealed class Player
{ {
Vector3 p = this.Position; Vector3 p = this.Position;
return new Vector3i( return new Vector3i(
Player.FloorDiv((int)MathF.Floor(p.X), VoxelChunk.Size), ChunkMath.FloorDiv((int)MathF.Floor(p.X), VoxelChunk.Size),
Player.FloorDiv((int)MathF.Floor(p.Y), VoxelChunk.Size), ChunkMath.FloorDiv((int)MathF.Floor(p.Y), VoxelChunk.Size),
Player.FloorDiv((int)MathF.Floor(p.Z), VoxelChunk.Size)); ChunkMath.FloorDiv((int)MathF.Floor(p.Z), VoxelChunk.Size));
} }
} }
@@ -35,11 +35,4 @@ public sealed class Player
public void Move(Vector3 delta) => this.Camera.Move(delta); public void Move(Vector3 delta) => this.Camera.Move(delta);
public void AddRotation(float yawDelta, float pitchDelta) => this.Camera.AddRotation(yawDelta, pitchDelta); public void AddRotation(float yawDelta, float pitchDelta) => this.Camera.AddRotation(yawDelta, pitchDelta);
private static int FloorDiv(int value, int size)
{
int q = value / size;
if (value % size != 0 && value < 0) q--;
return q;
}
} }

View File

@@ -1,22 +1,17 @@
using System.Collections; using System.Collections;
using OpenTK.Mathematics; using OpenTK.Mathematics;
using VoxelEngine.Core;
using VoxelEngine.World.Blocks; using VoxelEngine.World.Blocks;
using VoxelEngine.World.Persistence; using VoxelEngine.World.Persistence;
namespace VoxelEngine.World; namespace VoxelEngine.World;
public sealed class World : IWorld, IEnumerable<KeyValuePair<Vector3i, Chunk.Chunk>> public sealed class World(BlockRegistry registry, IChunkModificationStore modStore)
: IWorld, IEnumerable<KeyValuePair<Vector3i, Chunk.Chunk>>
{ {
private readonly Dictionary<Vector3i, Chunk.Chunk> _chunks = new(); private readonly Dictionary<Vector3i, Chunk.Chunk> _chunks = new();
private readonly BlockRegistry _registry;
public IChunkModificationStore ModificationStore { get; } public IChunkModificationStore ModificationStore { get; } = modStore;
public World(BlockRegistry registry, IChunkModificationStore modStore)
{
this._registry = registry;
this.ModificationStore = modStore;
}
public void SetChunk(Vector3i chunkPos, Chunk.Chunk chunk) => this._chunks[chunkPos] = chunk; public void SetChunk(Vector3i chunkPos, Chunk.Chunk chunk) => this._chunks[chunkPos] = chunk;
@@ -27,25 +22,25 @@ public sealed class World : IWorld, IEnumerable<KeyValuePair<Vector3i, Chunk.Chu
public IBlock GetBlock(int worldX, int worldY, int worldZ) public IBlock GetBlock(int worldX, int worldY, int worldZ)
{ {
Vector3i chunkPos = new( Vector3i chunkPos = new(
World.FloorDiv(worldX, Chunk.Chunk.Size), ChunkMath.FloorDiv(worldX, Chunk.Chunk.Size),
World.FloorDiv(worldY, Chunk.Chunk.Size), ChunkMath.FloorDiv(worldY, Chunk.Chunk.Size),
World.FloorDiv(worldZ, Chunk.Chunk.Size)); ChunkMath.FloorDiv(worldZ, Chunk.Chunk.Size));
Chunk.Chunk? chunk = this.GetChunk(chunkPos); Chunk.Chunk? chunk = this.GetChunk(chunkPos);
if (chunk == null) return this._registry.Air; if (chunk == null) return registry.Air;
int localX = worldX - chunkPos.X * Chunk.Chunk.Size; int localX = worldX - chunkPos.X * Chunk.Chunk.Size;
int localY = worldY - chunkPos.Y * Chunk.Chunk.Size; int localY = worldY - chunkPos.Y * Chunk.Chunk.Size;
int localZ = worldZ - chunkPos.Z * Chunk.Chunk.Size; int localZ = worldZ - chunkPos.Z * Chunk.Chunk.Size;
return this._registry.Get(chunk[localX, localY, localZ]); return registry.Get(chunk[localX, localY, localZ]);
} }
public bool SetBlock(int worldX, int worldY, int worldZ, ushort blockId) public bool SetBlock(int worldX, int worldY, int worldZ, ushort blockId)
{ {
Vector3i chunkPos = new( Vector3i chunkPos = new(
World.FloorDiv(worldX, Chunk.Chunk.Size), ChunkMath.FloorDiv(worldX, Chunk.Chunk.Size),
World.FloorDiv(worldY, Chunk.Chunk.Size), ChunkMath.FloorDiv(worldY, Chunk.Chunk.Size),
World.FloorDiv(worldZ, Chunk.Chunk.Size)); ChunkMath.FloorDiv(worldZ, Chunk.Chunk.Size));
Chunk.Chunk? chunk = this.GetChunk(chunkPos); Chunk.Chunk? chunk = this.GetChunk(chunkPos);
@@ -65,13 +60,6 @@ public sealed class World : IWorld, IEnumerable<KeyValuePair<Vector3i, Chunk.Chu
return true; return true;
} }
private static int FloorDiv(int value, int size)
{
int q = value / size;
if (value % size != 0 && value < 0) q--;
return q;
}
public IEnumerator<KeyValuePair<Vector3i, Chunk.Chunk>> GetEnumerator() => this._chunks.GetEnumerator(); public IEnumerator<KeyValuePair<Vector3i, Chunk.Chunk>> GetEnumerator() => this._chunks.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();