declare packets + commands
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <td/common/VarInt.h>
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
@@ -65,19 +66,24 @@ class DataBuffer {
|
|||||||
* \warning Don't use it for binary data !
|
* \warning Don't use it for binary data !
|
||||||
* \param str The string to append
|
* \param str The string to append
|
||||||
*/
|
*/
|
||||||
DataBuffer& operator<<(const std::string& str) {
|
DataBuffer& operator<<(const std::string& str);
|
||||||
std::size_t strlen = str.length() + 1; // including null character
|
|
||||||
Resize(GetSize() + strlen);
|
|
||||||
std::memcpy(m_Buffer.data() + GetSize() - strlen, str.data(), strlen);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Append data to the buffer from another const buffer
|
* \brief Append data to the buffer from another const buffer
|
||||||
* \param data The buffer to append
|
* \param data The buffer to append
|
||||||
*/
|
*/
|
||||||
DataBuffer& operator<<(const DataBuffer& data) {
|
DataBuffer& operator<<(const DataBuffer& data);
|
||||||
m_Buffer.insert(m_Buffer.end(), data.begin(), data.end());
|
|
||||||
|
/**
|
||||||
|
* \brief Append a vector to the buffer by first writing the size
|
||||||
|
* \param data The buffer to append
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
DataBuffer& operator<<(const std::vector<T>& data) {
|
||||||
|
*this << VarInt {data.size()};
|
||||||
|
for (const auto& element : data) {
|
||||||
|
*this << element;
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,25 +102,28 @@ class DataBuffer {
|
|||||||
* \brief Read some data from the buffer and assign to the new buffer
|
* \brief Read some data from the buffer and assign to the new buffer
|
||||||
* \param data The buffer to assign
|
* \param data The buffer to assign
|
||||||
*/
|
*/
|
||||||
DataBuffer& operator>>(DataBuffer& data) {
|
DataBuffer& operator>>(DataBuffer& data);
|
||||||
data.Resize(GetSize() - m_ReadOffset);
|
|
||||||
std::copy(m_Buffer.begin() + static_cast<difference_type>(m_ReadOffset), m_Buffer.end(), data.begin());
|
|
||||||
m_ReadOffset = m_Buffer.size();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Read a string from the buffer
|
* \brief Read a string from the buffer
|
||||||
* \param str The string to assign in the new buffer
|
* \param str The string to assign in the new buffer
|
||||||
* \warning Don't use it for binary data !
|
* \warning Don't use it for binary data !
|
||||||
*/
|
*/
|
||||||
DataBuffer& operator>>(std::string& str) {
|
DataBuffer& operator>>(std::string& str);
|
||||||
std::size_t stringSize =
|
|
||||||
strlen(reinterpret_cast<const char*>(m_Buffer.data()) + m_ReadOffset) + 1; // including null character
|
/**
|
||||||
str.resize(stringSize);
|
* \brief Read a vector (size + data) from the buffer
|
||||||
std::copy(m_Buffer.begin() + static_cast<difference_type>(m_ReadOffset),
|
* \pre The vector is assumed to be empty
|
||||||
m_Buffer.begin() + static_cast<difference_type>(m_ReadOffset + stringSize), str.begin());
|
*/
|
||||||
m_ReadOffset += stringSize;
|
template <typename T>
|
||||||
|
DataBuffer& operator>>(std::vector<T>& data) {
|
||||||
|
VarInt arraySize;
|
||||||
|
*this >> arraySize;
|
||||||
|
for (std::size_t i = 0; i < arraySize.GetValue(); i++) {
|
||||||
|
T newElement;
|
||||||
|
*this >> newElement;
|
||||||
|
data.push_back(newElement);
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,56 +132,35 @@ class DataBuffer {
|
|||||||
* \param buffer The buffer to write
|
* \param buffer The buffer to write
|
||||||
* \param amount The amount of data to write
|
* \param amount The amount of data to write
|
||||||
*/
|
*/
|
||||||
void WriteSome(const char* buffer, std::size_t amount) {
|
void WriteSome(const char* buffer, std::size_t amount);
|
||||||
std::size_t end_pos = m_Buffer.size();
|
|
||||||
m_Buffer.resize(m_Buffer.size() + amount);
|
|
||||||
std::memcpy(m_Buffer.data() + end_pos, buffer, amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Write some data to the buffer
|
* \brief Write some data to the buffer
|
||||||
* \param buffer The buffer to write
|
* \param buffer The buffer to write
|
||||||
* \param amount The amount of data to write
|
* \param amount The amount of data to write
|
||||||
*/
|
*/
|
||||||
void WriteSome(const std::uint8_t* buffer, std::size_t amount) {
|
void WriteSome(const std::uint8_t* buffer, std::size_t amount);
|
||||||
std::size_t end_pos = m_Buffer.size();
|
|
||||||
m_Buffer.resize(m_Buffer.size() + amount);
|
|
||||||
std::memcpy(m_Buffer.data() + end_pos, buffer, amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Read some data from the buffer
|
* \brief Read some data from the buffer
|
||||||
* \param buffer The buffer to Read
|
* \param buffer The buffer to Read
|
||||||
* \param amount The amount of data from the buffer
|
* \param amount The amount of data from the buffer
|
||||||
*/
|
*/
|
||||||
void ReadSome(char* buffer, std::size_t amount) {
|
void ReadSome(char* buffer, std::size_t amount);
|
||||||
assert(m_ReadOffset + amount <= GetSize());
|
|
||||||
std::copy_n(m_Buffer.begin() + static_cast<difference_type>(m_ReadOffset), amount, buffer);
|
|
||||||
m_ReadOffset += amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Read some data from the buffer
|
* \brief Read some data from the buffer
|
||||||
* \param buffer The buffer to Read
|
* \param buffer The buffer to Read
|
||||||
* \param amount The amount of data from the buffer
|
* \param amount The amount of data from the buffer
|
||||||
*/
|
*/
|
||||||
void ReadSome(std::uint8_t* buffer, std::size_t amount) {
|
void ReadSome(std::uint8_t* buffer, std::size_t amount);
|
||||||
assert(m_ReadOffset + amount <= GetSize());
|
|
||||||
std::copy_n(m_Buffer.begin() + static_cast<difference_type>(m_ReadOffset), amount, buffer);
|
|
||||||
m_ReadOffset += amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Read some data from the buffer
|
* \brief Read some data from the buffer
|
||||||
* \param buffer The buffer to Read
|
* \param buffer The buffer to Read
|
||||||
* \param amount The amount of data from the buffer
|
* \param amount The amount of data from the buffer
|
||||||
*/
|
*/
|
||||||
void ReadSome(DataBuffer& buffer, std::size_t amount) {
|
void ReadSome(DataBuffer& buffer, std::size_t amount);
|
||||||
assert(m_ReadOffset + amount <= GetSize());
|
|
||||||
buffer.Resize(amount);
|
|
||||||
std::copy_n(m_Buffer.begin() + static_cast<difference_type>(m_ReadOffset), amount, buffer.begin());
|
|
||||||
m_ReadOffset += amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Resize the buffer
|
* \brief Resize the buffer
|
||||||
|
|||||||
58
include/td/common/VarInt.h
Normal file
58
include/td/common/VarInt.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file VarInt.h
|
||||||
|
* \brief File containing the blitz::VarInt class
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace td {
|
||||||
|
|
||||||
|
class DataBuffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class VarInt
|
||||||
|
* \brief Variable-length format such that smaller numbers use fewer bytes.
|
||||||
|
*/
|
||||||
|
class VarInt {
|
||||||
|
private:
|
||||||
|
std::uint64_t m_Value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
VarInt() : m_Value(0) {}
|
||||||
|
/**
|
||||||
|
* \brief Construct a variable integer from a value
|
||||||
|
* \param value The value of the variable integer
|
||||||
|
*/
|
||||||
|
VarInt(std::uint64_t value) : m_Value(value) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Get the value of the variable integer
|
||||||
|
*/
|
||||||
|
std::uint64_t GetValue() const {
|
||||||
|
return m_Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Get the length of the serialized variable integer
|
||||||
|
*/
|
||||||
|
std::size_t GetSerializedLength() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Serialize the variable integer
|
||||||
|
* \param out The buffer to write the serialized variable integer to
|
||||||
|
* \param var The variable integer to serialize
|
||||||
|
*/
|
||||||
|
friend DataBuffer& operator<<(DataBuffer& out, const VarInt& var);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Deserialize the variable integer
|
||||||
|
* \param in The buffer to read the serialized variable integer from
|
||||||
|
* \param var The variable integer to deserialize
|
||||||
|
*/
|
||||||
|
friend DataBuffer& operator>>(DataBuffer& in, VarInt& var);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace td
|
||||||
38
include/td/misc/Format.h
Normal file
38
include/td/misc/Format.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file Format.h
|
||||||
|
* \brief This file contains the definition of the `Format` function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace td {
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Formats a string using a format string and variadic arguments.
|
||||||
|
*
|
||||||
|
* This function takes a format string and a variable number of arguments and returns a formatted string.
|
||||||
|
* The format string can contain placeholders that will be replaced by the corresponding arguments.
|
||||||
|
*
|
||||||
|
* \param format The format string.
|
||||||
|
* \param args The variadic arguments to be formatted.
|
||||||
|
* \return The formatted string.
|
||||||
|
* \throws std::runtime_error if an error occurs during formatting.
|
||||||
|
*/
|
||||||
|
template <typename... Args>
|
||||||
|
std::string Format(const std::string& format, Args... args) {
|
||||||
|
int size = snprintf(nullptr, 0, format.c_str(), args...) + 1; // Extra space for '\0'
|
||||||
|
if (size <= 0) {
|
||||||
|
throw std::runtime_error("Error during formatting.");
|
||||||
|
}
|
||||||
|
std::unique_ptr<char[]> buf(new char[size]);
|
||||||
|
snprintf(buf.get(), static_cast<std::size_t>(size), format.c_str(), args...);
|
||||||
|
return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace utils
|
||||||
|
} // namespace td
|
||||||
32
include/td/misc/Log.h
Normal file
32
include/td/misc/Log.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file Log.h
|
||||||
|
* \brief File defining log functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace td {
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Logs a normal message.
|
||||||
|
* \param msg The message to be logged.
|
||||||
|
*/
|
||||||
|
void LOG(const std::string& msg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Logs a normal message in debug mode.
|
||||||
|
* \param msg The message to be logged.
|
||||||
|
*/
|
||||||
|
void LOGD(const std::string& msg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Logs an error message.
|
||||||
|
* \param err The error message to be logged.
|
||||||
|
*/
|
||||||
|
void LOGE(const std::string& err);
|
||||||
|
|
||||||
|
} // namespace utils
|
||||||
|
} // namespace td
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <godot_cpp/variant/packed_byte_array.hpp>
|
|
||||||
#include <godot_cpp/variant/string.hpp>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace td {
|
|
||||||
namespace protocol {
|
|
||||||
|
|
||||||
class PlayerInfo;
|
|
||||||
|
|
||||||
class ByteBuffer {
|
|
||||||
private:
|
|
||||||
godot::PackedByteArray m_Buffer;
|
|
||||||
std::size_t m_ReadOffset;
|
|
||||||
|
|
||||||
public:
|
|
||||||
class ReadError : public std::runtime_error {
|
|
||||||
public:
|
|
||||||
ReadError(const std::string& msg) : std::runtime_error(msg) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
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
|
|
||||||
ByteBuffer& operator<<(int8_t a_Data);
|
|
||||||
ByteBuffer& operator>>(int8_t& a_Data);
|
|
||||||
ByteBuffer& operator<<(uint8_t a_Data);
|
|
||||||
ByteBuffer& operator>>(uint8_t& a_Data);
|
|
||||||
|
|
||||||
ByteBuffer& operator<<(int16_t a_Data);
|
|
||||||
ByteBuffer& operator>>(int16_t& a_Data);
|
|
||||||
ByteBuffer& operator<<(uint16_t a_Data);
|
|
||||||
ByteBuffer& operator>>(uint16_t& a_Data);
|
|
||||||
|
|
||||||
ByteBuffer& operator<<(int32_t a_Data);
|
|
||||||
ByteBuffer& operator>>(int32_t& a_Data);
|
|
||||||
ByteBuffer& operator<<(uint32_t a_Data);
|
|
||||||
ByteBuffer& operator>>(uint32_t& a_Data);
|
|
||||||
|
|
||||||
ByteBuffer& operator<<(int64_t a_Data);
|
|
||||||
ByteBuffer& operator>>(int64_t& a_Data);
|
|
||||||
ByteBuffer& operator<<(uint64_t a_Data);
|
|
||||||
ByteBuffer& operator>>(uint64_t& a_Data);
|
|
||||||
|
|
||||||
ByteBuffer& operator<<(float a_Data);
|
|
||||||
ByteBuffer& operator>>(float& a_Data);
|
|
||||||
ByteBuffer& operator<<(double a_Data);
|
|
||||||
ByteBuffer& operator>>(double& a_Data);
|
|
||||||
|
|
||||||
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 <typename T>
|
|
||||||
ByteBuffer& operator<<(const std::vector<T>& a_Data) {
|
|
||||||
*this << static_cast<std::uint32_t>(a_Data.size());
|
|
||||||
for (const T& data : a_Data) {
|
|
||||||
*this << data;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
ByteBuffer& operator>>(std::vector<T>& 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 td
|
|
||||||
@@ -2,25 +2,11 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <td/Types.h>
|
#include <td/Types.h>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
namespace protocol {
|
namespace protocol {
|
||||||
|
|
||||||
#define LOCKSTEP_BUFFER_SIZE 10
|
|
||||||
|
|
||||||
struct LockStepCommand {};
|
|
||||||
|
|
||||||
struct LockStep {
|
|
||||||
std::uint8_t m_CommandNumber;
|
|
||||||
std::vector<LockStepCommand> m_Commands;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LockSteps {
|
|
||||||
std::uint16_t m_FirstFrameNumber;
|
|
||||||
std::array<LockStep, LOCKSTEP_BUFFER_SIZE> m_LockSteps;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
namespace cdata {
|
namespace cdata {
|
||||||
|
|
||||||
|
|
||||||
@@ -58,6 +44,8 @@ struct PlayerJoin {
|
|||||||
std::string m_Name;
|
std::string m_Name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct End {};
|
||||||
|
|
||||||
} // namespace cdata
|
} // namespace cdata
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,15 +6,16 @@ namespace protocol {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* \def DeclareAllPacket
|
* \def DeclareAllPacket
|
||||||
* \brief Avoids repetitive operations on packets
|
* \brief Avoids repetitive operations on commands
|
||||||
*/
|
*/
|
||||||
#define DeclareAllCommand() \
|
#define DeclareAllCommand() \
|
||||||
|
DeclareCommand(End) \
|
||||||
DeclareCommand(PlaceTower) \
|
DeclareCommand(PlaceTower) \
|
||||||
DeclareCommand(UpgradeTower) \
|
DeclareCommand(PlayerJoin) \
|
||||||
DeclareCommand(SpawnTroop) \
|
DeclareCommand(SpawnTroop) \
|
||||||
DeclareCommand(UseItem) \
|
|
||||||
DeclareCommand(TeamChange) \
|
DeclareCommand(TeamChange) \
|
||||||
DeclareCommand(PlayerJoin)
|
DeclareCommand(UpgradeTower) \
|
||||||
|
DeclareCommand(UseItem)
|
||||||
|
|
||||||
|
|
||||||
} // namespace protocol
|
} // namespace protocol
|
||||||
|
|||||||
@@ -6,13 +6,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <td/protocol/Dispatcher.h>
|
#include <td/protocol/Dispatcher.h>
|
||||||
|
#include <td/protocol/command/Commands.h>
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
namespace protocol {
|
namespace protocol {
|
||||||
|
|
||||||
class CommandHandler;
|
using CommandDispatcher = Dispatcher<CommandType, CommandVisitor, Command>;
|
||||||
|
|
||||||
using CommandDispatcher = Dispatcher<CommandType, CommandHandler, Command>;
|
|
||||||
|
|
||||||
} // namespace protocol
|
} // namespace protocol
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file CommandHandler.h
|
|
||||||
* \brief File containing the td::protocol::CommandHandler class
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <td/protocol/command/CommandVisitor.h>
|
|
||||||
#include <td/protocol/command/Commands.h>
|
|
||||||
|
|
||||||
namespace td {
|
|
||||||
namespace protocol {
|
|
||||||
|
|
||||||
#define DeclareCommand(CommandName, ...) \
|
|
||||||
virtual void Visit(const commands::CommandName&); \
|
|
||||||
virtual void HandleCommand(const commands::CommandName&) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \class CommandHandler
|
|
||||||
* \brief Class used to handle packets
|
|
||||||
*/
|
|
||||||
class CommandHandler : public CommandVisitor {
|
|
||||||
public:
|
|
||||||
CommandHandler() {}
|
|
||||||
~CommandHandler() {}
|
|
||||||
|
|
||||||
DeclareAllCommand()
|
|
||||||
};
|
|
||||||
|
|
||||||
#undef DeclareCommand
|
|
||||||
|
|
||||||
} // namespace protocol
|
|
||||||
} // namespace td
|
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <td/common/NonCopyable.h>
|
#include <td/common/NonCopyable.h>
|
||||||
#include <td/protocol/command/CommandData.h>
|
#include <td/protocol/command/CommandData.h>
|
||||||
#include <td/protocol/command/CommandDeclare.h>
|
#include <td/protocol/command/CommandDeclare.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
namespace protocol {
|
namespace protocol {
|
||||||
@@ -104,5 +105,7 @@ DeclareAllCommand()
|
|||||||
|
|
||||||
} // namespace commands
|
} // namespace commands
|
||||||
|
|
||||||
|
using LockStep = std::vector<std::shared_ptr<protocol::Command>>;
|
||||||
|
|
||||||
} // namespace protocol
|
} // namespace protocol
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
#include <td/Types.h>
|
#include <td/Types.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <td/protocol/command/Commands.h>
|
||||||
|
|
||||||
|
// Make it dynamic ?
|
||||||
|
#define LOCKSTEP_BUFFER_SIZE 10
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
namespace protocol {
|
namespace protocol {
|
||||||
@@ -11,64 +15,60 @@ struct PlayerInfo {
|
|||||||
std::string m_PlayerName;
|
std::string m_PlayerName;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MapData {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
namespace pdata {
|
namespace pdata {
|
||||||
|
|
||||||
|
/** Client attempts to login (very basic) */
|
||||||
struct PlayerLogin {
|
struct PlayerLogin {
|
||||||
std::string m_PlayerName;
|
std::string m_PlayerName;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct UpdateHealth {
|
/** Server indicates success */
|
||||||
float m_NewHealth;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LoggingSuccess {
|
struct LoggingSuccess {
|
||||||
PlayerID m_PlayerId;
|
PlayerID m_PlayerId;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PlayerDeath {};
|
/** Player joins the lobby */
|
||||||
|
|
||||||
struct PlayerJoin {
|
struct PlayerJoin {
|
||||||
PlayerInfo m_Player;
|
PlayerInfo m_Player;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Player leaves the lobby */
|
||||||
struct PlayerLeave {
|
struct PlayerLeave {
|
||||||
PlayerID m_PlayerId;
|
PlayerID m_PlayerId;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PlayerStats {};
|
/** Keep alive */
|
||||||
|
|
||||||
struct PlayerList {
|
|
||||||
std::vector<PlayerInfo> m_Players;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ServerConfig {};
|
|
||||||
|
|
||||||
struct ServerTps {};
|
|
||||||
|
|
||||||
struct UpdateGameState {};
|
|
||||||
|
|
||||||
struct KeepAlive {
|
struct KeepAlive {
|
||||||
std::uint64_t m_KeepAliveId;
|
std::uint64_t m_KeepAliveId;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Disconnect {};
|
/** Can be used by both client and server */
|
||||||
|
struct Disconnect {
|
||||||
|
std::string m_Reason;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Chat message */
|
||||||
struct ChatMessage {
|
struct ChatMessage {
|
||||||
std::string m_Text;
|
std::string m_Text;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PlayerPositionAndRotation {
|
// TODO: handle players joining in the first second
|
||||||
PlayerID m_Player;
|
|
||||||
// godot::Vector3 m_Position;
|
struct BeginGame {
|
||||||
// godot::Vector3 m_Rotation;
|
MapData m_Map;
|
||||||
// godot::Vector3 m_Velocity;
|
std::vector<PlayerInfo> m_BlueTeam;
|
||||||
|
std::vector<PlayerInfo> m_RedTeam;
|
||||||
|
// optional, used for players joining mid game
|
||||||
|
std::vector<LockStep> m_FirstLocksteps;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PlayerShoot {
|
struct LockSteps {
|
||||||
PlayerID m_Sender;
|
std::uint16_t m_FirstFrameNumber;
|
||||||
// godot::Vector3 m_Position;
|
std::array<LockStep, LOCKSTEP_BUFFER_SIZE> m_LockSteps;
|
||||||
// godot::Vector3 m_Rotation;
|
|
||||||
// godot::Vector3 m_Velocity;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace pdata
|
} // namespace pdata
|
||||||
|
|||||||
@@ -34,21 +34,14 @@ enum class PacketSendType {
|
|||||||
*/
|
*/
|
||||||
#define DeclareAllPacket() \
|
#define DeclareAllPacket() \
|
||||||
DeclarePacket(ChatMessage, Reliable, Both) \
|
DeclarePacket(ChatMessage, Reliable, Both) \
|
||||||
|
DeclarePacket(BeginGame, Reliable, Server) \
|
||||||
DeclarePacket(Disconnect, Reliable, Both) \
|
DeclarePacket(Disconnect, Reliable, Both) \
|
||||||
DeclarePacket(KeepAlive, Reliable, Both) \
|
DeclarePacket(KeepAlive, Reliable, Both) \
|
||||||
|
DeclarePacket(LockSteps, Unreliable, Both) \
|
||||||
DeclarePacket(LoggingSuccess, Reliable, Server) \
|
DeclarePacket(LoggingSuccess, Reliable, Server) \
|
||||||
DeclarePacket(PlayerDeath, Reliable, Server) \
|
|
||||||
DeclarePacket(PlayerJoin, Reliable, Server) \
|
DeclarePacket(PlayerJoin, Reliable, Server) \
|
||||||
DeclarePacket(PlayerLeave, Reliable, Server) \
|
DeclarePacket(PlayerLeave, Reliable, Server) \
|
||||||
DeclarePacket(PlayerList, Reliable, Server) \
|
|
||||||
DeclarePacket(PlayerLogin, Reliable, Client) \
|
DeclarePacket(PlayerLogin, Reliable, Client) \
|
||||||
DeclarePacket(PlayerPositionAndRotation, Unreliable, Both) \
|
|
||||||
DeclarePacket(PlayerShoot, Reliable, Both) \
|
|
||||||
DeclarePacket(PlayerStats, Reliable, Server) \
|
|
||||||
DeclarePacket(ServerConfig, Reliable, Server) \
|
|
||||||
DeclarePacket(ServerTps, Reliable, Server) \
|
|
||||||
DeclarePacket(UpdateGameState, Reliable, Server) \
|
|
||||||
DeclarePacket(UpdateHealth, Reliable, Client)
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace protocol
|
} // namespace protocol
|
||||||
|
|||||||
@@ -6,13 +6,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <td/protocol/Dispatcher.h>
|
#include <td/protocol/Dispatcher.h>
|
||||||
|
#include <td/protocol/packet/Packets.h>
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
namespace protocol {
|
namespace protocol {
|
||||||
|
|
||||||
class PacketHandler;
|
using PacketDispatcher = Dispatcher<PacketType, PacketVisitor, Packet>;
|
||||||
|
|
||||||
using PacketDispatcher = Dispatcher<PacketType, PacketHandler, Packet>;
|
|
||||||
|
|
||||||
} // namespace protocol
|
} // namespace protocol
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file PacketHandler.h
|
|
||||||
* \brief File containing the td::protocol::PacketHandler class
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <td/protocol/packet/PacketVisitor.h>
|
|
||||||
#include <td/protocol/packet/Packets.h>
|
|
||||||
|
|
||||||
namespace td {
|
|
||||||
namespace protocol {
|
|
||||||
|
|
||||||
#define DeclarePacket(PacketName, ...) \
|
|
||||||
virtual void Visit(const packets::PacketName&); \
|
|
||||||
virtual void HandlePacket(const packets::PacketName&) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \class PacketHandler
|
|
||||||
* \brief Class used to handle packets
|
|
||||||
*/
|
|
||||||
class PacketHandler : public PacketVisitor {
|
|
||||||
public:
|
|
||||||
PacketHandler() {}
|
|
||||||
~PacketHandler() {}
|
|
||||||
|
|
||||||
DeclareAllPacket()
|
|
||||||
};
|
|
||||||
|
|
||||||
#undef DeclarePacket
|
|
||||||
|
|
||||||
} // namespace protocol
|
|
||||||
} // namespace td
|
|
||||||
@@ -2,14 +2,12 @@
|
|||||||
// #include <td/protocol/packet/PacketVisitor.h>
|
// #include <td/protocol/packet/PacketVisitor.h>
|
||||||
#include <td/protocol/command/CommandDispatcher.h>
|
#include <td/protocol/command/CommandDispatcher.h>
|
||||||
#include <td/protocol/command/CommandFactory.h>
|
#include <td/protocol/command/CommandFactory.h>
|
||||||
#include <td/protocol/command/CommandHandler.h>
|
|
||||||
#include <td/protocol/command/CommandSerializer.h>
|
#include <td/protocol/command/CommandSerializer.h>
|
||||||
#include <td/protocol/command/CommandVisitor.h>
|
#include <td/protocol/command/CommandVisitor.h>
|
||||||
|
#include <td/game/GameHistory.h>
|
||||||
|
|
||||||
class Test : public td::protocol::CommandVisitor {};
|
class Test : public td::protocol::CommandVisitor {};
|
||||||
|
|
||||||
class Test2 : public td::protocol::CommandHandler {};
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
// Test visitor;
|
// Test visitor;
|
||||||
// td::protocol::packets::ChatMessage chat{{"coucou"}};
|
// td::protocol::packets::ChatMessage chat{{"coucou"}};
|
||||||
|
|||||||
162
src/td/common/DataBuffer.cpp
Normal file
162
src/td/common/DataBuffer.cpp
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
#include <td/common/DataBuffer.h>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include <td/misc/Format.h>
|
||||||
|
#include <td/misc/Log.h>
|
||||||
|
|
||||||
|
namespace td {
|
||||||
|
|
||||||
|
DataBuffer::DataBuffer() : m_ReadOffset(0) {}
|
||||||
|
|
||||||
|
DataBuffer::DataBuffer(const DataBuffer& other) : m_Buffer(other.m_Buffer), m_ReadOffset(other.m_ReadOffset) {}
|
||||||
|
|
||||||
|
DataBuffer::DataBuffer(DataBuffer&& other) : m_Buffer(std::move(other.m_Buffer)), m_ReadOffset(std::move(other.m_ReadOffset)) {}
|
||||||
|
|
||||||
|
DataBuffer::DataBuffer(const std::string& str) : m_Buffer(str.begin(), str.end()), m_ReadOffset(0) {}
|
||||||
|
|
||||||
|
DataBuffer::DataBuffer(const DataBuffer& other, Data::difference_type offset) : m_ReadOffset(0) {
|
||||||
|
m_Buffer.reserve(other.GetSize() - static_cast<std::size_t>(offset));
|
||||||
|
std::copy(other.m_Buffer.begin() + offset, other.m_Buffer.end(), std::back_inserter(m_Buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
DataBuffer& DataBuffer::operator<<(const std::string& str) {
|
||||||
|
std::size_t strlen = str.length() + 1; // including null character
|
||||||
|
Resize(GetSize() + strlen);
|
||||||
|
std::memcpy(m_Buffer.data() + GetSize() - strlen, str.data(), strlen);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataBuffer& DataBuffer::operator<<(const DataBuffer& data) {
|
||||||
|
m_Buffer.insert(m_Buffer.end(), data.begin(), data.end());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataBuffer& DataBuffer::operator>>(std::string& str) {
|
||||||
|
std::size_t stringSize = strlen(reinterpret_cast<const char*>(m_Buffer.data()) + m_ReadOffset) + 1; // including null character
|
||||||
|
str.resize(stringSize);
|
||||||
|
std::copy(m_Buffer.begin() + static_cast<difference_type>(m_ReadOffset),
|
||||||
|
m_Buffer.begin() + static_cast<difference_type>(m_ReadOffset + stringSize), str.begin());
|
||||||
|
m_ReadOffset += stringSize;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataBuffer& DataBuffer::operator>>(DataBuffer& data) {
|
||||||
|
data.Resize(GetSize() - m_ReadOffset);
|
||||||
|
std::copy(m_Buffer.begin() + static_cast<difference_type>(m_ReadOffset), m_Buffer.end(), data.begin());
|
||||||
|
m_ReadOffset = m_Buffer.size();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataBuffer::WriteSome(const char* buffer, std::size_t amount) {
|
||||||
|
std::size_t end_pos = m_Buffer.size();
|
||||||
|
m_Buffer.resize(m_Buffer.size() + amount);
|
||||||
|
std::memcpy(m_Buffer.data() + end_pos, buffer, amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataBuffer::WriteSome(const std::uint8_t* buffer, std::size_t amount) {
|
||||||
|
std::size_t end_pos = m_Buffer.size();
|
||||||
|
m_Buffer.resize(m_Buffer.size() + amount);
|
||||||
|
std::memcpy(m_Buffer.data() + end_pos, buffer, amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataBuffer::ReadSome(char* buffer, std::size_t amount) {
|
||||||
|
assert(m_ReadOffset + amount <= GetSize());
|
||||||
|
std::copy_n(m_Buffer.begin() + static_cast<difference_type>(m_ReadOffset), amount, buffer);
|
||||||
|
m_ReadOffset += amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DataBuffer::ReadSome(std::uint8_t* buffer, std::size_t amount) {
|
||||||
|
assert(m_ReadOffset + amount <= GetSize());
|
||||||
|
std::copy_n(m_Buffer.begin() + static_cast<difference_type>(m_ReadOffset), amount, buffer);
|
||||||
|
m_ReadOffset += amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DataBuffer::ReadSome(DataBuffer& buffer, std::size_t amount) {
|
||||||
|
assert(m_ReadOffset + amount <= GetSize());
|
||||||
|
buffer.Resize(amount);
|
||||||
|
std::copy_n(m_Buffer.begin() + static_cast<difference_type>(m_ReadOffset), amount, buffer.begin());
|
||||||
|
m_ReadOffset += amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DataBuffer& DataBuffer::operator=(const DataBuffer& other) {
|
||||||
|
m_Buffer = other.m_Buffer;
|
||||||
|
m_ReadOffset = other.m_ReadOffset;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataBuffer& DataBuffer::operator=(DataBuffer&& other) {
|
||||||
|
m_Buffer = std::move(other.m_Buffer);
|
||||||
|
m_ReadOffset = std::move(other.m_ReadOffset);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataBuffer::SetReadOffset(std::size_t pos) {
|
||||||
|
assert(pos <= GetSize());
|
||||||
|
m_ReadOffset = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t DataBuffer::GetSize() const {
|
||||||
|
return m_Buffer.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t DataBuffer::GetRemaining() const {
|
||||||
|
return m_Buffer.size() - m_ReadOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataBuffer::iterator DataBuffer::begin() {
|
||||||
|
return m_Buffer.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
DataBuffer::iterator DataBuffer::end() {
|
||||||
|
return m_Buffer.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
DataBuffer::const_iterator DataBuffer::begin() const {
|
||||||
|
return m_Buffer.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
DataBuffer::const_iterator DataBuffer::end() const {
|
||||||
|
return m_Buffer.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, const DataBuffer& buffer) {
|
||||||
|
for (unsigned char u : buffer)
|
||||||
|
os << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>(u) << " ";
|
||||||
|
os << std::dec;
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DataBuffer::ReadFile(const std::string& fileName) {
|
||||||
|
try {
|
||||||
|
std::ifstream file(fileName, std::istream::binary);
|
||||||
|
std::ostringstream ss;
|
||||||
|
ss << file.rdbuf();
|
||||||
|
const std::string& s = ss.str();
|
||||||
|
m_Buffer = DataBuffer::Data(s.begin(), s.end());
|
||||||
|
m_ReadOffset = 0;
|
||||||
|
} catch (std::exception& e) {
|
||||||
|
utils::LOGE(utils::Format("[IO] Failed to read file %s ! reason : %s", fileName.c_str(), e.what()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return m_Buffer.size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DataBuffer::WriteFile(const std::string& fileName) const {
|
||||||
|
try {
|
||||||
|
std::ofstream file(fileName, std::ostream::binary);
|
||||||
|
file.write(reinterpret_cast<const char*>(m_Buffer.data()), static_cast<std::streamsize>(m_Buffer.size()));
|
||||||
|
file.flush();
|
||||||
|
} catch (std::exception& e) {
|
||||||
|
utils::LOGE(utils::Format("[IO] Failed to read file %s ! reason : %s", fileName.c_str(), e.what()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace td
|
||||||
52
src/td/common/VarInt.cpp
Normal file
52
src/td/common/VarInt.cpp
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#include <td/common/VarInt.h>
|
||||||
|
|
||||||
|
#include <td/common/DataBuffer.h>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace td {
|
||||||
|
|
||||||
|
static constexpr int SEGMENT_BITS = 0x7F;
|
||||||
|
static constexpr int CONTINUE_BIT = 0x80;
|
||||||
|
|
||||||
|
std::size_t VarInt::GetSerializedLength() const {
|
||||||
|
DataBuffer buffer;
|
||||||
|
buffer << *this;
|
||||||
|
return buffer.GetSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
DataBuffer& operator<<(DataBuffer& out, const VarInt& var) {
|
||||||
|
std::uint64_t value = var.m_Value;
|
||||||
|
while (true) {
|
||||||
|
if ((value & ~static_cast<std::uint64_t>(SEGMENT_BITS)) == 0) {
|
||||||
|
out << static_cast<std::uint8_t>(value);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
out << static_cast<std::uint8_t>((value & SEGMENT_BITS) | CONTINUE_BIT);
|
||||||
|
|
||||||
|
value >>= 7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DataBuffer& operator>>(DataBuffer& in, VarInt& var) {
|
||||||
|
var.m_Value = 0;
|
||||||
|
unsigned int position = 0;
|
||||||
|
std::uint8_t currentByte;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
in.ReadSome(¤tByte, 1);
|
||||||
|
var.m_Value |= static_cast<std::uint64_t>(currentByte & SEGMENT_BITS) << position;
|
||||||
|
|
||||||
|
if ((currentByte & CONTINUE_BIT) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
position += 7;
|
||||||
|
|
||||||
|
if (position >= 8 * sizeof(var.m_Value))
|
||||||
|
throw std::runtime_error("VarInt is too big");
|
||||||
|
}
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace td
|
||||||
37
src/td/misc/Log.cpp
Normal file
37
src/td/misc/Log.cpp
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#include <td/misc/Log.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TD_ANDROID_LOGGING
|
||||||
|
#include <android/log.h>
|
||||||
|
#else
|
||||||
|
#include <iostream>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace td {
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
|
void LOG(const std::string& msg) {
|
||||||
|
#ifdef TD_ANDROID_LOGGING
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, "TRACKERS", "%s", msg.c_str());
|
||||||
|
#else
|
||||||
|
std::cout << msg << "\n";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void LOGD(const std::string& msg) {
|
||||||
|
#if !defined(NDEBUG)
|
||||||
|
LOG(msg);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void LOGE(const std::string& err) {
|
||||||
|
#ifdef TD_ANDROID_LOGGING
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, "TRACKERS", "%s", err.c_str());
|
||||||
|
#else
|
||||||
|
std::cerr << err << "\n";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace utils
|
||||||
|
} // namespace td
|
||||||
Reference in New Issue
Block a user