using UnityEngine;
///
/// Чистые данные чанка — без MonoBehaviour, без Unity-объектов.
/// Легко сериализовать, передать в генератор, сохранить на диск.
///
public class ChunkData
{
public const int SIZE = 16; // блоков по X и Z
public const int HEIGHT = 16; // блоков по Y
public readonly Vector3Int ChunkPos; // позиция чанка в чанковых координатах
// null = пустой блок, иначе blockId
private readonly string[,,] _blocks = new string[SIZE, HEIGHT, SIZE];
public bool IsDirty { get; private set; } = true; // нужен ли пересчёт меша
public ChunkData(Vector3Int chunkPos)
{
ChunkPos = chunkPos;
}
/// Получить blockId по локальным координатам. null = пусто.
public string GetBlock(int x, int y, int z)
{
if (!InBounds(x, y, z)) return null;
return _blocks[x, y, z];
}
public string GetBlock(Vector3Int local) => GetBlock(local.x, local.y, local.z);
/// Установить блок. null = удалить.
public void SetBlock(int x, int y, int z, string blockId)
{
if (!InBounds(x, y, z)) return;
_blocks[x, y, z] = blockId;
IsDirty = true;
}
public void SetBlock(Vector3Int local, string blockId) =>
SetBlock(local.x, local.y, local.z, blockId);
public void ClearDirty() => IsDirty = false;
public static bool InBounds(int x, int y, int z) =>
x >= 0 && x < SIZE &&
y >= 0 && y < HEIGHT &&
z >= 0 && z < SIZE;
///
/// Перевод мировой позиции блока → позиция чанка (чанковые координаты).
///
public static Vector3Int WorldToChunkPos(Vector3Int worldBlock) =>
new Vector3Int(
Mathf.FloorToInt((float)worldBlock.x / SIZE),
Mathf.FloorToInt((float)worldBlock.y / HEIGHT),
Mathf.FloorToInt((float)worldBlock.z / SIZE));
///
/// Перевод мировой позиции блока → локальная позиция внутри чанка.
///
public static Vector3Int WorldToLocal(Vector3Int worldBlock)
{
int x = worldBlock.x % SIZE;
int y = worldBlock.y % HEIGHT;
int z = worldBlock.z % SIZE;
// Обработка отрицательных координат
if (x < 0) x += SIZE;
if (y < 0) y += HEIGHT;
if (z < 0) z += SIZE;
return new Vector3Int(x, y, z);
}
/// Позиция чанка → мировая позиция его нижнего-левого угла.
public static Vector3Int ChunkToWorld(Vector3Int chunkPos) =>
new Vector3Int(chunkPos.x * SIZE, chunkPos.y * HEIGHT, chunkPos.z * SIZE);
}