Jump to content

Recommended Posts

hello, in this topic you will find the necessary plugins for sending/receiving and processing packets between server-client and client-server using the bitsery serialization library.

 

 

Information:

-In the current system, the package size is fixed (there are exceptions), the size of the package created from the data serialized with Bitsery is variable. so you will need to develop a mechanism for this!

-you need to write a serialization function for each structure

-use fixed size data types

 

Let's get started!

This is the hidden content, please
 or 
This is the hidden content, please

 

server side

Packet.h add after #pragma once

#include <bitsery/bitsery.h>
#include <bitsery/adapter/buffer.h>
#include <bitsery/traits/vector.h>
#include <bitsery/traits/string.h>
#include <vector>

namespace bitsery_packet {
    using Buffer = std::vector<uint8_t>;
    using OutputAdapter = bitsery::OutputBufferAdapter<Buffer>;
    using InputAdapter = bitsery::InputBufferAdapter<Buffer>;

    template<typename T>
    struct PacketSerializer {
        static Buffer serialize(const T& data) {
            Buffer buffer;
            auto writtenSize = bitsery::quickSerialization<OutputAdapter>(buffer, data);
            buffer.resize(writtenSize);
            return buffer;
        }

        static bool deserialize(const Buffer& buffer, T& data) {
            auto state = bitsery::quickDeserialization<InputAdapter>(
                InputAdapter(buffer.begin(), buffer.size()), data);
            return state.first == bitsery::ReaderError::NoError && state.second;
        }

        static bool deserialize(const void* buffer_data, size_t size, T& data) {
            Buffer tempBuffer(static_cast<const uint8_t*>(buffer_data),
                static_cast<const uint8_t*>(buffer_data) + size);
            auto state = bitsery::quickDeserialization<InputAdapter>(
                InputAdapter(tempBuffer.begin(), tempBuffer.size()), data);
            return state.first == bitsery::ReaderError::NoError && state.second;
        }
    };
}

 

desc.h

find:

BYTE			GetP2PChannel() const	{ return m_bP2PChannel;	}

add below:

		template<typename T>
		void BitseryPacket(const T& packet_data) {

			auto serialized_buffer = bitsery_packet::PacketSerializer<T>::serialize(packet_data);

			// Header (uint8_t (1)) + payload size (uint16_t(2)) + data for size information
			std::vector<char> final_buffer;
			final_buffer.reserve(1 + 2 + serialized_buffer.size());

			//header
			final_buffer.push_back(static_cast<char>(*(reinterpret_cast<const uint8_t*>(&packet_data))));
            
            //payload size
			uint16_t size = static_cast<uint16_t>(serialized_buffer.size());
			final_buffer.push_back(size & 0xFF);
			final_buffer.push_back((size >> 8) & 0xFF);

			//serialized data
			final_buffer.insert(final_buffer.end(),
				serialized_buffer.begin(),
				serialized_buffer.end());
#if defined(_DEBUG)
			sys_log(0, "Sending bitsery packet, header %d, buffer size : %d", *(reinterpret_cast<const uint8_t*>(&packet_data)), final_buffer.size());
#endif

			Packet(final_buffer.data(), final_buffer.size());
		}

 

client side:

EterLib/NetStream.h

find:

#include "NetAddress.h"
  
add below:

#include <bitsery/bitsery.h>
#include <bitsery/adapter/buffer.h>
#include <bitsery/traits/vector.h>
#include <bitsery/traits/string.h>
#include <vector>
#include <algorithm>

namespace bitsery_packet {
	using Buffer = std::vector<uint8_t>;
	using OutputAdapter = bitsery::OutputBufferAdapter<Buffer>;
	using InputAdapter = bitsery::InputBufferAdapter<Buffer>;

	template<typename T>
	struct PacketSerializer {
		static Buffer serialize(const T& data) {
			Buffer buffer;
			auto writtenSize = bitsery::quickSerialization<OutputAdapter>(buffer, data);
			buffer.resize(writtenSize);
			return buffer;
		}

		static bool deserialize(const Buffer& buffer, T& data) {
			auto state = bitsery::quickDeserialization<InputAdapter>(
				InputAdapter(buffer.begin(), buffer.size()), data);
			return state.first == bitsery::ReaderError::NoError && state.second;
		}

