Meida working
This commit is contained in:
parent
579632c293
commit
a586f3b491
@ -163,97 +163,100 @@ const PlayerList: React.FC = () => {
|
||||
>
|
||||
<MediaAgent {...{ session, peers, setPeers }} />
|
||||
<List className="PlayerSelector">
|
||||
{players?.map((player) => (
|
||||
<Box
|
||||
key={player.session_id}
|
||||
sx={{ display: "flex", flexDirection: "column", alignItems: "center" }}
|
||||
className={`PlayerEntry ${player.local ? "PlayerSelf" : ""}`}
|
||||
>
|
||||
<Box>
|
||||
<Box style={{ display: "flex-wrap", alignItems: "center", justifyContent: "space-between" }}>
|
||||
<Box style={{ display: "flex-wrap", alignItems: "center" }}>
|
||||
<div className="Name">{player.name ? player.name : player.session_id}</div>
|
||||
{player.protected && (
|
||||
<div
|
||||
style={{ marginLeft: 8, fontSize: "0.8em", color: "#a00" }}
|
||||
title="This name is protected with a password"
|
||||
>
|
||||
🔒
|
||||
</div>
|
||||
)}
|
||||
{player.bot_instance_id && (
|
||||
<div style={{ marginLeft: 8, fontSize: "0.8em", color: "#00a" }} title="This is a bot">
|
||||
🤖
|
||||
</div>
|
||||
)}
|
||||
{players?.map((player) => {
|
||||
const peerObj = peers[player.session_id] || peers[player.name];
|
||||
return (
|
||||
<Box
|
||||
key={player.session_id}
|
||||
sx={{ display: "flex", flexDirection: "column", alignItems: "center" }}
|
||||
className={`PlayerEntry ${player.local ? "PlayerSelf" : ""}`}
|
||||
>
|
||||
<Box>
|
||||
<Box style={{ display: "flex-wrap", alignItems: "center", justifyContent: "space-between" }}>
|
||||
<Box style={{ display: "flex-wrap", alignItems: "center" }}>
|
||||
<div className="Name">{player.name ? player.name : player.session_id}</div>
|
||||
{player.protected && (
|
||||
<div
|
||||
style={{ marginLeft: 8, fontSize: "0.8em", color: "#a00" }}
|
||||
title="This name is protected with a password"
|
||||
>
|
||||
🔒
|
||||
</div>
|
||||
)}
|
||||
{player.bot_instance_id && (
|
||||
<div style={{ marginLeft: 8, fontSize: "0.8em", color: "#00a" }} title="This is a bot">
|
||||
🤖
|
||||
</div>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
{player.name && !player.live && <div className="NoNetwork"></div>}
|
||||
</Box>
|
||||
{player.name && !player.live && <div className="NoNetwork"></div>}
|
||||
</Box>
|
||||
{player.name && player.live && peers[player.session_id] && (player.local || player.has_media !== false) ? (
|
||||
<>
|
||||
<MediaControl
|
||||
sx={{ border: "3px solid blue" }}
|
||||
className="Medium"
|
||||
key={player.session_id}
|
||||
peer={peers[player.session_id]}
|
||||
isSelf={player.local}
|
||||
sendJsonMessage={player.local ? sendJsonMessage : undefined}
|
||||
remoteAudioMuted={peers[player.session_id].muted}
|
||||
remoteVideoOff={peers[player.session_id].video_on === false}
|
||||
/>
|
||||
{player.name && player.live && peerObj && (player.local || player.has_media !== false) ? (
|
||||
<>
|
||||
<MediaControl
|
||||
sx={{ border: "3px solid blue" }}
|
||||
className="Medium"
|
||||
key={player.session_id}
|
||||
peer={peerObj}
|
||||
isSelf={player.local}
|
||||
sendJsonMessage={player.local ? sendJsonMessage : undefined}
|
||||
remoteAudioMuted={peerObj?.muted}
|
||||
remoteVideoOff={peerObj?.video_on === false}
|
||||
/>
|
||||
|
||||
{/* If this is the local player and they haven't picked a color, show a picker */}
|
||||
{player.local && player.color === "unassigned" && (
|
||||
<div style={{ marginTop: 8, width: "100%" }}>
|
||||
<div style={{ marginBottom: 6, fontSize: "0.9em" }}>Pick your color:</div>
|
||||
<div style={{ display: "flex", gap: 8 }}>
|
||||
{["orange", "red", "white", "blue"].map((c) => (
|
||||
<Box
|
||||
key={c}
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: 8,
|
||||
padding: "6px 8px",
|
||||
borderRadius: 6,
|
||||
border: "1px solid #ccc",
|
||||
background: "#fff",
|
||||
cursor: sendJsonMessage ? "pointer" : "not-allowed",
|
||||
}}
|
||||
onClick={() => {
|
||||
if (!sendJsonMessage) return;
|
||||
sendJsonMessage({ type: "set", field: "color", value: c[0].toUpperCase() });
|
||||
}}
|
||||
>
|
||||
<PlayerColor color={c} />
|
||||
</Box>
|
||||
))}
|
||||
{/* If this is the local player and they haven't picked a color, show a picker */}
|
||||
{player.local && player.color === "unassigned" && (
|
||||
<div style={{ marginTop: 8, width: "100%" }}>
|
||||
<div style={{ marginBottom: 6, fontSize: "0.9em" }}>Pick your color:</div>
|
||||
<div style={{ display: "flex", gap: 8 }}>
|
||||
{["orange", "red", "white", "blue"].map((c) => (
|
||||
<Box
|
||||
key={c}
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: 8,
|
||||
padding: "6px 8px",
|
||||
borderRadius: 6,
|
||||
border: "1px solid #ccc",
|
||||
background: "#fff",
|
||||
cursor: sendJsonMessage ? "pointer" : "not-allowed",
|
||||
}}
|
||||
onClick={() => {
|
||||
if (!sendJsonMessage) return;
|
||||
sendJsonMessage({ type: "set", field: "color", value: c[0].toUpperCase() });
|
||||
}}
|
||||
>
|
||||
<PlayerColor color={c} />
|
||||
</Box>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
) : player.name && player.live && player.has_media === false ? (
|
||||
<div
|
||||
className="Video fade-in"
|
||||
style={{
|
||||
background: "#333",
|
||||
color: "#fff",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
fontSize: "14px",
|
||||
}}
|
||||
>
|
||||
💬 Chat Only
|
||||
</div>
|
||||
) : (
|
||||
<video className="Video"></video>
|
||||
)}
|
||||
</Box>
|
||||
))}
|
||||
)}
|
||||
</>
|
||||
) : player.name && player.live && player.has_media === false ? (
|
||||
<div
|
||||
className="Video fade-in"
|
||||
style={{
|
||||
background: "#333",
|
||||
color: "#fff",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
fontSize: "14px",
|
||||
}}
|
||||
>
|
||||
💬 Chat Only
|
||||
</div>
|
||||
) : (
|
||||
<video className="Video"></video>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
</List>
|
||||
</Paper>
|
||||
</Box>
|
||||
|
@ -1222,13 +1222,13 @@ const setPlayerName = (game: Game, session: Session, name: string): string | und
|
||||
message = `${name} has rejoined the lobby.`;
|
||||
}
|
||||
session.name = name;
|
||||
if (session.ws && game.id in audio && session.id in audio[game.id]) {
|
||||
webrtcPart(audio[game.id], session);
|
||||
if (session.ws && game.id in audio && session.id in audio[game.id]!) {
|
||||
webrtcPart(audio[game.id]!, session);
|
||||
}
|
||||
} else {
|
||||
message = `${session.name} has changed their name to ${name}.`;
|
||||
message = `${session.name} hs changed their name to ${name}.`;
|
||||
if (session.ws && game.id in audio) {
|
||||
webrtcPart(audio[game.id], session);
|
||||
webrtcPart(audio[game.id]!, session);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1245,7 +1245,7 @@ const setPlayerName = (game: Game, session: Session, name: string): string | und
|
||||
}
|
||||
|
||||
if (session.ws && session.hasAudio) {
|
||||
webrtcJoin(audio[game.id], session);
|
||||
webrtcJoin(audio[game.id]!, session);
|
||||
}
|
||||
console.log(`${info}: ${message}`);
|
||||
addChatMessage(game, null, message);
|
||||
@ -3726,7 +3726,7 @@ router.ws("/ws/:id", async (ws, req) => {
|
||||
/* ignore logging errors */
|
||||
}
|
||||
if (!(gameId in audio)) {
|
||||
audio[gameId] = {}; /* List of peer sockets using session.id as index. */
|
||||
audio[gameId] = {}; /* List of peer sockets using session.id as index. */
|
||||
console.log(`${short}: Game ${gameId} - New Game Audio`);
|
||||
} else {
|
||||
console.log(`${short}: Game ${gameId} - Already has Audio`);
|
||||
@ -3822,7 +3822,7 @@ router.ws("/ws/:id", async (ws, req) => {
|
||||
/* Cleanup any voice channels */
|
||||
if (gameId in audio) {
|
||||
try {
|
||||
webrtcPart(audio[gameId], session);
|
||||
webrtcPart(audio[gameId]!, session);
|
||||
} catch (e) {
|
||||
console.warn(`${short}: Error during part():`, e);
|
||||
}
|
||||
@ -3932,7 +3932,7 @@ router.ws("/ws/:id", async (ws, req) => {
|
||||
// Clean up peer from audio registry before replacing WebSocket
|
||||
if (gameId in audio) {
|
||||
try {
|
||||
webrtcPart(audio[gameId], session);
|
||||
webrtcPart(audio[gameId]!, session);
|
||||
console.log(`${short}: Cleaned up peer ${session.name} from audio registry during reconnection`);
|
||||
} catch (e) {
|
||||
console.warn(`${short}: Error cleaning up peer during reconnection:`, e);
|
||||
@ -3968,11 +3968,11 @@ router.ws("/ws/:id", async (ws, req) => {
|
||||
// Accept either legacy `config`, newer `data`, or flat payloads where
|
||||
// the client sent fields at the top level (normalizeIncoming will
|
||||
// populate `data` with the parsed object in that case).
|
||||
webrtcJoin(audio[gameId], session);
|
||||
webrtcJoin(audio[gameId]!, session);
|
||||
break;
|
||||
|
||||
case "part":
|
||||
webrtcPart(audio[gameId], session);
|
||||
webrtcPart(audio[gameId]!, session);
|
||||
break;
|
||||
|
||||
case "relayICECandidate":
|
||||
|
@ -10,7 +10,13 @@
|
||||
|
||||
import { Session } from "./games/types";
|
||||
|
||||
export const audio: Record<string, any> = {};
|
||||
interface Peer {
|
||||
ws: any;
|
||||
name: string;
|
||||
}
|
||||
|
||||
/* Map of session => peer_id => peer */
|
||||
export const audio: Record<string, Record<string, Peer>> = {};
|
||||
|
||||
// Default send helper used when caller doesn't provide a safeSend implementation.
|
||||
const defaultSend = (targetOrSession: any, message: any): boolean => {
|
||||
@ -29,7 +35,7 @@ const defaultSend = (targetOrSession: any, message: any): boolean => {
|
||||
}
|
||||
};
|
||||
|
||||
export const join = (peers: any, session: any): void => {
|
||||
export const join = (peers: Record<string, Peer>, session: Session): void => {
|
||||
const send = defaultSend;
|
||||
const ws = session.ws;
|
||||
|
||||
@ -45,18 +51,19 @@ export const join = (peers: any, session: any): void => {
|
||||
|
||||
console.log(`${session.short}: <- join - ${session.name}`);
|
||||
|
||||
const peer = peers[session.id];
|
||||
// Use session.id as the canonical peer key
|
||||
if (session.id in peers) {
|
||||
if (peer) {
|
||||
console.log(`${session.short}:${session.id} - Already joined to Audio, updating WebSocket reference.`);
|
||||
try {
|
||||
const prev = peers[session.id] && peers[session.id].ws;
|
||||
const prev = peer.ws;
|
||||
if (prev && prev._pingInterval) {
|
||||
clearInterval(prev._pingInterval);
|
||||
}
|
||||
} catch (e) {
|
||||
/* ignore */
|
||||
}
|
||||
peers[session.id].ws = ws;
|
||||
peer.ws = ws;
|
||||
|
||||
send(ws, {
|
||||
type: "join_status",
|
||||
@ -72,7 +79,7 @@ export const join = (peers: any, session: any): void => {
|
||||
type: "addPeer",
|
||||
data: {
|
||||
peer_id: peerId,
|
||||
peer_name: peers[peerId].name || peerId,
|
||||
peer_name: peers[peerId]!.name,
|
||||
should_create_offer: true,
|
||||
},
|
||||
});
|
||||
@ -82,7 +89,7 @@ export const join = (peers: any, session: any): void => {
|
||||
for (const peerId in peers) {
|
||||
if (peerId === session.id) continue;
|
||||
|
||||
send(peers[peerId].ws, {
|
||||
send(peers[peerId]!.ws, {
|
||||
type: "addPeer",
|
||||
data: {
|
||||
peer_id: session.id,
|
||||
@ -97,7 +104,7 @@ export const join = (peers: any, session: any): void => {
|
||||
|
||||
for (let peerId in peers) {
|
||||
// notify existing peers about the new client
|
||||
send(peers[peerId].ws, {
|
||||
send(peers[peerId]!.ws, {
|
||||
type: "addPeer",
|
||||
data: {
|
||||
peer_id: session.id,
|
||||
@ -111,7 +118,7 @@ export const join = (peers: any, session: any): void => {
|
||||
type: "addPeer",
|
||||
data: {
|
||||
peer_id: peerId,
|
||||
peer_name: peers[peerId].name || peerId,
|
||||
peer_name: peers[peerId]!.name || peerId,
|
||||
should_create_offer: true,
|
||||
},
|
||||
});
|
||||
@ -130,7 +137,7 @@ export const join = (peers: any, session: any): void => {
|
||||
});
|
||||
};
|
||||
|
||||
export const part = (peers: any, session: any): void => {
|
||||
export const part = (peers: Record<string, Peer>, session: Session): void => {
|
||||
const ws = session.ws;
|
||||
const send = defaultSend;
|
||||
|
||||
@ -151,7 +158,7 @@ export const part = (peers: any, session: any): void => {
|
||||
delete peers[session.id];
|
||||
|
||||
for (let peerId in peers) {
|
||||
send(peers[peerId].ws, {
|
||||
send(peers[peerId]!.ws, {
|
||||
type: "removePeer",
|
||||
data: {
|
||||
peer_id: session.id,
|
||||
@ -162,7 +169,7 @@ export const part = (peers: any, session: any): void => {
|
||||
type: "removePeer",
|
||||
data: {
|
||||
peer_id: peerId,
|
||||
peer_name: peers[peerId].name || peerId,
|
||||
peer_name: peers[peerId]!.name || peerId,
|
||||
},
|
||||
});
|
||||
}
|
||||
@ -195,8 +202,8 @@ export const handleRelayICECandidate = (gameId: string, cfg: any, session: Sessi
|
||||
},
|
||||
});
|
||||
|
||||
if (peer_id in audio[gameId]) {
|
||||
const target = audio[gameId][peer_id] as any;
|
||||
if (peer_id in audio[gameId]!) {
|
||||
const target = audio[gameId]![peer_id] as any;
|
||||
if (!target || !target.ws) {
|
||||
console.warn(`${session.id}:${gameId} relayICECandidate - target ${peer_id} has no ws`);
|
||||
} else if (!send(target.ws, message)) {
|
||||
@ -236,8 +243,8 @@ export const handleRelaySessionDescription = (gameId: string, cfg: any, session:
|
||||
session_description,
|
||||
},
|
||||
});
|
||||
if (peer_id in audio[gameId]) {
|
||||
const target = audio[gameId][peer_id] as any;
|
||||
if (peer_id in audio[gameId]!) {
|
||||
const target = audio[gameId]![peer_id] as any;
|
||||
if (!target || !target.ws) {
|
||||
console.warn(`${session.id}:${gameId} relaySessionDescription - target ${peer_id} has no ws`);
|
||||
} else if (!send(target.ws, message)) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user