feat: auto-start listed lobbies after 5 minutes

Hosts can't sit on a public listing: setListed(true) records listedAt,
and once listedAt + HOSTED_LOBBY_AUTO_START_MS passes, GameManager's
tick arms the normal start countdown (same path as the host's Start
button, honoring startDelay). Cancelling the countdown re-arms on the
next tick; unlisting cancels the deadline and relisting starts a fresh
one. Duplicate setListed(true) calls don't extend it.

The deadline rides to the host as autoStartAt in lobby info, rendered
as an amber countdown next to the Public/Private switch in the host
modal header (hidden once the real start countdown takes over).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
evanpelle
2026-07-06 09:11:13 -07:00
parent 5d21be826d
commit 2a82b01e30
6 changed files with 143 additions and 3 deletions
+8
View File
@@ -176,6 +176,11 @@ export type ScheduledPublicGameType = z.infer<
// and delists any overflow as the authoritative backstop.
export const MAX_HOSTED_LOBBIES = 10;
// How long a lobby may stay publicly listed before it starts automatically,
// so hosts can't sit on a listing indefinitely. Unlisting cancels the
// deadline; relisting starts a fresh one.
export const HOSTED_LOBBY_AUTO_START_MS = 5 * 60 * 1000;
export const UsernameSchema = z
.string()
.regex(/^(?=.*\S)[a-zA-Z0-9_ üÜ.]+$/u)
@@ -207,6 +212,9 @@ export const GameInfoSchema = z.object({
// UI stays in sync when the server delists (whitelist enabled, duplicate
// creator resolved by the master).
listed: z.boolean().optional(),
// Listed lobbies only: server timestamp when the lobby starts
// automatically (hosts can't sit on a public listing indefinitely).
autoStartAt: z.number().optional(),
});
// Browser-facing lobby info. Master/worker-internal fields (the creator hash