#include #include #include #include #include namespace blitz { namespace protocol { namespace PacketSerializer { #define VisitSerialize(ClassName) \ void Visit(const ClassName& a_Packet) override { \ const auto& packetData = a_Packet.m_Data; \ SerializePacketData(packetData); \ } \ \ void SerializePacketData(const ClassName::PacketDataType& a_Packet) #define VisitDeserialize(ClassName) \ void Visit(const ClassName& a_Packet) override { \ auto packetPtr = PacketFactory::CreatePacket(); \ auto& packetData = packetPtr->m_Data; \ \ DeserializePacketData(packetData); \ \ m_Packet = std::move(packetPtr); \ } \ \ void DeserializePacketData(ClassName::PacketDataType& a_Packet) class Serializer : public PacketVisitor { private: Nz::ByteStream& m_Buffer; public: Serializer(Nz::ByteStream& a_Buffer) : m_Buffer(a_Buffer) {} void Serialize(const Packet& a_Packet) { m_Buffer << static_cast(a_Packet.GetType()); Check(a_Packet); } VisitSerialize(packets::PlayerLogin); VisitSerialize(packets::UpdateHealth); VisitSerialize(packets::LoggingSuccess); VisitSerialize(packets::PlayerDeath); VisitSerialize(packets::PlayerJoin); VisitSerialize(packets::PlayerLeave); VisitSerialize(packets::PlayerList); VisitSerialize(packets::PlayerStats); VisitSerialize(packets::ServerConfig); VisitSerialize(packets::ServerTps); VisitSerialize(packets::UpdateGameState); VisitSerialize(packets::KeepAlive); VisitSerialize(packets::Disconnect); VisitSerialize(packets::ChatMessage); VisitSerialize(packets::PlayerPositionAndRotation); VisitSerialize(packets::PlayerShoot); }; class Deserializer : public PacketVisitor { private: Nz::ByteStream& m_Buffer; PacketPtr m_Packet; public: Deserializer(Nz::ByteStream&& a_Buffer) : m_Buffer(a_Buffer) {} bool Deserialize(const PacketPtr& a_Packet) { try { Check(*a_Packet.get()); } catch (std::exception& e) { return false; } return true; } PacketPtr& GetPacket() { return m_Packet; } VisitDeserialize(packets::PlayerLogin); VisitDeserialize(packets::UpdateHealth); VisitDeserialize(packets::LoggingSuccess); VisitDeserialize(packets::PlayerDeath); VisitDeserialize(packets::PlayerJoin); VisitDeserialize(packets::PlayerLeave); VisitDeserialize(packets::PlayerList); VisitDeserialize(packets::PlayerStats); VisitDeserialize(packets::ServerConfig); VisitDeserialize(packets::ServerTps); VisitDeserialize(packets::UpdateGameState); VisitDeserialize(packets::KeepAlive); VisitDeserialize(packets::Disconnect); VisitDeserialize(packets::ChatMessage); VisitDeserialize(packets::PlayerPositionAndRotation); VisitDeserialize(packets::PlayerShoot); }; Nz::ByteArray Serialize(const Packet& a_Packet) { Nz::ByteArray buffer; Nz::ByteStream stream(&buffer, Nz::OpenMode::Write); Serializer serializer(stream); serializer.Serialize(a_Packet); buffer.ShrinkToFit(); return buffer; } std::unique_ptr Deserialize(Nz::ByteArray& a_Data) { Nz::ByteStream stream(&a_Data, Nz::OpenMode::Read); PacketID packetId; stream >> packetId; if (packetId >= static_cast(PacketType::PACKET_COUNT)) return nullptr; PacketType packetType = PacketType(packetId); // for double-dispatch const PacketPtr& emptyPacket = PacketFactory::CreateReadOnlyPacket(packetType); Deserializer deserializer(std::move(stream)); if (deserializer.Deserialize(emptyPacket)) { PacketPtr packet = std::move(deserializer.GetPacket()); return packet; } return nullptr; } //--------------------------------------------- // Packet serializer implementation //---------------------------------------------- void Serializer::SerializePacketData(const data::PlayerLogin& a_Packet) { m_Buffer << a_Packet.m_PlayerName; } void Deserializer::DeserializePacketData(data::PlayerLogin& a_Packet) { m_Buffer >> a_Packet.m_PlayerName; } void Serializer::SerializePacketData(const data::UpdateHealth& a_Packet) { m_Buffer << a_Packet.m_NewHealth; } void Deserializer::DeserializePacketData(data::UpdateHealth& a_Packet) { m_Buffer >> a_Packet.m_NewHealth; } void Serializer::SerializePacketData(const data::LoggingSuccess& a_Packet) {} void Deserializer::DeserializePacketData(data::LoggingSuccess& a_Packet) {} void Serializer::SerializePacketData(const data::PlayerDeath& a_Packet) {} void Deserializer::DeserializePacketData(data::PlayerDeath& a_Packet) {} void Serializer::SerializePacketData(const data::PlayerJoin& a_Packet) {} void Deserializer::DeserializePacketData(data::PlayerJoin& a_Packet) {} void Serializer::SerializePacketData(const data::PlayerLeave& a_Packet) {} void Deserializer::DeserializePacketData(data::PlayerLeave& a_Packet) {} void Serializer::SerializePacketData(const data::PlayerList& a_Packet) {} void Deserializer::DeserializePacketData(data::PlayerList& a_Packet) {} void Serializer::SerializePacketData(const data::PlayerStats& a_Packet) {} void Deserializer::DeserializePacketData(data::PlayerStats& a_Packet) {} void Serializer::SerializePacketData(const data::ServerConfig& a_Packet) {} void Deserializer::DeserializePacketData(data::ServerConfig& a_Packet) {} void Serializer::SerializePacketData(const data::ServerTps& a_Packet) {} void Deserializer::DeserializePacketData(data::ServerTps& a_Packet) {} void Serializer::SerializePacketData(const data::UpdateGameState& a_Packet) {} void Deserializer::DeserializePacketData(data::UpdateGameState& a_Packet) {} void Serializer::SerializePacketData(const data::KeepAlive& a_Packet) {} void Deserializer::DeserializePacketData(data::KeepAlive& a_Packet) {} void Serializer::SerializePacketData(const data::Disconnect& a_Packet) {} void Deserializer::DeserializePacketData(data::Disconnect& a_Packet) {} void Serializer::SerializePacketData(const data::ChatMessage& a_Packet) { m_Buffer << a_Packet.m_Text; } void Deserializer::DeserializePacketData(data::ChatMessage& a_Packet) { m_Buffer >> a_Packet.m_Text; } void Serializer::SerializePacketData(const data::PlayerPositionAndRotation& a_Packet) {} void Deserializer::DeserializePacketData(data::PlayerPositionAndRotation& a_Packet) {} void Serializer::SerializePacketData(const data::PlayerShoot& a_Packet) {} void Deserializer::DeserializePacketData(data::PlayerShoot& a_Packet) {} } // namespace PacketSerializer } // namespace protocol } // namespace blitz