The roster sent to clients now contains living characters only. Retirement stays server-side bookkeeping for archival; from the player's side a dead character is simply gone, and listing it offers a choice that cannot be taken. The XP bar only moved on a level-up or a character swap because it read the character roster, which is re-sent only when the SET of characters changes. Experience now rides the snapshot -- four bytes on a message already going out at 20Hz -- and the server mirrors each grant into the world immediately rather than only when a level is crossed. The create field starts with a suggested name instead of blank, and offers another after each creation. Two bugs found while testing, both mine: The first was a bad patch of my own: a change meant for the snapshot decoder also matched inside decode_characters, which then read a four-byte field its encoder never wrote and ran off the end of every packet. This is precisely the "encodes but decodes wrong" failure the codec tests exist to catch, and it was caught within a minute of the test being written. Chasing that exposed a real robustness gap: StreamPeerBuffer.get_utf8_string() pushes an engine error and returns garbage when the buffer is short, so a truncated or hostile character/roster packet produced error spam instead of degrading. Both decoders now bounds-check every field, with tests that slice each packet at many lengths and assert it degrades rather than inventing entries -- the same guarantee the input decoder already had. 206 tests. check.sh, test.sh, smoke.sh and both diagnostics pass.
This commit is contained in:
@@ -174,3 +174,13 @@ at level 15 — a capped character regains 1.2 hp/s against a level 1's 0.5, and
|
||||
both take about 200 seconds to heal from nothing. No combat gate because at this
|
||||
rate it cannot out-heal anything actually shooting at you, and a trickle that
|
||||
never stops is easier to reason about than a timer players have to learn.
|
||||
|
||||
**A dead character is gone, as far as the player is concerned.** Retirement is
|
||||
the server's own bookkeeping for archival and troubleshooting; the roster the
|
||||
client receives contains living characters only. Listing the dead would offer a
|
||||
choice that cannot be taken.
|
||||
|
||||
**Experience rides the snapshot, not the character roster.** The roster is only
|
||||
re-sent when the *set* of characters changes, so a bar fed from it moved only on
|
||||
level-up or a swap. The live total is four bytes on a message that already goes
|
||||
out at 20 Hz.
|
||||
|
||||
+3
-1
@@ -85,7 +85,9 @@ play off server events. Enough to prove the pipeline, not a finished look.
|
||||
| XP from kills, bosses worth far more | done | `ServerRuntime._award_kill` |
|
||||
| Colour visible in world and on the HUD | done | snapshot carries it; `WorldView._draw_ship` tints |
|
||||
| Swap character from the hub | done | Esc menu → Change character; refused server-side in a dungeon |
|
||||
| XP percentage to next level | done | `HUD._draw_xp_bar` |
|
||||
| XP percentage to next level | done | `HUD._draw_xp_bar`, fed live from the snapshot |
|
||||
| Dead characters hidden from the roster | done | `ServerRuntime._send_characters` sends living only |
|
||||
| Suggested name when creating | done | `Character.random_name` |
|
||||
| Passive health regeneration | done | `SimPlayer.regenerate`, 0.5%/s of maximum |
|
||||
|
||||
Verified end to end by `tools/diag_progression.tscn`, which drives the real
|
||||
|
||||
Reference in New Issue
Block a user