The game kit: the shared infrastructure of Wiz-War and Waving Hands as a template
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141G6xqLeNRYEtviLWSB5Up
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
<script lang="ts">
|
||||
import TableTalk from './TableTalk.svelte';
|
||||
import type { Room } from '$lib/net/room.svelte';
|
||||
|
||||
let { room, link }: { room: Room; link: string } = $props();
|
||||
|
||||
const v = $derived(room.view);
|
||||
const hostName = $derived(v.seats.find((s) => s.id === v.host)?.name ?? 'the host');
|
||||
const seatFree = $derived(v.seats.length < v.size);
|
||||
let copied = $state(false);
|
||||
|
||||
async function copyLink() {
|
||||
try {
|
||||
await navigator.clipboard.writeText(link);
|
||||
copied = true;
|
||||
setTimeout(() => (copied = false), 1600);
|
||||
} catch {
|
||||
// The link is on screen to copy by hand.
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<section class="lobby">
|
||||
{#if room.spectating}
|
||||
<h2>At the table</h2>
|
||||
{#if seatFree}
|
||||
<p>{hostName} is gathering players. Sit down above, or watch from the gallery until the game begins.</p>
|
||||
{:else}
|
||||
<p>The table is full. You watch from the Peanut Gallery; the game begins when {hostName} says.</p>
|
||||
{/if}
|
||||
{:else}
|
||||
<p class="eyebrow">room {v.roomId}</p>
|
||||
<h2>The table is laid</h2>
|
||||
<p>Send this link, or the code. Whoever opens it takes a seat. Anyone who arrives once the game has begun watches from the Peanut Gallery.</p>
|
||||
<p class="link-row"><code>{link}</code><button type="button" class="quiet" onclick={copyLink}>{copied ? 'Copied' : 'Copy link'}</button></p>
|
||||
{/if}
|
||||
<ul class="roster">
|
||||
{#each v.seats as s (s.id)}
|
||||
<li>
|
||||
<span class="seat-name">{s.name}</span>
|
||||
<span class="muted">{s.id === v.host ? 'opened the table' : s.bot ? 'the bot' : 'seated'}{s.id === v.me ? ', you' : ''}</span>
|
||||
</li>
|
||||
{/each}
|
||||
<li class="empty muted">{v.size - v.seats.length} of {v.size} seats empty{#if v.audience > 0}; {v.audience} in the gallery{/if}</li>
|
||||
</ul>
|
||||
{#if !room.spectating}
|
||||
<div class="ways">
|
||||
{#if seatFree}
|
||||
<button type="button" class="quiet" onclick={() => room.addBot()}>Seat a bot</button>
|
||||
{/if}
|
||||
{#if room.isHost}
|
||||
<button type="button" class="commit small" disabled={v.seats.length < 2} onclick={() => room.begin()}>Begin</button>
|
||||
<span class="muted">{v.seats.length < 2 ? 'once a second player is seated' : `with ${v.seats.length} players`}</span>
|
||||
{:else}
|
||||
<span class="muted">{hostName} will begin when the table is ready.</span>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
{#if room.error}<p class="warning">{room.error}</p>{/if}
|
||||
<div class="lobby-talk"><TableTalk {room} /></div>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.lobby {
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
padding: 1rem var(--gutter) 2rem;
|
||||
}
|
||||
|
||||
.lobby h2 {
|
||||
font-size: 1.4rem;
|
||||
margin-bottom: 0.4rem;
|
||||
}
|
||||
|
||||
.lobby p + p {
|
||||
margin-top: 0.6rem;
|
||||
}
|
||||
|
||||
.roster {
|
||||
list-style: none;
|
||||
margin: 0.9rem 0 0.6rem;
|
||||
padding: 0;
|
||||
max-width: 28em;
|
||||
}
|
||||
|
||||
.roster li {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
padding: 0.3rem 0;
|
||||
border-bottom: 1px solid var(--rule);
|
||||
}
|
||||
|
||||
.roster li.empty {
|
||||
border-bottom: 0;
|
||||
justify-content: flex-start;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.seat-name {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.ways {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 0.5rem 0.9rem;
|
||||
margin-top: 0.4rem;
|
||||
}
|
||||
|
||||
.link-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 0.5rem 0.75rem;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: var(--font);
|
||||
background: var(--slate);
|
||||
padding: 0.3rem 0.6rem;
|
||||
border-radius: 4px;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.lobby-talk {
|
||||
max-width: 28em;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user