#pragma once #include #include #include namespace blitz { namespace protocol { class PlayerInfo; #define Operators(Type, GodotType) \ ByteBuffer& operator>>(Type& a_Data) { \ a_Data = m_Buffer.decode_##GodotType(m_ReadOffset); \ m_ReadOffset += sizeof(a_Data); \ return *this; \ } \ \ ByteBuffer& operator<<(Type a_Data) { \ m_Buffer.resize(m_Buffer.size() + sizeof(a_Data)); \ m_Buffer.encode_##GodotType(m_Buffer.size() - sizeof(a_Data), a_Data); \ return *this; \ } class ByteBuffer { private: godot::PackedByteArray m_Buffer; std::size_t m_ReadOffset; public: ByteBuffer(godot::PackedByteArray&& a_Buffer) : m_Buffer(std::move(a_Buffer)), m_ReadOffset(0) {} ByteBuffer() : m_ReadOffset(0) { m_Buffer.resize(0); } const godot::PackedByteArray& GetByteArray() const { return m_Buffer; } godot::PackedByteArray& GetByteArray() { return m_Buffer; } // Integers Operators(int8_t, s8); Operators(uint8_t, u8); Operators(int16_t, s16); Operators(uint16_t, u16); Operators(int32_t, s32); Operators(uint32_t, u32); Operators(int64_t, s64); Operators(uint64_t, u64); // Reals Operators(float, float); Operators(double, double); ByteBuffer& operator<<(const godot::String& a_Data); ByteBuffer& operator>>(godot::String& a_Data); ByteBuffer& operator<<(const godot::Vector3& a_Data); ByteBuffer& operator>>(godot::Vector3& a_Data); template ByteBuffer& operator<<(const std::vector& a_Data) { *this << static_cast(a_Data.size()); for (const T& data : a_Data) { *this << data; } return *this; } template ByteBuffer& operator>>(std::vector& a_Data) { std::uint32_t arraySize; *this >> arraySize; a_Data.resize(arraySize); for (std::uint32_t i = 0; i < arraySize; i++) { *this >> a_Data[i]; } return *this; } ByteBuffer& operator<<(const PlayerInfo& a_Data); ByteBuffer& operator>>(PlayerInfo& a_Data); }; } // namespace protocol } // namespace blitz