Block mutability for aligned bitfields (1.16 style)
TODO: "In versions prior to 1.16, the full range of bits is used, where the remaining bits of a block index continue on the next long value."
This commit is contained in:
parent
b15e039d61
commit
b218552cc4
|
@ -246,10 +246,17 @@ namespace Feather
|
||||||
sections.WriteVarInt(sect.blockStates.palette.ByID(j));
|
sections.WriteVarInt(sect.blockStates.palette.ByID(j));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Block State Data
|
||||||
|
|
||||||
sections.WriteVarInt(dataLength);
|
sections.WriteVarInt(dataLength);
|
||||||
// Can't just copy because endian-ness!
|
|
||||||
for (size_t i = 0; i < dataLength; i++)
|
{
|
||||||
sections.Write<uint64_t>(sect.blockStates.data[i]);
|
auto [data, lock] = sect.blockStates.data.borrow();
|
||||||
|
|
||||||
|
// Can't just copy because endian-ness!
|
||||||
|
for (size_t i = 0; i < dataLength; i++)
|
||||||
|
sections.Write<uint64_t>(data[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Log::Trace("Section bits: {:#b}", sectionsBits);
|
//Log::Trace("Section bits: {:#b}", sectionsBits);
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <map>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
namespace Feather
|
namespace Feather
|
||||||
{
|
{
|
||||||
|
@ -25,4 +27,10 @@ namespace Feather
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using LockableList = Lockable<std::list<T>>;
|
using LockableList = Lockable<std::list<T>>;
|
||||||
|
|
||||||
|
template <typename Key, typename T>
|
||||||
|
using LockableMap = Lockable<std::map<Key, T>>;
|
||||||
|
|
||||||
|
template <typename T, size_t Size>
|
||||||
|
using LockableArray = Lockable<std::array<T, Size>>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,11 @@ namespace Feather
|
||||||
return m_IDtoValue.at(id);
|
return m_IDtoValue.at(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool HasValue(const T& value) const
|
||||||
|
{
|
||||||
|
return m_ValueToID.contains(value);
|
||||||
|
}
|
||||||
|
|
||||||
inline size_t Size() const
|
inline size_t Size() const
|
||||||
{
|
{
|
||||||
return m_IDtoValue.size();
|
return m_IDtoValue.size();
|
||||||
|
@ -53,4 +58,4 @@ namespace Feather
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,8 +96,12 @@ namespace Feather
|
||||||
|
|
||||||
Assert(blockStates.GetLength() < section->blockStates.GetNumLongs());
|
Assert(blockStates.GetLength() < section->blockStates.GetNumLongs());
|
||||||
|
|
||||||
for (size_t i = 0; i < blockStates.GetLength(); i++)
|
{
|
||||||
section->blockStates.data[i] = blockStates[i];
|
auto [data, lock] = section->blockStates.data.borrow();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < blockStates.GetLength(); i++)
|
||||||
|
data[i] = blockStates[i];
|
||||||
|
}
|
||||||
|
|
||||||
section->blockStates.SetBits(Math::CeilDiv(blockStates.GetLength() * bitsizeof(int64), ChunkSection::NUM_BLOCKS));
|
section->blockStates.SetBits(Math::CeilDiv(blockStates.GetLength() * bitsizeof(int64), ChunkSection::NUM_BLOCKS));
|
||||||
|
|
||||||
|
@ -108,11 +112,40 @@ namespace Feather
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Chunk::SetBlock(BlockPos& pos, BlockState& state)
|
bool Chunk::SetBlock(const BlockPos& pos, const BlockState& state)
|
||||||
{
|
{
|
||||||
ChunkSection& section = sections[GetSection(pos)];
|
int i = GetSection(pos);
|
||||||
|
ChunkSection& section = sections[i];
|
||||||
|
|
||||||
|
Log::Debug("Chunk::SetBlock: ({}, {}, {}) -> ({}, {}, {}) Chunk Local",
|
||||||
|
pos.x, pos.y, pos.z,
|
||||||
|
pos.x & 0xF, pos.y & 0xF, pos.z & 0xF
|
||||||
|
);
|
||||||
|
|
||||||
|
int index = GetSectionIndex(pos);
|
||||||
|
|
||||||
|
Log::Debug("Chunk::SetBlock -> section {}, index {}", i, index);
|
||||||
|
|
||||||
|
//if (!section.blockStates.palette.HasValue(state))
|
||||||
|
|
||||||
return false;
|
// TODO: temp code. use BlockState instead of global ID
|
||||||
|
{
|
||||||
|
int id = World::GLOBAL_PALETTE.GetID(state);
|
||||||
|
|
||||||
|
if (!section.blockStates.palette.HasValue(id)) {
|
||||||
|
Log::Warn("Chunk::SetBlock for block that is not in section's local palette. NYI");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int localId = section.blockStates.palette.GetID(id);
|
||||||
|
|
||||||
|
uint prev = section.blockStates.GetAndSet(index, localId);
|
||||||
|
|
||||||
|
Log::Debug("Chunk::SetBlock changed block from {} to {}", prev, localId);
|
||||||
|
}
|
||||||
|
|
||||||
|
//section.blockStates.GetAndSet(GetSectionIndex(pos), )
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,8 +44,17 @@ namespace Feather
|
||||||
|
|
||||||
Chunk(ChunkPos& pos, std::unique_ptr<NBT::CompoundTag> tag);
|
Chunk(ChunkPos& pos, std::unique_ptr<NBT::CompoundTag> tag);
|
||||||
|
|
||||||
inline int GetSection(BlockPos& pos) { return pos.y >> 4; }
|
inline int GetSection(const BlockPos& pos) { return pos.y >> 4; }
|
||||||
|
|
||||||
bool SetBlock(BlockPos& pos, BlockState& state);
|
inline int GetSectionIndex(const BlockPos& pos)
|
||||||
|
{
|
||||||
|
int x = pos.x & 0xF;
|
||||||
|
int y = pos.y & 0xF;
|
||||||
|
int z = pos.z & 0xF;
|
||||||
|
|
||||||
|
return y << 8 | z << 4 | x;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SetBlock(const BlockPos& pos, const BlockState& state);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,8 +2,7 @@
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "Palette.h"
|
#include "Palette.h"
|
||||||
|
#include "Lockable.h"
|
||||||
#include <array>
|
|
||||||
|
|
||||||
namespace Feather
|
namespace Feather
|
||||||
{
|
{
|
||||||
|
@ -15,7 +14,9 @@ namespace Feather
|
||||||
|
|
||||||
static constexpr size_t NUM_LONGS = Math::CeilDiv(MaxSize * MaxBits, bitsizeof(uint64));
|
static constexpr size_t NUM_LONGS = Math::CeilDiv(MaxSize * MaxBits, bitsizeof(uint64));
|
||||||
|
|
||||||
std::array<uint64, NUM_LONGS> data;
|
static constexpr size_t BITS_PER_CELL = bitsizeof(uint64);
|
||||||
|
|
||||||
|
LockableArray<uint64, NUM_LONGS> data;
|
||||||
|
|
||||||
// TODO: this could eventually be Palette<BlockState> to avoid double lookup
|
// TODO: this could eventually be Palette<BlockState> to avoid double lookup
|
||||||
// Palette of local indexs to indexs in the global palette
|
// Palette of local indexs to indexs in the global palette
|
||||||
|
@ -23,11 +24,53 @@ namespace Feather
|
||||||
|
|
||||||
uint size = MaxSize;
|
uint size = MaxSize;
|
||||||
uint8 bits = MaxBits;
|
uint8 bits = MaxBits;
|
||||||
|
uint64 mask = 0;
|
||||||
|
uint valuesPerCell = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PalettedContainer(uint size, uint8 bits) : size(size), bits(bits), data() {}
|
PalettedContainer(uint size, uint8 bits) : size(size), data() { SetBits(bits); }
|
||||||
|
|
||||||
inline void SetBits(uint8 nbits) { bits = nbits; }
|
inline void SetBits(uint8 nbits)
|
||||||
|
{
|
||||||
|
bits = nbits;
|
||||||
|
mask = (1 << bits) - 1;
|
||||||
|
valuesPerCell = BITS_PER_CELL / bits;
|
||||||
|
|
||||||
|
Log::Debug("PalettedContainer::SetBits: {}, mask = {:#b}, valuesPerCell = {}", bits, mask, valuesPerCell);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: optimize all math here
|
||||||
|
|
||||||
|
inline int CellIndex(int index)
|
||||||
|
{
|
||||||
|
return index / valuesPerCell;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update value, returns previous value
|
||||||
|
// TODO: change from uint to const T&
|
||||||
|
inline uint GetAndSet(int index, uint value)
|
||||||
|
{
|
||||||
|
auto [d, lock] = data.borrow();
|
||||||
|
|
||||||
|
int id = value; // palette.GetID(value);
|
||||||
|
int cellIndex = CellIndex(index);
|
||||||
|
uint64 shift = (index - cellIndex * valuesPerCell) * bits;//(index % valuesPerCell) * bits;
|
||||||
|
|
||||||
|
Log::Debug("PalettedContainer::GetAndSet: index {} -> cell {}, [{}:{}]", index, cellIndex, shift, shift + bits);
|
||||||
|
|
||||||
|
uint64 cell = d[cellIndex];
|
||||||
|
int prev = (cell >> shift) & mask;
|
||||||
|
|
||||||
|
//d[cellIndex] = ((cell & (mask << shift ^ 0xFFFFFFFFFFFFFFFFL)) | (uint64(id) & mask)) << shift;
|
||||||
|
|
||||||
|
d[cellIndex] &= ~(mask << shift); // clear target bits
|
||||||
|
d[cellIndex] |= ((uint64)id & mask) << shift; // set target bits
|
||||||
|
|
||||||
|
//Log::Debug("Changed from {:#b} to {:#b}", cell, d[cellIndex]);
|
||||||
|
Log::Debug("Changed from {} (g: {}) to {} (g: {})", prev, palette.ByID(prev), value, palette.ByID(value));
|
||||||
|
|
||||||
|
return (uint)prev; // palette.ByID(prev);
|
||||||
|
}
|
||||||
|
|
||||||
inline constexpr size_t GetNumLongs() { return NUM_LONGS; }
|
inline constexpr size_t GetNumLongs() { return NUM_LONGS; }
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue