184 lines
5.4 KiB
C++
184 lines
5.4 KiB
C++
#pragma once
|
|
|
|
#include <stdint.h>
|
|
#include <array>
|
|
#include <memory>
|
|
#include <vector>
|
|
#include <unordered_map>
|
|
|
|
#include "Util/Span.h"
|
|
|
|
#include "config.h"
|
|
#include "Types/Tile.h"
|
|
#include "Components/Misc.hpp"
|
|
|
|
struct Chunk
|
|
{
|
|
public:
|
|
typedef uint8_t CoordinateType;
|
|
static constexpr int ChunkSizePowerOfTwo = 6;
|
|
static constexpr int ChunkSize = 1 << ChunkSizePowerOfTwo;
|
|
static constexpr int TotalChunkTiles = ChunkSize * ChunkSize;
|
|
static constexpr int ChunkMask = (1 << ChunkSizePowerOfTwo) - 1;
|
|
static_assert(sizeof(CoordinateType) * 8 >= ChunkSizePowerOfTwo, "CoordinateType is too small to support chunk size");
|
|
|
|
static constexpr uint8_t WorldToLocal(int world) { return world & ChunkMask; }
|
|
|
|
std::array<Tile, TotalChunkTiles> Tiles;
|
|
|
|
public:
|
|
static void Assert(int x, int y) { DEV_ASSERT(x < ChunkSize && x >= 0 && y < ChunkSize && y >= 0); }
|
|
public:
|
|
Tile GetTile(int x, int y) const { Assert(x, y); return Tiles[y * ChunkSize + x]; }
|
|
Tile GetTile(Vector2 pos) const { return GetTile(pos.X, pos.Y); }
|
|
const Tile& GetTileRef(int x, int y) const { Assert(x, y); return Tiles[y * ChunkSize + x]; }
|
|
Tile& GetTile(int x, int y) { Assert(x, y); return Tiles[y * ChunkSize + x]; }
|
|
Tile& GetTile(Vector2 pos) { return GetTile(pos.X, pos.Y); }
|
|
};
|
|
|
|
struct ChunkCoordinate
|
|
{
|
|
ChunkCoordinate() = default;
|
|
ChunkCoordinate(int x, int y) : X{ static_cast<uint8_t>(x) }, Y{ static_cast<uint8_t>(y) } { DEV_ASSERT(x >= 0 && x < Chunk::ChunkSize && y >= 0 && y < Chunk::ChunkSize); }
|
|
ChunkCoordinate(Vector2 pos) : ChunkCoordinate{pos.X, pos.Y} {}
|
|
|
|
uint8_t X{};
|
|
uint8_t Y{};
|
|
|
|
operator Vector2() const { return Vector2(X, Y); }
|
|
};
|
|
|
|
static_assert(sizeof(ChunkCoordinate) / 2 >= Chunk::ChunkSizePowerOfTwo / 8);
|
|
|
|
struct EntityTile final
|
|
{
|
|
public:
|
|
EntityTile() = default;
|
|
EntityTile(flecs::entity entity, int worldX, int worldY)
|
|
: Entity{ entity }
|
|
, ChunkX{ Chunk::WorldToLocal(worldX) }
|
|
, ChunkY{ Chunk::WorldToLocal(worldY) }
|
|
{}
|
|
|
|
public:
|
|
flecs::entity Entity{};
|
|
Chunk::CoordinateType ChunkX{};
|
|
Chunk::CoordinateType ChunkY{};
|
|
};
|
|
|
|
struct ChunkKey
|
|
{
|
|
public:
|
|
static constexpr int16_t WorldToChunk(int pos) { return static_cast<int16_t>(pos >> Chunk::ChunkSizePowerOfTwo); }
|
|
static constexpr int32_t ChunkToWorld(int16_t pos) { return pos << Chunk::ChunkSizePowerOfTwo; }
|
|
|
|
public:
|
|
int16_t X{}, Y{};
|
|
|
|
public:
|
|
ChunkKey() = default;
|
|
ChunkKey(int WorldX, int WorldY) : X{ WorldToChunk(WorldX) }, Y{ WorldToChunk(WorldY) } {}
|
|
|
|
public:
|
|
uint64_t hash64() const { static_assert(sizeof(uint32_t) == sizeof(ChunkKey)); return std::hash<uint32_t>{}(*reinterpret_cast<const uint32_t*>(this)); }
|
|
uint32_t hash() const { return static_cast<uint32_t>(hash64()); }
|
|
static uint32_t hash(ChunkKey key) { return key.hash(); }
|
|
|
|
Bounds GetBounds() const { return Bounds{Vector2{ChunkToWorld(X), ChunkToWorld(Y)}, Vector2{ChunkToWorld(X + 1), ChunkToWorld(Y + 1)}}; }
|
|
|
|
public:
|
|
bool operator==(const ChunkKey& rhs) const { return hash() == rhs.hash(); }
|
|
};
|
|
|
|
static_assert(sizeof(ChunkKey) == 4);
|
|
|
|
struct ChunkData
|
|
{
|
|
public:
|
|
void MarkAsPersistant(flecs::entity entity);
|
|
void RemovePersistance(flecs::entity entity);
|
|
void Clear()
|
|
{
|
|
TileData = {};
|
|
Entities.resize(0);
|
|
}
|
|
|
|
public:
|
|
std::unique_ptr<Chunk> TileData{};
|
|
std::vector<EntityTile> Entities{};
|
|
std::vector<EntityTile> PersistantEntities{};
|
|
};
|
|
|
|
struct ChunkCollection
|
|
{
|
|
public:
|
|
const Chunk& GetChunk(int x, int y);
|
|
const Chunk& GetChunk(ChunkKey key);
|
|
Chunk const* TryGetChunk(int x, int y) const;
|
|
Chunk const* TryGetChunk(ChunkKey key) const;
|
|
ChunkData& GetChunkData(int x, int y);
|
|
ChunkData& GetChunkData(ChunkKey key);
|
|
|
|
Tile GetTile(int x, int y);
|
|
Tile const* TryGetTile(int x, int y) const;
|
|
flecs::entity GetEntity(int x, int y) const;
|
|
|
|
void SetChunkTiles(int x, int y, std::unique_ptr<Chunk>&& chunk);
|
|
void SetChunkTiles(ChunkKey key, std::unique_ptr<Chunk>&& chunk);
|
|
void AddEntity(flecs::entity entity, tcb::span<Vector2> claimedPositions);
|
|
void AddPersistantEntity(flecs::entity entity, tcb::span<Vector2> claimedPositions);
|
|
|
|
void MarkAsPersistant(flecs::entity entity);
|
|
void RemovePersistance(flecs::entity entity);
|
|
|
|
void RemoveEntity(flecs::entity entity);
|
|
void RemoveChunk(int x, int y);
|
|
void RemoveChunk(ChunkKey key);
|
|
|
|
private:
|
|
int GetChunkIndex(int x, int y);
|
|
int GetChunkIndex(ChunkKey key);
|
|
int TryGetChunkIndex(int x, int y) const;
|
|
int TryGetChunkIndex(ChunkKey key) const;
|
|
Chunk& GetChunkInternal(int x, int y);
|
|
Chunk& GetChunkInternal(ChunkKey key);
|
|
Tile& GetTileInternal(int x, int y);
|
|
|
|
void SetTile(Tile tile, int x, int y);
|
|
|
|
void InvalidateCachedChunk();
|
|
|
|
private:
|
|
std::vector<ChunkData> ChunkDatas;
|
|
std::unordered_map<ChunkKey, int, ChunkKey> ChunkMap{};
|
|
ChunkKey CachedChunkKey{};
|
|
int CachedChunk{-1};
|
|
};
|
|
|
|
// struct LightValue
|
|
// {
|
|
// constexpr static uint8_t LightLevelBits = 5;
|
|
// constexpr static uint8_t PenetrationBits = 8 - LightLevelBits;
|
|
// constexpr static uint8_t MaxLightVal = (1 << LightLevelBits) - 1;
|
|
// constexpr static uint8_t MaxPenetration = (1 << PenetrationBits) - 1;
|
|
|
|
// uint8_t Penetration : PenetrationBits;
|
|
// uint8_t Val : LightLevelBits;
|
|
|
|
// LightValue()
|
|
// {
|
|
// Penetration = 1;
|
|
// Val = 0;
|
|
// }
|
|
// };
|
|
|
|
//static_assert(sizeof(LightValue) == 1);
|
|
|
|
// struct LightChunk
|
|
// {
|
|
// std::array<LightValue, Chunk::TotalChunkTiles> Tiles;
|
|
|
|
// public:
|
|
// LightValue GetTile(int x, int y) const { Chunk::Assert(x, y); return Tiles[y * Chunk::ChunkSize + x]; }
|
|
// LightValue& GetTile(int x, int y) { Chunk::Assert(x, y); return Tiles[y * Chunk::ChunkSize + x]; }
|
|
// };
|