1er commit

This commit is contained in:
2021-08-21 10:14:47 +02:00
commit a99ecf7c2d
99 changed files with 66605 additions and 0 deletions

409
src/protocol/Protocol.cpp Normal file
View File

@@ -0,0 +1,409 @@
#include "protocol/PacketHandler.h"
#include <cmath>
#define REGISTER_DISPATCH_CLASS(className) void className::Dispatch(PacketHandler* handler){handler->HandlePacket(this);}
namespace td {
namespace protocol {
const int BITS_IN_BYTE = 8;
const int BITS_IN_LONG = BITS_IN_BYTE * sizeof(std::uint64_t);
unsigned int countBits(unsigned int number){
// log function in base 2
// take only integer part
return (int)std::log2(number) + 1;
}
DataBuffer& operator<<(DataBuffer& buffer, game::TilePtr tile){
buffer << tile->getType();
switch (tile->getType()){
case game::TileType::Tower:{
const std::shared_ptr<game::TowerTile>& towerTile = (const std::shared_ptr<game::TowerTile>&) tile;
buffer << towerTile->color_palette_ref << towerTile->team_owner;
break;
}
case game::TileType::Walk:{
const std::shared_ptr<game::WalkableTile>& walkTile = (const std::shared_ptr<game::WalkableTile>&) tile;
buffer << walkTile->direction;
break;
}
case game::TileType::Decoration:{
const std::shared_ptr<game::DecorationTile>& decoTile = (const std::shared_ptr<game::DecorationTile>&) tile;
buffer << decoTile->color_palette_ref;
break;
}
}
return buffer;
}
DataBuffer& operator>>(DataBuffer& buffer, game::TilePtr& tile){
game::TileType tileType;
buffer >> tileType;
switch (tileType){
case game::TileType::Tower:{
std::shared_ptr<game::TowerTile> tilePtr = std::make_shared<game::TowerTile>();
buffer >> tilePtr->color_palette_ref >> tilePtr->team_owner;
tile = tilePtr;
break;
}
case game::TileType::Walk:{
std::shared_ptr<game::WalkableTile> tilePtr = std::make_shared<game::WalkableTile>();
buffer >> tilePtr->direction;
tile = tilePtr;
break;
}
case game::TileType::Decoration:{
std::shared_ptr<game::DecorationTile> tilePtr = std::make_shared<game::DecorationTile>();
buffer >> tilePtr->color_palette_ref;
tile = tilePtr;
break;
}
}
return buffer;
}
DataBuffer PlayerLoginPacket::Serialize() const{
DataBuffer data;
data << getID() << m_PlayerName;
return data;
}
void PlayerLoginPacket::Deserialize(DataBuffer& data){
data >> m_PlayerName;
}
DataBuffer WorldBeginDataPacket::Serialize() const{
DataBuffer data;
const game::TowerTileColorPalette towerTilePalette = m_World->getTowerTileColorPalette();
const std::vector<game::Color>& decoTilePalette = m_World->getDecorationPalette();
data << getID() << towerTilePalette << 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((void*)data.data() + bufferSize, decoTilePalette.data(), decoTilePalette.size() * sizeof(game::Color));
const game::Spawn& redSpawn = m_World->getRedSpawn(), blueSpawn = m_World->getBlueSpawn();
const game::TeamCastle& redCastle = m_World->getRedCastle(), blueCastle = m_World->getBlueCastle();
data << redSpawn << redCastle;
data << blueSpawn << blueCastle;
// tile palette
data << m_World->getTilePalette().size();
for (game::TilePtr tile : m_World->getTilePalette()){
data << tile;
}
data << m_World->getSpawnColors();
return data;
}
void WorldBeginDataPacket::Deserialize(DataBuffer& data){
data >> m_TowerPlacePalette >> m_WalkablePalette;
std::uint16_t decoPaletteSize;
data >> decoPaletteSize;
std::size_t decoPalletteSizeByte = decoPaletteSize * sizeof(game::Color);
m_DecorationPalette.reserve(decoPaletteSize);
memcpy((void*)m_DecorationPalette.data(), data.data() + data.GetReadOffset(), decoPalletteSizeByte);
data.SetReadOffset(data.GetReadOffset() + decoPalletteSizeByte);
data >> m_RedSpawn >> m_RedTower;
data >> m_BlueSpawn >> m_BlueTower;
std::size_t tilePaletteSize;
data >> tilePaletteSize;
m_TilePalette.reserve(tilePaletteSize);
for (int i = 0; i < tilePaletteSize; i++){
game::TilePtr tile;
data >> tile;
m_TilePalette.push_back(tile);
}
data >> m_SpawnColorPalette;
}
typedef std::vector<uint64_t> ChunkPackedData;
DataBuffer WorldDataPacket::Serialize() const{
DataBuffer data;
data << getID() << m_World->getChunks().size();
for (const auto& pair : m_World->getChunks()){
game::ChunkCoord coords = pair.first;
game::ChunkPtr chunk = pair.second;
data << coords.first << coords.second << chunk->palette.size();
std::size_t bufferSize = data.GetSize();
data.Resize(data.GetSize() + chunk->palette.size() * sizeof(game::ChunkPalette::value_type));
memcpy((void*)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((void*)data.data() + bufferSize, chunkData.data(), chunkData.size() * sizeof(ChunkPackedData::value_type));
}
return data;
}
void WorldDataPacket::Deserialize(DataBuffer& data){
std::size_t chunkCount;
data >> chunkCount;
for (int chunkNumber = 0; chunkNumber < chunkCount; chunkNumber++){
game::ChunkPtr chunk = std::make_shared<game::Chunk>();
game::ChunkCoord::first_type chunkX, chunkY;
data >> chunkX >> chunkY;
std::size_t chunkPaletteSize;
data >> chunkPaletteSize;
game::ChunkPalette chunkPalette(chunkPaletteSize);
memcpy((void*)chunkPalette.data(), data.data() + data.GetReadOffset(), chunkPaletteSize * sizeof(game::ChunkPalette::value_type));
data.SetReadOffset(data.GetReadOffset() + chunkPaletteSize * sizeof(game::ChunkPalette::value_type));
chunk->palette = chunkPalette;
std::uint8_t bitsPerTile = countBits(chunkPaletteSize);
// A bitmask that contains bitsPerTile set bits
game::ChunkData::value_type individualValueMask = ((1 << bitsPerTile) - 1);
ChunkPackedData chunkData(game::Chunk::ChunkSize / (BITS_IN_BYTE * sizeof(ChunkPackedData::value_type) / bitsPerTile), 0);
memcpy((void*)chunkData.data(), data.data() + data.GetReadOffset(), chunkData.size() * sizeof(ChunkPackedData::value_type));
data.SetReadOffset(data.GetReadOffset() + chunkData.size() * sizeof(ChunkPackedData::value_type));
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;
game::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;
}
m_Chunks.insert({{chunkX, chunkY}, chunk});
}
}
DataBuffer KeepAlivePacket::Serialize() const{
DataBuffer data;
data << getID() << m_AliveID;
return data;
}
void KeepAlivePacket::Deserialize(DataBuffer& data){
data >> m_AliveID;
}
DataBuffer UpdateMoneyPacket::Serialize() const{
DataBuffer data;
data << getID() << m_NewAmount;
return data;
}
void UpdateMoneyPacket::Deserialize(DataBuffer& data){
data >> m_NewAmount;
}
DataBuffer UpdateExpPacket::Serialize() const{
DataBuffer data;
data << getID() << m_NewAmount;
return data;
}
void UpdateExpPacket::Deserialize(DataBuffer& data){
data >> m_NewAmount;
}
DataBuffer UpdateLobbyTimePacket::Serialize() const{
DataBuffer data;
data << getID() << m_RemainingTime;
return data;
}
void UpdateLobbyTimePacket::Deserialize(DataBuffer& data){
data >> m_RemainingTime;
}
DataBuffer UpdateGameStatePacket::Serialize() const{
DataBuffer data;
data << getID() << m_GameState;
return data;
}
void UpdateGameStatePacket::Deserialize(DataBuffer& data){
data >> m_GameState;
}
DataBuffer PlayerListPacket::Serialize() const{
DataBuffer data;
data << getID() << (std::uint8_t)m_Players.size();
for (auto pair : m_Players){
data << pair.first << pair.second.name << pair.second.team;
}
return data;
}
void PlayerListPacket::Deserialize(DataBuffer& data){
std::uint8_t playerCount;
data >> playerCount;
for (int i = 0; i < playerCount; i++){
std::uint8_t playerID;
PlayerInfo playerInfo;
data >> playerID >> playerInfo.name >> playerInfo.team;
m_Players.insert({playerID, playerInfo});
}
}
DataBuffer PlayerJoinPacket::Serialize() const{
DataBuffer data;
data << getID() << m_PlayerID << m_PlayerName;
return data;
}
void PlayerJoinPacket::Deserialize(DataBuffer& data){
data >> m_PlayerID >> m_PlayerName;
}
DataBuffer PlayerLeavePacket::Serialize() const{
DataBuffer data;
data << getID() << m_PlayerID;
return data;
}
void PlayerLeavePacket::Deserialize(DataBuffer& data){
data >> m_PlayerID;
}
DataBuffer ConnexionInfoPacket::Serialize() const{
DataBuffer data;
data << getID() << m_ConnectionID;
return data;
}
void ConnexionInfoPacket::Deserialize(DataBuffer& data){
data >> m_ConnectionID;
}
DataBuffer SelectTeamPacket::Serialize() const{
DataBuffer data;
data << getID() << m_SelectedTeam;
return data;
}
void SelectTeamPacket::Deserialize(DataBuffer& data){
data >> m_SelectedTeam;
}
DataBuffer UpdatePlayerTeamPacket::Serialize() const{
DataBuffer data;
data << getID() << m_PlayerID << m_SelectedTeam;
return data;
}
void UpdatePlayerTeamPacket::Deserialize(DataBuffer& data){
data >> m_PlayerID >> m_SelectedTeam;
}
DataBuffer DisconnectPacket::Serialize() const{
DataBuffer data;
data << getID() << m_Reason;
return data;
}
void DisconnectPacket::Deserialize(DataBuffer& data){
data >> m_Reason;
}
DataBuffer ServerTpsPacket::Serialize() const{
DataBuffer data;
data << getID() << m_TPS << m_PacketSendTime;
return data;
}
void ServerTpsPacket::Deserialize(DataBuffer& data){
data >> m_TPS >> m_PacketSendTime;
}
DataBuffer SpawnMobPacket::Serialize() const{
DataBuffer data;
data << getID() << m_MobID << m_MobType << m_MobLevel << m_MobDirection
<< m_Sender << m_MobX << m_MobY;
return data;
}
void SpawnMobPacket::Deserialize(DataBuffer& data){
data >> m_MobID >> m_MobType >> m_MobLevel >> m_MobDirection
>> m_Sender >> m_MobX >> m_MobY;
}
REGISTER_DISPATCH_CLASS(PlayerLoginPacket);
REGISTER_DISPATCH_CLASS(WorldBeginDataPacket);
REGISTER_DISPATCH_CLASS(WorldDataPacket);
REGISTER_DISPATCH_CLASS(KeepAlivePacket);
REGISTER_DISPATCH_CLASS(UpdateExpPacket);
REGISTER_DISPATCH_CLASS(UpdateMoneyPacket);
REGISTER_DISPATCH_CLASS(UpdateLobbyTimePacket);
REGISTER_DISPATCH_CLASS(UpdateGameStatePacket);
REGISTER_DISPATCH_CLASS(PlayerListPacket);
REGISTER_DISPATCH_CLASS(PlayerJoinPacket);
REGISTER_DISPATCH_CLASS(PlayerLeavePacket);
REGISTER_DISPATCH_CLASS(ConnexionInfoPacket);
REGISTER_DISPATCH_CLASS(SelectTeamPacket);
REGISTER_DISPATCH_CLASS(UpdatePlayerTeamPacket);
REGISTER_DISPATCH_CLASS(DisconnectPacket);
REGISTER_DISPATCH_CLASS(ServerTpsPacket);
REGISTER_DISPATCH_CLASS(SpawnMobPacket);
} // namespace protocol
} // namespace td