Protocol¶
Définitions du protocole réseau R-Type.
Synopsis¶
#include "Protocol.hpp"
// Check message type
if (header.type == static_cast<uint16_t>(MessageType::Login)) {
auto login = LoginRequest::from_bytes(payload, len);
}
Ports¶
| Service | Port | Protocole | Description |
|---|---|---|---|
| Auth | 4125 | TCP + TLS | Authentification et gestion de rooms |
| Game | 4124 | UDP | Gameplay temps réel |
| Voice | 4126 | UDP | Chat vocal |
Constantes¶
// Protocol.hpp
// Buffer
static constexpr std::size_t BUFFER_SIZE = 4096;
// Limits
static constexpr uint8_t MAX_PLAYERS = 4;
static constexpr uint8_t MAX_MISSILES = 32;
static constexpr uint8_t MAX_ENEMIES = 16;
static constexpr uint8_t MAX_ENEMY_MISSILES = 32;
// Room system
static constexpr size_t ROOM_NAME_LEN = 32;
static constexpr size_t ROOM_CODE_LEN = 6;
static constexpr uint8_t MAX_ROOM_PLAYERS = 6;
static constexpr uint8_t MIN_ROOM_PLAYERS = 1;
// Session token (256 bits)
static constexpr size_t TOKEN_SIZE = 32;
// Voice
static constexpr uint16_t VOICE_UDP_PORT = 4126;
Types de Messages¶
MessageType¶
enum class MessageType: uint16_t {
// === UDP Messages ===
HeartBeat = 0x0001,
HeartBeatAck = 0x0002,
// UDP Session authentication
JoinGame = 0x0010,
JoinGameAck = 0x0011,
JoinGameNack = 0x0012,
// UDP Game messages
Snapshot = 0x0040,
PlayerInput = 0x0061,
PlayerJoin = 0x0070,
PlayerLeave = 0x0071,
ShootMissile = 0x0080,
MissileSpawned = 0x0081,
MissileDestroyed = 0x0082,
EnemyDestroyed = 0x0091,
PlayerDamaged = 0x00A0,
PlayerDied = 0x00A1,
// === TCP Messages ===
// Authentication (0x01xx)
Login = 0x0100,
LoginAck = 0x0101,
Register = 0x0102,
RegisterAck = 0x0103,
// Room Management (0x02xx)
CreateRoom = 0x0200,
CreateRoomAck = 0x0201,
JoinRoomByCode = 0x0210,
JoinRoomAck = 0x0211,
JoinRoomNack = 0x0212,
LeaveRoom = 0x0220,
LeaveRoomAck = 0x0221,
SetReady = 0x0230,
SetReadyAck = 0x0231,
StartGame = 0x0240,
StartGameAck = 0x0241,
StartGameNack = 0x0242,
// Room Notifications
RoomUpdate = 0x0250,
GameStarting = 0x0251,
SetRoomConfig = 0x0252,
SetRoomConfigAck = 0x0253,
// Kick System (0x026x)
KickPlayer = 0x0260,
KickPlayerAck = 0x0261,
PlayerKicked = 0x0262,
// Room Browser (0x027x)
BrowsePublicRooms = 0x0270,
BrowsePublicRoomsAck = 0x0271,
QuickJoin = 0x0272,
QuickJoinAck = 0x0273,
QuickJoinNack = 0x0274,
// User Settings (0x028x)
GetUserSettings = 0x0280,
GetUserSettingsAck = 0x0281,
SaveUserSettings = 0x0282,
SaveUserSettingsAck = 0x0283,
// Chat System (0x029x)
SendChatMessage = 0x0290,
SendChatMessageAck = 0x0291,
ChatMessageBroadcast = 0x0292,
ChatHistory = 0x0293,
// Voice Chat (0x030x)
VoiceJoin = 0x0300,
VoiceJoinAck = 0x0301,
VoiceLeave = 0x0302,
VoiceFrame = 0x0303,
VoiceMute = 0x0304,
};
Header UDP¶
struct UDPHeader {
uint16_t type; // MessageType
uint16_t sequence_num; // Numéro de séquence
uint64_t timestamp; // Millisecondes depuis epoch
static constexpr size_t WIRE_SIZE = 12;
void to_bytes(void* buf) const;
static std::optional<UDPHeader> from_bytes(const void* buf, size_t len);
};
Format binaire (12 bytes, big-endian):
| Offset | Taille | Champ |
|---|---|---|
| 0 | 2 | type |
| 2 | 2 | sequence_num |
| 4 | 8 | timestamp |
Input Keys¶
namespace InputKeys {
constexpr uint16_t UP = 0x0001;
constexpr uint16_t DOWN = 0x0002;
constexpr uint16_t LEFT = 0x0004;
constexpr uint16_t RIGHT = 0x0008;
constexpr uint16_t SHOOT = 0x0010;
}
Structures Principales¶
SessionToken¶
Token d'authentification pour la session UDP (32 bytes).
struct SessionToken {
uint8_t bytes[TOKEN_SIZE]; // 32 bytes
std::string toHex() const;
static std::optional<SessionToken> fromHex(const std::string& hex);
void to_bytes(uint8_t* buf) const;
static std::optional<SessionToken> from_bytes(const void* buf, size_t len);
};
PlayerState¶
État d'un joueur dans le snapshot (23 bytes).
struct PlayerState {
uint8_t id;
uint16_t x, y;
uint8_t health;
uint8_t alive;
uint16_t lastAckedInputSeq;
uint8_t shipSkin;
uint32_t score;
uint16_t kills;
uint8_t combo; // x10 (15 = 1.5x)
uint8_t currentWeapon; // WeaponType enum
uint8_t chargeLevel; // Wave Cannon 0-3
uint8_t speedLevel; // 0-3
uint8_t weaponLevel; // 0-3
uint8_t hasForce; // 0 or 1
uint8_t shieldTimer; // Reserved (always 0)
static constexpr size_t WIRE_SIZE = 23;
};
MissileState¶
État d'un missile (8 bytes).
struct MissileState {
uint16_t id;
uint8_t owner_id;
uint16_t x, y;
uint8_t weapon_type; // WeaponType enum
static constexpr size_t WIRE_SIZE = 8;
};
EnemyState¶
État d'un ennemi (8 bytes).
struct EnemyState {
uint16_t id;
uint16_t x, y;
uint8_t health;
uint8_t enemy_type;
static constexpr size_t WIRE_SIZE = 8;
};
GameSnapshot¶
Snapshot complet du jeu (taille variable).
struct GameSnapshot {
uint8_t player_count;
PlayerState players[MAX_PLAYERS];
uint8_t missile_count;
MissileState missiles[MAX_MISSILES];
uint8_t enemy_count;
EnemyState enemies[MAX_ENEMIES];
uint8_t enemy_missile_count;
MissileState enemy_missiles[MAX_ENEMY_MISSILES];
};
VoiceFrame¶
Frame audio encodé Opus (5-485 bytes).
struct VoiceFrame {
uint8_t speaker_id;
uint16_t sequence;
uint16_t opus_len;
uint8_t opus_data[480];
static constexpr size_t HEADER_SIZE = 5;
static constexpr size_t MAX_OPUS_SIZE = 480;
};
Sérialisation¶
Toutes les structures utilisent big-endian (network byte order).
// Fonctions de conversion
inline uint16_t swap16(uint16_t v) { return __builtin_bswap16(v); }
inline uint32_t swap32(uint32_t v) { return __builtin_bswap32(v); }
inline uint64_t swap64(uint64_t v) { return __builtin_bswap64(v); }
// Pattern de sérialisation
void to_bytes(uint8_t* buf) const {
uint16_t net_x = swap16(x); // Host → Network
std::memcpy(buf, &net_x, 2);
}
static std::optional<T> from_bytes(const void* buf, size_t len) {
uint16_t net_x;
std::memcpy(&net_x, buf, 2);
x = swap16(net_x); // Network → Host
}
Diagramme des Messages¶
flowchart TB
subgraph "TCP (Port 4125 + TLS)"
Auth[Authentication<br/>Login/Register]
Room[Room Management<br/>Create/Join/Leave]
Chat[Chat System<br/>Messages]
Settings[User Settings]
end
subgraph "UDP (Port 4124)"
Session[Session Auth<br/>JoinGame]
Input[Player Input]
Snapshot[Game Snapshot]
Events[Game Events<br/>Missiles/Enemies]
end
subgraph "Voice UDP (Port 4126)"
VJoin[Voice Join/Leave]
VFrame[Voice Frames]
end
Client --> Auth
Client --> Session
Client --> VJoin
style Auth fill:#059669,color:#fff
style Room fill:#059669,color:#fff
style Chat fill:#059669,color:#fff
style Settings fill:#059669,color:#fff
style Session fill:#7c3aed,color:#fff
style Input fill:#7c3aed,color:#fff
style Snapshot fill:#7c3aed,color:#fff
style Events fill:#7c3aed,color:#fff
style VJoin fill:#ea580c,color:#fff
style VFrame fill:#ea580c,color:#fff
Tailles des Messages¶
| Message | Taille (bytes) |
|---|---|
| UDPHeader | 12 |
| SessionToken | 32 |
| PlayerState | 23 |
| MissileState | 8 |
| EnemyState | 8 |
| PlayerInput | 4 |
| VoiceFrame | 5-485 |
| GameSnapshot | Variable (~300-700) |