Skip to content

cpp-toolbox/packet_handler

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 
 
 
 
 

Repository files navigation

packet_handler

In the following example we will show how to use the packet handler in the context of a client server game. First you have to create a subproject called packet_types that defines a struct as follows:

packet_type.hpp (client and server):

enum class PacketType : uint8_t {
    UNIQUE_CLIENT_ID,
    GAME_UPDATE_POSITIONS,
    GAME_UPDATE_ONE_TIME_EVENTS,
    USER_MESSAGES,
};

NOTE: its very important that you inherit from unint8_t or else the logic that deserialized the header will go wrong when you run sbpt it will correctly include it. Additionally both the client and server must have the same packet types available.

Next when constructing a PacketHandler you must create a map like this (client):

std::unordered_map<PacketType, PacketHandler::HandlerFunction> initialize_packet_handlers() {
    std::unordered_map<PacketType, PacketHandler::HandlerFunction> handlers;

    handlers[PacketType::UNIQUE_CLIENT_ID] = [](const void* data) {
        const UniqueClientIDPacket* packet = reinterpret_cast<const UniqueClientIDPacket*>(data);
        handle_unique_client_id_packet(*packet);
    };

    handlers[PacketType::GAME_UPDATE_POSITIONS] = [](const void* data) {
        const PacketHeader* header = reinterpret_cast<const PacketHeader*>(data);
        size_t num_positions = header->size_of_data_without_header / sizeof(PositionArray);

        GameUpdatePositionsPacket packet;
        packet.header = *header;
        packet.positions.resize(num_positions);
        std::memcpy(packet.positions.data(), reinterpret_cast<const char*>(data) + sizeof(PacketHeader), num_positions * sizeof(PositionArray));

        handle_game_update_positions_packet(packet);
    };

    return handlers;
}

and pass it in when you construct the packet handler, this will allow it to automatically run the correct callback function whenever a packet of that type is received, to make this happen you usually want to do something like this:

        std::cout << "tick" << "\n";
        std::vector<PacketWithSize> packets_since_last_tick = network.get_network_events_received_since_last_tick();
        for (const auto& packet : packets_since_last_tick) {
            std::cout << "Received packet of size: " << packet.size << "\n";
        }
        packet_handler.handle_packets(packets_since_last_tick);

To send over packets you should do something similar to this:

        server.get_network_events_since_last_tick();

        GameUpdatePositionsPacket packet = toggle ? create_mock_game_update_positions_packet_2() : create_mock_game_update_positions_packet_1();

        size_t packet_size = sizeof(PacketHeader) + packet.positions.size() * sizeof(PositionArray);
        std::vector<char> buffer(packet_size);
        std::memcpy(buffer.data(), &packet.header, sizeof(PacketHeader));
        std::memcpy(buffer.data() + sizeof(PacketHeader), packet.positions.data(), packet.positions.size() * sizeof(PositionArray));

        server.reliable_broadcast(buffer.data(), buffer.size());

creating packets

Note that in the above code we assumed that at the start of the packet, there was a packet header this is an assumption that is made by the packet_handler system and you must do this to properly integrate with it, therefore when creating packets, they must have the following form:

class XPacket {
public:
    PacketHeader header;
    ...
}

About

SUBPROJECT

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages