diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index e2d433907e..013ad0caa7 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -26,6 +26,8 @@ add_files(
pool_type.hpp
random_func.cpp
random_func.hpp
+ serialisation.cpp
+ serialisation.hpp
smallmap_type.hpp
smallmatrix_type.hpp
smallstack_type.hpp
diff --git a/src/core/serialisation.cpp b/src/core/serialisation.cpp
new file mode 100644
index 0000000000..7fed2cf1a8
--- /dev/null
+++ b/src/core/serialisation.cpp
@@ -0,0 +1,137 @@
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see .
+ */
+
+/** @file serialisation.cpp Implementation related to (de)serialisation of buffers. */
+
+#include "../stdafx.h"
+#include "serialisation.hpp"
+
+/**
+ * Is it safe to write to the packet, i.e. didn't we run over the buffer?
+ * @param bytes_to_write The amount of bytes we want to try to write.
+ * @return True iff the given amount of bytes can be written to the packet.
+ */
+static bool BufferCanWriteToPacket(const std::vector &buffer, size_t limit, size_t bytes_to_write)
+{
+ return buffer.size() + bytes_to_write <= limit;
+}
+
+/*
+ * The next couple of functions make sure we can send
+ * uint8, uint16, uint32 and uint64 endian-safe
+ * over the network. The least significant bytes are
+ * sent first.
+ *
+ * So 0x01234567 would be sent as 67 45 23 01.
+ *
+ * A bool is sent as a uint8 where zero means false
+ * and non-zero means true.
+ */
+
+/**
+ * Package a boolean in the packet.
+ * @param data The data to send.
+ */
+void BufferSend_bool(std::vector &buffer, size_t limit, bool data)
+{
+ BufferSend_uint8(buffer, limit, data ? 1 : 0);
+}
+
+/**
+ * Package a 8 bits integer in the packet.
+ * @param data The data to send.
+ */
+void BufferSend_uint8(std::vector &buffer, size_t limit, uint8 data)
+{
+ assert(BufferCanWriteToPacket(buffer, limit, sizeof(data)));
+ buffer.emplace_back(data);
+}
+
+/**
+ * Package a 16 bits integer in the packet.
+ * @param data The data to send.
+ */
+void BufferSend_uint16(std::vector &buffer, size_t limit, uint16 data)
+{
+ assert(BufferCanWriteToPacket(buffer, limit, sizeof(data)));
+ buffer.insert(buffer.end(), {
+ (uint8)GB(data, 0, 8),
+ (uint8)GB(data, 8, 8),
+ });
+}
+
+/**
+ * Package a 32 bits integer in the packet.
+ * @param data The data to send.
+ */
+void BufferSend_uint32(std::vector &buffer, size_t limit, uint32 data)
+{
+ assert(BufferCanWriteToPacket(buffer, limit, sizeof(data)));
+ buffer.insert(buffer.end(), {
+ (uint8)GB(data, 0, 8),
+ (uint8)GB(data, 8, 8),
+ (uint8)GB(data, 16, 8),
+ (uint8)GB(data, 24, 8),
+ });
+}
+
+/**
+ * Package a 64 bits integer in the packet.
+ * @param data The data to send.
+ */
+void BufferSend_uint64(std::vector &buffer, size_t limit, uint64 data)
+{
+ assert(BufferCanWriteToPacket(buffer, limit, sizeof(data)));
+ buffer.insert(buffer.end(), {
+ (uint8)GB(data, 0, 8),
+ (uint8)GB(data, 8, 8),
+ (uint8)GB(data, 16, 8),
+ (uint8)GB(data, 24, 8),
+ (uint8)GB(data, 32, 8),
+ (uint8)GB(data, 40, 8),
+ (uint8)GB(data, 48, 8),
+ (uint8)GB(data, 56, 8),
+ });
+}
+
+/**
+ * Sends a string over the network. It sends out
+ * the string + '\0'. No size-byte or something.
+ * @param data The string to send
+ */
+void BufferSend_string(std::vector &buffer, size_t limit, const std::string_view data)
+{
+ assert(BufferCanWriteToPacket(buffer, limit, data.size() + 1));
+ buffer.insert(buffer.end(), data.begin(), data.end());
+ buffer.emplace_back('\0');
+}
+
+/**
+ * Send as many of the bytes as possible in the packet. This can mean
+ * that it is possible that not all bytes are sent. To cope with this
+ * the function returns the amount of bytes that were actually sent.
+ * @param begin The begin of the buffer to send.
+ * @param end The end of the buffer to send.
+ * @return The number of bytes that were added to this packet.
+ */
+size_t BufferSend_bytes(std::vector &buffer, size_t limit, const byte *begin, const byte *end)
+{
+ size_t amount = std::min(end - begin, limit - buffer.size());
+ buffer.insert(buffer.end(), begin, begin + amount);
+ return amount;
+}
+
+/**
+ * Sends a binary data over the network.
+ * @param data The data to send
+ */
+void BufferSend_binary(std::vector &buffer, size_t limit, const char *data, const size_t size)
+{
+ assert(data != nullptr);
+ assert(BufferCanWriteToPacket(buffer, limit, size));
+ buffer.insert(buffer.end(), data, data + size);
+}
diff --git a/src/core/serialisation.hpp b/src/core/serialisation.hpp
new file mode 100644
index 0000000000..1431824689
--- /dev/null
+++ b/src/core/serialisation.hpp
@@ -0,0 +1,78 @@
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see .
+ */
+
+/** @file serialisation.hpp Functions related to (de)serialisation of buffers */
+
+#ifndef SERIALISATION_HPP
+#define SERIALISATION_HPP
+
+#include "bitmath_func.hpp"
+
+#include
+#include
+
+void BufferSend_bool (std::vector &buffer, size_t limit, bool data);
+void BufferSend_uint8 (std::vector &buffer, size_t limit, uint8 data);
+void BufferSend_uint16(std::vector &buffer, size_t limit, uint16 data);
+void BufferSend_uint32(std::vector &buffer, size_t limit, uint32 data);
+void BufferSend_uint64(std::vector &buffer, size_t limit, uint64 data);
+void BufferSend_string(std::vector &buffer, size_t limit, const std::string_view data);
+size_t BufferSend_bytes (std::vector &buffer, size_t limit, const byte *begin, const byte *end);
+void BufferSend_binary(std::vector &buffer, size_t limit, const char *data, const size_t size);
+
+template
+struct BufferSerialisationHelper {
+ void Send_bool(bool data)
+ {
+ T *self = static_cast(this);
+ BufferSend_bool(self->GetSerialisationBuffer(), self->GetSerialisationLimit(), data);
+ }
+
+ void Send_uint8(uint8 data)
+ {
+ T *self = static_cast(this);
+ BufferSend_uint8(self->GetSerialisationBuffer(), self->GetSerialisationLimit(), data);
+ }
+
+ void Send_uint16(uint16 data)
+ {
+ T *self = static_cast(this);
+ BufferSend_uint16(self->GetSerialisationBuffer(), self->GetSerialisationLimit(), data);
+ }
+
+ void Send_uint32(uint32 data)
+ {
+ T *self = static_cast(this);
+ BufferSend_uint32(self->GetSerialisationBuffer(), self->GetSerialisationLimit(), data);
+ }
+
+ void Send_uint64(uint64 data)
+ {
+ T *self = static_cast(this);
+ BufferSend_uint64(self->GetSerialisationBuffer(), self->GetSerialisationLimit(), data);
+ }
+
+ void Send_string(const std::string_view data)
+ {
+ T *self = static_cast(this);
+ BufferSend_string(self->GetSerialisationBuffer(), self->GetSerialisationLimit(), data);
+ }
+
+ size_t Send_bytes(const byte *begin, const byte *end)
+ {
+ T *self = static_cast(this);
+ return BufferSend_bytes(self->GetSerialisationBuffer(), self->GetSerialisationLimit(), begin, end);
+ }
+
+ void Send_binary(const char *data, const size_t size)
+ {
+ T *self = static_cast(this);
+ BufferSend_binary(self->GetSerialisationBuffer(), self->GetSerialisationLimit(), data, size);
+ }
+};
+
+#endif /* SERIALISATION_HPP */
diff --git a/src/network/core/packet.cpp b/src/network/core/packet.cpp
index cef68c902e..64ecfee2c4 100644
--- a/src/network/core/packet.cpp
+++ b/src/network/core/packet.cpp
@@ -85,121 +85,6 @@ bool Packet::CanWriteToPacket(size_t bytes_to_write)
return this->Size() + bytes_to_write <= this->limit;
}
-/*
- * The next couple of functions make sure we can send
- * uint8, uint16, uint32 and uint64 endian-safe
- * over the network. The least significant bytes are
- * sent first.
- *
- * So 0x01234567 would be sent as 67 45 23 01.
- *
- * A bool is sent as a uint8 where zero means false
- * and non-zero means true.
- */
-
-/**
- * Package a boolean in the packet.
- * @param data The data to send.
- */
-void Packet::Send_bool(bool data)
-{
- this->Send_uint8(data ? 1 : 0);
-}
-
-/**
- * Package a 8 bits integer in the packet.
- * @param data The data to send.
- */
-void Packet::Send_uint8(uint8 data)
-{
- assert(this->CanWriteToPacket(sizeof(data)));
- this->buffer.emplace_back(data);
-}
-
-/**
- * Package a 16 bits integer in the packet.
- * @param data The data to send.
- */
-void Packet::Send_uint16(uint16 data)
-{
- assert(this->CanWriteToPacket(sizeof(data)));
- this->buffer.insert(this->buffer.end(), {
- (uint8)GB(data, 0, 8),
- (uint8)GB(data, 8, 8),
- });
-}
-
-/**
- * Package a 32 bits integer in the packet.
- * @param data The data to send.
- */
-void Packet::Send_uint32(uint32 data)
-{
- assert(this->CanWriteToPacket(sizeof(data)));
- this->buffer.insert(this->buffer.end(), {
- (uint8)GB(data, 0, 8),
- (uint8)GB(data, 8, 8),
- (uint8)GB(data, 16, 8),
- (uint8)GB(data, 24, 8),
- });
-}
-
-/**
- * Package a 64 bits integer in the packet.
- * @param data The data to send.
- */
-void Packet::Send_uint64(uint64 data)
-{
- assert(this->CanWriteToPacket(sizeof(data)));
- this->buffer.insert(this->buffer.end(), {
- (uint8)GB(data, 0, 8),
- (uint8)GB(data, 8, 8),
- (uint8)GB(data, 16, 8),
- (uint8)GB(data, 24, 8),
- (uint8)GB(data, 32, 8),
- (uint8)GB(data, 40, 8),
- (uint8)GB(data, 48, 8),
- (uint8)GB(data, 56, 8),
- });
-}
-
-/**
- * Sends a string over the network. It sends out
- * the string + '\0'. No size-byte or something.
- * @param data The string to send
- */
-void Packet::Send_string(const std::string_view data)
-{
- assert(this->CanWriteToPacket(data.size() + 1));
- this->buffer.insert(this->buffer.end(), data.begin(), data.end());
- this->buffer.emplace_back('\0');
-}
-
-/**
- * Send as many of the bytes as possible in the packet. This can mean
- * that it is possible that not all bytes are sent. To cope with this
- * the function returns the amount of bytes that were actually sent.
- * @param begin The begin of the buffer to send.
- * @param end The end of the buffer to send.
- * @return The number of bytes that were added to this packet.
- */
-size_t Packet::Send_bytes(const byte *begin, const byte *end)
-{
- size_t amount = std::min(end - begin, this->limit - this->Size());
- this->buffer.insert(this->buffer.end(), begin, begin + amount);
- return amount;
-}
-
-/**
- * Sends a binary data over the network.
- * @param data The data to send
- */
-void Packet::Send_binary(const char *data, const size_t size)
-{
- assert(data != nullptr);
- assert(this->CanWriteToPacket(size));
- this->buffer.insert(this->buffer.end(), data, data + size);
-}
/*
diff --git a/src/network/core/packet.h b/src/network/core/packet.h
index 31b42fda20..bae98d65fb 100644
--- a/src/network/core/packet.h
+++ b/src/network/core/packet.h
@@ -16,6 +16,7 @@
#include "config.h"
#include "core.h"
#include "../../string_type.h"
+#include "../../core/serialisation.hpp"
#include
#include
#include
@@ -42,7 +43,7 @@ typedef uint8 PacketType; ///< Identifier for the packet
* - years that are leap years in the 'days since X' to 'date' calculations:
* (year % 4 == 0) and ((year % 100 != 0) or (year % 400 == 0))
*/
-struct Packet {
+struct Packet : public BufferSerialisationHelper {
private:
/** The current read/write position in the packet */
PacketSize pos;
@@ -63,15 +64,10 @@ public:
/* Sending/writing of packets */
void PrepareToSend();
+ std::vector &GetSerialisationBuffer() { return this->buffer; }
+ size_t GetSerialisationLimit() const { return this->limit; }
+
bool CanWriteToPacket(size_t bytes_to_write);
- void Send_bool (bool data);
- void Send_uint8 (uint8 data);
- void Send_uint16(uint16 data);
- void Send_uint32(uint32 data);
- void Send_uint64(uint64 data);
- void Send_string(const std::string_view data);
- size_t Send_bytes (const byte *begin, const byte *end);
- void Send_binary(const char *data, const size_t size);
/* Reading/receiving of packets */
size_t ReadRawPacketSize() const;