← game_protocol · API reference · version 0.1.7
2 file(s), 142 lines. This is the source the published version ships, and it is loft — the library is written in the same language you call it from.
Public items
A worked example is a call site the author chose as the thing to read first. Call sites are every line naming the item, found mechanically over the source with comments excluded — so an item with no worked example is not an item nobody uses.
| Item | Defined | Worked example | Call sites |
|---|---|---|---|
MsgType enum | 7 | — | 24 47 58 69 80 91 … (13 total) |
WsMessage struct | 23 | — | 35 47 58 69 80 91 … (7 total) |
GameEnvelope struct | 30 | — | 41 42 52 53 63 64 … (12 total) |
msg_ping fn | 41 | — | 3 7 |
msg_pong fn | 52 | — | 3 11 |
msg_chat fn | 63 | — | 3 16 |
msg_input fn | 74 | — | 3 23 |
msg_state fn | 85 | — | 3 29 |
msg_error fn | 96 | — | 3 35 |
src/game_protocol.loft
// Copyright (c) 2026 Jurjen Stellingwerff
// SPDX-License-Identifier: LGPL-3.0-or-later
// --- Game Protocol ---
// Shared message types for client-server game communication.
// Message types for the game protocol envelope.
pub enum MsgType {
StateFullSync,
StateDelta,
PlayerInput,
Ping,
Pong,
ChatMessage,
LobbyJoin,
LobbyLeave,
LobbyList,
MatchStart,
MatchEnd,
Error
}
// A WebSocket message wrapper for game communication.
pub struct WsMessage {
pub msg_type: MsgType,
pub payload: text
}
// The outer envelope for all game messages.
// Contains routing info + the actual message.
pub struct GameEnvelope {
pub sender: text,
pub recipient: text,
pub sequence: integer,
pub timestamp: integer,
pub message: WsMessage
}
// --- Message constructors ---
// Create a ping message.
pub fn msg_ping(seq: integer) -> GameEnvelope {
GameEnvelope {
sender: "",
recipient: "",
sequence: seq,
timestamp: now(),
message: WsMessage { msg_type: MsgType.Ping, payload: "" }
}
}
// Create a pong response.
pub fn msg_pong(seq: integer) -> GameEnvelope {
GameEnvelope {
sender: "",
recipient: "",
sequence: seq,
timestamp: now(),
message: WsMessage { msg_type: MsgType.Pong, payload: "" }
}
}
// Create a chat message.
pub fn msg_chat(sender: text, content: text) -> GameEnvelope {
GameEnvelope {
sender: sender,
recipient: "",
sequence: 0,
timestamp: now(),
message: WsMessage { msg_type: MsgType.ChatMessage, payload: content }
}
}
// Create a player input message.
pub fn msg_input(sender: text, input_data: text) -> GameEnvelope {
GameEnvelope {
sender: sender,
recipient: "",
sequence: 0,
timestamp: now(),
message: WsMessage { msg_type: MsgType.PlayerInput, payload: input_data }
}
}
// Create a state sync message.
pub fn msg_state(state_data: text) -> GameEnvelope {
GameEnvelope {
sender: "",
recipient: "",
sequence: 0,
timestamp: now(),
message: WsMessage { msg_type: MsgType.StateFullSync, payload: state_data }
}
}
// Create an error message.
pub fn msg_error(error_text: text) -> GameEnvelope {
GameEnvelope {
sender: "",
recipient: "",
sequence: 0,
timestamp: now(),
message: WsMessage { msg_type: MsgType.Error, payload: error_text }
}
}
tests/protocol.loft
// Copyright (c) 2026 Jurjen Stellingwerff
// SPDX-License-Identifier: LGPL-3.0-or-later
use game_protocol::(msg_ping, msg_pong, msg_chat, msg_input, msg_state, msg_error);
use game_protocol::MsgType;
fn test_ping_pong() {
ping = msg_ping(1);
assert(ping.message.msg_type == MsgType.Ping, "ping type");
assert(ping.sequence == 1, "ping seq");
pong = msg_pong(1);
assert(pong.message.msg_type == MsgType.Pong, "pong type");
}
fn test_chat() {
msg = msg_chat("alice", "hello");
assert(msg.sender == "alice", "chat sender");
assert(msg.message.payload == "hello", "chat payload");
assert(msg.message.msg_type == MsgType.ChatMessage, "chat type");
}
fn test_input() {
msg = msg_input("player1", "move:left");
assert(msg.sender == "player1", "input sender");
assert(msg.message.payload == "move:left", "input payload");
}
fn test_state() {
msg = msg_state("score:42");
assert(msg.message.msg_type == MsgType.StateFullSync, "state type");
assert(msg.message.payload == "score:42", "state payload");
}
fn test_error() {
msg = msg_error("invalid move");
assert(msg.message.msg_type == MsgType.Error, "error type");
assert(msg.message.payload == "invalid move", "error payload");
}