using System.Collections; using OpenTK.Mathematics; using VoxelEngine.World.Blocks; namespace VoxelEngine.World; public sealed class World : IWorld, IEnumerable> { private readonly Dictionary _chunks = new(); private readonly BlockRegistry _registry; public World(BlockRegistry registry) { this._registry = registry; } public void SetChunk(Vector3i chunkPos, Chunk.Chunk chunk) { this._chunks[chunkPos] = chunk; } public Chunk.Chunk? GetChunk(Vector3i chunkPos) { return this._chunks.GetValueOrDefault(chunkPos); } public IBlock GetBlock(int worldX, int worldY, int worldZ) { Vector3i chunkPos = new( World.FloorDiv(worldX, Chunk.Chunk.Size), World.FloorDiv(worldY, Chunk.Chunk.Size), World.FloorDiv(worldZ, Chunk.Chunk.Size) ); Chunk.Chunk? chunk = this.GetChunk(chunkPos); if (chunk == null) { return this._registry.Air; } int localX = worldX - chunkPos.X * Chunk.Chunk.Size; int localY = worldY - chunkPos.Y * Chunk.Chunk.Size; int localZ = worldZ - chunkPos.Z * Chunk.Chunk.Size; return this._registry.Get(chunk[localX, localY, localZ]); } private static int FloorDiv(int value, int size) { int quotient = value / size; if (value % size != 0 && value < 0) { quotient--; } return quotient; } public IEnumerator> GetEnumerator() => this._chunks.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); }