Skip to content

Commit 2f67ae0

Browse files
committed
docs: document game ping-pong slice
1 parent 6bafd89 commit 2f67ae0

7 files changed

Lines changed: 167 additions & 2 deletions

File tree

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Current scope of the project:
1616
- A deterministic single-character `MOVE` round-trip wired through the current bootstrap runtime.
1717
- A deterministic selected-character `SYNC_POSITION` reconciliation path wired through the current bootstrap runtime.
1818
- A tolerant `CLIENT_VERSION` metadata path accepted during `LOADING` before `ENTERGAME`.
19+
- A tolerant `PONG` control path accepted in `GAME` for server-driven ping probes.
1920
- Character deletion on the selection surface with deterministic success/failure responses.
2021
- A first visible-world bootstrap that inserts the selected character into the game world after `ENTERGAME`.
2122
- A first self-only `CHARACTER_UPDATE` refresh emitted immediately after the visible-world insert.
@@ -117,6 +118,7 @@ Legend:
117118
- `spec/protocol/select-world-entry.md`
118119
- `spec/protocol/character-delete-selection.md`
119120
- `spec/protocol/client-version-loading.md`
121+
- `spec/protocol/game-ping-pong.md`
120122
- `spec/protocol/visible-world-bootstrap.md`
121123
- `spec/protocol/character-update-bootstrap.md`
122124
- `spec/protocol/player-point-change-bootstrap.md`
@@ -207,6 +209,7 @@ What exists today:
207209
- bootstrap movement updates character coordinates and persists them across fresh auth/game sessions
208210
- empty-account bootstrap flow can select empire before first character creation, and that choice persists across fresh auth/game sessions
209211
- tolerant `CLIENT_VERSION` acceptance in `LOADING` with no phase transition and no server response
212+
- tolerant `PONG` acceptance in `GAME` with no phase transition and no server response
210213
- the selected character is inserted into the visible world after `ENTERGAME` via minimal `CHARACTER_ADD` + `CHAR_ADDITIONAL_INFO` + `CHARACTER_UPDATE` + `PLAYER_POINT_CHANGE`
211214

212215
What still does not exist yet:
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Game Ping/Pong Slice Implementation Plan
2+
3+
> For Hermes: use test-driven-development. Keep slices tiny and push one commit at a time.
4+
5+
Goal: freeze the first minimal control-plane `PING`/`PONG` behavior for a session that is already in `GAME`, so a future server-side ping probe can receive a valid client `PONG` without desynchronizing the world session.
6+
7+
Architecture: extend the control codec with explicit `PING` encode and `PONG` decode helpers, teach the `GAME` flow to accept `PONG` as a phase-stable no-op, then document the narrowed scope in protocol docs.
8+
9+
Tech stack: Go 1.26, existing `internal/proto/control`, `internal/game`, and protocol docs.
10+
11+
---
12+
13+
## Task 1: Freeze `PING`/`PONG` codec helpers
14+
Objective: make the control codec symmetric for the minimal server-driven ping path.
15+
16+
Files:
17+
- Modify: `internal/proto/control/control.go`
18+
- Modify: `internal/proto/control/control_test.go`
19+
20+
Steps:
21+
1. Write failing tests for:
22+
- `PING` encode against the frozen fixture
23+
- `PONG` decode for a header-only frame
24+
2. Run: `go test ./internal/proto/control`
25+
3. Implement the smallest codec changes to pass.
26+
4. Re-run: `go test ./internal/proto/control`
27+
5. Commit: `feat: add game ping-pong control support`
28+
29+
## Task 2: Accept `PONG` in `GAME`
30+
Objective: allow the live game session to tolerate the automatic client reply path.
31+
32+
Files:
33+
- Modify: `internal/game/flow.go`
34+
- Modify: `internal/game/flow_test.go`
35+
36+
Steps:
37+
1. Write a failing test proving `PONG` is accepted in `GAME`.
38+
2. Run: `go test ./internal/game`
39+
3. Implement the smallest game-phase branch to decode and ignore `PONG`.
40+
4. Re-run: `go test ./internal/game`
41+
5. Keep the session in `GAME` and emit no server frames.
42+
43+
## Task 3: Update docs
44+
Objective: record the phase-stable in-world control path.
45+
46+
Files:
47+
- Modify: `README.md`
48+
- Modify: `spec/protocol/README.md`
49+
- Modify: `spec/protocol/boot-path.md`
50+
- Modify: `spec/protocol/packet-matrix.md`
51+
- Modify: `spec/protocol/session-phases.md`
52+
- Create: `spec/protocol/game-ping-pong.md`
53+
54+
Steps:
55+
1. Document the packet layouts and the no-response `PONG` behavior.
56+
2. Note that the current slice does not yet add a periodic ping scheduler.
57+
3. Run: `go test ./... && go vet ./...`
58+
4. Commit: `docs: document game ping-pong slice`
59+
60+
## Verification
61+
- `go test ./internal/proto/control ./internal/game`
62+
- `go test ./...`
63+
- `go vet ./...`
64+
65+
## Scope guardrails
66+
- Do not add a timer loop or heartbeat scheduler in this slice.
67+
- Do not introduce disconnect policy for missed replies yet.
68+
- Do not broaden the slice into movement, chat, or warp work.
69+
- Do not invent extra `PONG` payload fields.

