diff options
| author | salmonik <salmonik@tuta.io> | 2026-11-08 03:29:35 +0100 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-11-08 03:29:35 +0100 |
| commit | 058432130628d00764663ecf819a9adc6793768d (patch) | |
| tree | d3f49f111fbfaa48647cca2600adcf9017af2d30 /web/play/index.html | |
| parent | web: serve latest.php through PHP and refuse stray PHP files (diff) | |
| download | zagan-bet-058432130628d00764663ecf819a9adc6793768d.tar.gz zagan-bet-058432130628d00764663ecf819a9adc6793768d.zip | |
v5.0.0: protocol v5 and the browser frontend
Protocol v5 replaces newline lines with bounded [u32 len][text] frames and REQ/RES/EVT envelopes. Requests carry correlation ids and the server replays the last 256 replies per connection, so a gateway retry cannot double-debit and a late reply cannot clobber a newer request. HELLO/PONG carry server time; crash rounds announce started_at and push coalesced 10 Hz ticks. Crash now commits sha256(seed) before a round and reveals the seed when it ends, so clients recompute the crash point.
Adds the webd/ gateway: one blocking thread, one ClientCore and one pinned upstream TLS connection per session, an HttpOnly session cookie, takeover, and a 60-second grace window. The browser sends Command JSON and renders View JSON; it never speaks the game protocol or stores credentials.
Adds the vanilla TypeScript browser app at /play/ (login, lobby, all four games, history, notices, crash verification), the nginx /play and /ws routes, and the headless DOM smoke test. webd and the app stay out of the TUI/GUI/server build graph.
The client/server version moves to 5.0.0 in lockstep; v4 peers are refused at HELLO.
Diffstat (limited to 'web/play/index.html')
| -rw-r--r-- | web/play/index.html | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/web/play/index.html b/web/play/index.html new file mode 100644 index 0000000..e9d4b79 --- /dev/null +++ b/web/play/index.html | |||
| @@ -0,0 +1,112 @@ | |||
| 1 | <!doctype html> | ||
| 2 | <html lang="en"> | ||
| 3 | <head> | ||
| 4 | <meta charset="utf-8"> | ||
| 5 | <meta name="viewport" content="width=device-width, initial-scale=1"> | ||
| 6 | <title>Play — żagań.bet</title> | ||
| 7 | <meta name="description" content="Play slots, roulette, blackjack and crash with play credits. No real money."> | ||
| 8 | <meta name="color-scheme" content="dark"> | ||
| 9 | <meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self' ws: wss:; img-src 'self' data:; base-uri 'none'; form-action 'self'"> | ||
| 10 | <link rel="stylesheet" href="style.css"> | ||
| 11 | </head> | ||
| 12 | <body> | ||
| 13 | <div class="shell"> | ||
| 14 | <header class="topbar"> | ||
| 15 | <a class="brand" href="/">żagań<span>.bet</span></a> | ||
| 16 | <span class="tagline">Play credits · no real money</span> | ||
| 17 | <span class="spacer"></span> | ||
| 18 | <div id="session-bar" class="session" hidden> | ||
| 19 | <span class="who">Signed in as <strong id="account-name"></strong></span> | ||
| 20 | <span id="account-balance" class="balance">— Kr</span> | ||
| 21 | <button id="logout" class="btn ghost small" type="button">Log out</button> | ||
| 22 | </div> | ||
| 23 | </header> | ||
| 24 | |||
| 25 | <main> | ||
| 26 | <section id="auth-screen" hidden> | ||
| 27 | <div class="auth-wrap"> | ||
| 28 | <div class="auth-card"> | ||
| 29 | <h1>Play żagań.bet</h1> | ||
| 30 | <p class="muted" style="margin: 6px 0 20px">Play-money casino. Your balance is play credit; nothing here is real money.</p> | ||
| 31 | <div class="auth-tabs" role="tablist"> | ||
| 32 | <button id="tab-login" class="auth-tab active" type="button" role="tab">Log in</button> | ||
| 33 | <button id="tab-register" class="auth-tab" type="button" role="tab">Register</button> | ||
| 34 | </div> | ||
| 35 | <form id="auth-form"> | ||
| 36 | <label class="field"> | ||
| 37 | <span class="label">Username</span> | ||
| 38 | <input id="auth-user" class="input" type="text" autocomplete="username" maxlength="32" required> | ||
| 39 | </label> | ||
| 40 | <label class="field"> | ||
| 41 | <span class="label">Password</span> | ||
| 42 | <input id="auth-pass" class="input" type="password" autocomplete="current-password" required> | ||
| 43 | </label> | ||
| 44 | <p id="auth-error" class="error-text" style="margin: 0; min-height: 18px"></p> | ||
| 45 | <button id="auth-submit" class="btn primary wide big" type="submit">Log in</button> | ||
| 46 | </form> | ||
| 47 | <p class="auth-foot">Registration gives you 1 000 Kr of play credit. No deposits, no withdrawals, no personal data beyond a username.</p> | ||
| 48 | </div> | ||
| 49 | </div> | ||
| 50 | </section> | ||
| 51 | |||
| 52 | <section id="lobby-screen" hidden> | ||
| 53 | <div class="lobby-head"> | ||
| 54 | <div> | ||
| 55 | <h1>Lobby</h1> | ||
| 56 | <p class="muted" style="margin: 4px 0 0">Choose a game. Bets are play credits.</p> | ||
| 57 | </div> | ||
| 58 | <span class="spacer"></span> | ||
| 59 | <button id="show-history" class="btn ghost" type="button">Play history</button> | ||
| 60 | <button id="refresh-lobby" class="btn ghost" type="button">Refresh</button> | ||
| 61 | </div> | ||
| 62 | <div id="game-grid" class="game-grid"></div> | ||
| 63 | </section> | ||
| 64 | |||
| 65 | <section id="game-screen" hidden> | ||
| 66 | <div class="game-head"> | ||
| 67 | <button id="leave-game" class="btn ghost" type="button">← Lobby</button> | ||
| 68 | <h1 id="game-title">Game</h1> | ||
| 69 | <span class="spacer"></span> | ||
| 70 | <span id="game-badge" class="label"></span> | ||
| 71 | </div> | ||
| 72 | <div class="game-body"> | ||
| 73 | <div id="game-board" class="board"></div> | ||
| 74 | <aside id="game-side" class="sidebar"></aside> | ||
| 75 | </div> | ||
| 76 | </section> | ||
| 77 | |||
| 78 | <section id="history-screen" hidden> | ||
| 79 | <div class="lobby-head"> | ||
| 80 | <div> | ||
| 81 | <h1>Play history</h1> | ||
| 82 | <p class="muted" style="margin: 4px 0 0">The last plays on your account.</p> | ||
| 83 | </div> | ||
| 84 | <span class="spacer"></span> | ||
| 85 | <button id="history-back" class="btn ghost" type="button">← Lobby</button> | ||
| 86 | </div> | ||
| 87 | <div id="history-body"></div> | ||
| 88 | </section> | ||
| 89 | </main> | ||
| 90 | </div> | ||
| 91 | |||
| 92 | <div id="toasts" aria-live="polite"></div> | ||
| 93 | |||
| 94 | <div id="replaced-overlay" class="overlay" hidden> | ||
| 95 | <div class="modal"> | ||
| 96 | <h2>Opened in another tab</h2> | ||
| 97 | <p>This game was opened somewhere else. Only one tab can play a session at a time.</p> | ||
| 98 | <button id="reload-replaced" class="btn primary" type="button">Reload this tab</button> | ||
| 99 | </div> | ||
| 100 | </div> | ||
| 101 | |||
| 102 | <div id="reconnect-overlay" class="overlay" hidden> | ||
| 103 | <div class="modal"> | ||
| 104 | <h2>Connection lost</h2> | ||
| 105 | <p id="reconnect-message">Trying to reach the game server…</p> | ||
| 106 | <button id="reload-reconnect" class="btn ghost" type="button">Reload</button> | ||
| 107 | </div> | ||
| 108 | </div> | ||
| 109 | |||
| 110 | <script src="app.js" defer></script> | ||
| 111 | </body> | ||
| 112 | </html> | ||
