FeatherMC/src/world/Chunk.cpp

119 lines
2.8 KiB
C++

#include "Chunk.h"
#include "World.h"
namespace Feather
{
Chunk::Chunk(ChunkPos& pos, std::unique_ptr<NBT::CompoundTag> tag)
: pos(pos), nbt(std::move(tag))
{
using namespace NBT;
CompoundTag level = nbt->GetCompound("Level");
//Log::Trace("Loading chunk ({}, {}) from NBT", pos.x, pos.z);
if (pos.x != level.Get<int>("xPos") || pos.z != level.Get<int>("zPos"))
{
Log::Error("Tried to load chunk ({}, {}) from NBT but NBT says chunk pos is ({}, {})",
pos.x, pos.z,
level.Get<int>("xPos"), level.Get<int>("zPos")
);
}
// TODO: Heightmaps
ListTag<CompoundTag> sectionsList = level.GetList<CompoundTag>("Sections");
int n = 0;
for (CompoundTag& sectData : sectionsList)
{
//std::cout << sectData << "\n";
int8_t y = sectData.Get<int8_t>("Y");
if (y < 0 || y >= NUM_SECTIONS) {
//Log::Trace("Skipping section {}", y);
continue;
}
//Log::Trace("Loading section {}/{} at Y {}", n + 1, NUM_SECTIONS, y);
if (n >= NUM_SECTIONS)
{
Log::Error("Chunk ({}, {}) has more than {} sections!", pos.x, pos.z, NUM_SECTIONS);
break;
}
ChunkSection* section = &sections[y];
// Section Palette
ListTag<CompoundTag> palette = sectData.GetList<CompoundTag>("Palette");
for (size_t i = 0; i < palette.GetLength(); i++)
{
CompoundTag state = palette[i];
const char* name = state.Get<StringTag>("Name").GetValue();
BlockState stateLookup(name);
CompoundTag properties = state.GetCompound("Properties");
if (properties)
{
for (auto& prop : properties)
{
stateLookup.AddProperty(prop.GetName(), prop.GetValueString());
}
}
int id;
// TODO: handle this in IdMapper
try {
id = World::GLOBAL_PALETTE.GetID(stateLookup);
}
catch (std::out_of_range& err) {
(void)err;
int defaultId = World::GLOBAL_PALETTE.GetDefaultID();
section->blockStates.palette.AddMapping(i, defaultId);
Log::Warn("Chunk Section Palette maps id {} to invalid block state with name '{}'", i, name);
continue;
}
// TODO: could use Add()
section->blockStates.palette.AddMapping(i, id);
//Log::Trace(" {} -> {} {}", i, id, name);
}
// Block States
LongArrayTag blockStates = sectData.Get<LongArrayTag>("BlockStates");
if (!blockStates) {
Log::Warn("Skipping section with no block states.");
continue;
}
Assert(blockStates.GetLength() < section->blockStates.GetNumLongs());
for (size_t i = 0; i < blockStates.GetLength(); i++)
section->blockStates.data[i] = blockStates[i];
section->blockStates.SetBits(Math::CeilDiv(blockStates.GetLength() * bitsizeof(int64), ChunkSection::NUM_BLOCKS));
n++;
}
}
bool Chunk::SetBlock(BlockPos& pos, BlockState& state)
{
ChunkSection& section = sections[GetSection(pos)];
return false;
}
}