4.7 KiB
Development
Prerequisites
| Tool | Version | Used for |
|---|---|---|
| .NET SDK | 10.0 | Server and tests |
| Node.js + npm | 22 | Website |
| Docker + Compose | recent | Optional, for container builds |
Running locally
Two terminals:
# 1. Game server on http://localhost:5080
cd actionBlocks_server
dotnet run --project src/ActionBlocks.Server --urls http://localhost:5080
# 2. Website on http://localhost:5173
cd actionBlocks_website
npm install
npm run dev
The Vite dev server proxies /hub (including WebSockets) to http://localhost:5080, so the default hub URL <origin>/hub just works. To point it at another server, use DEV_SERVER_URL=http://host:port npm run dev.
To play against yourself, open the site in two browser windows. Create a lobby in one and join with the code in the other. Keyboard focus decides which window receives input.
Handy server settings for testing
dotnet run finds config/game.json in the repo root automatically. Edit it (changes apply from the next match), point GAME_CONFIG to a separate test file, or override single values with environment variables:
Game__ItemSpawnChance=0.9 Game__CountdownSeconds=1 \
dotnet run --project src/ActionBlocks.Server --urls http://localhost:5080
That gives items on almost every piece and a near-instant start, which is useful for testing items. To test one item, set the weight of all others to 0 in a test config.
Commands
| Where | Command | Does |
|---|---|---|
actionBlocks_server/ |
dotnet build |
Builds all projects |
dotnet test |
Runs the game logic tests | |
actionBlocks_website/ |
npm run dev |
Dev server with hot reload |
npm run typecheck |
TypeScript check only | |
npm run build |
Typecheck + production build into dist/ |
|
npm run preview |
Serves dist/ locally |
|
| repo root | docker compose build |
Builds both images (server image runs the tests) |
docker compose config |
Validates the compose file and .env |
Testing strategy
- Game rules live in
ActionBlocks.Gameand are covered by unit tests. When you change or add a rule, add a test intests/ActionBlocks.Game.Tests. UseTestHelpers.CreatePlayerfor a deterministic player: it takes a fixed piece sequence and an item chance (0 or 1). UseFillRowto build board situations. - Networking and lobby flow has no automated tests yet. Test it manually, or with a small script client (see Protocol → Writing a test client).
- Bots are an effective test tool. A script client that joins a lobby and plays with a simple heuristic shows how garbage and items work under real conditions: it clears lines, collects items and uses them on you. One works like this:
- Read your board from the snapshot.
- For every rotation and x position of the active piece, simulate dropping it and score the result: lines cleared minus holes, height and bumpiness.
- Send the best move's
RotateCw/MoveLeft/MoveRight/HardDropinputs. - Send
UseItemwhenever the inventory is not empty.
- Frontend has no unit tests.
npm run build(which includes the typecheck) catches type errors, and visual checks happen in the browser.
Debugging tips
- Server logs go to stdout. Exceptions in the tick loop are logged per lobby as
Failed to update lobby {Code}. - Inspect live snapshots. In the browser devtools, open Network → WS → the
/hubconnection → Messages. EachMatchStateframe shows the full state, and its records are separated by\u001e. GET /healthon the server tells you whether the process is up.- Is the hub reachable?
curl -X POST "<hub-url>/negotiate?negotiateVersion=1"must return JSON listing the available transports.
Code conventions
Server
- File-scoped namespaces, nullable reference types enabled, one main type per file. Small closely related types may share a file, e.g. all items in
Items.cs. ActionBlocks.Gamemust stay free of ASP.NET or serialization dependencies. Mapping to the wire format happens inActionBlocks.Server/Dtos.- Game objects are not thread-safe. Only touch them inside
lock (lobby.Sync). - Prefer adding a value to
GameSettings, or an implementation of an existing interface, over hard-coding numbers in logic.
Website
- Function components and hooks. No state library: server state is owned by
useGameConnection. - Styling only through
*.module.css, plus the CSS variables intheme/global.css. Don't use inline styles except for computed sizes and colors. - Reference graphics and colors only through
theme/assets.tsandtheme/colors.ts. - Keep
net/types.tsin sync with the server DTOs. - UI text in the pixel font: ASCII only.
- No trademarked names in user-facing text or assets.