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