<feed xmlns='http://www.w3.org/2005/Atom'>
<title>typerpunk/crates/steam/src, branch main</title>
<subtitle>Rust + WASM typing game.
</subtitle>
<id>https://srdusr.com/git/typerpunk/atom?h=main</id>
<link rel='self' href='https://srdusr.com/git/typerpunk/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://srdusr.com/git/typerpunk/'/>
<updated>2025-12-05T20:56:00+00:00</updated>
<entry>
<title>Show the passage during the countdown, and fix navigation across screens</title>
<updated>2025-12-05T20:56:00+00:00</updated>
<author>
<name>srdusr</name>
<email>99972264+srdusr@users.noreply.github.com</email>
</author>
<published>2025-12-05T20:56:00+00:00</published>
<link rel='alternate' type='text/html' href='https://srdusr.com/git/typerpunk/commit/?id=076f29369e51dfb5798f70099a330ebeb1b66a4e'/>
<id>urn:sha1:076f29369e51dfb5798f70099a330ebeb1b66a4e</id>
<content type='text'>
Countdown
- Five seconds instead of three, and shown over the passage on the race
  screen rather than in an empty lobby. New ServerMessage::RaceText carries
  the text (and its attribution) just before the countdown starts, so every
  client can put it on screen and let players read the opening words while
  the numbers run - what TypeRacer and 10FastFingers both do. Typing is
  locked until Start lifts the gate.
- Two subscriptions had to move with it. Building the race view tears the
  lobby down, and the lobby owned the only handlers for Countdown and Start,
  so the count stopped arriving exactly when it was needed and the gate would
  never have lifted.
- The TUI and Steam clients match ServerMessage exhaustively, so both gained
  an arm for the new variant; whole workspace checks clean.

Multiplayer attribution
- Race passages now carry who wrote them, so a race shows its source the way
  single player always has. Previously the server sent bare strings and both
  the race and its end screen showed nothing.

Navigation
- Every screen's full-width "Back" button becomes a close control at the top
  of the content. The wordmark and Escape already went back, so it was a
  third way to do the same thing and the least reachable of them.
- The multiplayer screen had a Back button on top of that; gone.

Fixes
- The end screen graph is drawn into a canvas, so it cannot inherit a theme
  change the way the rest of the page does. It now redraws on one - switching
  theme used to leave the chart in the old palette.
- .stats-empty was align-self:flex-start inside a centred column, so "Sign in
  to add friends" sat on a different axis from its own Sign In button.
- The store showed a sign-in prompt instead of its catalogue, so nobody could
  see what signing in would get them. The catalogue now renders signed out,
  with prices, behind a sign-in note.
- The room code field is sized for the five characters a code actually is,
  and Join carries the same weight as the field it belongs to.
</content>
</entry>
<entry>
<title>Add multiplayer bots, typing languages, and rework the UI layout</title>
<updated>2025-09-11T19:53:00+00:00</updated>
<author>
<name>srdusr</name>
<email>99972264+srdusr@users.noreply.github.com</email>
</author>
<published>2025-09-11T19:53:00+00:00</published>
<link rel='alternate' type='text/html' href='https://srdusr.com/git/typerpunk/commit/?id=a726d9f5fb56e1fd7983c5ac806d408ad78daa86'/>
<id>urn:sha1:a726d9f5fb56e1fd7983c5ac806d408ad78daa86</id>
<content type='text'>
Multiplayer
- Quick match: POST /api/multiplayer/quickmatch returns whichever room is
  still filling, or opens one. Players never see a room code; joining by
  code stays for racing specific people.
- Bots fill quick-match rooms after a short wait so a new game is never an
  empty lobby. They only ever join quick-match rooms, never a room opened
  by code. One or two per room, drawn from separate ~40 and ~80 WPM tiers so
  two bots are never near each other's pace, and they stall to correct
  mistakes rather than typing a clean straight line.
- Live player count via GET /api/multiplayer/online, shown on the
  Multiplayer control and under the main menu's Multiplayer button.
- Per-racer colours: you are the theme accent, opponents take distinct hues
  that stay the same from lobby to race.
- The countdown no longer holds the room lock for its full three seconds,
  which is what reset clients mid-countdown.

Typing languages
- 16 languages for the generated-word modes, each with its own
  high-frequency vocabulary rather than a translation of the English list.
- Picker in the top-right rail; non-English uses its own list at every
  difficulty tier instead of falling back to English words.

Fix UTF-8 accuracy in the game core
- update_game_state mixed byte and character counts: total_characters_typed
  accumulated byte-length deltas while total_correct_characters compared a
  char index against that byte count. Equal on ASCII, so it went unnoticed;
  a correctly typed Spanish passage scored 6%. The old byte slicing would
  also have panicked if an index landed inside a multi-byte character.
  Rewritten char-based, with regression tests.

Programming mode
- Replaced prose about programming with real code: 26 syntax-highlighted
  snippets across JavaScript, Python, Rust, C/Go/Java and shell. Single-line
  by necessity, since the typing input is a single-line field.

Layout and readability
- One icon rail arrangement on every screen: Settings/Store under the
  wordmark, Language/Theme/Friends/Account top-right, Stats/Leaderboard/
  Multiplayer bottom-right.
- Main menu: mode picker moved out of the Single Player button, which it was
  notching a divider through and pushing the label off-centre.
- Escape returns to the menu, closing any open popover first, and confirms
  before abandoning a live race.
- Split --text-color and --sub-color per theme; they shared one value that
  measured 3.65:1 against the background, below the 4.5:1 body-text floor.
- Semantic colours used in exactly one place each: gold for a personal best,
  amber for the race countdown and the mobile-result badge.
- Passage now sits in the same place on the typing and end screens, and its
  column is a whole number of characters wide so wrapping cannot leave a
  permanent gap on the right.
- End screen: keystrokes and a correct/wrong/extra/missed split, attribution
  carried over from the typing screen, and a graph with a separate error
  axis, axis titles including seconds, and smoothed lines.
</content>
</entry>
</feed>
