weto3184 7 Posted June 28 Share Posted June 28 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 Sign In or Sign Up or This is the hidden content, please Sign In or Sign Up 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)) 2 5 Link to comment https://metin2.dev/topic/33819-using-the-bitsery-serialization-library-in-packet-delivery/ Share on other sites More sharing options...
Active Member Valki 647 Posted June 30 Active Member Share Posted June 30 It looks good, but what is it trying to solve? (asking as someone who never heard about bitsery) Can this handle optional values? Link to comment https://metin2.dev/topic/33819-using-the-bitsery-serialization-library-in-packet-delivery/#findComment-171304 Share on other sites More sharing options...
Recommended Posts
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