The protocol module owns the whole wire contract
Status: Accepted (2026-11-06)
Context
Besides encoding and decoding, the server's protocol module (src/protocol/mod.rs) holds field ranges (HANDLING_RANGES, WEAPON_PROPERTY_RANGES, the MAX_* limits), several dozen validators (gravity_ok, label_ok, ...), classes of weapon and damage ids (is_hitscan_weapon, is_melee_weapon, ...), and the values a fresh connection starts with (DEFAULT_GRAVITY, DEFAULT_FIGHTING_STYLE). They look like gameplay rules, and moving them into the domain modules as gamemode rules was proposed.
Decision
- The range of a field, the class of ids a field may carry, and the value a field has on a fresh connection are part of the wire contract. They live in the protocol module next to the packet.
- The test is: the value is described in the protocol specification, and either the decoder checks it or the client must check it before applying a value received from the network.
- Only what the server alone knows goes into domain modules: anti-cheat thresholds, timing, damage tables and gamemode policy (
weapons,vitals,anticheat).
Consequences
src/protocol/mod.rsreads as the specification in code: the format, the bounds and the meaning of field values.- A new field constraint is added to
src/protocol/mod.rsand to the specification together; server policy on top of it goes into the domain module.
Alternatives considered
- Moving the validators and classes into
weapons,hudorvehicle_handling. Decoding and the packets themselves depend on them (the decoder calls the*_okvalidators, and whether a weapon carries properties depends onis_hitscan_weapon). The protocol would then depend on domain modules, and a field's bound would be split between two files and drift from the specification. Rejected.
