mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-10 16:04:04 +00:00
docs: explain why the matchmaking control plane is Go, fix stale status
Add a Go-vs-C#/Rust/C++ rationale for the matchmaking control plane to TECH_STACK.md, and point at it from MATCHMAKING.md and README.md. Also correct CLAUDE.md and README.md, which still described the backend as unstarted/not built even though server/ has ~13k lines of Go across matcher, allocator, api, store, security, supervisor and agones.
This commit is contained in:
@@ -6,7 +6,7 @@ Important rule: never create co-authored commits. Never mention Claude in commit
|
||||
|
||||
## Project overview
|
||||
|
||||
Cosmic Clash is an open-source, physics-based "vehicle soccer" game (a spiritual successor to Rocket League) built in Godot 4.7, using space ships instead of cars. It is GDScript/Godot only today — the "C# backend" in README.md was never started, and the dedicated server is an export of this same Godot project. A **separate backend service is now planned** (not started) for casual/ranked matchmaking, which is a 1.0 launch blocker; see `docs/MATCHMAKING.md`. README.md's "MVP is local-only against bots" section is historical: server-authoritative online multiplayer, a headless dedicated server, Docker/CI verification, and an optional Steam transport are all implemented (Phases 1–6). See `multiplayer-next.md` for what actually remains.
|
||||
Cosmic Clash is an open-source, physics-based "vehicle soccer" game (a spiritual successor to Rocket League) built in Godot 4.7, using space ships instead of cars. The game and the dedicated server are GDScript/Godot only — the "C# backend" an early README described was never started, and the dedicated server is an export of this same Godot project. There is one component outside the Godot project: a **Go matchmaking control plane** in `server/` for casual/ranked queues, ranked ratings and Agones-based server allocation. It is partially implemented and a 1.0 launch blocker — see `docs/MATCHMAKING.md` for the design, `multiplayer-next.md` §0 and §7 for what remains (a real deployment cannot complete a match end to end today), and `docs/TECH_STACK.md` for why the control plane is Go rather than C#, Rust or C++. README.md's "MVP is local-only against bots" section is historical: server-authoritative online multiplayer, a headless dedicated server, Docker/CI verification, and an optional Steam transport are all implemented (Phases 1–6). See `multiplayer-next.md` for what actually remains.
|
||||
|
||||
Because the gameplay concept (vehicle soccer) can't be copyrighted but specific expression can, all code/art/assets must be original — this is why the project uses Godot instead of Unreal/Unity and ships instead of cars. Keep this in mind when writing code or pulling in assets: don't port or closely mirror Rocket League's actual implementation.
|
||||
|
||||
@@ -19,8 +19,8 @@ The prose docs carry far more design rationale than the code comments, and sever
|
||||
- `SERVER.md` — dedicated-server build, config, systemd deploy, sizing.
|
||||
- `STEAM.md` — optional GodotSteam custom-build setup and the transport contract.
|
||||
- `FLIGHT_MANUAL.md` — the player-facing flight model.
|
||||
- `docs/MATCHMAKING.md` — casual/ranked queue design. Not implemented; a 1.0 launch blocker, and the reason a backend service now exists in the plan.
|
||||
- `docs/TECH_STACK.md` — what the project is built with and why.
|
||||
- `docs/MATCHMAKING.md` — casual/ranked queue design, and the locked constraints (Go/PostgreSQL/Redis/Agones) the `server/` module implements. Partially implemented; a 1.0 launch blocker, and the reason a backend service outside the Godot project exists at all.
|
||||
- `docs/TECH_STACK.md` — what the project is built with and why, including the Go-vs-C#/Rust/C++ rationale for the matchmaking control plane.
|
||||
- `TODO.md` — deferred non-multiplayer work (audio is the big one: there is none at all).
|
||||
|
||||
## Godot MCP server
|
||||
|
||||
@@ -18,7 +18,7 @@ The concept of 'vehicle soccer' cannot be copyrighted, but the original expressi
|
||||
|
||||
Cosmic Clash is a single Godot 4.7 project, written entirely in GDScript. That same project exports both the interactive game and a headless dedicated server for online multiplayer. See [`docs/TECH_STACK.md`](docs/TECH_STACK.md) for the full stack and the reasoning behind each choice.
|
||||
|
||||
Online play with casual and ranked queues is a 1.0 requirement, and it needs a small backend service for identity, matchmaking and ratings — separate from the Godot project, and not yet built. See [`docs/MATCHMAKING.md`](docs/MATCHMAKING.md).
|
||||
Online play with casual and ranked queues is a 1.0 requirement, and it needs a backend service for identity, matchmaking and ratings — separate from the Godot project. That control plane is written in Go (with PostgreSQL, Redis and Agones on Kubernetes), chosen for the Agones/Kubernetes-native ecosystem rather than for raw speed: it never touches a simulation packet. See [`docs/MATCHMAKING.md`](docs/MATCHMAKING.md) for the design and [`docs/TECH_STACK.md`](docs/TECH_STACK.md) for why Go over C#, Rust or C++.
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
+5
-1
@@ -29,7 +29,11 @@ Locked constraints:
|
||||
SDR. Direct ENet remains first-class for local development, CI, LAN,
|
||||
self-hosting, and community servers.
|
||||
- The control plane is Go, PostgreSQL, and Redis, deployed on Kubernetes.
|
||||
Agones owns game-server allocation and lifecycle.
|
||||
Agones owns game-server allocation and lifecycle. Go is chosen for the
|
||||
Agones/Kubernetes-native client ecosystem and its concurrency model, not
|
||||
for raw speed — the control plane never touches a simulation packet. See
|
||||
"Matchmaking control plane" in [`TECH_STACK.md`](TECH_STACK.md) for the
|
||||
full rationale and the alternatives weighed.
|
||||
- Infrastructure is provider-portable. Provider-specific cluster, network,
|
||||
DNS, and secret-store configuration lives behind isolated deployment
|
||||
overlays; application code never calls a provider allocation API.
|
||||
|
||||
+49
-3
@@ -133,6 +133,50 @@ most familiar with. That matches what's independently visible in the repo —
|
||||
(`make verify-phase6`), while the systemd unit is native-deployment
|
||||
documentation only, with no automated verification of its own.
|
||||
|
||||
## Matchmaking control plane: Go, PostgreSQL, Redis, Agones
|
||||
|
||||
The one part of the project that is *not* the Godot project. `server/` is a Go
|
||||
module (~13k lines of non-test code across `matcher`, `allocator`, `api`,
|
||||
`store`, `security`, `supervisor`, `agones`, `migrations`, `observability`)
|
||||
implementing the casual/ranked queue design in
|
||||
[`MATCHMAKING.md`](MATCHMAKING.md), plus a small PID-1 supervisor that exists
|
||||
because Godot/GDScript cannot intercept `SIGTERM` and Agones needs a graceful
|
||||
drain signal to land somewhere.
|
||||
|
||||
**Why Go, and why "performance" is the wrong reason to give:** the control
|
||||
plane is not in the simulation hot path. Physics, snapshots and 60 Hz input
|
||||
all live in the Godot dedicated server over ENet/SDR (see the transport
|
||||
sections above); Go never touches a game packet. Its actual workload is many
|
||||
mostly-idle WebSocket connections, a matcher loop that runs on a sub-second
|
||||
tick, and I/O against PostgreSQL, Redis and the Kubernetes API. That is
|
||||
I/O- and concurrency-bound, not CPU-bound, so the raw single-thread speed a
|
||||
systems language would buy is spent on work this service doesn't do. What
|
||||
actually drove the choice:
|
||||
|
||||
- **Agones and Kubernetes are Go-native.** Allocation, the GameServer SDK and
|
||||
the k8s client are all first-party Go. Any other language means hand-rolling
|
||||
REST against the Agones allocation service — see `server/agones/`, which uses
|
||||
those clients directly.
|
||||
- **Goroutines plus `context` are the right shape for the problem** — many
|
||||
concurrent idle connections, a few periodic loops, and cancel-everything-on-
|
||||
shutdown semantics that the PID-1 supervisor depends on.
|
||||
- **The surrounding operational ecosystem is Go** — Prometheus instrumentation
|
||||
(`server/observability/`), structured logging, migrations, and the
|
||||
provider-portable deployment tooling.
|
||||
- **Static binaries and slim containers**, which matters for the supervisor and
|
||||
for keeping the allocated game-server image close to the existing one.
|
||||
|
||||
**Alternatives, honestly weighed:** Rust or C++ would be the correct answer for
|
||||
a custom UDP relay or the simulation server itself, and buy nothing measurable
|
||||
for a queue-and-allocate service — while costing significantly in iteration
|
||||
speed. C# is the only serious contender (ASP.NET Core is fast, its async model
|
||||
is excellent, and Postgres/Redis/WebSocket support is mature); it loses on the
|
||||
Agones/Kubernetes side, where the clients are community-maintained rather than
|
||||
first-party, and on container weight. TypeScript or Python would prototype
|
||||
faster but fit poorly for a service whose failure modes are almost entirely
|
||||
races and timeouts. None of those gaps is large enough to justify rewriting the
|
||||
Go that already exists.
|
||||
|
||||
## AI opponents: reinforcement learning, trained out-of-process, run in pure GDScript
|
||||
|
||||
Two entirely separate pieces, deliberately joined only at a JSON file:
|
||||
@@ -177,9 +221,11 @@ Python, no .NET, no network." Keeping the shipped game GDScript-only (no
|
||||
## What's deliberately absent
|
||||
|
||||
- **No C# or .NET runtime anywhere in the shipped game or server.** The
|
||||
"C# backend" in `README.md`'s early framing was never built. A backend
|
||||
service *is* now planned for matchmaking (see below), but nothing has
|
||||
chosen C# for it — that framing predates every real decision here.
|
||||
"C# backend" an early version of `README.md` described was never built —
|
||||
that wording is long gone from the README itself. A backend
|
||||
service *does* now exist for matchmaking, but it is Go, not C# — that
|
||||
framing predates every real decision here. See "Matchmaking control plane"
|
||||
above for why Go was chosen over C# and over Rust/C++.
|
||||
- **No HTTP/WebSocket/gRPC layer for simulation traffic** — the live game uses
|
||||
ENet/Steam SDR over UDP via Godot's own `MultiplayerAPI`. The matchmaking
|
||||
control plane now has an authenticated Go REST/WebSocket boundary for queue,
|
||||
|
||||
Reference in New Issue
Block a user