Audited rather than appended. What had drifted, now corrected: - ROADMAP's opening still described the project before this session: no word of the anti-cheat fixes, 468 tests, 23 smoke assertions, and a screenshot list half its current size. It now summarises the session, lists seven open items raised with the user and not yet decided (the boss-kill experience edge, the hub frame rate, aggro through corner cracks, the Warden-hall alcoves, one-tile arena doors, the Proving Grounds before release, hit feedback), and quotes current numbers. Its radius table still gave BULLET_INTEREST_RADIUS as the bullet cull at 2200; it is a 2900 ceiling over a per-bullet check. - NETCODE described the flat bullet radius as the design, claimed the respawn lockout gates connected players (they are unbound on death), and called actor scoping "next stage". All corrected, and a new section covers what the handshake and server now refuse: duplicate sessions, reasons that now arrive, paced control messages, coalesced store writes, bounds-checked hot decoders. - DECISIONS gains the audit's rules, the Proving Grounds' status, the tunnel and entrance rules, and the interface calls -- each flagged as the user's or as a judgement call. - ARCHITECTURE's file map lacked the actor classes, the dev auth provider, the menu backdrop and any tools section. - README told people to start a client with --name, which now only names bot characters, and its feature list predated fog, tunnels and carried health. CLAUDE.md gains three invariants (health on the record, one session per account, tools that host use scratch data); WORKFLOW gains the four traps this session fell into or nearly did. Every doc was checked for unintended deletions against the session's start, and every relative link resolves. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
94ad6b3429
commit
08f58af1a8
7 files changed
+251
-26
No files matched your search
+42
-7
@@ -23,6 +23,23 @@ a lobby hub with dungeon runs, and an emergency escape. All of that exists, plus
|
||||
the four stages that followed: characters and permadeath, inventory and loot,
|
||||
upgrades, and a second boss that moves.
|
||||
|
||||
Since then, in one long session:
|
||||
|
||||
- **An anti-cheat audit, and its fixes.** Item duplication through two sessions
|
||||
on one account; shots through walls from muzzle offsets (the player's and every
|
||||
boss's); every firing enemy located by the flat bullet-interest radius;
|
||||
unbounded store writes from small packets; the hub's escape channel; hub loot
|
||||
griefing; unbounded snapshot and event decoders. Each is in DECISIONS.md under
|
||||
"The anti-cheat audit".
|
||||
- **Health survives a door**, the hub regenerates it at 10%/s, and experience goes
|
||||
only to players within `XP_AWARD_RADIUS` of the kill.
|
||||
- **Fog lit by rays**, so shadows cut through tiles ([visibility.gd](../src/view/visibility.gd)),
|
||||
and **bullets fade past the edge of sight** without ever arriving unseen.
|
||||
- **Tunnels 2–4 wide**, an occasional enemy group in them, nothing watching the
|
||||
entrance on arrival, and arenas that keep their walls.
|
||||
- **Two interface passes** — see the Interface section of DECISIONS.md.
|
||||
- **The smoke flake is fixed** (below).
|
||||
|
||||
So there is no obvious "next ticket". What follows is the honest list of
|
||||
candidates, none of which the user has chosen — **ask before starting one.**
|
||||
|
||||
@@ -35,6 +52,18 @@ candidates, none of which the user has chosen — **ask before starting one.**
|
||||
| **Replace the two non-redistributable packs** | Bullet and FX art is local-only and non-commercial, which blocks both a public repo copy and a commercial release. | CC0 or CC BY replacements. See [ASSETS.md](ASSETS.md). |
|
||||
| **Transport encryption** | `ENetMultiplayerPeer` supports DTLS. Required before a public server, not before then. | Follows the auth decision. |
|
||||
|
||||
And smaller things raised with the user and not yet answered or chosen:
|
||||
|
||||
| Open item | What is known |
|
||||
| --- | --- |
|
||||
| **A boss kill can pay nothing** | Both arenas are wider corner to corner (803 and 630 units) than `XP_AWARD_RADIUS` (506), so a player in the far corner when the boss dies gets no experience for the run. Suggested fix: anyone inside the boss room counts as present for a boss kill. |
|
||||
| **The hub renders at ~60 fps, a dungeon at ~240** | Measured with the old fog and the new, same scene: not the fog. Cause unknown. |
|
||||
| **Aggro sees through cracks the fog closes** | `MapGrid.has_line_of_sight` steps diagonally between two tiles that touch only at a corner. The fog treats that as closed, so an enemy can occasionally see and shoot you through a gap you cannot see through. |
|
||||
| **Two one-tile alcoves in the Warden's hall** | Rows 4 and 8 of `Rooms.warden_hall()` are one character longer than the rest, leaving notches in the east wall. Possibly a typo; asked, not answered. |
|
||||
| **Arena doors are one tile wide** | Authored in the stamps. Tunnels into them are now at least two. |
|
||||
| **The Proving Grounds must not ship** | Full experience for an 8%-health boss. Remove it from `Dungeons.ORDER` and its `P` marker before a release. |
|
||||
| **Hit feedback on enemies** | `Art.IMPACT` is still loaded and never played (the candidate above). |
|
||||
|
||||
Each stage below also carries its own **Known gaps** section — those are smaller
|
||||
and more specific than the table above.
|
||||
|
||||
@@ -60,8 +89,8 @@ What "everything passes" currently means. Numbers move; the shape does not.
|
||||
| Gate | Covers | Runtime |
|
||||
| --- | --- | --- |
|
||||
| `tools/check.sh` | every script parses and type-checks | ~5s |
|
||||
| `tools/test.sh` | 468 GUT tests, no SceneTree | ~4s |
|
||||
| `tools/smoke.sh` | 23 assertions over a real ENet socket: handshake, auth, character creation and persistence, both dungeon kinds, escape, hard kill, polite disconnect | ~40s |
|
||||
| `tools/test.sh` | 576 GUT tests, no SceneTree | ~4s |
|
||||
| `tools/smoke.sh` | 27 assertions over a real ENet socket: handshake, auth, character creation and persistence, all three dungeons, escape, hard kill, polite disconnect, a duplicate account refused with its reason | ~40s |
|
||||
| `diag_prediction.tscn` | client-prediction gap, with injected clock drift | ~10s |
|
||||
| `diag_progression.tscn` | kill → xp → level → health, death → retire → roster, swap guards | ~10s |
|
||||
| `diag_loot.tscn` | drop → snapshot → pick up → persist → use → drop, and both loot visibilities on the wire | ~10s |
|
||||
@@ -69,10 +98,15 @@ What "everything passes" currently means. Numbers move; the shape does not.
|
||||
|
||||
`tools/screenshot.tscn` is a **manual** check, not a gate: it needs a display,
|
||||
and it is the only thing in the project that can tell you the interface
|
||||
actually rendered. Run it after touching `src/ui/`. It captures the main menu,
|
||||
the HUD, the pause menu, settings, credits and the upgrade choice — the last of
|
||||
those by staging an offer, because earning one would make the shot depend on a
|
||||
dungeon run.
|
||||
actually rendered. Run it after touching `src/ui/` or `src/view/`. It captures
|
||||
the connect screen, the hub standing on a portal, the pause menu, settings,
|
||||
credits, the upgrade choice, the roster after a death, a dungeon arrival, a
|
||||
tunnel (with and without F1), a staged boss fight, and the escape banner. It runs
|
||||
on **its own character store and account** — it used to host on the player's
|
||||
real ones — and stages what it cannot earn (an offer, a party, a death).
|
||||
Timings are frame counts and frames run as fast as the display allows, so
|
||||
anything tied to server ticks is captured by condition instead (see the escape
|
||||
shot).
|
||||
|
||||
It has now caught four bugs that every other gate passed: the theme applying to
|
||||
nothing, the test suite rewriting the player's settings, an invisible slider
|
||||
@@ -126,7 +160,8 @@ terrain it does not have.
|
||||
| `FOG_VIEW_RADIUS` | 460 | — | What the player can see. |
|
||||
| `ACTOR_INTEREST_RADIUS` | 800 | fog radius | Enemies beyond it are never sent. Above the fog radius so nothing pops in at the edge of sight. |
|
||||
| `MAP_STREAM_RADIUS` | 900 | fog radius | Client predicts movement and simulates bullets against terrain it cannot see. |
|
||||
| `BULLET_INTEREST_RADIUS` | 2200 | longest bullet travel + fog radius | A bullet is announced once at spawn. Withhold one that later flies into view and it becomes invisible damage. `test_interest.gd` computes the floor from real content, so a faster bullet fails a test instead. |
|
||||
| `BULLET_INTEREST_RADIUS` | 2900 | longest bullet travel + fog radius | **A ceiling only.** Spawns are culled per bullet — can *this* one reach visible ground (`ServerRuntime._bullet_concerns`). As a flat cull it exceeded the depth-1 map and located every firing enemy for everyone. |
|
||||
| `XP_AWARD_RADIUS` | 506 | 1.1 × fog radius | Experience goes to the living players within it of the kill, undivided. |
|
||||
|
||||
Fog is a *rendering* rule and defends nothing on its own — a modified client
|
||||
draws whatever it holds. The defence is what the server declines to send.
|
||||
|
||||
Reference in new issue
Block a user