diff --git a/include/td/game/WorldTypes.h b/include/td/game/WorldTypes.h index 745aa0b..4177225 100644 --- a/include/td/game/WorldTypes.h +++ b/include/td/game/WorldTypes.h @@ -65,7 +65,7 @@ using AllTiles = std::tuple; using TileFactory = sp::MessageFactory; -class TileHandler : public sp::GenericHandler{}; +class TileHandler : public sp::GenericHandler {}; using TilePtr = std::shared_ptr>; @@ -79,35 +79,14 @@ typedef std::uint32_t TileIndex; // 32 x 32 area struct Chunk { enum { ChunkWidth = 32, ChunkHeight = 32, ChunkSize = ChunkWidth * ChunkHeight }; - typedef std::array ChunkData; + using ChunkData = std::array; + using ChunkPackedData = std::vector; // stores index of tile palette - ChunkData m_Tiles{0}; ChunkPalette m_Palette; + ChunkPackedData m_Data; - TileIndex GetTileIndex(std::uint16_t tileNumber) const { - TileIndex chunkPaletteIndex = m_Tiles.at(tileNumber); - if (chunkPaletteIndex == 0) // index 0 means empty tile index 1 = first tile - return 0; - return m_Palette.at(chunkPaletteIndex); - } - - // TODO: keep data packed - /* - std::size_t startLong = static_cast((tileNumber * bitsPerTile) / BITS_IN_LONG); - std::size_t startOffset = static_cast((tileNumber * bitsPerTile) % BITS_IN_LONG); - std::size_t endLong = static_cast(((tileNumber + 1) * bitsPerTile - 1) / BITS_IN_LONG); - - std::uint64_t value = static_cast(a_Chunk->m_Tiles[tileNumber]); - - value &= individualValueMask; - - chunkData[startLong] |= (value << startOffset); - - if (startLong != endLong) { - chunkData[endLong] = (value >> (BITS_IN_LONG - startOffset)); - } - */ + TileIndex GetTileIndex(std::uint16_t tileNumber) const; }; typedef std::shared_ptr ChunkPtr; diff --git a/include/td/protocol/command/Commands.h b/include/td/protocol/command/Commands.h index b55102b..77c9f1a 100644 --- a/include/td/protocol/command/Commands.h +++ b/include/td/protocol/command/Commands.h @@ -7,13 +7,13 @@ #include #include +#include #include #include #include #include #include #include -#include namespace td { namespace protocol { diff --git a/src/main.cpp b/src/main.cpp index 6de07e6..ab13d0d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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(); + + std::ofstream fStream("test/tdmap.tdmap3"); + auto out = std::make_shared(fStream); + + sp::MessageStream stream(std::move(out), std::move(comp)); + + stream.WriteMessage(header); + stream.WriteMessage(data); +} + td::game::World GetWorld() { auto comp = std::make_shared(); @@ -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(); - - std::ofstream fStream("test/tdmap.tdmap2"); - auto out = std::make_shared(fStream); - - sp::MessageStream 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) { diff --git a/src/td/game/WorldTypes.cpp b/src/td/game/WorldTypes.cpp index 25d25f6..a9c2f96 100644 --- a/src/td/game/WorldTypes.cpp +++ b/src/td/game/WorldTypes.cpp @@ -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(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 diff --git a/src/td/protocol/packet/ChunkSerialize.cpp b/src/td/protocol/packet/ChunkSerialize.cpp index 1f9fe2c..b666424 100644 --- a/src/td/protocol/packet/ChunkSerialize.cpp +++ b/src/td/protocol/packet/ChunkSerialize.cpp @@ -1,78 +1,18 @@ #include -typedef std::vector 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(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((tileNumber * bitsPerTile) / BITS_IN_LONG); - std::size_t startOffset = static_cast((tileNumber * bitsPerTile) % BITS_IN_LONG); - std::size_t endLong = static_cast(((tileNumber + 1) * bitsPerTile - 1) / BITS_IN_LONG); - - std::uint64_t value = static_cast(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(); - 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