Refactor project structure and update documentation. Replace PixiJS with plain DOM for UI rendering, enhance README with game features, and revise protocol documentation for HTTP API. Remove unused files and streamline client code for better maintainability.
ci / server (push) Failing after 3m31s
ci / client (push) Successful in 17s

This commit is contained in:
Leonid Pershin
2026-08-18 12:27:30 +03:00
parent e6739e7912
commit b9ddc018d3
73 changed files with 4387 additions and 2930 deletions
+35 -23
View File
@@ -1,11 +1,11 @@
# h-school
Base for a multiplayer browser game: an authoritative .NET server simulating the world with an
ECS, a PixiJS client that renders snapshots, and .NET Aspire tying them together for local runs
and integration tests.
Base for a school-management game: an authoritative .NET server that owns the saves and their
in-game calendars, a TypeScript client that renders the menus, and .NET Aspire tying them together
for local runs and integration tests.
There is no game here yet — there is a world with a few obstacles, players that can walk around
it, and every piece of plumbing needed to build a game on top.
What exists today is the shell around a game: a main menu of schools, a creation form, and a
school screen with a running game clock. The school itself is still empty.
## Stack
@@ -13,8 +13,8 @@ it, and every piece of plumbing needed to build a game on top.
| --- | --- |
| Server | .NET 10, ASP.NET Core |
| Simulation | [Arch](https://github.com/genaray/Arch) ECS, fixed 20 Hz tick |
| Transport | raw WebSocket, custom binary protocol |
| Client | TypeScript, [PixiJS 8](https://pixijs.com/), Vite |
| Transport | REST for the menu, raw WebSocket + binary protocol for the clock |
| Client | TypeScript, Vite, plain DOM ([PixiJS 8](https://pixijs.com/) is installed for the game view that comes next) |
| Orchestration | .NET Aspire 13 |
| Tests | xUnit v3, Vitest, `Aspire.Hosting.Testing` |
@@ -36,10 +36,22 @@ and Node are on PATH first and passes any arguments through
The Aspire dashboard opens with two resources: `server` (ASP.NET Core) and `client` (Vite dev
server). Aspire assigns the client a random port on every run, so take its URL from the dashboard
rather than guessing. Open it and use **WASD** or the arrow keys to move — the HUD shows
connection state, server tick, round-trip time and entity count.
rather than guessing.
Open the same URL in a second tab to see another player: both are simulated by the one server.
## What you can do
- **Main menu** — every school as a card with its name and its current in-game date and time,
ticking live. Deleting one asks for confirmation first.
- **Create a school** — type a name or roll a random one, pick a start date (3 April 2012, 06:00
by default). At six schools the create button is disabled and says why.
- **Inside a school** — the date, time and weekday of the game calendar, play/pause and the
×½ ×1 ×2 ×3 ×4 speed buttons, plus a way back to the menu.
Time runs at 5 game minutes per real second at ×1. **Every school runs on its own**, whether or
not you are inside it — the menu cards keep counting. Only the pause button stops a school, and it
stays paused (the card says so) until you press play again.
Schools live in server memory: restarting the server clears them.
## Run the pieces separately
@@ -61,30 +73,30 @@ dotnet test
```
- `tests/HSchool.Protocol.Tests` — wire-format round-trips and byte layouts.
- `tests/HSchool.Simulation.Tests`ECS behaviour against `GameWorld`, no host involved.
- `tests/HSchool.AppHost.Tests` — boots the real Aspire graph, connects a WebSocket, plays a few
ticks. Runs headless (`--HSchool:Headless=true`), so no Node install is needed.
- `tests/HSchool.Simulation.Tests`the game clock and the school registry, no host involved.
- `tests/HSchool.AppHost.Tests` — boots the real Aspire graph, drives the menu API and the
WebSocket clock. Runs headless (`--HSchool:Headless=true`), so no Node install is needed.
```bash
npm --prefix src/HSchool.Client test
```
Vitest covers the client codec and snapshot interpolation.
Vitest covers the client codec and the calendar formatting.
## Layout
```
src/
HSchool.Protocol/ binary wire format (shared contract with the client)
HSchool.Simulation/ Arch ECS world, components, systems
HSchool.Server/ ASP.NET Core host, WebSocket endpoint, game loop
HSchool.Simulation/ schools, the game clock, the Arch ECS world
HSchool.Server/ ASP.NET Core host, menu API, WebSocket endpoint, game loop
HSchool.ServiceDefaults/ Aspire telemetry, health checks, resilience
HSchool.AppHost/ Aspire orchestration
HSchool.Client/ Vite + TypeScript + PixiJS renderer
HSchool.Client/ Vite + TypeScript UI
tests/
docs/
architecture.md how the pieces fit together
protocol.md the wire format, byte by byte
protocol.md the HTTP API and the wire format, byte by byte
AGENTS.md working agreements for humans and coding agents
```
@@ -96,12 +108,12 @@ Simulation tunables live under the `Simulation` section of
| Key | Default | Meaning |
| --- | --- | --- |
| `TickRate` | 20 | fixed simulation steps per second |
| `WorldWidth` / `WorldHeight` | 1600 × 900 | field size in simulation units |
| `PlayerSpeed` | 260 | units per second |
| `PlayerRadius` | 18 | player body radius |
| `MaxSchools` | 6 | how many schools may exist at once |
| `GameMinutesPerRealSecond` | 5 | game minutes per real second at ×1 |
| `DefaultStartDate` | `2012-04-03T06:00:00` | prefilled start of a new school |
## What is deliberately missing
No authentication, no persistence, no client-side prediction, no delta compression, no rooms or
matchmaking. Each of these has a natural seam described in
No persistence, no authentication, and nothing inside a school yet — every school owns an empty
ECS world waiting for its first entities. Each of these has a seam described in
[`docs/architecture.md`](docs/architecture.md).