using OpenTK.Mathematics;
namespace RubyDung;
public class World
{
private Shader shader;
// private Chunk chunk;
// private Chunk[,,] chunks;
private Dictionary<Vector3, Chunk> chunks = new Dictionary<Vector3, Chunk>();
// private byte[,,] blocks;
private Dictionary<Vector3, byte> blocks = new Dictionary<Vector3, byte>();
private int chunkSize = 16;
public Vector3i worldSize = new Vector3i(256, 256, 16);
private int xChunks;
private int yChunks;
private int zChunks;
private int viewDistance = 1;
public World(Shader shader)
{
this.shader = shader;
viewDistance *= chunkSize;
// blocks = new byte[worldSize.X, worldSize.Y, worldSize.Z];
for (int x = -viewDistance; x < viewDistance; x++)
{
for (int y = -viewDistance; y < viewDistance; y++)
{
for (int z = 0; z < worldSize.Z; z++)
{
// blocks[x, y, z] = 1;
blocks[new Vector3(x, y, z)] = 1;
}
}
}
// chunk = new Chunk(shader, this, 0, 0, 0, 16, 16, 16);
xChunks = viewDistance / chunkSize;
yChunks = viewDistance / chunkSize;
zChunks = worldSize.Z / chunkSize;
// chunks = new Chunk[xChunks, yChunks, zChunks];
//*
for (int x = -xChunks; x < xChunks; x++)
{
for (int y = -yChunks; y < yChunks; y++)
{
for (int z = 0; z < zChunks; z++)
{
int x0 = x * chunkSize;
int y0 = y * chunkSize;
int z0 = z * chunkSize;
int x1 = (x + 1) * chunkSize;
int y1 = (y + 1) * chunkSize;
int z1 = (z + 1) * chunkSize;
// chunks[x, y, z] = new Chunk(shader, this, x0, y0, z0, x1, y1, z1);
chunks[new Vector3(x, y, z)] = new Chunk(shader, this, x0, y0, z0, x1, y1, z1);
}
}
}
//*/
}
public void OnLoad()
{
//*
// foreach (Chunk chunk in chunks)
foreach (Chunk chunk in chunks.Values)
{
chunk.OnLoad();
}
//*/
}
public void OnUpdateFrame(Camera camera)
{
// Calcular qual chunk o jogador está
int posX = (int)Math.Floor(camera.cameraPos.X / chunkSize);
int posY = (int)Math.Floor(camera.cameraPos.Y / chunkSize);
// int blockGenerated = 0;
for (int x = posX - viewDistance; x < posX + viewDistance; x++)
{
for (int y = posY - viewDistance; y < posY + viewDistance; y++)
{
for (int z = 0; z < worldSize.Z; z++)
{
if (!blocks.ContainsKey(new Vector3(x, y, z)))
{
blocks[new Vector3(x, y, z)] = 1;
// blockGenerated++;
}
}
}
}
// Debug.Log($"Blocos gerados: {blockGenerated}");
// Debug.Log($"Position: {posX}, {posY}; Chunk: {xChunks}, {yChunks}");
//*
for (int x = posX - xChunks; x < posX + xChunks; x++)
{
for (int y = posY - yChunks; y < posY + yChunks; y++)
{
for (int z = 0; z < zChunks; z++)
{
if (!chunks.ContainsKey(new Vector3(x, y, z)))
{
// Debug.Log($"Novo chunk criado em: {x}, {y}, {z}");
int x0 = x * chunkSize;
int y0 = y * chunkSize;
int z0 = z * chunkSize;
int x1 = (x + 1) * chunkSize;
int y1 = (y + 1) * chunkSize;
int z1 = (z + 1) * chunkSize;
chunks[new Vector3(x, y, z)] = new Chunk(shader, this, x0, y0, z0, x1, y1, z1);
chunks[new Vector3(x, y, z)].OnLoad();
}
}
}
}
//*/
// Debug.Log($"Renderizando {chunks.Count} chunks");
// foreach (Chunk chunk in chunks)
foreach (Chunk chunk in chunks.Values)
{
chunk.OnUpdateFrame();
}
}
public void OnRenderFrame()
{
// foreach (Chunk chunk in chunks)
foreach (Chunk chunk in chunks.Values)
{
chunk.OnRenderFrame();
}
}
public bool IsTile(int x, int y, int z)
{
if (x >= -viewDistance && x < viewDistance)
{
if (y >= -viewDistance && y < viewDistance)
{
if (z >= 0 && z < worldSize.Z)
{
// return blocks[x, y, z] == 1;
return blocks.ContainsKey(new Vector3(x, y, z));
}
}
}
return false;
}
public bool IsSolidTile(int x, int y, int z)
{
return IsTile(x, y, z);
}
public List<AABB> GetCubes(AABB other)
{
List<AABB> cubes = new List<AABB>();
int x0 = (int)other.x0 - 1;
int y0 = (int)other.y0 - 1;
int z0 = (int)other.z0 - 1;
int x1 = (int)other.x1 + 1;
int y1 = (int)other.y1 + 1;
int z1 = (int)other.z1 + 1;
/*
// Arredonda para baixo os limites mínimos
int x0 = (int)Math.Floor(other.x0);
int y0 = (int)Math.Floor(other.y0);
int z0 = (int)Math.Floor(other.z0);
// Arredonda para cima os limites máximos
int x1 = (int)Math.Ceiling(other.x1);
int y1 = (int)Math.Ceiling(other.y1);
int z1 = (int)Math.Ceiling(other.z1);
*/
//*
if (x0 < -viewDistance)
{
x0 = -viewDistance;
}
if (y0 < -viewDistance)
{
y0 = -viewDistance;
}
if (z0 < 0)
{
z0 = 0;
}
if (x1 > viewDistance)
{
x1 = viewDistance;
}
if (y1 > viewDistance)
{
y1 = viewDistance;
}
if (z1 > worldSize.Z)
{
z1 = worldSize.Z;
}
//*/
// Limita as coordenadas aos limites do mundo
/*
x0 = Math.Max(x0, -viewDistance);
y0 = Math.Max(y0, -viewDistance);
z0 = Math.Max(z0, 0);
x1 = Math.Min(x1, viewDistance);
y1 = Math.Min(y1, viewDistance);
z1 = Math.Min(z1, worldSize.Z);
*/
for (int x = x0; x < x1; x++)
{
for (int y = y0; y < y1; y++)
{
for (int z = z0; z < z1; z++)
{
if (IsSolidTile(x, y, z))
{
cubes.Add(new AABB(
(float)x, (float)y, (float)z,
(float)x + 1.0f, (float)y + 1.0f, (float)z + 1.0f
));
}
}
}
}
return cubes;
}
}