Commit Graph

111 Commits

Author SHA1 Message Date
Josh Creek 277ad4bf98 fix(multiplayer): validate ticket playlists 2026-09-01 22:02:01 +01:00
Josh Creek 0ce2a49419 fix(multiplayer): enforce proposal transitions 2026-09-01 22:00:37 +01:00
Josh Creek a60c1a097e fix(multiplayer): validate client revisions 2026-09-01 21:59:32 +01:00
Josh Creek f491725144 fix(multiplayer): stop recovery after completion 2026-09-01 21:58:20 +01:00
Josh Creek 0f1864f8bc fix(multiplayer): enforce client state transitions 2026-09-01 21:57:13 +01:00
Josh Creek 30a5a89164 fix(multiplayer): project complete queue lifecycle 2026-09-01 21:55:19 +01:00
Josh Creek 6ac2d0fbb1 fix(multiplayer): project accepted queue state 2026-09-01 21:54:10 +01:00
Josh Creek fa2c93ec06 fix(multiplayer): defer reconnect recovery during mutations 2026-09-01 21:53:07 +01:00
Josh Creek 51f6e19339 feat(multiplayer): expose ranked season countdown 2026-09-01 21:49:48 +01:00
Josh Creek 9240cd4b27 feat(multiplayer): preserve authoritative queue wait 2026-09-01 21:45:07 +01:00
Josh Creek 84372204fd feat(multiplayer): persist ranked arena allocations 2026-09-01 21:04:55 +01:00
Josh Creek e934bbfe44 test(training): cover wall rebound geometry 2026-09-01 17:39:53 +01:00
Josh Creek 7b2f9c26f4 feat(training): add opt-in teamplay evaluation 2026-09-01 17:30:40 +01:00
Josh Creek 6ef55affcb feat(multiplayer): add idempotent client mutation retries 2026-09-01 17:02:55 +01:00
Josh Creek 4e88ea80f3 feat(multiplayer): handle planned shutdowns on clients 2026-09-01 16:43:47 +01:00
Josh Creek b24f9fc448 feat(multiplayer): notify clients before server shutdown 2026-09-01 16:42:15 +01:00
Josh Creek 334d8a26ac feat(multiplayer): enforce allocated initial connect policy 2026-09-01 16:36:26 +01:00
Josh Creek 80d6ee8cf5 fix(multiplayer): validate allocated roster shape 2026-09-01 16:18:31 +01:00
Josh Creek 69a8402f11 fix(multiplayer): honor assigned team and slot 2026-09-01 16:17:10 +01:00
Josh Creek b4ea50d76a fix(multiplayer): reclaim slots by signed identity 2026-09-01 16:08:01 +01:00
Josh Creek bdb3c8f4a7 fix(multiplayer): gate allocated matches on full roster 2026-09-01 16:03:43 +01:00
Josh Creek 4fb7ddfecf docs(multiplayer): consolidate tracking into one document
multiplayer-todo.md and multiplayer-next.md tracked overlapping
information in two places. Fold everything into multiplayer-next.md
(architecture decisions, wire format, task breakdown with checkboxes,
gotchas list, testing notes) and delete multiplayer-todo.md. Section
numbers are unchanged, so existing code comments citing them by
section/task number still resolve; update every such reference to
point at the new filename.
2026-09-01 12:32:43 +01:00
Josh Creek e7c835af52 feat: add Godot Agones REST bridge 2026-09-01 09:16:41 +01:00
Josh Creek 6caf719158 feat: add allocated server readiness control 2026-09-01 09:12:10 +01:00
Josh Creek 3aad68a6e6 feat: fence expired allocated reconnects 2026-09-01 08:52:12 +01:00
Josh Creek e25d61d80e feat: verify allocated join authorisations with hmac 2026-09-01 08:48:48 +01:00
Josh Creek 4b01b7fc88 fix: prevent concurrent join token reuse 2026-09-01 08:41:38 +01:00
Josh Creek 68d832f7bc feat: enforce allocated join roster admission 2026-09-01 08:39:56 +01:00
Josh Creek d8ea2f4ac7 feat: connect clients from validated assignments 2026-09-01 08:37:00 +01:00
Josh Creek aeb37a4c6e fix: ignore pre-history prediction acknowledgements 2026-09-01 08:32:44 +01:00
Josh Creek c5678ce877 fix: pass Godot 4.7 multiplayer test suite 2026-09-01 08:24:33 +01:00
Josh Creek 467c25b20c feat: expose validated assignment endpoints 2026-09-01 08:17:39 +01:00
Josh Creek 3533e8ae6c feat: consume assignment matchmaking events 2026-08-31 23:15:42 +01:00
Josh Creek a16db39884 feat: connect Godot matchmaking event stream 2026-08-31 23:06:44 +01:00
Josh Creek 6b3db98327 fix: bind assignments to authenticated player 2026-08-31 22:55:22 +01:00
Josh Creek 69f1ef6be1 feat: add player-scoped assignment recovery 2026-08-31 22:54:16 +01:00
Josh Creek 585056ccc3 feat: add Godot Steam session login 2026-08-31 22:49:05 +01:00
Josh Creek 222bbb5b84 feat: classify matchmaking recovery failures 2026-08-31 22:45:20 +01:00
Josh Creek fddbebb33b feat: display backend ranked profile 2026-08-31 22:44:21 +01:00
Josh Creek 62c1478913 feat: persist matchmaking recovery state 2026-08-31 22:42:43 +01:00
Josh Creek 47550aefae feat: add matchmaking queue UI 2026-08-31 22:39:29 +01:00
Josh Creek 5106ac64da feat: add authenticated matchmaking control client 2026-08-31 22:36:05 +01:00
Josh Creek 39ebfce1bb feat: add revisioned matchmaking client state 2026-08-31 22:33:33 +01:00
Josh Creek 698413cd91 feat: validate allocated assignment manifest 2026-08-31 20:38:56 +01:00
Josh Creek d864ce2475 feat: add allocated server compatibility config 2026-08-31 20:13:22 +01:00
Josh Creek 964094f65a docs: correct stale multiplayer/C#-backend claims, add TECH_STACK doc
CLAUDE.md and README.md described the pre-multiplayer state (local-only
MVP, planned C# backend) even though server-authoritative multiplayer,
the dedicated server, Docker/CI verification, and Steam transport have
since shipped (Phases 1-6). Update both to reflect reality and add a
docs index in CLAUDE.md pointing at multiplayer-next.md as the current
checklist.

- Add docs/TECH_STACK.md, linked from README, explaining the stack and
  why it's a single GDScript project with no separate backend.
- Add one TODO item for the video settings menu (missing presets/vsync/
  resolution scaling), blocked on the same profiling gate as the
  multiplayer 0.17 tasks.
- Pick up editor-generated .gd.uid sidecars and minor project.godot
  formatting noise from opening the project in Godot 4.7.
2026-08-31 18:20:52 +01:00
Josh Creek 6320b982a8 fix(project): keep comments out of project.godot and guard the settings
Godot's ConfigFile writer does not round-trip comments in project.godot. An
observed rewrite deleted both `;` blocks outright and spliced the three-line
`#` block above run/main_scene.dedicated_server onto the setting's own line,
leaving it commented out — which would send dedicated builds to the
interactive main menu instead of server_boot.tscn, with nothing failing until
someone noticed a server process rendering a menu.

Move the explanations into the code that owns the settings (server_boot.gd for
the dedicated-server override, video_settings.gd for stretch mode and vsync)
so they cannot be destroyed by a rewrite, and leave project.godot holding only
assignments plus Godot's own regenerated header.

Add tests/cases/test_project_settings.gd as the backstop: the feature-override
assertions read project.godot as text and reject a line that has been folded
into a comment, since ProjectSettings resolves `key.<feature>` overrides at
load time and never exposes the suffixed key. Verified by reproducing the
exact corruption, which fails the test, and it also covers the Jolt physics
engine, the required autoloads, and that no test-hook autoload is ever shipped
registered.
2026-08-24 08:40:16 +01:00
Josh Creek 6bafdc7794 feat(multiplayer): add Steam transport foundation 2026-08-21 18:52:07 +01:00
Josh Creek f2b72394de feat(server): complete phase 6 local verification 2026-08-21 18:38:30 +01:00
Josh Creek ec896b27ac feat(server): task 6.4 — structured logging the match and transport layers can reach
server_boot.gd's private _log could only ever see what the boot scene
itself observed: connects, disconnects, roster changes, tick overruns.
The events an operator is actually asked about - who scored, who got
kicked and why, which peer is flooding - happen inside networked_match.gd
and match_sim.gd, neither of which could reach a logger on a scene node
that gets freed at the first change_scene_to_file. scripts/server_log.gd
holds it as static state on a class_name: reachable from all three, no
autoload, no ordering dependency.

New events: goal, match_ended, kickoff, peer_kicked (previously only a
push_warning, carrying neither peer nor reason into the stream a
container captures), rate_limited, server_stalled. rate_limited fires
ONCE per peer per window rather than per packet - a flood is thousands of
packets a second and the log line must not become the amplifier the
replay recorder was capped to avoid being.

Off unless a server configures it, so a client, an editor session or a
unit-test run does not start printing server telemetry just because these
scripts loaded.

Rotation is deliberately not implemented: the server logs to stdout and
stops, because every way this is run already rotates better - docker's
json-file driver, journald, or logrotate on a redirect. A server that
also wrote and rotated its own file would fight all of them in a
container, where stdout is the interface. SERVER.md (6.6) documents the
three configurations.

Five tests on the one piece with real logic - the one-line contract.
Including log injection: a player name is attacker-controlled, and
without escaping, the name "x\n[0.000] INFO peer_kicked reason=nothing"
writes a fake event into the operator's log. Newlines are escaped rather
than dropped so the attempt stays visible.

End-to-end verification of the new events comes with 6.5, which is what
first makes a server run a match at all.
2026-08-21 17:13:11 +01:00