6.1 KiB
Tech stack (baseline decision)
Status: Baseline for prototype through early pre-production. Revisit before vertical-slice freeze if tooling or hiring assumptions change.
Constraints from product vision: Solo operator, server-authoritative critical paths, fixed isometric 3D client, tab-target combat, data-driven skills/items/recipes/quests, optional PvP zones, eventual scale-out (not day one).
Server runtime (locked): C# / .NET 8 — primary author has ~10 years C# experience; authoritative game logic, persistence, and ops stay in this stack.
Client scripting (locked): GDScript in Godot—fast iteration, native engine integration; server remains the only C# game-logic surface.
Other operator skills: JavaScript and TypeScript remain useful for content tooling and one-off scripts—not the authoritative server.
Summary
| Layer | Choice | Role |
|---|---|---|
| Game client | Godot 4.x + GDScript | Rendering, input, camera, local prediction (if any), UI, telemetry emit |
| Game server | C# / .NET 8 (ASP.NET Core) | Authoritative simulation, zones, combat/crafting resolution, persistence boundaries |
| RPC / messages | Protobuf (or JSON for earliest spike only) | Versioned contracts between client and server |
| Primary database | PostgreSQL | Characters, inventory, progression, economy ledger, idempotent transactions |
| Cache / presence (when needed) | Redis | Sessions, rate limits, hot read models—defer until second scaling pain |
| Content data | JSON or YAML + JSON Schema (or CUE later) | Skills, items, recipes, quests; validated in CI (can use Node or dotnet validators) |
| Repo / CI | Git + GitHub Actions or Gitea Actions | dotnet build, schema validation, optional Godot export |
Client: Godot 4
Why
- Strong fit for solo iteration: fast reload, small install, no revenue cap.
- 3D isometric camera (orthographic or perspective), zoom, and no rotation are straightforward in a single-camera rig.
- GDScript (locked) for all client gameplay and UI code—quick reload, examples and addons match; share contracts with the server via Protobuf or JSON (spike), not shared C# assemblies.
- Networking: treat WebSocket or TCP as transport only; authoritative logic stays on the ASP.NET Core server, not in Godot’s high-level multiplayer templates, to avoid fighting engine assumptions.
Prototype discipline
- One contained district; no multi-region streaming in engine until pre-production handoff slice.
- Client sends intents (
MoveIntent,UseAbilityIntent, …); server emits state deltas or snapshots.
Plan B
- Unity (6000 LTS track) if the art pipeline shifts; server stays C#—reuse patterns and types where practical.
Defer
- Unreal for this phase unless art direction requires it.
Server: C# (.NET 8)
Why
- ASP.NET Core (minimal APIs or controllers) + Kestrel; WebSockets, gRPC, or raw TCP alongside HTTP health/metrics.
- PostgreSQL via Npgsql; EF Core (migrations) or Dapper + FluentMigrator / DbUp—pick ORM vs hand-written SQL and stay consistent.
- Protobuf: Grpc.Net or protobuf-net; JSON is acceptable for the first spike only.
- Prototype shape: single
GameHost(or named) process—in-memory zone state + PostgreSQL for durable character/inventory; split processes only when metrics demand it.
Pre-production
- Optional read replicas or separate presence service; job queues only when needed.
Server alternative (not default)
TypeScript / Node remains viable for tools-only or a secondary BFF; avoid splitting authoritative state across two runtimes unless there is a clear boundary (e.g. web shop vs simulation).
Other server languages (optional later)
| If you… | Consider |
|---|---|
| Want a tiny deploy binary for a worker | Go — isolated sidecar, not replacing the main C# sim without a decision doc |
| Experiment | Rust — only for proven hot paths |
Data and persistence
- PostgreSQL as source of truth for anything that must survive restarts or be audit-able (inventory, trades, progression).
- Migrations: EF Core or FluentMigrator / DbUp with Npgsql; keep migrations in-repo.
- Avoid client-trust for economy: craft outcomes, loot grants, and trades commit only after server validation + DB transaction where required.
Content pipeline
- Author in JSON/YAML; validate with JSON Schema in CI (Node-based ajv/CLI, dotnet-based validators, or CUE later).
- Server loads tables at boot or hot-reloads in dev; client may receive bundles or hash-versioned blobs to avoid drift.
- Epic 3/7 decomposition modules (
RecipeDef,QuestDef, …) map directly to these files.
Observability
- Serilog and/or OpenTelemetry for .NET from early prototype.
- Align event names with
E9.M1 TelemetryEventSchemain the vision doc; client batches to server or OTLP endpoint as capacity allows.
Security (proportionate to phase)
- Prototype: TLS on public endpoints if exposed; auth token or session secret; minimal PII handling.
- Pre-production: Rate limits, input validation on all RPCs, admin tools behind separate auth.
Explicit non-goals for stack selection
- Choosing a commercial “MMO middleware” that locks data formats or hosting.
- Client-authoritative combat or inventory.
- Full anti-cheat and bot defense before core loop fun is proven (track with E9.M4 workflows later).
Revision triggers
Revisit this document if:
- Target platforms add console or mobile with hard certification constraints.
- Art pipeline commits to an engine not listed above.
- Co-op session model forces P2P or large physics sync (unlikely for tab-target isometric).
- Simulation CPU bottlenecks justify a Go/Rust worker for isolated workloads—document the split; keep C# as orchestration unless you rewrite the decision.
Related docs
neon_sprawl_vision.plan.md— product locks and phase gatesdocs/decomposition/README.md— epic/module decomposition