The glass board is open to everyone: the gate and its word are gone, and the toggle shows under the flat boards at every table and on the told game
The flat boards stay the default; the glass board is a tap away. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CCLa2PaEeCj8njQZSWGqHx
This commit is contained in:
1 parent
9a43952ad1
commit
5099cf67e7
5 files changed
+5
-49
No files matched your search
@@ -34,9 +34,9 @@ tables, the Peanut Gallery, the ledgers and the ops tools are the kit's;
|
||||
takes the same taps as the flat boards. The figures in `static/figures/`
|
||||
are glTF, one per kind, with a `livery` material the view recolours per
|
||||
side; `docs/figures-brief.md` is what they were made from. three.js and
|
||||
the figures load only when the view is opened. Until the keeper opens it
|
||||
to everyone, the view shows only to a browser let in through
|
||||
`src/lib/glass.svelte.ts`.
|
||||
the figures load only when the view is opened. The flat boards are the
|
||||
default; the glass board is offered under them at the table and on the
|
||||
told game.
|
||||
- The guide's figures are screenshots in `static/guide/`, taken from the
|
||||
running site at 960 pixels wide.
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
} from '$lib/game';
|
||||
import type { Room } from '$lib/net/room.svelte';
|
||||
import { prefs, reducedMotion } from '$lib/prefs.svelte';
|
||||
import { glass } from '$lib/glass.svelte';
|
||||
|
||||
let { room }: { room: Room } = $props();
|
||||
|
||||
@@ -218,9 +217,7 @@
|
||||
{/if}
|
||||
{#if room.error}<p class="warning">{room.error}</p>{/if}
|
||||
|
||||
{#if glass.open}
|
||||
<p class="muted small glass-way"><button type="button" class="link plain" disabled={fetching} aria-busy={fetching} onclick={() => seeGlass(!onGlass)}>{fetching ? 'Fetching the glass board…' : onGlass ? 'Back to the flat boards' : 'See the glass board'}</button></p>
|
||||
{/if}
|
||||
<p class="muted small glass-way"><button type="button" class="link plain" disabled={fetching} aria-busy={fetching} onclick={() => seeGlass(!onGlass)}>{fetching ? 'Fetching the glass board…' : onGlass ? 'Back to the flat boards' : 'See the glass board'}</button></p>
|
||||
{#if onGlass && Glass}
|
||||
<Glass {g} {mySide} {selected} {targets} {reach} {shownSquares} {shownCaptured} {checkSquare} {calm} {tap} />
|
||||
{:else}
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
import TallyBoard from './Tally.svelte';
|
||||
import Preferences from './Preferences.svelte';
|
||||
import { prefs, setPref } from '$lib/prefs.svelte';
|
||||
import '$lib/glass.svelte';
|
||||
import { allSeats, doubtSeat, forgetSeat, rememberSeat, ServerError, trustSeat } from '$lib/net/client';
|
||||
import { api, NAME_MAX, playerName, rememberName, Room } from '$lib/net/room.svelte';
|
||||
import { unreadTalk } from '$lib/net/talk';
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
// The glass board, the three-dimensional view of a game, is shown only to
|
||||
// a browser that has been let in. A visit to any page with ?glass=<word>
|
||||
// opens it for that browser, if the word's hash is the one kept here; the
|
||||
// word itself is nowhere in the site. Until the keeper decides the view is
|
||||
// ready for everyone, this is the whole of the gate.
|
||||
|
||||
const KEY = 'wyrm:glass';
|
||||
const GATE = 'eec81ab3bd646536b3464bb0411aea9b2e92e6387c6a04ef15743191ac4d142f';
|
||||
|
||||
function remembered(): boolean {
|
||||
try {
|
||||
return localStorage.getItem(KEY) === '1';
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** Whether this browser may open the glass board. */
|
||||
export const glass = $state({ open: typeof localStorage !== 'undefined' && remembered() });
|
||||
|
||||
/** Let the browser in if the address carries the word, and remember it. */
|
||||
export async function claimGlass(): Promise<void> {
|
||||
if (glass.open || typeof location === 'undefined') return;
|
||||
const word = new URLSearchParams(location.search).get('glass');
|
||||
if (!word) return;
|
||||
const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(word));
|
||||
const hex = Array.from(new Uint8Array(digest), (b) => b.toString(16).padStart(2, '0')).join('');
|
||||
if (hex !== GATE) return;
|
||||
glass.open = true;
|
||||
try {
|
||||
localStorage.setItem(KEY, '1');
|
||||
} catch {
|
||||
// Opened for this visit only.
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof location !== 'undefined') void claimGlass();
|
||||
@@ -7,7 +7,6 @@
|
||||
import { narrate } from '$lib/game/chronicle';
|
||||
import { notation, kingSquare, inCheck, movesFrom, legalMovesFrom, sideOf } from '$lib/game';
|
||||
import { prefs, reducedMotion } from '$lib/prefs.svelte';
|
||||
import { glass } from '$lib/glass.svelte';
|
||||
|
||||
/** The glass board, loaded the first time it is asked for. */
|
||||
let Glass = $state<typeof import('$lib/components/Glass.svelte').default | null>(null);
|
||||
@@ -79,9 +78,7 @@
|
||||
|
||||
<section class="stage">
|
||||
<div class="boards">
|
||||
{#if glass.open}
|
||||
<p class="muted small"><button type="button" class="link plain" disabled={fetching} aria-busy={fetching} onclick={() => seeGlass(!onGlass)}>{fetching ? 'Fetching the glass board…' : onGlass ? 'Back to the flat boards' : 'See the glass board'}</button></p>
|
||||
{/if}
|
||||
<p class="muted small"><button type="button" class="link plain" disabled={fetching} aria-busy={fetching} onclick={() => seeGlass(!onGlass)}>{fetching ? 'Fetching the glass board…' : onGlass ? 'Back to the flat boards' : 'See the glass board'}</button></p>
|
||||
{#if onGlass && Glass}
|
||||
<Glass {g} {shownSquares} {shownCaptured} {checkSquare} selected={inspected} {reach} {calm} {tap} />
|
||||
{:else}
|
||||
|
||||
Reference in new issue
Block a user