migrating save files
This commit is contained in:
@@ -31,23 +31,17 @@ class Team;
|
|||||||
|
|
||||||
class TeamCastle : public utils::shape::Rectangle {
|
class TeamCastle : public utils::shape::Rectangle {
|
||||||
private:
|
private:
|
||||||
const Team* m_Team;
|
|
||||||
float m_Life;
|
float m_Life;
|
||||||
public:
|
public:
|
||||||
static constexpr int CastleMaxLife = 1000;
|
static constexpr int CastleMaxLife = 1000;
|
||||||
|
|
||||||
TeamCastle(const Team* team) : m_Team(team), m_Life(CastleMaxLife) {
|
TeamCastle() : m_Life(CastleMaxLife) {
|
||||||
SetWidth(5);
|
SetWidth(5);
|
||||||
SetHeight(5);
|
SetHeight(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
TeamCastle() : TeamCastle(nullptr) {}
|
|
||||||
|
|
||||||
float GetLife() const { return m_Life; }
|
float GetLife() const { return m_Life; }
|
||||||
|
|
||||||
const Team* GetTeam() const { return m_Team; }
|
|
||||||
void SetTeam(const Team* team) { m_Team = team; }
|
|
||||||
|
|
||||||
void SetLife(float life) { m_Life = life; }
|
void SetLife(float life) { m_Life = life; }
|
||||||
void Damage(float damage) { m_Life = std::max(0.0f, m_Life - damage); }
|
void Damage(float damage) { m_Life = std::max(0.0f, m_Life - damage); }
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class World {
|
|||||||
std::vector<Color> m_DecorationPalette;
|
std::vector<Color> m_DecorationPalette;
|
||||||
Color m_Background;
|
Color m_Background;
|
||||||
|
|
||||||
std::unordered_map<ChunkCoord, ChunkPtr> m_Chunks;
|
ChunkList m_Chunks;
|
||||||
|
|
||||||
SpawnColorPalette m_SpawnColorPalette;
|
SpawnColorPalette m_SpawnColorPalette;
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ class World {
|
|||||||
|
|
||||||
TowerPtr GetTower(const Vec2f& position) const; // returns null if no tower is here
|
TowerPtr GetTower(const Vec2f& position) const; // returns null if no tower is here
|
||||||
|
|
||||||
const std::unordered_map<ChunkCoord, ChunkPtr>& GetChunks() const {
|
const ChunkList& GetChunks() const {
|
||||||
return m_Chunks;
|
return m_Chunks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,14 +7,8 @@
|
|||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
namespace game {
|
namespace game {
|
||||||
struct ChunkCoord {
|
|
||||||
std::int16_t x, y;
|
|
||||||
|
|
||||||
friend bool operator==(const td::game::ChunkCoord& first, const td::game::ChunkCoord& other) {
|
|
||||||
return first.x == other.x && first.y == other.y;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
using ChunkCoord = Vec2<std::int16_t>;
|
||||||
|
|
||||||
class Game;
|
class Game;
|
||||||
|
|
||||||
@@ -80,15 +74,17 @@ struct Chunk {
|
|||||||
typedef std::array<std::uint16_t, ChunkSize> ChunkData;
|
typedef std::array<std::uint16_t, ChunkSize> ChunkData;
|
||||||
|
|
||||||
// stores index of tile palette
|
// stores index of tile palette
|
||||||
ChunkData tiles{0};
|
ChunkData m_Tiles{0};
|
||||||
ChunkPalette palette;
|
ChunkPalette m_Palette;
|
||||||
|
|
||||||
TileIndex GetTileIndex(std::uint16_t tileNumber) const {
|
TileIndex GetTileIndex(std::uint16_t tileNumber) const {
|
||||||
TileIndex chunkPaletteIndex = tiles.at(tileNumber);
|
TileIndex chunkPaletteIndex = m_Tiles.at(tileNumber);
|
||||||
if (chunkPaletteIndex == 0) // index 0 means empty tile index 1 = first tile
|
if (chunkPaletteIndex == 0) // index 0 means empty tile index 1 = first tile
|
||||||
return 0;
|
return 0;
|
||||||
return palette.at(chunkPaletteIndex);
|
return m_Palette.at(chunkPaletteIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: keep data packed
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<Chunk> ChunkPtr;
|
typedef std::shared_ptr<Chunk> ChunkPtr;
|
||||||
@@ -103,6 +99,8 @@ typedef std::array<Color, 2> SpawnColorPalette;
|
|||||||
|
|
||||||
typedef std::vector<TowerPtr> TowerList;
|
typedef std::vector<TowerPtr> TowerList;
|
||||||
|
|
||||||
|
using ChunkList = std::unordered_map<ChunkCoord, ChunkPtr>;
|
||||||
|
|
||||||
sp::DataBuffer& operator>>(sp::DataBuffer& buffer, TilePtr& tile);
|
sp::DataBuffer& operator>>(sp::DataBuffer& buffer, TilePtr& tile);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ struct WorldHeader {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct WorldData {
|
struct WorldData {
|
||||||
std::unordered_map<game::ChunkCoord, game::ChunkPtr> m_Chunks;
|
game::ChunkList m_Chunks;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace pdata
|
} // namespace pdata
|
||||||
|
|||||||
@@ -6,10 +6,60 @@ namespace sp {
|
|||||||
|
|
||||||
class DataBuffer;
|
class DataBuffer;
|
||||||
|
|
||||||
|
// temp
|
||||||
template <>
|
template <>
|
||||||
void ReadMessage(DataBuffer& a_Buffer, td::protocol::pdata::WorldHeader& a_Header);
|
void ReadMessage(DataBuffer& a_Buffer, td::protocol::pdata::PredictCommand& a_Header);
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void ReadMessage(DataBuffer& a_Buffer, td::protocol::pdata::WorldData& a_WorldData);
|
DataBuffer WriteMessage(const td::protocol::pdata::PredictCommand& a_Header);
|
||||||
|
|
||||||
} // namespace sp
|
} // namespace sp
|
||||||
|
|
||||||
|
|
||||||
|
namespace td {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
sp::DataBuffer& operator<<(sp::DataBuffer& a_Buffer, const Vec2<T>& a_Vec) {
|
||||||
|
return a_Buffer << a_Vec.x << a_Vec.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
sp::DataBuffer& operator>>(sp::DataBuffer& a_Buffer, Vec2<T>& a_Vec) {
|
||||||
|
return a_Buffer >> a_Vec.x >> a_Vec.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
sp::DataBuffer& operator<<(sp::DataBuffer& a_Buffer, const Vec3<T>& a_Vec) {
|
||||||
|
return a_Buffer << a_Vec.x << a_Vec.y << a_Vec.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
sp::DataBuffer& operator>>(sp::DataBuffer& a_Buffer, Vec3<T>& a_Vec) {
|
||||||
|
return a_Buffer >> a_Vec.x >> a_Vec.y >> a_Vec.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
sp::DataBuffer& operator<<(sp::DataBuffer& a_Buffer, const Vec4<T>& a_Vec) {
|
||||||
|
return a_Buffer << a_Vec.x << a_Vec.y << a_Vec.z << a_Vec.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
sp::DataBuffer& operator>>(sp::DataBuffer& a_Buffer, Vec4<T>& a_Vec) {
|
||||||
|
return a_Buffer >> a_Vec.x >> a_Vec.y >> a_Vec.z >> a_Vec.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace game {
|
||||||
|
|
||||||
|
sp::DataBuffer& operator<<(sp::DataBuffer& a_Buffer, const TeamCastle& a_Castle);
|
||||||
|
sp::DataBuffer& operator>>(sp::DataBuffer& a_Buffer, TeamCastle& a_Castle);
|
||||||
|
|
||||||
|
sp::DataBuffer& operator<<(sp::DataBuffer& a_Buffer, const ChunkPtr& a_Chunk);
|
||||||
|
sp::DataBuffer& operator>>(sp::DataBuffer& a_Buffer, ChunkPtr& a_Chunk);
|
||||||
|
|
||||||
|
sp::DataBuffer& operator<<(sp::DataBuffer& buffer, const TilePtr& tile);
|
||||||
|
sp::DataBuffer& operator>>(sp::DataBuffer& buffer, TilePtr& tile);
|
||||||
|
|
||||||
|
} // namespace game
|
||||||
|
} // namespace td
|
||||||
|
|||||||
47
src/main.cpp
47
src/main.cpp
@@ -9,11 +9,15 @@
|
|||||||
#include <td/protocol/packet/Packets.h>
|
#include <td/protocol/packet/Packets.h>
|
||||||
|
|
||||||
#include <td/render/renderer/EntityRenderer.h>
|
#include <td/render/renderer/EntityRenderer.h>
|
||||||
#include <td/render/renderer/WorldRenderer.h>
|
|
||||||
#include <td/render/renderer/TowerRenderer.h>
|
#include <td/render/renderer/TowerRenderer.h>
|
||||||
|
#include <td/render/renderer/WorldRenderer.h>
|
||||||
|
|
||||||
#include <td/simulation/RealTimeSimulation.h>
|
#include <td/simulation/RealTimeSimulation.h>
|
||||||
|
|
||||||
|
#include <sp/io/MessageStream.h>
|
||||||
|
#include <sp/io/StdIo.h>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
class WorldApply : public td::protocol::PacketHandler {
|
class WorldApply : public td::protocol::PacketHandler {
|
||||||
private:
|
private:
|
||||||
td::game::World& m_World;
|
td::game::World& m_World;
|
||||||
@@ -32,18 +36,15 @@ class WorldApply : public td::protocol::PacketHandler {
|
|||||||
};
|
};
|
||||||
|
|
||||||
td::game::World GetWorld() {
|
td::game::World GetWorld() {
|
||||||
sp::DataBuffer buffer;
|
auto comp = std::make_shared<sp::ZlibCompress>();
|
||||||
buffer.ReadFile("test/tdmap.tdmap2");
|
|
||||||
|
|
||||||
sp::DataBuffer buffer1 = sp::zlib::Decompress(buffer, 84);
|
std::ifstream fStream("test/tdmap.tdmap2");
|
||||||
buffer.SetReadOffset(buffer.GetReadOffset() + 83);
|
auto out = std::make_shared<sp::StdInput>(fStream);
|
||||||
sp::DataBuffer buffer2 = sp::zlib::Decompress(buffer, 511);
|
|
||||||
|
|
||||||
td::protocol::packets::WorldHeaderPacket header;
|
sp::MessageStream<td::protocol::PacketFactory> stream(std::move(out), std::move(comp));
|
||||||
header.Read(buffer1);
|
|
||||||
|
|
||||||
td::protocol::packets::WorldDataPacket data;
|
auto header = stream.ReadMessage();
|
||||||
data.Read(buffer2);
|
auto data = stream.ReadMessage();
|
||||||
|
|
||||||
td::game::World w;
|
td::game::World w;
|
||||||
WorldApply wa(w);
|
WorldApply wa(w);
|
||||||
@@ -52,12 +53,24 @@ td::game::World GetWorld() {
|
|||||||
d.RegisterHandler(td::protocol::PacketID::WorldData, &wa);
|
d.RegisterHandler(td::protocol::PacketID::WorldData, &wa);
|
||||||
d.RegisterHandler(td::protocol::PacketID::WorldHeader, &wa);
|
d.RegisterHandler(td::protocol::PacketID::WorldHeader, &wa);
|
||||||
|
|
||||||
d.Dispatch(header);
|
d.Dispatch(*header);
|
||||||
d.Dispatch(data);
|
d.Dispatch(*data);
|
||||||
|
|
||||||
return w;
|
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) {
|
void FastForward(td::game::World& a_World, const td::sim::GameHistory& a_LockSteps) {
|
||||||
@@ -81,6 +94,7 @@ td::sim::GameHistory GetCustomHistory() {
|
|||||||
return gh;
|
return gh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
td::game::World w = GetWorld();
|
td::game::World w = GetWorld();
|
||||||
|
|
||||||
@@ -89,9 +103,7 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
td::render::Camera cam;
|
td::render::Camera cam;
|
||||||
|
|
||||||
display.OnAspectRatioChange.Connect([&cam](float a_AspectRatio){
|
display.OnAspectRatioChange.Connect([&cam](float a_AspectRatio) { cam.UpdatePerspective(a_AspectRatio); });
|
||||||
cam.UpdatePerspective(a_AspectRatio);
|
|
||||||
});
|
|
||||||
|
|
||||||
td::sim::GameHistory gh = GetCustomHistory();
|
td::sim::GameHistory gh = GetCustomHistory();
|
||||||
|
|
||||||
@@ -105,9 +117,10 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
td::sim::RealTimeSimulation simulation(w, 500);
|
td::sim::RealTimeSimulation simulation(w, 500);
|
||||||
|
|
||||||
display.OnKeyDown.Connect([&simulation](SDL_Keycode key){
|
display.OnKeyDown.Connect([&simulation](SDL_Keycode key) {
|
||||||
if (key == SDLK_A) {
|
if (key == SDLK_A) {
|
||||||
auto spawn = std::make_shared<td::protocol::commands::SpawnTroopCommand>(0, 0, td::Vec2fp{td::FpFloat(77), td::FpFloat(13)}, 0);
|
auto spawn =
|
||||||
|
std::make_shared<td::protocol::commands::SpawnTroopCommand>(0, 0, td::Vec2fp{td::FpFloat(77), td::FpFloat(13)}, 0);
|
||||||
td::Array<td::protocol::LockStep, LOCKSTEP_BUFFER_SIZE> steps{};
|
td::Array<td::protocol::LockStep, LOCKSTEP_BUFFER_SIZE> steps{};
|
||||||
steps[0].push_back(spawn);
|
steps[0].push_back(spawn);
|
||||||
td::protocol::packets::LockStepsPacket packet{0, steps};
|
td::protocol::packets::LockStepsPacket packet{0, steps};
|
||||||
|
|||||||
@@ -40,10 +40,10 @@ bool World::LoadMap(const protocol::pdata::WorldHeader& a_WorldHeader) {
|
|||||||
m_SpawnColorPalette = a_WorldHeader.m_SpawnColorPalette;
|
m_SpawnColorPalette = a_WorldHeader.m_SpawnColorPalette;
|
||||||
|
|
||||||
GetRedTeam().GetCastle() = a_WorldHeader.m_RedCastle;
|
GetRedTeam().GetCastle() = a_WorldHeader.m_RedCastle;
|
||||||
GetRedTeam().GetCastle().SetTeam(&GetRedTeam());
|
// GetRedTeam().GetCastle().SetTeam(&GetRedTeam());
|
||||||
|
|
||||||
GetBlueTeam().GetCastle() = a_WorldHeader.m_BlueCastle;
|
GetBlueTeam().GetCastle() = a_WorldHeader.m_BlueCastle;
|
||||||
GetBlueTeam().GetCastle().SetTeam(&GetBlueTeam());
|
// GetBlueTeam().GetCastle().SetTeam(&GetBlueTeam());
|
||||||
|
|
||||||
m_TilePalette = a_WorldHeader.m_TilePalette;
|
m_TilePalette = a_WorldHeader.m_TilePalette;
|
||||||
|
|
||||||
|
|||||||
@@ -5,40 +5,7 @@
|
|||||||
namespace td {
|
namespace td {
|
||||||
namespace game {
|
namespace game {
|
||||||
|
|
||||||
sp::DataBuffer& operator>>(sp::DataBuffer& buffer, TileType& tile) {
|
|
||||||
std::uint8_t raw;
|
|
||||||
buffer >> raw;
|
|
||||||
tile = TileType(raw);
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
sp::DataBuffer& operator>>(sp::DataBuffer& buffer, TilePtr& tile) {
|
|
||||||
game::TileType tileType;
|
|
||||||
buffer >> tileType;
|
|
||||||
switch (tileType) {
|
|
||||||
case game::TileType::Tower: {
|
|
||||||
auto tilePtr = std::make_shared<game::TowerTile>();
|
|
||||||
buffer >> tilePtr->color_palette_ref >> tilePtr->team_owner;
|
|
||||||
tile = tilePtr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case game::TileType::Walk: {
|
|
||||||
auto tilePtr = std::make_shared<game::WalkableTile>();
|
|
||||||
buffer >> tilePtr->direction;
|
|
||||||
tile = tilePtr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case game::TileType::Decoration: {
|
|
||||||
auto tilePtr = std::make_shared<game::DecorationTile>();
|
|
||||||
buffer >> tilePtr->color_palette_ref;
|
|
||||||
tile = tilePtr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace game
|
} // namespace game
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
|||||||
79
src/td/protocol/packet/ChunkSerialize.cpp
Normal file
79
src/td/protocol/packet/ChunkSerialize.cpp
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace game
|
||||||
|
} // namespace td
|
||||||
@@ -1,113 +1,88 @@
|
|||||||
|
#include <td/protocol/packet/PacketData.h>
|
||||||
#include <td/protocol/packet/PacketSerialize.h>
|
#include <td/protocol/packet/PacketSerialize.h>
|
||||||
|
|
||||||
#include <sp/io/MessageIO.h>
|
|
||||||
|
|
||||||
namespace sp {
|
namespace sp {
|
||||||
|
|
||||||
template <>
|
// temp
|
||||||
void ReadMessage(DataBuffer& a_Buffer, td::protocol::pdata::WorldHeader& a_Header) {
|
template<>
|
||||||
a_Buffer >> a_Header.m_TowerPlacePalette >> a_Header.m_WalkablePalette;
|
void ReadMessage(DataBuffer& a_Buffer, td::protocol::pdata::PredictCommand& a_Header){}
|
||||||
|
|
||||||
std::uint16_t decoPaletteSize;
|
template<>
|
||||||
a_Buffer >> decoPaletteSize;
|
DataBuffer WriteMessage(const td::protocol::pdata::PredictCommand& a_Header){}
|
||||||
|
|
||||||
std::size_t decoPalletteSizeByte = decoPaletteSize * sizeof(td::Color);
|
} // namespace sp
|
||||||
|
|
||||||
a_Header.m_DecorationPalette.resize(decoPaletteSize);
|
namespace td {
|
||||||
|
namespace game {
|
||||||
|
|
||||||
memcpy(reinterpret_cast<std::uint8_t*>(a_Header.m_DecorationPalette.data()), a_Buffer.data() + a_Buffer.GetReadOffset(),
|
sp::DataBuffer& operator<<(sp::DataBuffer& a_Buffer, const TeamCastle& a_Castle) {
|
||||||
decoPalletteSizeByte);
|
return a_Buffer << a_Castle.GetCenterX() << a_Castle.GetCenterY();
|
||||||
|
|
||||||
a_Buffer.SetReadOffset(a_Buffer.GetReadOffset() + decoPalletteSizeByte);
|
|
||||||
|
|
||||||
a_Buffer >> a_Header.m_Background;
|
|
||||||
|
|
||||||
td::utils::shape::Rectangle redCastle, blueCastle;
|
|
||||||
|
|
||||||
a_Buffer >> a_Header.m_RedSpawn >> redCastle;
|
|
||||||
a_Buffer >> a_Header.m_BlueSpawn >> blueCastle;
|
|
||||||
|
|
||||||
a_Header.m_RedCastle.SetShape(redCastle);
|
|
||||||
a_Header.m_BlueCastle.SetShape(blueCastle);
|
|
||||||
|
|
||||||
std::uint64_t tilePaletteSize;
|
|
||||||
a_Buffer >> tilePaletteSize;
|
|
||||||
|
|
||||||
a_Header.m_TilePalette.reserve(tilePaletteSize);
|
|
||||||
|
|
||||||
for (std::uint64_t tileNumber = 0; tileNumber < tilePaletteSize; tileNumber++) {
|
|
||||||
td::game::TilePtr tile;
|
|
||||||
a_Buffer >> tile;
|
|
||||||
a_Header.m_TilePalette.push_back(tile);
|
|
||||||
}
|
|
||||||
|
|
||||||
a_Buffer >> a_Header.m_SpawnColorPalette;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef std::vector<uint64_t> ChunkPackedData;
|
sp::DataBuffer& operator>>(sp::DataBuffer& a_Buffer, TeamCastle& a_Castle) {
|
||||||
|
float x, y;
|
||||||
const int BITS_IN_BYTE = 8;
|
a_Buffer >> x >> y;
|
||||||
const int BITS_IN_LONG = BITS_IN_BYTE * sizeof(std::uint64_t);
|
a_Castle.SetCenter({x, y});
|
||||||
|
return a_Buffer;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sp::DataBuffer& operator<<(sp::DataBuffer& buffer, const TilePtr& tile) {
|
||||||
|
buffer << tile->GetType();
|
||||||
|
|
||||||
template <>
|
switch (tile->GetType()) {
|
||||||
void ReadMessage(DataBuffer& a_Buffer, td::protocol::pdata::WorldData& a_WorldData) {
|
|
||||||
std::uint64_t chunkCount;
|
|
||||||
a_Buffer >> chunkCount;
|
|
||||||
|
|
||||||
for (std::uint64_t chunkNumber = 0; chunkNumber < chunkCount; chunkNumber++) {
|
case game::TileType::Tower: {
|
||||||
td::game::ChunkPtr chunk = std::make_shared<td::game::Chunk>();
|
const game::TowerTile* towerTile = dynamic_cast<const game::TowerTile*>(tile.get());
|
||||||
|
buffer << towerTile->color_palette_ref << towerTile->team_owner;
|
||||||
td::game::ChunkCoord chunkCoords;
|
break;
|
||||||
a_Buffer >> chunkCoords.x >> chunkCoords.y;
|
|
||||||
|
|
||||||
std::uint64_t chunkPaletteSize;
|
|
||||||
// std::reverse(reinterpret_cast<std::uint8_t*>(&chunkPaletteSize), reinterpret_cast<std::uint8_t*>(&chunkPaletteSize) + 4);
|
|
||||||
a_Buffer >> chunkPaletteSize;
|
|
||||||
|
|
||||||
td::game::ChunkPalette chunkPalette(chunkPaletteSize);
|
|
||||||
|
|
||||||
memcpy(reinterpret_cast<void*>(chunkPalette.data()), a_Buffer.data() + a_Buffer.GetReadOffset(),
|
|
||||||
chunkPaletteSize * sizeof(td::game::ChunkPalette::value_type));
|
|
||||||
a_Buffer.SetReadOffset(a_Buffer.GetReadOffset() + chunkPaletteSize * sizeof(td::game::ChunkPalette::value_type));
|
|
||||||
|
|
||||||
chunk->palette = chunkPalette;
|
|
||||||
|
|
||||||
std::uint8_t bitsPerTile = countBits(chunkPaletteSize);
|
|
||||||
|
|
||||||
// A bitmask that contains bitsPerTile set bits
|
|
||||||
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);
|
|
||||||
|
|
||||||
memcpy(reinterpret_cast<void*>(chunkData.data()), a_Buffer.data() + a_Buffer.GetReadOffset(),
|
|
||||||
chunkData.size() * sizeof(ChunkPackedData::value_type));
|
|
||||||
a_Buffer.SetReadOffset(a_Buffer.GetReadOffset() + chunkData.size() * sizeof(ChunkPackedData::value_type));
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
chunk->tiles[tileNumber] = value;
|
|
||||||
}
|
}
|
||||||
a_WorldData.m_Chunks.insert({chunkCoords, chunk});
|
|
||||||
|
case game::TileType::Walk: {
|
||||||
|
const game::WalkableTile* walkTile = dynamic_cast<const game::WalkableTile*>(tile.get());
|
||||||
|
buffer << walkTile->direction;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case game::TileType::Decoration: {
|
||||||
|
const game::DecorationTile* decoTile = dynamic_cast<const game::DecorationTile*>(tile.get());
|
||||||
|
buffer << decoTile->color_palette_ref;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sp
|
sp::DataBuffer& operator>>(sp::DataBuffer& buffer, TilePtr& tile) {
|
||||||
|
game::TileType tileType;
|
||||||
|
buffer >> tileType;
|
||||||
|
switch (tileType) {
|
||||||
|
case game::TileType::Tower: {
|
||||||
|
auto tilePtr = std::make_shared<game::TowerTile>();
|
||||||
|
buffer >> tilePtr->color_palette_ref >> tilePtr->team_owner;
|
||||||
|
tile = tilePtr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case game::TileType::Walk: {
|
||||||
|
auto tilePtr = std::make_shared<game::WalkableTile>();
|
||||||
|
buffer >> tilePtr->direction;
|
||||||
|
tile = tilePtr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case game::TileType::Decoration: {
|
||||||
|
auto tilePtr = std::make_shared<game::DecorationTile>();
|
||||||
|
buffer >> tilePtr->color_palette_ref;
|
||||||
|
tile = tilePtr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace game
|
||||||
|
} // namespace td
|
||||||
|
|||||||
@@ -17,10 +17,7 @@ GL::VertexArray LoadWorldModel(const td::game::World* world) {
|
|||||||
std::vector<float> positions;
|
std::vector<float> positions;
|
||||||
std::vector<float> colors;
|
std::vector<float> colors;
|
||||||
|
|
||||||
for (const auto& chunkInfo : world->GetChunks()) {
|
for (const auto& [coords, chunk] : world->GetChunks()) {
|
||||||
const td::game::ChunkCoord& coords = chunkInfo.first;
|
|
||||||
td::game::ChunkPtr chunk = chunkInfo.second;
|
|
||||||
|
|
||||||
std::int32_t chunkX = coords.x * td::game::Chunk::ChunkWidth;
|
std::int32_t chunkX = coords.x * td::game::Chunk::ChunkWidth;
|
||||||
std::int32_t chunkY = coords.y * td::game::Chunk::ChunkHeight;
|
std::int32_t chunkY = coords.y * td::game::Chunk::ChunkHeight;
|
||||||
|
|
||||||
|
|||||||
BIN
test/tdmap.tdmap
Normal file
BIN
test/tdmap.tdmap
Normal file
Binary file not shown.
Binary file not shown.
@@ -3,7 +3,7 @@ add_rules("mode.debug", "mode.release")
|
|||||||
add_repositories("persson-repo https://git.ale-pri.com/Persson-dev/xmake-repo.git")
|
add_repositories("persson-repo https://git.ale-pri.com/Persson-dev/xmake-repo.git")
|
||||||
|
|
||||||
add_requires("imgui 1.92.0", {configs = {sdl3 = true, opengl3 = true}})
|
add_requires("imgui 1.92.0", {configs = {sdl3 = true, opengl3 = true}})
|
||||||
add_requires("splib 2.0.0", "zlib")
|
add_requires("splib 2.0.1", "zlib")
|
||||||
add_requires("libsdl3 3.2.16", "glew", "fpm", "enet6")
|
add_requires("libsdl3 3.2.16", "glew", "fpm", "enet6")
|
||||||
|
|
||||||
set_languages("c++17")
|
set_languages("c++17")
|
||||||
|
|||||||
Reference in New Issue
Block a user