feat: allow map edition with exteral tools
This commit is contained in:
@@ -33,6 +33,25 @@ enum class PacketType : std::uint8_t {
|
|||||||
WorldRemoveTower,
|
WorldRemoveTower,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct WorldHeader {
|
||||||
|
game::TowerTileColorPalette m_TowerPlacePalette;
|
||||||
|
game::Color m_WalkablePalette;
|
||||||
|
std::vector<game::Color> m_DecorationPalette;
|
||||||
|
|
||||||
|
game::SpawnColorPalette m_SpawnColorPalette;
|
||||||
|
|
||||||
|
game::TilePalette m_TilePalette;
|
||||||
|
|
||||||
|
game::Spawn m_RedSpawn, m_BlueSpawn;
|
||||||
|
game::TeamCastle m_RedCastle, m_BlueCastle;
|
||||||
|
|
||||||
|
const game::World* m_World;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WorldData {
|
||||||
|
std::unordered_map<game::ChunkCoord, game::ChunkPtr> m_Chunks;
|
||||||
|
};
|
||||||
|
|
||||||
class Packet {
|
class Packet {
|
||||||
public:
|
public:
|
||||||
Packet() {}
|
Packet() {}
|
||||||
@@ -83,21 +102,12 @@ public:
|
|||||||
|
|
||||||
class WorldBeginDataPacket : public Packet {
|
class WorldBeginDataPacket : public Packet {
|
||||||
private:
|
private:
|
||||||
game::TowerTileColorPalette m_TowerPlacePalette;
|
WorldHeader m_Header;
|
||||||
game::Color m_WalkablePalette;
|
|
||||||
std::vector<game::Color> m_DecorationPalette;
|
|
||||||
|
|
||||||
game::SpawnColorPalette m_SpawnColorPalette;
|
|
||||||
|
|
||||||
game::TilePalette m_TilePalette;
|
|
||||||
|
|
||||||
game::Spawn m_RedSpawn, m_BlueSpawn;
|
|
||||||
game::TeamCastle m_RedTower, m_BlueTower;
|
|
||||||
|
|
||||||
const game::World* m_World;
|
|
||||||
public:
|
public:
|
||||||
WorldBeginDataPacket() {}
|
WorldBeginDataPacket() {}
|
||||||
WorldBeginDataPacket(const game::World* world) : m_World(world) {}
|
WorldBeginDataPacket(const game::World* world) {
|
||||||
|
m_Header.m_World = world;
|
||||||
|
}
|
||||||
virtual ~WorldBeginDataPacket() {}
|
virtual ~WorldBeginDataPacket() {}
|
||||||
|
|
||||||
virtual DataBuffer Serialize() const;
|
virtual DataBuffer Serialize() const;
|
||||||
@@ -106,24 +116,27 @@ public:
|
|||||||
|
|
||||||
virtual PacketType getType() const { return PacketType::WorldBeginData; }
|
virtual PacketType getType() const { return PacketType::WorldBeginData; }
|
||||||
|
|
||||||
const game::TowerTileColorPalette& getTowerTilePalette() const { return m_TowerPlacePalette; }
|
const game::TowerTileColorPalette& getTowerTilePalette() const { return m_Header.m_TowerPlacePalette; }
|
||||||
const game::Color& getWalkableTileColor() const { return m_WalkablePalette; }
|
const game::Color& getWalkableTileColor() const { return m_Header.m_WalkablePalette; }
|
||||||
const std::vector<game::Color>& getDecorationPalette() const { return m_DecorationPalette; }
|
const std::vector<game::Color>& getDecorationPalette() const { return m_Header.m_DecorationPalette; }
|
||||||
|
|
||||||
const game::Spawn& getRedSpawn() const { return m_RedSpawn; }
|
const game::Spawn& getRedSpawn() const { return m_Header.m_RedSpawn; }
|
||||||
const game::Spawn& getBlueSpawn() const { return m_BlueSpawn; }
|
const game::Spawn& getBlueSpawn() const { return m_Header.m_BlueSpawn; }
|
||||||
|
|
||||||
const game::SpawnColorPalette& getSpawnPalette() const { return m_SpawnColorPalette; }
|
const game::SpawnColorPalette& getSpawnPalette() const { return m_Header.m_SpawnColorPalette; }
|
||||||
|
|
||||||
const game::TeamCastle& getRedCastle() const { return m_RedTower; }
|
const game::TeamCastle& getRedCastle() const { return m_Header.m_RedCastle; }
|
||||||
const game::TeamCastle& getBlueCastle() const { return m_BlueTower; }
|
const game::TeamCastle& getBlueCastle() const { return m_Header.m_BlueCastle; }
|
||||||
|
|
||||||
const game::TilePalette getTilePalette() const { return m_TilePalette; }
|
const game::TilePalette getTilePalette() const { return m_Header.m_TilePalette; }
|
||||||
|
|
||||||
|
DataBuffer SerializeCustom() const; // allow serialisation with invalid World member
|
||||||
|
void setWorldHeader(const WorldHeader& header) { m_Header = header; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class WorldDataPacket : public Packet {
|
class WorldDataPacket : public Packet {
|
||||||
private:
|
private:
|
||||||
std::unordered_map<game::ChunkCoord, game::ChunkPtr> m_Chunks;
|
WorldData m_WorldData;
|
||||||
|
|
||||||
const game::World* m_World;
|
const game::World* m_World;
|
||||||
public:
|
public:
|
||||||
@@ -137,7 +150,10 @@ public:
|
|||||||
|
|
||||||
virtual PacketType getType() const { return PacketType::WorldData; }
|
virtual PacketType getType() const { return PacketType::WorldData; }
|
||||||
|
|
||||||
const std::unordered_map<game::ChunkCoord, game::ChunkPtr>& getChunks() const { return m_Chunks; }
|
const std::unordered_map<game::ChunkCoord, game::ChunkPtr>& getChunks() const { return m_WorldData.m_Chunks; }
|
||||||
|
|
||||||
|
DataBuffer SerializeCustom() const; // allow serialisation with invalid World member
|
||||||
|
void setWorldData(const WorldData& worldData) { m_WorldData = worldData; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class UpdateMoneyPacket : public Packet {
|
class UpdateMoneyPacket : public Packet {
|
||||||
|
|||||||
@@ -77,12 +77,12 @@ void PlayerLoginPacket::Deserialize(DataBuffer& data) {
|
|||||||
data >> m_PlayerName;
|
data >> m_PlayerName;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataBuffer WorldBeginDataPacket::Serialize() const {
|
DataBuffer WorldBeginDataPacket::SerializeCustom() const {
|
||||||
DataBuffer data;
|
DataBuffer data;
|
||||||
const game::TowerTileColorPalette towerTilePalette = m_World->getTowerTileColorPalette();
|
const game::TowerTileColorPalette towerTilePalette = m_Header.m_TowerPlacePalette;
|
||||||
const std::vector<game::Color>& decoTilePalette = m_World->getDecorationPalette();
|
const std::vector<game::Color>& decoTilePalette = m_Header.m_DecorationPalette;
|
||||||
|
|
||||||
data << getID() << towerTilePalette << m_World->getWalkableTileColor()
|
data << getID() << towerTilePalette << m_Header.m_WalkablePalette
|
||||||
<< (std::uint16_t)decoTilePalette.size();
|
<< (std::uint16_t)decoTilePalette.size();
|
||||||
|
|
||||||
// deco color palette
|
// deco color palette
|
||||||
@@ -91,57 +91,132 @@ DataBuffer WorldBeginDataPacket::Serialize() const {
|
|||||||
|
|
||||||
memcpy((std::uint8_t*)data.data() + bufferSize, decoTilePalette.data(), decoTilePalette.size() * sizeof(game::Color));
|
memcpy((std::uint8_t*)data.data() + bufferSize, decoTilePalette.data(), decoTilePalette.size() * sizeof(game::Color));
|
||||||
|
|
||||||
const game::Spawn& redSpawn = m_World->getRedTeam().getSpawn(), blueSpawn = m_World->getBlueTeam().getSpawn();
|
const game::Spawn& redSpawn = m_Header.m_RedSpawn, blueSpawn = m_Header.m_BlueSpawn;
|
||||||
const game::TeamCastle& redCastle = m_World->getRedTeam().getCastle(), blueCastle = m_World->getBlueTeam().getCastle();
|
const game::TeamCastle& redCastle = m_Header.m_RedCastle, blueCastle = m_Header.m_BlueCastle;
|
||||||
|
|
||||||
data << redSpawn << redCastle;
|
data << redSpawn << redCastle;
|
||||||
data << blueSpawn << blueCastle;
|
data << blueSpawn << blueCastle;
|
||||||
|
|
||||||
// tile palette
|
// tile palette
|
||||||
data << m_World->getTilePalette().size();
|
data << m_Header.m_TilePalette.size();
|
||||||
|
|
||||||
for (game::TilePtr tile : m_World->getTilePalette()) {
|
for (game::TilePtr tile : m_Header.m_TilePalette) {
|
||||||
data << tile;
|
data << tile;
|
||||||
}
|
}
|
||||||
|
|
||||||
data << m_World->getSpawnColors();
|
data << m_Header.m_SpawnColorPalette;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataBuffer WorldBeginDataPacket::Serialize() const {
|
||||||
|
DataBuffer data;
|
||||||
|
const game::TowerTileColorPalette towerTilePalette = m_Header.m_World->getTowerTileColorPalette();
|
||||||
|
const std::vector<game::Color>& decoTilePalette = m_Header.m_World->getDecorationPalette();
|
||||||
|
|
||||||
|
data << getID() << towerTilePalette << m_Header.m_World->getWalkableTileColor()
|
||||||
|
<< (std::uint16_t)decoTilePalette.size();
|
||||||
|
|
||||||
|
// deco color palette
|
||||||
|
std::size_t bufferSize = data.GetSize();
|
||||||
|
data.Resize(bufferSize + decoTilePalette.size() * sizeof(game::Color));
|
||||||
|
|
||||||
|
memcpy((std::uint8_t*)data.data() + bufferSize, decoTilePalette.data(), decoTilePalette.size() * sizeof(game::Color));
|
||||||
|
|
||||||
|
const game::Spawn& redSpawn = m_Header.m_World->getRedTeam().getSpawn(), blueSpawn = m_Header.m_World->getBlueTeam().getSpawn();
|
||||||
|
const game::TeamCastle& redCastle = m_Header.m_World->getRedTeam().getCastle(), blueCastle = m_Header.m_World->getBlueTeam().getCastle();
|
||||||
|
|
||||||
|
data << redSpawn << redCastle;
|
||||||
|
data << blueSpawn << blueCastle;
|
||||||
|
|
||||||
|
// tile palette
|
||||||
|
data << m_Header.m_World->getTilePalette().size();
|
||||||
|
|
||||||
|
for (game::TilePtr tile : m_Header.m_World->getTilePalette()) {
|
||||||
|
data << tile;
|
||||||
|
}
|
||||||
|
|
||||||
|
data << m_Header.m_World->getSpawnColors();
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldBeginDataPacket::Deserialize(DataBuffer& data) {
|
void WorldBeginDataPacket::Deserialize(DataBuffer& data) {
|
||||||
data >> m_TowerPlacePalette >> m_WalkablePalette;
|
data >> m_Header.m_TowerPlacePalette >> m_Header.m_WalkablePalette;
|
||||||
|
|
||||||
std::uint16_t decoPaletteSize;
|
std::uint16_t decoPaletteSize;
|
||||||
data >> decoPaletteSize;
|
data >> decoPaletteSize;
|
||||||
|
|
||||||
std::size_t decoPalletteSizeByte = decoPaletteSize * sizeof(game::Color);
|
std::size_t decoPalletteSizeByte = decoPaletteSize * sizeof(game::Color);
|
||||||
|
|
||||||
m_DecorationPalette.reserve(decoPaletteSize);
|
m_Header.m_DecorationPalette.reserve(decoPaletteSize);
|
||||||
|
|
||||||
memcpy((void*)m_DecorationPalette.data(), data.data() + data.GetReadOffset(), decoPalletteSizeByte);
|
memcpy((void*)m_Header.m_DecorationPalette.data(), data.data() + data.GetReadOffset(), decoPalletteSizeByte);
|
||||||
|
|
||||||
data.SetReadOffset(data.GetReadOffset() + decoPalletteSizeByte);
|
data.SetReadOffset(data.GetReadOffset() + decoPalletteSizeByte);
|
||||||
|
|
||||||
data >> m_RedSpawn >> m_RedTower;
|
data >> m_Header.m_RedSpawn >> m_Header.m_RedCastle;
|
||||||
data >> m_BlueSpawn >> m_BlueTower;
|
data >> m_Header.m_BlueSpawn >> m_Header.m_BlueCastle;
|
||||||
|
|
||||||
std::uint64_t tilePaletteSize;
|
std::uint64_t tilePaletteSize;
|
||||||
data >> tilePaletteSize;
|
data >> tilePaletteSize;
|
||||||
|
|
||||||
m_TilePalette.reserve(tilePaletteSize);
|
m_Header.m_TilePalette.reserve(tilePaletteSize);
|
||||||
|
|
||||||
for (std::uint64_t tileNumber = 0; tileNumber < tilePaletteSize; tileNumber++) {
|
for (std::uint64_t tileNumber = 0; tileNumber < tilePaletteSize; tileNumber++) {
|
||||||
game::TilePtr tile;
|
game::TilePtr tile;
|
||||||
data >> tile;
|
data >> tile;
|
||||||
m_TilePalette.push_back(tile);
|
m_Header.m_TilePalette.push_back(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
data >> m_SpawnColorPalette;
|
data >> m_Header.m_SpawnColorPalette;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef std::vector<uint64_t> ChunkPackedData;
|
typedef std::vector<uint64_t> ChunkPackedData;
|
||||||
|
|
||||||
|
DataBuffer WorldDataPacket::SerializeCustom() const {
|
||||||
|
DataBuffer data;
|
||||||
|
data << getID() << m_WorldData.m_Chunks.size();
|
||||||
|
for (const auto& pair : m_WorldData.m_Chunks) {
|
||||||
|
game::ChunkCoord coords = pair.first;
|
||||||
|
game::ChunkPtr chunk = pair.second;
|
||||||
|
|
||||||
|
data << coords.first << coords.second << (std::uint64_t)chunk->palette.size();
|
||||||
|
|
||||||
|
std::size_t bufferSize = data.GetSize();
|
||||||
|
data.Resize(data.GetSize() + chunk->palette.size() * sizeof(game::ChunkPalette::value_type));
|
||||||
|
memcpy((std::uint8_t*)data.data() + bufferSize, chunk->palette.data(), chunk->palette.size() * sizeof(game::ChunkPalette::value_type));
|
||||||
|
|
||||||
|
std::uint8_t bitsPerTile = countBits(chunk->palette.size());
|
||||||
|
|
||||||
|
game::ChunkData::value_type individualValueMask = ((1 << bitsPerTile) - 1);
|
||||||
|
|
||||||
|
ChunkPackedData chunkData(game::Chunk::ChunkSize / (BITS_IN_BYTE * sizeof(ChunkPackedData::value_type) / bitsPerTile), 0);
|
||||||
|
|
||||||
|
for (int tileNumber = 0; tileNumber < game::Chunk::ChunkSize; tileNumber++) {
|
||||||
|
int startLong = (tileNumber * bitsPerTile) / BITS_IN_LONG;
|
||||||
|
int startOffset = (tileNumber * bitsPerTile) % BITS_IN_LONG;
|
||||||
|
int endLong = ((tileNumber + 1) * bitsPerTile - 1) / BITS_IN_LONG;
|
||||||
|
|
||||||
|
std::uint64_t value = chunk->tiles[tileNumber];
|
||||||
|
|
||||||
|
value &= individualValueMask;
|
||||||
|
|
||||||
|
|
||||||
|
chunkData[startLong] |= (value << startOffset);
|
||||||
|
|
||||||
|
if (startLong != endLong) {
|
||||||
|
chunkData[endLong] = (value >> (BITS_IN_LONG - startOffset));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bufferSize = data.GetSize();
|
||||||
|
data.Resize(data.GetSize() + chunkData.size() * sizeof(ChunkPackedData::value_type));
|
||||||
|
memcpy((std::uint8_t*)data.data() + bufferSize, chunkData.data(), chunkData.size() * sizeof(ChunkPackedData::value_type));
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
DataBuffer WorldDataPacket::Serialize() const {
|
DataBuffer WorldDataPacket::Serialize() const {
|
||||||
DataBuffer data;
|
DataBuffer data;
|
||||||
data << getID() << m_World->getChunks().size();
|
data << getID() << m_World->getChunks().size();
|
||||||
@@ -233,7 +308,7 @@ void WorldDataPacket::Deserialize(DataBuffer& data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
m_Chunks.insert({ {chunkX, chunkY}, chunk });
|
m_WorldData.m_Chunks.insert({ {chunkX, chunkY}, chunk });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user