		static bool deserialize(const void* buffer_data, size_t size, T& data) {
			Buffer tempBuffer(static_cast<const uint8_t*>(buffer_data),
				static_cast<const uint8_t*>(buffer_data) + size);
			auto state = bitsery::quickDeserialization<InputAdapter>(
				InputAdapter(tempBuffer.begin(), tempBuffer.size()), data);
			return state.first == bitsery::ReaderError::NoError && state.second;
		}
	};
}

find:

bool AutoRecv(T& c_pvData) {
	return Recv(sizeof(T), &c_pvData);
}

add below:

        template <typename T>
        bool SendBitseryPacket(const T& data) {
        auto buffer = bitsery_packet::template PacketSerializer<T>::serialize(data);
        return Send(static_cast<int>(buffer.size()),
        reinterpret_cast<const char*>(buffer.data()));
        }

		template<typename T>
		bool BitseryAutoRecv(T& packet_data) {

			uint8_t received_header;
			if (!Recv(1, &received_header)) {
				TraceError("Failed to read header");
				return false;
			}

			uint16_t payload_size;
			if (!Recv(sizeof(payload_size), &payload_size)) {
				TraceError("Failed to read size information");
				return false;
			}

			std::vector<uint8_t> buffer(payload_size);
			if (!Recv(payload_size, buffer.data())) {
				TraceError("Data could not be read. Expected: %d, Present: %d",
					payload_size, GetRecvBufferSize());
				return false;
			}

			// 5. Deserialization
			if (!bitsery_packet::PacketSerializer<T>::deserialize(buffer, packet_data)) {
				TraceError("Deserialization failed");
				return false;
			}

			return true;
		}

 

sample package sending and receiving for tem drop and character point

 

packet.h (server and client)

find:

typedef struct packet_points
{
	uint8_t	header;
	uint16_t		points[POINT_MAX_NUM];
} TPacketGCPoints;

add below:

template<typename S>
void serialize(S& serializer, TPacketGCPoints& packet) {
	serializer.value1b(packet.header);
	for (int i = 0; i < POINT_MAX_NUM; ++i) {
		serializer.value2b(packet.points[i]);
	}
}

find:

typedef struct command_item_drop //HEADER_CG_ITEM_DROP
{
	uint8_t 	header;
	TItemPos 	Cell;
	uint32_t	gold;
#if defined(ENABLE_CHEQUE_SYSTEM) && !defined(DISABLE_CHEQUE_DROP)
	uint32_t	cheque;
#endif
} TPacketCGItemDrop;

add below:

template<typename S>
void serialize(S& serializer, TPacketCGItemDrop& packet) {
	serializer.value1b(packet.header);
	serializer.object(packet.Cell);
	serializer.value4b(packet.gold);
#if defined(ENABLE_CHEQUE_SYSTEM) && !defined(DISABLE_CHEQUE_DROP)
	serializer.value4b(packet.cheque);
#endif
}

 

char.cpp

find in void CHARACTER::PointsPacket():

GetDesc()->Packet(pack);

change:

GetDesc()->BitseryPacket(pack);

 

input_main.cpp

 

find:

void CInputMain::ItemDrop(LPCHARACTER ch, const char * data)

change function:

void CInputMain::ItemDrop(LPCHARACTER ch, const char * data)
{
	TPacketCGItemDrop pinfo;

	if (bitsery_packet::PacketSerializer<TPacketCGItemDrop>::deserialize(data, sizeof(TPacketCGItemDrop), pinfo))
	{
		if (!ch)
			return;

#if defined(ENABLE_CHEQUE_SYSTEM) && !defined(DISABLE_CHEQUE_DROP)
		if (pinfo.cheque > 0)
		{
			ch->DropCheque(pinfo->cheque);
			return;
		}
#endif

		if (pinfo.gold > 0)
			ch->DropGold(pinfo.gold);
		else
			ch->DropItem(pinfo.Cell);
	}
	else
	{
		sys_err("packet deserialization failed");
	}

}

 

userinterface/PythonNetworkStreamPhaseGameItem.cpp

 

find in bool CPythonNetworkStream::SendItemDropPacket():

if (!Send(itemDropPacket))

change:

if (!SendBitseryPacket(itemDropPacket))

 

userinterface/PythonNetworkStreamPhaseLoading.cpp

 

find in bool CPythonNetworkStream::__RecvPlayerPoints():

if (!AutoRecv(PointsPacket))

change:

if (!BitseryAutoRecv(PointsPacket))

 

  • Metin2 Dev 2
  • Love 5

Don't use any images from : imgur, turkmmop, freakgamers, inforge, hizliresim... Or your content will be deleted without notice...
Use : https://metin2.download/media/add/

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.