spec/protocol/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ The repository targets TMP4-era client compatibility, but the protocol contract
1212
- `select-world-entry.md` — minimal selection, loading, and enter-game packet choreography
1313
- `character-delete-selection.md` — deterministic character deletion in `SELECT`
1414
- `client-version-loading.md` — tolerant `CLIENT_VERSION` metadata path during `LOADING`
15+
- `game-ping-pong.md` — minimal control-plane `PING`/`PONG` behavior once the session is in `GAME`
1516
- `character-update-bootstrap.md` — first self-only state refresh after entering `GAME`
1617
- `player-point-change-bootstrap.md` — first self-only point refresh after entering `GAME`
1718
- `sync-position-bootstrap.md` — first self-only sync-position reconciliation after entering `GAME`

spec/protocol/boot-path.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ This document depends on:
141141
- `spec/protocol/packet-matrix.md`
142142
- `spec/protocol/character-delete-selection.md`
143143
- `spec/protocol/client-version-loading.md`
144+
- `spec/protocol/game-ping-pong.md`
144145
- `spec/protocol/character-update-bootstrap.md`
145146
- `spec/protocol/player-point-change-bootstrap.md`
146147
- `spec/protocol/sync-position-bootstrap.md`

spec/protocol/game-ping-pong.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Game Ping/Pong Control Path
2+
3+
This document freezes the first minimal control-plane `PING`/`PONG` behavior relevant once a session is already in `GAME`.
4+
5+
The goal of this slice is deliberately narrow:
6+
- preserve the `PING` packet layout as server-owned control data
7+
- accept a header-only client `PONG` while the session is in `GAME`
8+
- keep the session in `GAME`
9+
- emit no server response when `PONG` is received
10+
11+
This slice does not yet add a periodic ping scheduler.
12+
It only freezes the packet codec and the accepted reply path.
13+
14+
## Covered packets
15+
16+
- `PING`
17+
- `PONG`
18+
19+
## Envelope
20+
21+
The packets use the project-wide CG/GC frame envelope:
22+
23+
- `header``uint16`, little-endian
24+
- `length``uint16`, little-endian, total frame size including the 4-byte envelope
25+
- `payload` — packet-specific bytes
26+
27+
See `frame-layout.md` for the envelope contract.
28+
29+
## `PING`
30+
31+
Direction:
32+
- server -> client
33+
34+
Header:
35+
- `0x0007`
36+
37+
Payload layout:
38+
- `server_time``uint32`, little-endian
39+
40+
Frame length:
41+
- `8` bytes total (`4 + 4`)
42+
43+
Notes:
44+
- `server_time` is control-plane compatibility data.
45+
- The first implementation only freezes the codec; it does not schedule periodic probes yet.
46+
47+
## `PONG`
48+
49+
Direction:
50+
- client -> server
51+
52+
Header:
53+
- `0x0006`
54+
55+
Payload layout:
56+
- none
57+
58+
Frame length:
59+
- `4` bytes total (`4 + 0`)
60+
61+
Notes:
62+
- `PONG` is a header-only control reply.
63+
- The first implementation accepts it in `GAME` as a no-op.
64+
65+
## Working flow
66+
67+
The current server-owned behavior is:
68+
69+
1. the session is already in `GAME`
70+
2. the server may emit `PING(server_time)`
71+
3. the client may reply with `PONG`
72+
4. the server accepts `PONG`
73+
5. the server emits no response packet
74+
6. the session remains in `GAME`
75+
76+
## Slice scope
77+
78+
This slice freezes:
79+
- `PING` encode support
80+
- `PONG` decode support
81+
- tolerant `PONG` acceptance in `GAME`
82+
- no-response behavior for `PONG`
83+
- phase-stable handling in the live game session
84+
85+
It does not yet freeze:
86+
- periodic ping cadence
87+
- timeout or disconnect policy
88+
- server-time synchronization semantics beyond the carried `server_time` field
89+
- acceptance of `PONG` outside the currently documented phases

spec/protocol/packet-matrix.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ Status values:
1212

1313
| Name | Direction | Header | Phase | Status | Notes |
1414
| --- | --- | --- | --- | --- | --- |
15-
| `PONG` | client -> server | `0x0006` | handshake/control | documented | response to server ping |
16-
| `PING` | server -> client | `0x0007` | handshake/control | documented | includes `server_time` |
15+
| `PONG` | client -> server | `0x0006` | handshake/game control | documented | accepted as a header-only reply to server `PING`; phase-stable in `HANDSHAKE` and `GAME` |
16+
| `PING` | server -> client | `0x0007` | handshake/game control | documented | carries `server_time`; current slice freezes the codec and the matching `PONG` reply path |
1717
| `PHASE` | server -> client | `0x0008` | control | documented | phase transition control packet |
1818
| `KEY_RESPONSE` | client -> server | `0x000A` | handshake | documented | cryptographic response path |
1919
| `KEY_CHALLENGE` | server -> client | `0x000B` | handshake | documented | challenge + server key material |

spec/protocol/session-phases.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ Initial milestone scope:
111111
Typical traffic in this phase:
112112
- move
113113
- sync position
114+
- control-plane `PING`/`PONG` that should not disturb the live phase
114115
- minimal world updates
115116

116117
## 6. `CLOSE`
@@ -165,6 +166,7 @@ A packet decoder may still parse them, but the session layer must not process th
165166
### `GAME`
166167
- a character is bound to the connection
167168
- movement is allowed
169+
- control-plane `PONG` may be accepted here without changing phase
168170
- later milestones may enable additional systems here
169171

170172
## Notes for implementation

0 commit comments

Comments
 (0)