diff --git a/BlockData.cs b/BlockData.cs index 14109aa..69b4f4a 100644 --- a/BlockData.cs +++ b/BlockData.cs @@ -1,7 +1,12 @@ -namespace Voxel +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Voxel { public class BlockData { - } } diff --git a/Chunk.cs b/Chunk.cs index 33c58c0..fb322f6 100644 --- a/Chunk.cs +++ b/Chunk.cs @@ -10,6 +10,7 @@ private Dictionary _blockData; private Blocks[] _blocks; + public Dictionary Neighbors = new(); public Chunk(int x, int y) { @@ -89,7 +90,7 @@ ( 0, 0, -1) // -Z }; - private void UpdateChunkMesh() + public void UpdateChunkMesh() { List faces = new List(Size * Size * Height / 2); @@ -129,6 +130,21 @@ int ni = GetBlockIndex(nx, ny, nz); if (GetBlockIndex(nx, ny, nz) == -1) { + if (Neighbors.TryGetValue((Orientation)face, out Chunk neighbor) && neighbor != null) + { + int localX = nx; + int localZ = nz; + + if (nx < 0) localX = nx + Size; + if (nx >= Size) localX = nx - Size; + + if (nz < 0) localZ = nz + Size; + if (nz >= Size) localZ = nz - Size; + + Blocks neighborBlock = neighbor.GetBlock(localX, y, localZ); + if (neighborBlock != Blocks.Air) + continue; + } AddFace(); continue; } diff --git a/Player.cs b/Player.cs index 8b67037..ce9851d 100644 --- a/Player.cs +++ b/Player.cs @@ -15,6 +15,8 @@ namespace Voxel private World _world; public double lastClick = 0; public readonly float mouseCooldown = 0.2f; + private int _blockIndex = 0; + private Blocks _selectedBlock = Blocks.Dirt; public Player(World world, Vector3 startPos) { @@ -30,7 +32,7 @@ namespace Voxel y += normal.Y; z += normal.Z; - _world.SetBlock(x, y, z, Blocks.OakPlanks); + _world.SetBlock(x, y, z, _selectedBlock); } public void BreakBlock() @@ -70,5 +72,22 @@ namespace Voxel BreakBlock(); } } + + public void SwitchBlock(bool inverted) + { + var keys = BlockDefinitions.Blocks.Keys.ToList(); + + if (inverted) + if (_blockIndex == 0) + _blockIndex = keys.Count -1; + else + _blockIndex -= 1; + else + _blockIndex += 1; + + _blockIndex = _blockIndex % keys.Count; + _selectedBlock = keys[_blockIndex]; + Console.WriteLine(_selectedBlock); + } } } diff --git a/Window.cs b/Window.cs index f345f63..6a97ddf 100644 --- a/Window.cs +++ b/Window.cs @@ -114,5 +114,17 @@ namespace Voxel base.OnMouseUp(e); Input.SetMouseButton(e.Button, false); } + + protected override void OnMouseWheel(MouseWheelEventArgs e) + { + base.OnMouseWheel(e); + + bool inverted = false; + + if (e.OffsetY < 0) + inverted = true; + + Player.SwitchBlock(inverted); + } } } diff --git a/World.cs b/World.cs index 54ffab4..2c2a166 100644 --- a/World.cs +++ b/World.cs @@ -1,5 +1,6 @@ using OpenTK.Mathematics; using System.Collections.Generic; +using System.Drawing; namespace Voxel { @@ -21,6 +22,22 @@ namespace Voxel public void AddChunk(Chunk chunk) { _chunks[(chunk.X, chunk.Y)] = chunk; + + Dictionary oppositeOrientation = new() + { + {Orientation.West, Orientation.East}, + {Orientation.East, Orientation.West}, + {Orientation.North, Orientation.South}, + {Orientation.South, Orientation.North}, + }; + + foreach (var (orientation, neighbor) in GetChunkNeighbors(chunk)) + { + neighbor.Neighbors[oppositeOrientation[orientation]] = chunk; + chunk.Neighbors[orientation] = neighbor; + neighbor.UpdateChunkMesh(); + } + chunk.UpdateChunkMesh(); } public void RemoveChunk(int chunkX, int chunkZ) @@ -46,6 +63,18 @@ namespace Voxel return chunk.GetBlock(localX, worldY, localZ); } + List GetEdgeOrientations(int localX, int localZ, int size) + { + var orientations = new List(); + + if (localX == 0) orientations.Add(Orientation.West); + if (localX == size - 1) orientations.Add(Orientation.East); + if (localZ == size - 1) orientations.Add(Orientation.South); // assuming Z+ is North + if (localZ == 0) orientations.Add(Orientation.North); + + return orientations; + } + public void SetBlock(int worldX, int worldY, int worldZ, Blocks block) { int chunkX = worldX / Chunk.Size; @@ -57,6 +86,39 @@ namespace Voxel int localZ = worldZ % Chunk.Size; chunk.SetBlock(localX, worldY, localZ, block); + + if (block == Blocks.Air && (localX == 15 || localX == 0) || (localZ == 15 || localZ == 0)) + { + foreach (var orientation in GetEdgeOrientations(localX, localZ, Chunk.Size)) + { + if (chunk.Neighbors.TryGetValue(orientation, out var neighbor) && neighbor != null) + { + neighbor.UpdateChunkMesh(); + Console.WriteLine($"Updated neighbor at {orientation}"); + } + } + } + } + + public IEnumerable<(Orientation orientation, Chunk neighbor)> GetChunkNeighbors(Chunk chunk) + { + Dictionary offsets = new() + { + { Orientation.West, (1, 0) }, + { Orientation.East, (-1, 0) }, + { Orientation.North, (0, 1) }, + { Orientation.South, (0, -1) } + }; + + foreach (var kv in offsets) + { + int nx = chunk.X + kv.Value.x; + int ny = chunk.Y + kv.Value.y; + + Chunk neighbor = GetChunk(nx, ny); + if (neighbor != null) + yield return (kv.Key, neighbor); + } } public (bool success, Blocks block, int x, int y, int z, Vector3i normal) Raycast(Vector3 origin, Vector3 direction, float maxDistance)