Compare commits
2 Commits
010b5a593e
...
b76bcbffb2
| Author | SHA1 | Date | |
|---|---|---|---|
| b76bcbffb2 | |||
| 67bd8d9e77 |
@@ -50,16 +50,12 @@
|
|||||||
<div class="land-card">
|
<div class="land-card">
|
||||||
<div class="land-card-icon">⬜</div>
|
<div class="land-card-icon">⬜</div>
|
||||||
<h2>// JOIN A SESSION</h2>
|
<h2>// JOIN A SESSION</h2>
|
||||||
<p>Enter a room code and your name to join an existing session.</p>
|
<p>Enter a room code to join an existing session. You'll be assigned a numeric ID.</p>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>ROOM CODE</label>
|
<label>ROOM CODE</label>
|
||||||
<input id="ji-code" maxlength="8" placeholder="XXXXXX" style="letter-spacing:5px;text-transform:uppercase;font-size:20px;"
|
<input id="ji-code" maxlength="8" placeholder="XXXXXX" style="letter-spacing:5px;text-transform:uppercase;font-size:20px;"
|
||||||
oninput="this.value=this.value.toUpperCase()" />
|
oninput="this.value=this.value.toUpperCase()" />
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
|
||||||
<label>YOUR NAME</label>
|
|
||||||
<input id="ji-name" maxlength="24" placeholder="Enter name…" />
|
|
||||||
</div>
|
|
||||||
<button class="btn btn-g btn-full" onclick="joinRoom()">JOIN ROOM →</button>
|
<button class="btn btn-g btn-full" onclick="joinRoom()">JOIN ROOM →</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ function schedReconn(){
|
|||||||
const d=Math.min(8000,500*Math.pow(1.5,reconnAttempts++));
|
const d=Math.min(8000,500*Math.pow(1.5,reconnAttempts++));
|
||||||
reconnTimer=setTimeout(()=>{
|
reconnTimer=setTimeout(()=>{
|
||||||
if(role==='mod'){const m=loadMod();if(m)connect(()=>ws_send({type:'mod_rejoin',roomId:m.id,modSecret:m.s}));}
|
if(role==='mod'){const m=loadMod();if(m)connect(()=>ws_send({type:'mod_rejoin',roomId:m.id,modSecret:m.s}));}
|
||||||
else if(role==='player'&&myId){const p=loadPlay();if(p)connect(()=>ws_send({type:'join_room',roomId:p.rid,playerId:p.pid}));}
|
else if(role==='player'&&myId){const p=loadPlay();if(p)connect(()=>ws_send({type:'join_room',roomId:p.rid,playerName:p.name,playerId:p.pid}));}
|
||||||
else connect(null);
|
else connect(null);
|
||||||
},d);
|
},d);
|
||||||
}
|
}
|
||||||
@@ -172,8 +172,7 @@ function goSetup(){renderSetupTeamNames();showScr('s-setup');}
|
|||||||
function joinRoom(){
|
function joinRoom(){
|
||||||
const code=document.getElementById('ji-code').value.trim().toUpperCase();
|
const code=document.getElementById('ji-code').value.trim().toUpperCase();
|
||||||
if(!code){toast('Enter room code','err');return;}
|
if(!code){toast('Enter room code','err');return;}
|
||||||
const autoId=Math.floor(Math.random()*99999999)+1;
|
connect(()=>ws_send({type:'join_room',roomId:code}));
|
||||||
connect(()=>ws_send({type:'join_room',roomId:code,playerId:autoId}));
|
|
||||||
}
|
}
|
||||||
function openRejoin(){
|
function openRejoin(){
|
||||||
const m=loadMod();if(!m)return;
|
const m=loadMod();if(!m)return;
|
||||||
@@ -410,7 +409,7 @@ function renderModPlayerList(){
|
|||||||
row.className='pl-row'+(p.isConnected?'':' offline');
|
row.className='pl-row'+(p.isConnected?'':' offline');
|
||||||
row.innerHTML=`
|
row.innerHTML=`
|
||||||
<div class="pl-info" style="flex:1;min-width:0;">
|
<div class="pl-info" style="flex:1;min-width:0;">
|
||||||
<div class="pl-name">${esc(p.name)} <span class="tag tag-y" style="font-size:12px;padding:3px 8px;background:rgba(249,226,175,0.15);color:var(--yellow);border:none;">#${p.playerId}</span> ${p.isConnected?'':`<span class="tag tag-red" style="font-size:9px;padding:2px 6px;">OFFLINE</span>`}</div>
|
<div class="pl-name">${esc(p.name)} ${p.isConnected?'':`<span class="tag tag-red" style="font-size:9px;padding:2px 6px;">OFFLINE</span>`}</div>
|
||||||
${teamName?`<div class="pl-meta" style="color:${color}">${esc(teamName)}</div>`:'<div class="pl-meta">No team</div>'}
|
${teamName?`<div class="pl-meta" style="color:${color}">${esc(teamName)}</div>`:'<div class="pl-meta">No team</div>'}
|
||||||
${teamSel}
|
${teamSel}
|
||||||
</div>
|
</div>
|
||||||
@@ -436,7 +435,7 @@ function renderModTeams(){
|
|||||||
card.innerHTML=`
|
card.innerHTML=`
|
||||||
<div class="tc-n" style="color:${color}">${esc(name)}</div>
|
<div class="tc-n" style="color:${color}">${esc(name)}</div>
|
||||||
<div class="tc-c" style="color:${color}">${members.length}</div>
|
<div class="tc-c" style="color:${color}">${members.length}</div>
|
||||||
<div class="tc-m">${members.map(p=>`#${p.playerId}`).join('<br>')||'—'}</div>
|
<div class="tc-m">${members.map(p=>esc(p.name)).join('<br>')||'—'}</div>
|
||||||
`;
|
`;
|
||||||
grid.appendChild(card);
|
grid.appendChild(card);
|
||||||
if(typeof gsap!=='undefined'){
|
if(typeof gsap!=='undefined'){
|
||||||
@@ -526,7 +525,7 @@ function renderPlayer(){
|
|||||||
if(!room)return;
|
if(!room)return;
|
||||||
document.getElementById('p-code').textContent=room.id;
|
document.getElementById('p-code').textContent=room.id;
|
||||||
const me=room.players.find(p=>p.id===myId);
|
const me=room.players.find(p=>p.id===myId);
|
||||||
document.getElementById('p-namelbl').textContent=`#${me?.playerId||'?'}`;
|
document.getElementById('p-namelbl').textContent=me?.name??'';
|
||||||
renderTeamPicker();
|
renderTeamPicker();
|
||||||
renderPlayerBuzzer();
|
renderPlayerBuzzer();
|
||||||
renderRoster();
|
renderRoster();
|
||||||
@@ -625,7 +624,7 @@ function renderRoster(){
|
|||||||
row.className='roster-row'+(isMe?' roster-me':'');
|
row.className='roster-row'+(isMe?' roster-me':'');
|
||||||
row.innerHTML=`
|
row.innerHTML=`
|
||||||
<div class="roster-dot" style="background:${p.isConnected?(isMe?'var(--g)':color):'var(--border2)'}"></div>
|
<div class="roster-dot" style="background:${p.isConnected?(isMe?'var(--g)':color):'var(--border2)'}"></div>
|
||||||
<div style="flex:1">${esc(p.name)} ${isMe?`<span style="font-size:11px;color:var(--dim);letter-spacing:1px;">(#${p.playerId}) (YOU)</span>`:''}</div>
|
<div style="flex:1">${esc(p.name)}${isMe?' <span style="font-size:11px;color:var(--dim);letter-spacing:1px;">(YOU)</span>':''}</div>
|
||||||
${teamName?`<div style="font-size:12px;color:${color};letter-spacing:0.5px;">${esc(teamName)}</div>`:''}
|
${teamName?`<div style="font-size:12px;color:${color};letter-spacing:0.5px;">${esc(teamName)}</div>`:''}
|
||||||
`;
|
`;
|
||||||
el.appendChild(row);
|
el.appendChild(row);
|
||||||
@@ -637,11 +636,10 @@ function addFeed(evt){
|
|||||||
const isFirst=evt.buzzOrder?.[0]===evt.playerId;
|
const isFirst=evt.buzzOrder?.[0]===evt.playerId;
|
||||||
const color=evt.teamIndex!==null?teamColor(evt.teamIndex):'var(--g)';
|
const color=evt.teamIndex!==null?teamColor(evt.teamIndex):'var(--g)';
|
||||||
const teamStr=(room?.settings.mode==='teams'&&evt.teamIndex!==null)?` [${esc(room.settings.teamNames[evt.teamIndex]??'')}]`:'';
|
const teamStr=(room?.settings.mode==='teams'&&evt.teamIndex!==null)?` [${esc(room.settings.teamNames[evt.teamIndex]??'')}]`:'';
|
||||||
const playerStr=`#${evt.playerId}`;
|
|
||||||
const div=document.createElement('div');
|
const div=document.createElement('div');
|
||||||
div.className='feed-entry'+(isFirst?' first':'');
|
div.className='feed-entry'+(isFirst?' first':'');
|
||||||
div.style.borderLeftColor=isFirst?'var(--yellow)':color;
|
div.style.borderLeftColor=isFirst?'var(--yellow)':color;
|
||||||
div.innerHTML=`<strong>${playerStr}</strong>${teamStr} buzzed${isFirst?' <span style="color:var(--yellow);font-weight:700;"> — FIRST!</span>':''}`;
|
div.innerHTML=`<strong>${esc(evt.playerName)}</strong>${teamStr} buzzed${isFirst?' <span style="color:var(--yellow);font-weight:700;"> — FIRST!</span>':''}`;
|
||||||
feed.prepend(div);
|
feed.prepend(div);
|
||||||
if(typeof gsap!=='undefined'){
|
if(typeof gsap!=='undefined'){
|
||||||
gsap.fromTo(div,
|
gsap.fromTo(div,
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ export interface RoomSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface Player {
|
export interface Player {
|
||||||
id: number;
|
id: string;
|
||||||
|
name: string;
|
||||||
teamIndex: number | null;
|
teamIndex: number | null;
|
||||||
ws: ServerWebSocket<unknown> | null;
|
ws: ServerWebSocket<unknown> | null;
|
||||||
isConnected: boolean;
|
isConnected: boolean;
|
||||||
@@ -80,6 +81,7 @@ export function publicRoom(room: Room) {
|
|||||||
},
|
},
|
||||||
players: Array.from(room.players.values()).map(p => ({
|
players: Array.from(room.players.values()).map(p => ({
|
||||||
id: p.id,
|
id: p.id,
|
||||||
|
name: p.name,
|
||||||
teamIndex: p.teamIndex,
|
teamIndex: p.teamIndex,
|
||||||
isConnected: p.isConnected,
|
isConnected: p.isConnected,
|
||||||
})),
|
})),
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import type { ServerWebSocket } from "bun";
|
|||||||
import {
|
import {
|
||||||
rooms, wsToPlayer,
|
rooms, wsToPlayer,
|
||||||
Room, Player,
|
Room, Player,
|
||||||
sanitize, freshBuzzer, publicRoom, broadcast, toMod,
|
genId, greekName, sanitize, freshBuzzer, publicRoom, broadcast, toMod,
|
||||||
} from "./rooms";
|
} from "./rooms";
|
||||||
|
|
||||||
type WS = ServerWebSocket<unknown>;
|
type WS = ServerWebSocket<unknown>;
|
||||||
@@ -65,19 +65,15 @@ export function handleMessage(ws: WS, raw: string) {
|
|||||||
if (!room) { er(ws, "Room not found"); return; }
|
if (!room) { er(ws, "Room not found"); return; }
|
||||||
if (room.locked) { er(ws, "Room is locked"); return; }
|
if (room.locked) { er(ws, "Room is locked"); return; }
|
||||||
|
|
||||||
|
const name = sanitize(msg.playerName ?? "Player", 24) || "Player";
|
||||||
const existingId = sanitize(msg.playerId ?? "", 12);
|
const existingId = sanitize(msg.playerId ?? "", 12);
|
||||||
let player: Player | undefined;
|
let player: Player | undefined;
|
||||||
|
|
||||||
if (existingId && existingId.match(/^\d+$/)) {
|
if (existingId && room.players.has(existingId)) {
|
||||||
if (room.players.has(existingId)) {
|
|
||||||
player = room.players.get(existingId)!;
|
player = room.players.get(existingId)!;
|
||||||
player.ws = ws; player.isConnected = true;
|
player.ws = ws; player.isConnected = true; player.name = name;
|
||||||
} else {
|
} else {
|
||||||
er(ws, "Invalid player ID"); return;
|
player = { id: genId(), name, teamIndex: null, ws, isConnected: true };
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const autoId = Math.floor(Math.random() * 99999999) + 1;
|
|
||||||
player = { id: autoId, teamIndex: null, ws, isConnected: true };
|
|
||||||
room.players.set(player.id, player);
|
room.players.set(player.id, player);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,8 +118,8 @@ export function handleMessage(ws: WS, raw: string) {
|
|||||||
const p = room.players.get(ctx.playerId)!;
|
const p = room.players.get(ctx.playerId)!;
|
||||||
const pubOrder = room.settings.showBuzzOrder ? bz.buzzOrder : [bz.buzzOrder[0]];
|
const pubOrder = room.settings.showBuzzOrder ? bz.buzzOrder : [bz.buzzOrder[0]];
|
||||||
|
|
||||||
broadcast(room, { type: "buzz_event", playerId: ctx.playerId, teamIndex: p.teamIndex, buzzOrder: pubOrder, room: publicRoom(room) });
|
broadcast(room, { type: "buzz_event", playerId: ctx.playerId, playerName: p.name, teamIndex: p.teamIndex, buzzOrder: pubOrder, room: publicRoom(room) });
|
||||||
toMod(room, { type: "buzz_event", playerId: ctx.playerId, teamIndex: p.teamIndex, buzzOrder: bz.buzzOrder, buzzTimes: Object.fromEntries(bz.buzzTimes), room: publicRoom(room) });
|
toMod(room, { type: "buzz_event", playerId: ctx.playerId, playerName: p.name, teamIndex: p.teamIndex, buzzOrder: bz.buzzOrder, buzzTimes: Object.fromEntries(bz.buzzTimes), room: publicRoom(room) });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user