diff --git a/app/src/lib/api.ts b/app/src/lib/api.ts index d93a0d1..9b6ff44 100644 --- a/app/src/lib/api.ts +++ b/app/src/lib/api.ts @@ -24,6 +24,7 @@ export interface Ergebnis { export interface RaumZustand { code: string + raumname: string status: RaumStatus runde: number anzahlRunden: number @@ -110,6 +111,7 @@ export async function raumBeitreten(code: string, name: string): Promise<{ sessi export const zustandLaden = (s: RaumSession) => anfrage('GET', `/${s.code}`, undefined, s.token) export const readySetzen = (s: RaumSession, ready: boolean) => anfrage('POST', `/${s.code}/ready`, { ready }, s.token) export const redModeSetzen = (s: RaumSession, redMode: boolean) => anfrage('POST', `/${s.code}/redmode`, { redMode }, s.token) +export const raumUmbenennen = (s: RaumSession) => anfrage('POST', `/${s.code}/rename`, {}, s.token) export const frageStellen = (s: RaumSession, frage: string) => anfrage('POST', `/${s.code}/question`, { frage }, s.token) export const rankingAbgeben = (s: RaumSession, reihenfolge: string[]) => anfrage('POST', `/${s.code}/ranking`, { reihenfolge }, s.token) diff --git a/app/src/pages/Game.tsx b/app/src/pages/Game.tsx index 63095f0..a70616f 100644 --- a/app/src/pages/Game.tsx +++ b/app/src/pages/Game.tsx @@ -3,6 +3,7 @@ import { Check, Copy, Crown, + Dice5, DoorOpen, Eraser, EyeOff, @@ -24,6 +25,7 @@ import { zustandLaden, readySetzen, redModeSetzen, + raumUmbenennen, frageStellen, rankingAbgeben, naechstePhase, @@ -265,7 +267,7 @@ function Lobby({ const teilen = async () => { if (navigator.share) { try { - await navigator.share({ title: '1 bis 8 Party', text: `Tritt meinem Spielraum ${z.code} bei!`, url: beitrittsUrl }) + await navigator.share({ title: '1 bis 8 Party', text: `Tritt „${z.raumname}“ bei! Spielraum-Code: ${z.code}`, url: beitrittsUrl }) return } catch { /* User abgebrochen -> Copy Fallback */ @@ -294,7 +296,20 @@ function Lobby({ /> )}
Spielraum-Code
+Spielraum
+{z.raumname}
+ {ich?.istHost && ( + + )} +Code
{z.code}
Alle öffnen 1bis.hocks.eu auf dem Handy und diff --git a/server/game/api/server.js b/server/game/api/server.js index 4bd26bd..e233e9e 100644 --- a/server/game/api/server.js +++ b/server/game/api/server.js @@ -13,6 +13,8 @@ * POST /api/game/room/:code/question -> Fragesteller stellt die Frage * POST /api/game/room/:code/ranking -> eigenes geheimes Ranking abgeben * POST /api/game/room/:code/next -> Auflösung -> Punktestand -> neue Runde + * POST /api/game/room/:code/redmode -> Red Mode an/aus (Host, nur Lobby) + * POST /api/game/room/:code/rename -> Raumnamen neu würfeln (Host, nur Lobby) * * Auth: X-Player-Token-Header (oder Body-Feld "token"), pro Spieler ein Token. * Start: Sobald ALLE Spieler ready sind (min. 3), wechselt der Raum automatisch @@ -116,6 +118,49 @@ function neuerCode() { return null; } +/* ── Lustige Raumnamen ──────────────────────────────────── */ +const NAMEN = { + adj: [ + 'durstigen', 'tanzenden', 'kichernden', 'brüllenden', 'flüsternden', 'glühenden', + 'schunkelnden', 'zappelnden', 'grölenden', 'funkelnden', 'randalierenden', 'frechen', + 'mutigen', 'verpeilten', 'torkelnden', 'jauchzenden', 'grinsenden', 'schwatzenden', + 'pfeifenden', 'trommelnden', 'hopsenden', 'sabbernden', 'schleimigen', 'schillernden', + 'tollpatschigen', 'unersättlichen', 'übermütigen', 'schäumenden', 'quietschenden', + 'polternden', 'strahlenden', 'müden', + ], + tier: [ + 'Piraten', 'Kartoffeln', 'Nachteulen', 'Chamäleons', 'Pinguine', 'Flamingos', + 'Rentiere', 'Einhörner', 'Gurken', 'Muffins', 'Kekse', 'Bananen', 'Tomaten', + 'Schildkröten', 'Waschbären', 'Faultiere', 'Kängurus', 'Seehunde', 'Wombats', + 'Lemminge', 'Spechte', 'Otter', 'Marder', 'Igel', 'Kamele', 'Lamas', 'Alpakas', + 'Zebras', 'Quokkas', 'Tukane', 'Kronkorken', 'Glühbirnen', 'Staubsauger', 'Kaugummis', + 'Regenwürmer', 'Luftballons', 'Wackelpuddinge', 'Nudeln', 'Schokolinsen', 'Popcorntüten', + ], + sing: [ + 'Pinguin', 'Kartoffel', 'Muffin', 'Einhorn', 'Otter', 'Faultier', 'Kamel', 'Lama', + 'Wackelpudding', 'Kronkorken', 'Kaugummi', 'Regenwurm', 'Igel', 'Quokka', 'Flamingo', + 'Waschbär', 'Specht', 'Tomate', 'Banane', 'Keks', + ], + event: ['Alarm', 'Manie', 'Panik', 'Invasion', 'Verschwörung', 'Olympiade', 'Revolution', 'Notstand', 'Expedition', 'Befreiung'], + action: ['Party', 'Chaos', 'Krawall', 'Sause', 'Rambazamba', 'Zoff'], + ort: ['Keller', 'Garten', 'Palast', 'U-Boot', 'Zirkus', 'All', 'Baumhaus', 'Schloss', 'Dschungel', 'Wolkenkuckucksheim', 'Kiosk', 'Weltraum'], +}; + +const pick = (liste) => liste[crypto.randomInt(liste.length)]; + +function lustigerRaumname() { + for (let versuch = 0; versuch < 25; versuch++) { + const typ = crypto.randomInt(3); + let name; + if (typ === 0) name = `Die ${pick(NAMEN.adj)} ${pick(NAMEN.tier)}`; + else if (typ === 1) name = `${pick(NAMEN.sing)}-${pick(NAMEN.event)}`; + else name = `${pick(NAMEN.action)} im ${pick(NAMEN.ort)}`; + const vergeben = Object.values(rooms).some((r) => r.raumname === name); + if (!vergeben) return name; + } + return `Die ${pick(NAMEN.adj)} ${pick(NAMEN.tier)} ${crypto.randomInt(100)}`; +} + function raumFinden(code) { const raum = rooms[(code || '').toUpperCase()]; if (!raum) return null; @@ -141,6 +186,7 @@ function oeffentlicherZustand(raum, token) { const alleReady = raum.spieler.length >= MIN_SPIELER && raum.spieler.every((s) => s.ready); return { code: raum.code, + raumname: raum.raumname || '', status: raum.status, runde: raum.runde, anzahlRunden: raum.spieler.length, @@ -207,6 +253,7 @@ const server = http.createServer(async (req, res) => { if (!neuerRaumCode) return fehler(res, 500, 'kein Raumcode frei'); const raum = { code: neuerRaumCode, + raumname: lustigerRaumname(), erstelltAm: Date.now(), aktivitaet: Date.now(), status: 'lobby', @@ -271,6 +318,15 @@ const server = http.createServer(async (req, res) => { return antwort(res, 200, { ok: true, zustand: oeffentlicherZustand(raum, token) }); } + /* Raumnamen neu wuerfeln (nur Host, nur vor Spielstart) */ + if (req.method === 'POST' && aktion === 'rename') { + if (raum.status !== 'lobby') return fehler(res, 409, 'Der Raumname ist nur vor Spielstart aenderbar'); + if (!spieler.istHost) return fehler(res, 403, 'Nur der Host kann den Raumnamen aendern'); + raum.raumname = lustigerRaumname(); + speichern(); + return antwort(res, 200, { ok: true, zustand: oeffentlicherZustand(raum, token) }); + } + /* Frage stellen */ if (req.method === 'POST' && aktion === 'question') { if (raum.status !== 'question') return fehler(res, 409, 'Keine Fragephase');