packed chunk data

This commit is contained in:
2025-07-31 19:03:41 +02:00
parent 1a455a3d6b
commit fa663d0481
5 changed files with 51 additions and 104 deletions

View File

@@ -32,6 +32,18 @@ class WorldApply : public td::protocol::PacketHandler {
}
};
void Save(const td::protocol::PacketBase& header, const td::protocol::PacketBase& data) {
auto comp = std::make_shared<sp::ZlibCompress>();
std::ofstream fStream("test/tdmap.tdmap3");
auto out = std::make_shared<sp::StdOuput>(fStream);
sp::MessageStream<td::protocol::PacketFactory> stream(std::move(out), std::move(comp));
stream.WriteMessage(header);
stream.WriteMessage(data);
}
td::game::World GetWorld() {
auto comp = std::make_shared<sp::ZlibCompress>();
@@ -53,23 +65,11 @@ td::game::World GetWorld() {
d.Dispatch(*header);
d.Dispatch(*data);
Save(*header, *data);
return w;
}
void Save(td::protocol::packets::WorldHeaderPacket header, td::protocol::packets::WorldDataPacket data) {
auto comp = std::make_shared<sp::ZlibCompress>();
std::ofstream fStream("test/tdmap.tdmap2");
auto out = std::make_shared<sp::StdOuput>(fStream);
sp::MessageStream<td::protocol::PacketFactory> stream(std::move(out), std::move(comp));
stream.WriteMessage(header);
stream.WriteMessage(data);
}
void FastForward(td::game::World& a_World, const td::sim::GameHistory& a_LockSteps) {
const td::FpFloat delta = td::FpFloat(1) / td::FpFloat(75);
for (const auto& lockstep : a_LockSteps) {

View File

@@ -3,7 +3,35 @@
namespace td {
namespace game {
const int BITS_IN_BYTE = 8;
const int BITS_IN_LONG = BITS_IN_BYTE * sizeof(std::uint64_t);
static unsigned int countBits(unsigned int number) {
// log function in base 2
// take only integer part
return static_cast<unsigned int>(std::log2(number) + 1);
}
TileIndex Chunk::GetTileIndex(std::uint16_t tileNumber) const {
const std::uint8_t bitsPerTile = countBits(m_Palette.size());
const std::size_t startLong = (tileNumber * bitsPerTile) / BITS_IN_LONG;
const std::size_t startOffset = (tileNumber * bitsPerTile) % BITS_IN_LONG;
const std::size_t endLong = ((tileNumber + 1) * bitsPerTile - 1) / BITS_IN_LONG;
const Chunk::ChunkData::value_type individualValueMask = ((1 << bitsPerTile) - 1);
td::game::Chunk::ChunkData::value_type value;
if (startLong == endLong) {
value = (m_Data[startLong] >> startOffset);
} else {
int endOffset = BITS_IN_LONG - startOffset;
value = (m_Data[startLong] >> startOffset | m_Data[endLong] << endOffset);
}
value &= individualValueMask;
return m_Palette.at(value);
}
} // namespace game
} // namespace td

View File

@@ -1,78 +1,18 @@
#include <td/protocol/packet/PacketSerialize.h>
typedef std::vector<uint64_t> ChunkPackedData;
const int BITS_IN_BYTE = 8;
const int BITS_IN_LONG = BITS_IN_BYTE * sizeof(std::uint64_t);
static unsigned int countBits(unsigned int number) {
// log function in base 2
// take only integer part
return static_cast<unsigned int>(std::log2(number) + 1);
}
namespace td {
namespace game {
sp::DataBuffer& operator<<(sp::DataBuffer& a_Buffer, const ChunkPtr& a_Chunk) {
a_Buffer << a_Chunk->m_Palette;
int bitsPerTile = countBits(a_Chunk->m_Palette.size());
td::game::Chunk::ChunkData::value_type individualValueMask = ((1 << bitsPerTile) - 1);
ChunkPackedData chunkData(td::game::Chunk::ChunkSize / (BITS_IN_BYTE * sizeof(ChunkPackedData::value_type) / bitsPerTile), 0);
for (unsigned int tileNumber = 0; tileNumber < td::game::Chunk::ChunkSize; tileNumber++) {
std::size_t startLong = static_cast<std::size_t>((tileNumber * bitsPerTile) / BITS_IN_LONG);
std::size_t startOffset = static_cast<std::size_t>((tileNumber * bitsPerTile) % BITS_IN_LONG);
std::size_t endLong = static_cast<std::size_t>(((tileNumber + 1) * bitsPerTile - 1) / BITS_IN_LONG);
std::uint64_t value = static_cast<std::uint64_t>(a_Chunk->m_Tiles[tileNumber]);
value &= individualValueMask;
chunkData[startLong] |= (value << startOffset);
if (startLong != endLong) {
chunkData[endLong] = (value >> (BITS_IN_LONG - startOffset));
}
}
return a_Buffer << chunkData;
a_Buffer << a_Chunk->m_Data;
return a_Buffer;
}
sp::DataBuffer& operator>>(sp::DataBuffer& a_Buffer, ChunkPtr& a_Chunk) {
a_Chunk = std::make_shared<td::game::Chunk>();
a_Buffer >> a_Chunk->m_Palette;
std::uint8_t bitsPerTile = countBits(a_Chunk->m_Palette.size());
// A bitmask that contains bitsPerTile set bits
td::game::Chunk::ChunkData::value_type individualValueMask = ((1 << bitsPerTile) - 1);
ChunkPackedData chunkData;
a_Buffer >> chunkData;
for (unsigned int tileNumber = 0; tileNumber < td::game::Chunk::ChunkSize; tileNumber++) {
std::size_t startLong = (tileNumber * bitsPerTile) / BITS_IN_LONG;
std::size_t startOffset = (tileNumber * bitsPerTile) % BITS_IN_LONG;
std::size_t endLong = ((tileNumber + 1) * bitsPerTile - 1) / BITS_IN_LONG;
td::game::Chunk::ChunkData::value_type value;
if (startLong == endLong) {
value = (chunkData[startLong] >> startOffset);
} else {
int endOffset = BITS_IN_LONG - startOffset;
value = (chunkData[startLong] >> startOffset | chunkData[endLong] << endOffset);
}
value &= individualValueMask;
a_Chunk->m_Tiles[tileNumber] = value;
}
return a_Buffer;
return a_Buffer >> a_Chunk->m_Data;
}
} // namespace game