Building but users still not listing
This commit is contained in:
parent
720c0aa143
commit
81d366286a
@ -87,7 +87,7 @@ const Activity: React.FC<ActivityProps> = ({ keep, activity }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Activities: React.FC = () => {
|
const Activities: React.FC = () => {
|
||||||
const { ws, sendJsonMessage } = useContext(GlobalContext);
|
const { lastJsonMessage, sendJsonMessage } = useContext(GlobalContext);
|
||||||
const [activities, setActivities] = useState<ActivityData[]>([]);
|
const [activities, setActivities] = useState<ActivityData[]>([]);
|
||||||
const [turn, setTurn] = useState<TurnData | undefined>(undefined);
|
const [turn, setTurn] = useState<TurnData | undefined>(undefined);
|
||||||
const [color, setColor] = useState<string | undefined>(undefined);
|
const [color, setColor] = useState<string | undefined>(undefined);
|
||||||
@ -103,15 +103,16 @@ const Activities: React.FC = () => {
|
|||||||
} else {
|
} else {
|
||||||
request = fields;
|
request = fields;
|
||||||
}
|
}
|
||||||
ws?.send(
|
sendJsonMessage({
|
||||||
JSON.stringify({
|
|
||||||
type: "get",
|
type: "get",
|
||||||
fields: request,
|
fields: request,
|
||||||
})
|
});
|
||||||
);
|
|
||||||
};
|
};
|
||||||
const onWsMessage = (event: MessageEvent) => {
|
useEffect(() => {
|
||||||
const data = JSON.parse(event.data) as { type: string; update?: Record<string, unknown> };
|
if (!lastJsonMessage) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const data = lastJsonMessage;
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case "game-update": {
|
case "game-update": {
|
||||||
const ignoring: string[] = [],
|
const ignoring: string[] = [],
|
||||||
@ -153,21 +154,8 @@ const Activities: React.FC = () => {
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
}, [lastJsonMessage, activities, turn, players, timestamp, color, state, fields]);
|
||||||
const refWsMessage = useRef(onWsMessage);
|
|
||||||
useEffect(() => {
|
|
||||||
refWsMessage.current = onWsMessage;
|
|
||||||
});
|
|
||||||
useEffect(() => {
|
|
||||||
if (!ws) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const cbMessage = (e: MessageEvent) => refWsMessage.current(e);
|
|
||||||
ws.addEventListener("message", cbMessage as EventListener);
|
|
||||||
return () => {
|
|
||||||
ws.removeEventListener("message", cbMessage as EventListener);
|
|
||||||
};
|
|
||||||
}, [ws, refWsMessage]);
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!sendJsonMessage) {
|
if (!sendJsonMessage) {
|
||||||
return;
|
return;
|
||||||
|
@ -3,7 +3,7 @@ import Paper from "@mui/material/Paper";
|
|||||||
import List from "@mui/material/List";
|
import List from "@mui/material/List";
|
||||||
import ListItem from "@mui/material/ListItem";
|
import ListItem from "@mui/material/ListItem";
|
||||||
import ListItemText from "@mui/material/ListItemText";
|
import ListItemText from "@mui/material/ListItemText";
|
||||||
import { formatDistanceToNow, formatDuration, intervalToDuration } from 'date-fns';
|
import { formatDistanceToNow, formatDuration, intervalToDuration } from "date-fns";
|
||||||
import TextField from "@mui/material/TextField";
|
import TextField from "@mui/material/TextField";
|
||||||
import equal from "fast-deep-equal";
|
import equal from "fast-deep-equal";
|
||||||
|
|
||||||
@ -34,10 +34,13 @@ const Chat: React.FC = () => {
|
|||||||
return () => clearInterval(timer);
|
return () => clearInterval(timer);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const { ws, name, sendJsonMessage } = useContext(GlobalContext);
|
const { lastJsonMessage, name, sendJsonMessage } = useContext(GlobalContext);
|
||||||
const fields = useMemo(() => ["chat", "startTime"], []);
|
const fields = useMemo(() => ["chat", "startTime"], []);
|
||||||
const onWsMessage = (event: MessageEvent) => {
|
useEffect(() => {
|
||||||
const data = JSON.parse(event.data);
|
if (!lastJsonMessage) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const data = lastJsonMessage;
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case "game-update":
|
case "game-update":
|
||||||
console.log(`chat - game update`);
|
console.log(`chat - game update`);
|
||||||
@ -52,30 +55,13 @@ const Chat: React.FC = () => {
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
}, [lastJsonMessage, chat, startTime]);
|
||||||
const refWsMessage = useRef(onWsMessage);
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
refWsMessage.current = onWsMessage;
|
|
||||||
});
|
|
||||||
useEffect(() => {
|
|
||||||
if (!ws) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const cbMessage = (e: MessageEvent) => refWsMessage.current(e);
|
|
||||||
ws.addEventListener("message", cbMessage);
|
|
||||||
return () => {
|
|
||||||
ws.removeEventListener("message", cbMessage);
|
|
||||||
};
|
|
||||||
}, [ws, refWsMessage]);
|
|
||||||
useEffect(() => {
|
|
||||||
if (!ws) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sendJsonMessage({
|
sendJsonMessage({
|
||||||
type: "get",
|
type: "get",
|
||||||
fields,
|
fields,
|
||||||
});
|
});
|
||||||
}, [ws, fields, sendJsonMessage]);
|
}, [fields, sendJsonMessage]);
|
||||||
|
|
||||||
const chatKeyPress = useCallback(
|
const chatKeyPress = useCallback(
|
||||||
(event: React.KeyboardEvent<HTMLInputElement>) => {
|
(event: React.KeyboardEvent<HTMLInputElement>) => {
|
||||||
@ -84,13 +70,11 @@ const Chat: React.FC = () => {
|
|||||||
setAutoScroll(true);
|
setAutoScroll(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ws) {
|
|
||||||
sendJsonMessage({ type: "chat", message: (event.target as HTMLInputElement).value });
|
sendJsonMessage({ type: "chat", message: (event.target as HTMLInputElement).value });
|
||||||
(event.target as HTMLInputElement).value = "";
|
(event.target as HTMLInputElement).value = "";
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
[ws, setAutoScroll, autoScroll]
|
[setAutoScroll, autoScroll]
|
||||||
);
|
);
|
||||||
|
|
||||||
const chatScroll = (event: React.UIEvent<HTMLUListElement>) => {
|
const chatScroll = (event: React.UIEvent<HTMLUListElement>) => {
|
||||||
@ -217,9 +201,7 @@ const Chat: React.FC = () => {
|
|||||||
{item.color && <PlayerColor color={item.color} />}
|
{item.color && <PlayerColor color={item.color} />}
|
||||||
<ListItemText
|
<ListItemText
|
||||||
primary={message}
|
primary={message}
|
||||||
secondary={
|
secondary={item.color && formatDistanceToNow(new Date(item.date > now ? now : item.date))}
|
||||||
item.color && formatDistanceToNow(new Date(item.date > now ? now : item.date))
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
);
|
);
|
||||||
@ -248,7 +230,7 @@ const Chat: React.FC = () => {
|
|||||||
const hours = duration.hours || 0;
|
const hours = duration.hours || 0;
|
||||||
const minutes = duration.minutes || 0;
|
const minutes = duration.minutes || 0;
|
||||||
const seconds = duration.seconds || 0;
|
const seconds = duration.seconds || 0;
|
||||||
return `${hours}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
return `${hours}:${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;
|
||||||
})()}
|
})()}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
@ -12,15 +12,19 @@ import { GlobalContext } from "./GlobalContext";
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
|
||||||
const ChooseCard: React.FC = () => {
|
const ChooseCard: React.FC = () => {
|
||||||
const { ws, sendJsonMessage } = useContext(GlobalContext);
|
const { lastJsonMessage, sendJsonMessage } = useContext(GlobalContext);
|
||||||
const [turn, setTurn] = useState<any>(undefined);
|
const [turn, setTurn] = useState<any>(undefined);
|
||||||
const [color, setColor] = useState<string | undefined>(undefined);
|
const [color, setColor] = useState<string | undefined>(undefined);
|
||||||
const [state, setState] = useState<string | undefined>(undefined);
|
const [state, setState] = useState<string | undefined>(undefined);
|
||||||
const [cards, setCards] = useState<string[]>([]);
|
const [cards, setCards] = useState<string[]>([]);
|
||||||
const fields = useMemo(() => ["turn", "color", "state"], []);
|
const fields = useMemo(() => ["turn", "color", "state"], []);
|
||||||
|
|
||||||
const onWsMessage = (event: MessageEvent) => {
|
useEffect(() => {
|
||||||
const data = JSON.parse(event.data);
|
if (!lastJsonMessage) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = lastJsonMessage;
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case "game-update":
|
case "game-update":
|
||||||
console.log(`choose-card - game-update: `, data.update);
|
console.log(`choose-card - game-update: `, data.update);
|
||||||
@ -37,21 +41,7 @@ const ChooseCard: React.FC = () => {
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
}, [lastJsonMessage, turn, color, state]);
|
||||||
const refWsMessage = useRef(onWsMessage);
|
|
||||||
useEffect(() => {
|
|
||||||
refWsMessage.current = onWsMessage;
|
|
||||||
});
|
|
||||||
useEffect(() => {
|
|
||||||
if (!ws) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const cbMessage = (e: MessageEvent) => refWsMessage.current(e);
|
|
||||||
ws.addEventListener("message", cbMessage);
|
|
||||||
return () => {
|
|
||||||
ws.removeEventListener("message", cbMessage);
|
|
||||||
};
|
|
||||||
}, [ws, refWsMessage]);
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!sendJsonMessage) {
|
if (!sendJsonMessage) {
|
||||||
return;
|
return;
|
||||||
|
@ -21,13 +21,13 @@ interface PlayerItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const GameOrder: React.FC = () => {
|
const GameOrder: React.FC = () => {
|
||||||
const { ws, sendJsonMessage } = useContext(GlobalContext);
|
const { lastJsonMessage, sendJsonMessage } = useContext(GlobalContext);
|
||||||
const [players, setPlayers] = useState<{ [key: string]: any }>({});
|
const [players, setPlayers] = useState<{ [key: string]: any }>({});
|
||||||
const [color, setColor] = useState<string | undefined>(undefined);
|
const [color, setColor] = useState<string | undefined>(undefined);
|
||||||
const fields = useMemo(() => ["players", "color"], []);
|
const fields = useMemo(() => ["players", "color"], []);
|
||||||
|
|
||||||
const onWsMessage = (event: MessageEvent) => {
|
useEffect(() => {
|
||||||
const data = JSON.parse(event.data);
|
const data = lastJsonMessage;
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case "game-update":
|
case "game-update":
|
||||||
console.log(`GameOrder game-update: `, data.update);
|
console.log(`GameOrder game-update: `, data.update);
|
||||||
@ -41,21 +41,7 @@ const GameOrder: React.FC = () => {
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
}, [lastJsonMessage, players, color]);
|
||||||
const refWsMessage = useRef(onWsMessage);
|
|
||||||
useEffect(() => {
|
|
||||||
refWsMessage.current = onWsMessage;
|
|
||||||
});
|
|
||||||
useEffect(() => {
|
|
||||||
if (!ws) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const cbMessage = (e: MessageEvent) => refWsMessage.current(e);
|
|
||||||
ws.addEventListener("message", cbMessage);
|
|
||||||
return () => {
|
|
||||||
ws.removeEventListener("message", cbMessage);
|
|
||||||
};
|
|
||||||
}, [ws, refWsMessage]);
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!sendJsonMessage) {
|
if (!sendJsonMessage) {
|
||||||
return;
|
return;
|
||||||
@ -66,12 +52,8 @@ const GameOrder: React.FC = () => {
|
|||||||
});
|
});
|
||||||
}, [sendJsonMessage, fields]);
|
}, [sendJsonMessage, fields]);
|
||||||
|
|
||||||
const sendMessage = (data: any) => {
|
|
||||||
ws!.send(JSON.stringify(data));
|
|
||||||
};
|
|
||||||
|
|
||||||
const rollClick = () => {
|
const rollClick = () => {
|
||||||
sendMessage({ type: "roll" });
|
sendJsonMessage({ type: "roll" });
|
||||||
};
|
};
|
||||||
|
|
||||||
let hasRolled = true;
|
let hasRolled = true;
|
||||||
|
@ -34,7 +34,7 @@ interface HandProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Hand: React.FC<HandProps> = ({ buildActive, setBuildActive, setCardActive }) => {
|
const Hand: React.FC<HandProps> = ({ buildActive, setBuildActive, setCardActive }) => {
|
||||||
const { ws, sendJsonMessage } = useContext(GlobalContext);
|
const { lastJsonMessage, sendJsonMessage } = useContext(GlobalContext);
|
||||||
const [priv, setPriv] = useState<any>(undefined);
|
const [priv, setPriv] = useState<any>(undefined);
|
||||||
const [color, setColor] = useState<string | undefined>(undefined);
|
const [color, setColor] = useState<string | undefined>(undefined);
|
||||||
const [turn, setTurn] = useState<any>(undefined);
|
const [turn, setTurn] = useState<any>(undefined);
|
||||||
@ -49,8 +49,12 @@ const Hand: React.FC<HandProps> = ({ buildActive, setBuildActive, setCardActive
|
|||||||
() => ["private", "turn", "color", "longestRoad", "largestArmy", "mostPorts", "mostDeveloped"],
|
() => ["private", "turn", "color", "longestRoad", "largestArmy", "mostPorts", "mostDeveloped"],
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
const onWsMessage = (event: MessageEvent) => {
|
useEffect(() => {
|
||||||
const data = JSON.parse(event.data);
|
if (!lastJsonMessage) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = lastJsonMessage;
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case "game-update":
|
case "game-update":
|
||||||
console.log(`hand - game-update: `, data.update);
|
console.log(`hand - game-update: `, data.update);
|
||||||
@ -79,21 +83,7 @@ const Hand: React.FC<HandProps> = ({ buildActive, setBuildActive, setCardActive
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
}, [lastJsonMessage, priv, turn, color, longestRoad, largestArmy, mostPorts, mostDeveloped]);
|
||||||
const refWsMessage = useRef(onWsMessage);
|
|
||||||
useEffect(() => {
|
|
||||||
refWsMessage.current = onWsMessage;
|
|
||||||
});
|
|
||||||
useEffect(() => {
|
|
||||||
if (!ws) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const cbMessage = (e: MessageEvent) => refWsMessage.current(e);
|
|
||||||
ws.addEventListener("message", cbMessage);
|
|
||||||
return () => {
|
|
||||||
ws.removeEventListener("message", cbMessage);
|
|
||||||
};
|
|
||||||
}, [ws, refWsMessage]);
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!sendJsonMessage) {
|
if (!sendJsonMessage) {
|
||||||
return;
|
return;
|
||||||
|
@ -247,14 +247,17 @@ interface HouseRulesProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const HouseRules: React.FC<HouseRulesProps> = ({ houseRulesActive, setHouseRulesActive }) => {
|
const HouseRules: React.FC<HouseRulesProps> = ({ houseRulesActive, setHouseRulesActive }) => {
|
||||||
const { ws, name, sendJsonMessage } = useContext(GlobalContext);
|
const { lastJsonMessage, name, sendJsonMessage } = useContext(GlobalContext);
|
||||||
const [rules, setRules] = useState<any>({});
|
const [rules, setRules] = useState<any>({});
|
||||||
const [state, setState] = useState<any>({});
|
const [state, setState] = useState<any>({});
|
||||||
const [gameState, setGameState] = useState<string>("");
|
const [gameState, setGameState] = useState<string>("");
|
||||||
|
|
||||||
const fields = useMemo(() => ["state", "rules"], []);
|
const fields = useMemo(() => ["state", "rules"], []);
|
||||||
const onWsMessage = (event: MessageEvent) => {
|
useEffect(() => {
|
||||||
const data = JSON.parse(event.data);
|
if (!lastJsonMessage) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const data = lastJsonMessage;
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case "game-update":
|
case "game-update":
|
||||||
console.log(`house-rules - game-update: `, data.update);
|
console.log(`house-rules - game-update: `, data.update);
|
||||||
@ -268,21 +271,7 @@ const HouseRules: React.FC<HouseRulesProps> = ({ houseRulesActive, setHouseRules
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
}, [lastJsonMessage, rules, gameState]);
|
||||||
const refWsMessage = useRef(onWsMessage);
|
|
||||||
useEffect(() => {
|
|
||||||
refWsMessage.current = onWsMessage;
|
|
||||||
});
|
|
||||||
useEffect(() => {
|
|
||||||
if (!ws) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const cbMessage = (e: MessageEvent) => refWsMessage.current(e);
|
|
||||||
ws.addEventListener("message", cbMessage);
|
|
||||||
return () => {
|
|
||||||
ws.removeEventListener("message", cbMessage);
|
|
||||||
};
|
|
||||||
}, [ws, refWsMessage]);
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!sendJsonMessage) {
|
if (!sendJsonMessage) {
|
||||||
return;
|
return;
|
||||||
@ -477,7 +466,7 @@ const HouseRules: React.FC<HouseRulesProps> = ({ houseRulesActive, setHouseRules
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
].sort((a, b) => a.category.localeCompare(b.category)),
|
].sort((a, b) => a.category.localeCompare(b.category)),
|
||||||
[rules, setRules, state, ws, setRule, name, gameState]
|
[rules, setRules, state, setRule, name, gameState]
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!houseRulesActive) {
|
if (!houseRulesActive) {
|
||||||
|
@ -1123,9 +1123,14 @@ const MediaAgent = (props: MediaAgentProps) => {
|
|||||||
if (media && joinStatus.status === "Not joined" && readyState === ReadyState.OPEN) {
|
if (media && joinStatus.status === "Not joined" && readyState === ReadyState.OPEN) {
|
||||||
console.log(`media-agent - Initiating media join for ${session.name}`);
|
console.log(`media-agent - Initiating media join for ${session.name}`);
|
||||||
setJoinStatus({ status: "Joining" });
|
setJoinStatus({ status: "Joining" });
|
||||||
sendJsonMessage({ type: "join", data: {} });
|
sendJsonMessage({
|
||||||
|
type: "join",
|
||||||
|
data: {
|
||||||
|
has_media: session.has_media !== false, // Default to true for backward compatibility
|
||||||
}
|
}
|
||||||
}, [media, joinStatus.status, sendJsonMessage, readyState, session.name]);
|
});
|
||||||
|
}
|
||||||
|
}, [media, joinStatus.status, sendJsonMessage, readyState, session.name, session.has_media]);
|
||||||
|
|
||||||
// Update local peer in peers list
|
// Update local peer in peers list
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
import React, { useState, useContext, useEffect, useRef } from "react";
|
|
||||||
import { GlobalContext } from "./GlobalContext";
|
|
||||||
import "./PingPong.css";
|
|
||||||
|
|
||||||
const PingPong: React.FC = () => {
|
|
||||||
const [count, setCount] = useState<number>(0);
|
|
||||||
const global = useContext(GlobalContext);
|
|
||||||
|
|
||||||
const onWsMessage = (event: MessageEvent) => {
|
|
||||||
const data = JSON.parse(event.data as string);
|
|
||||||
switch (data.type) {
|
|
||||||
case "ping":
|
|
||||||
if (global.ws) {
|
|
||||||
global.ws.send(JSON.stringify({ type: "pong", timestamp: data.ping }));
|
|
||||||
}
|
|
||||||
setCount(count + 1);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const refWsMessage = useRef(onWsMessage);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
refWsMessage.current = onWsMessage;
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!global.ws) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const cbMessage = (e: MessageEvent) => refWsMessage.current(e);
|
|
||||||
global.ws.addEventListener("message", cbMessage);
|
|
||||||
return () => {
|
|
||||||
global.ws.removeEventListener("message", cbMessage);
|
|
||||||
};
|
|
||||||
}, [global.ws, refWsMessage]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="PingPong">
|
|
||||||
Game {global.gameId}: {global.name} {global.ws ? "has socket" : "no socket"} {count} pings
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export { PingPong };
|
|
@ -16,13 +16,7 @@ type PlacardProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Placard: React.FC<PlacardProps> = ({ type, disabled, count, buildActive, setBuildActive, className, sx }) => {
|
const Placard: React.FC<PlacardProps> = ({ type, disabled, count, buildActive, setBuildActive, className, sx }) => {
|
||||||
const { ws, sendJsonMessage } = useContext(GlobalContext);
|
const { lastJsonMessage, sendJsonMessage } = useContext(GlobalContext);
|
||||||
const sendMessage = useCallback(
|
|
||||||
(data: Record<string, unknown>) => {
|
|
||||||
sendJsonMessage(data);
|
|
||||||
},
|
|
||||||
[sendJsonMessage]
|
|
||||||
);
|
|
||||||
|
|
||||||
const dismissClicked = () => {
|
const dismissClicked = () => {
|
||||||
setBuildActive && setBuildActive(false);
|
setBuildActive && setBuildActive(false);
|
||||||
@ -37,19 +31,19 @@ const Placard: React.FC<PlacardProps> = ({ type, disabled, count, buildActive, s
|
|||||||
};
|
};
|
||||||
|
|
||||||
const roadClicked = () => {
|
const roadClicked = () => {
|
||||||
sendMessage({ type: "buy-road" });
|
sendJsonMessage({ type: "buy-road" });
|
||||||
setBuildActive && setBuildActive(false);
|
setBuildActive && setBuildActive(false);
|
||||||
};
|
};
|
||||||
const settlementClicked = () => {
|
const settlementClicked = () => {
|
||||||
sendMessage({ type: "buy-settlement" });
|
sendJsonMessage({ type: "buy-settlement" });
|
||||||
setBuildActive && setBuildActive(false);
|
setBuildActive && setBuildActive(false);
|
||||||
};
|
};
|
||||||
const cityClicked = () => {
|
const cityClicked = () => {
|
||||||
sendMessage({ type: "buy-city" });
|
sendJsonMessage({ type: "buy-city" });
|
||||||
setBuildActive && setBuildActive(false);
|
setBuildActive && setBuildActive(false);
|
||||||
};
|
};
|
||||||
const developmentClicked = () => {
|
const developmentClicked = () => {
|
||||||
sendMessage({ type: "buy-development" });
|
sendJsonMessage({ type: "buy-development" });
|
||||||
setBuildActive && setBuildActive(false);
|
setBuildActive && setBuildActive(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -60,21 +60,24 @@ const PlayerList: React.FC = () => {
|
|||||||
}
|
}
|
||||||
const data: any = lastJsonMessage;
|
const data: any = lastJsonMessage;
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case "players": {
|
case "game-update": {
|
||||||
type RoomStateData = {
|
console.log(`PlayerList - game-update:`, data.update);
|
||||||
participants: Player[];
|
|
||||||
};
|
// Handle participants list
|
||||||
const room_state = data as RoomStateData;
|
if ("participants" in data.update && data.update.participants) {
|
||||||
console.log(`Players - room_state`, room_state.participants);
|
const participantsList: Player[] = data.update.participants;
|
||||||
room_state.participants.forEach((player) => {
|
console.log(`PlayerList - participants:`, participantsList);
|
||||||
player.local = player.session_id === session.id;
|
|
||||||
|
participantsList.forEach((player) => {
|
||||||
|
player.local = player.session_id === session?.id;
|
||||||
});
|
});
|
||||||
room_state.participants.sort(sortPlayers);
|
participantsList.sort(sortPlayers);
|
||||||
setPlayers(room_state.participants);
|
setPlayers(participantsList);
|
||||||
|
|
||||||
// Initialize peers with remote mute/video state
|
// Initialize peers with remote mute/video state
|
||||||
setPeers((prevPeers) => {
|
setPeers((prevPeers) => {
|
||||||
const updated: Record<string, Peer> = { ...prevPeers };
|
const updated: Record<string, Peer> = { ...prevPeers };
|
||||||
room_state.participants.forEach((player) => {
|
participantsList.forEach((player) => {
|
||||||
// Only update remote peers, never overwrite local peer object
|
// Only update remote peers, never overwrite local peer object
|
||||||
if (!player.local && updated[player.session_id]) {
|
if (!player.local && updated[player.session_id]) {
|
||||||
updated[player.session_id] = {
|
updated[player.session_id] = {
|
||||||
@ -86,12 +89,6 @@ const PlayerList: React.FC = () => {
|
|||||||
});
|
});
|
||||||
return updated;
|
return updated;
|
||||||
});
|
});
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "update_name": {
|
|
||||||
// Update local session name immediately
|
|
||||||
if (data && typeof data.name === "string") {
|
|
||||||
session.name = data.name;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -99,12 +96,12 @@ const PlayerList: React.FC = () => {
|
|||||||
// Update peer state in peers, but do not override local mute
|
// Update peer state in peers, but do not override local mute
|
||||||
setPeers((prevPeers) => {
|
setPeers((prevPeers) => {
|
||||||
const updated = { ...prevPeers };
|
const updated = { ...prevPeers };
|
||||||
const peerId = data.peer_id;
|
const peerId = data.data?.peer_id || data.peer_id;
|
||||||
if (peerId && updated[peerId]) {
|
if (peerId && updated[peerId]) {
|
||||||
updated[peerId] = {
|
updated[peerId] = {
|
||||||
...updated[peerId],
|
...updated[peerId],
|
||||||
muted: data.muted,
|
muted: data.data?.muted ?? data.muted,
|
||||||
video_on: data.video_on,
|
video_on: data.data?.video_on ?? data.video_on,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return updated;
|
return updated;
|
||||||
@ -117,11 +114,13 @@ const PlayerList: React.FC = () => {
|
|||||||
}, [lastJsonMessage, session, sortPlayers, setPeers, setPlayers]);
|
}, [lastJsonMessage, session, sortPlayers, setPeers, setPlayers]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (players !== null) {
|
if (players !== null || !sendJsonMessage) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Request participants list
|
||||||
sendJsonMessage({
|
sendJsonMessage({
|
||||||
type: "list_Players",
|
type: "get",
|
||||||
|
fields: ["participants"],
|
||||||
});
|
});
|
||||||
}, [players, sendJsonMessage]);
|
}, [players, sendJsonMessage]);
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ interface PlayersStatusProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const PlayersStatus: React.FC<PlayersStatusProps> = ({ active }) => {
|
const PlayersStatus: React.FC<PlayersStatusProps> = ({ active }) => {
|
||||||
const { ws, sendJsonMessage } = useContext(GlobalContext);
|
const { lastJsonMessage, sendJsonMessage } = useContext(GlobalContext);
|
||||||
const [players, setPlayers] = useState<any>(undefined);
|
const [players, setPlayers] = useState<any>(undefined);
|
||||||
const [color, setColor] = useState<string | undefined>(undefined);
|
const [color, setColor] = useState<string | undefined>(undefined);
|
||||||
const [largestArmy, setLargestArmy] = useState<string | undefined>(undefined);
|
const [largestArmy, setLargestArmy] = useState<string | undefined>(undefined);
|
||||||
@ -141,8 +141,12 @@ const PlayersStatus: React.FC<PlayersStatusProps> = ({ active }) => {
|
|||||||
const [mostPorts, setMostPorts] = useState<string | undefined>(undefined);
|
const [mostPorts, setMostPorts] = useState<string | undefined>(undefined);
|
||||||
const [mostDeveloped, setMostDeveloped] = useState<string | undefined>(undefined);
|
const [mostDeveloped, setMostDeveloped] = useState<string | undefined>(undefined);
|
||||||
const fields = useMemo(() => ["players", "color", "longestRoad", "largestArmy", "mostPorts", "mostDeveloped"], []);
|
const fields = useMemo(() => ["players", "color", "longestRoad", "largestArmy", "mostPorts", "mostDeveloped"], []);
|
||||||
const onWsMessage = (event: MessageEvent) => {
|
useEffect(() => {
|
||||||
const data = JSON.parse(event.data);
|
if (!lastJsonMessage) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = lastJsonMessage;
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case "game-update":
|
case "game-update":
|
||||||
console.log(`players-status - game-update: `, data.update);
|
console.log(`players-status - game-update: `, data.update);
|
||||||
@ -168,21 +172,7 @@ const PlayersStatus: React.FC<PlayersStatusProps> = ({ active }) => {
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
}, [lastJsonMessage, players, color, longestRoad, largestArmy, mostPorts, mostDeveloped]);
|
||||||
const refWsMessage = useRef(onWsMessage);
|
|
||||||
useEffect(() => {
|
|
||||||
refWsMessage.current = onWsMessage;
|
|
||||||
});
|
|
||||||
useEffect(() => {
|
|
||||||
if (!ws) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const cbMessage = (e: MessageEvent) => refWsMessage.current(e);
|
|
||||||
ws.addEventListener("message", cbMessage);
|
|
||||||
return () => {
|
|
||||||
ws.removeEventListener("message", cbMessage);
|
|
||||||
};
|
|
||||||
}, [ws, refWsMessage]);
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!sendJsonMessage) {
|
if (!sendJsonMessage) {
|
||||||
return;
|
return;
|
||||||
|
@ -11,13 +11,16 @@ import { GlobalContext } from "./GlobalContext";
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||||
|
|
||||||
const SelectPlayer: React.FC = () => {
|
const SelectPlayer: React.FC = () => {
|
||||||
const { ws, sendJsonMessage } = useContext(GlobalContext);
|
const { lastJsonMessage, sendJsonMessage } = useContext(GlobalContext);
|
||||||
const [turn, setTurn] = useState<any>(undefined);
|
const [turn, setTurn] = useState<any>(undefined);
|
||||||
const [color, setColor] = useState<string | undefined>(undefined);
|
const [color, setColor] = useState<string | undefined>(undefined);
|
||||||
const fields = useMemo(() => ["turn", "color"], []);
|
const fields = useMemo(() => ["turn", "color"], []);
|
||||||
|
|
||||||
const onWsMessage = (event: MessageEvent) => {
|
useEffect(() => {
|
||||||
const data = JSON.parse(event.data);
|
if (!lastJsonMessage) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const data = lastJsonMessage;
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case "game-update":
|
case "game-update":
|
||||||
console.log(`select-players - game-update: `, data.update);
|
console.log(`select-players - game-update: `, data.update);
|
||||||
@ -31,21 +34,7 @@ const SelectPlayer: React.FC = () => {
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
}, [lastJsonMessage, turn, color]);
|
||||||
const refWsMessage = useRef(onWsMessage);
|
|
||||||
useEffect(() => {
|
|
||||||
refWsMessage.current = onWsMessage;
|
|
||||||
});
|
|
||||||
useEffect(() => {
|
|
||||||
if (!ws) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const cbMessage = (e: MessageEvent) => refWsMessage.current(e);
|
|
||||||
ws.addEventListener("message", cbMessage);
|
|
||||||
return () => {
|
|
||||||
ws.removeEventListener("message", cbMessage);
|
|
||||||
};
|
|
||||||
}, [ws, refWsMessage]);
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!sendJsonMessage) {
|
if (!sendJsonMessage) {
|
||||||
return;
|
return;
|
||||||
|
@ -16,13 +16,16 @@ interface ViewCardProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ViewCard: React.FC<ViewCardProps> = ({ cardActive, setCardActive }) => {
|
const ViewCard: React.FC<ViewCardProps> = ({ cardActive, setCardActive }) => {
|
||||||
const { ws, sendJsonMessage } = useContext(GlobalContext);
|
const { lastJsonMessage, sendJsonMessage } = useContext(GlobalContext);
|
||||||
const [priv, setPriv] = useState<any>(undefined);
|
const [priv, setPriv] = useState<any>(undefined);
|
||||||
const [turns, setTurns] = useState<number>(0);
|
const [turns, setTurns] = useState<number>(0);
|
||||||
const [rules, setRules] = useState<any>({});
|
const [rules, setRules] = useState<any>({});
|
||||||
const fields = useMemo(() => ["private", "turns", "rules"], []);
|
const fields = useMemo(() => ["private", "turns", "rules"], []);
|
||||||
const onWsMessage = (event: MessageEvent) => {
|
useEffect(() => {
|
||||||
const data = JSON.parse(event.data as string);
|
if (!lastJsonMessage) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const data = lastJsonMessage;
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case "game-update":
|
case "game-update":
|
||||||
console.log(`view-card - game update`);
|
console.log(`view-card - game update`);
|
||||||
@ -39,21 +42,7 @@ const ViewCard: React.FC<ViewCardProps> = ({ cardActive, setCardActive }) => {
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
}, [lastJsonMessage, priv, turns, rules]);
|
||||||
const refWsMessage = useRef(onWsMessage);
|
|
||||||
useEffect(() => {
|
|
||||||
refWsMessage.current = onWsMessage;
|
|
||||||
});
|
|
||||||
useEffect(() => {
|
|
||||||
if (!ws) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const cbMessage = (e: MessageEvent) => refWsMessage.current(e);
|
|
||||||
ws.addEventListener("message", cbMessage);
|
|
||||||
return () => {
|
|
||||||
ws.removeEventListener("message", cbMessage);
|
|
||||||
};
|
|
||||||
}, [ws, refWsMessage]);
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!sendJsonMessage) {
|
if (!sendJsonMessage) {
|
||||||
return;
|
return;
|
||||||
|
@ -17,12 +17,16 @@ interface WinnerProps {
|
|||||||
|
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
const Winner: React.FC<WinnerProps> = ({ winnerDismissed, setWinnerDismissed }) => {
|
const Winner: React.FC<WinnerProps> = ({ winnerDismissed, setWinnerDismissed }) => {
|
||||||
const { ws, sendJsonMessage } = useContext(GlobalContext);
|
const { lastJsonMessage, sendJsonMessage } = useContext(GlobalContext);
|
||||||
const [winner, setWinner] = useState<any>(undefined);
|
const [winner, setWinner] = useState<any>(undefined);
|
||||||
const [state, setState] = useState<string | undefined>(undefined);
|
const [state, setState] = useState<string | undefined>(undefined);
|
||||||
const fields = useMemo(() => ["winner", "state"], []);
|
const fields = useMemo(() => ["winner", "state"], []);
|
||||||
const onWsMessage = (event: MessageEvent) => {
|
useEffect(() => {
|
||||||
const data: { type: string; update: any } = JSON.parse(event.data);
|
if (!lastJsonMessage) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = lastJsonMessage;
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case "game-update":
|
case "game-update":
|
||||||
console.log(`winner - game update`, data.update);
|
console.log(`winner - game update`, data.update);
|
||||||
@ -40,21 +44,7 @@ const Winner: React.FC<WinnerProps> = ({ winnerDismissed, setWinnerDismissed })
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
}, [lastJsonMessage, winner, state, setWinnerDismissed]);
|
||||||
const refWsMessage = useRef(onWsMessage);
|
|
||||||
useEffect(() => {
|
|
||||||
refWsMessage.current = onWsMessage;
|
|
||||||
});
|
|
||||||
useEffect(() => {
|
|
||||||
if (!ws) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const cbMessage = (e: MessageEvent) => refWsMessage.current(e);
|
|
||||||
ws.addEventListener("message", cbMessage);
|
|
||||||
return () => {
|
|
||||||
ws.removeEventListener("message", cbMessage);
|
|
||||||
};
|
|
||||||
}, [ws, refWsMessage]);
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!sendJsonMessage) {
|
if (!sendJsonMessage) {
|
||||||
return;
|
return;
|
||||||
|
@ -1163,6 +1163,7 @@ const setPlayerName = (game: Game, session: Session, name: string): string | und
|
|||||||
});
|
});
|
||||||
sendUpdateToPlayers(game, {
|
sendUpdateToPlayers(game, {
|
||||||
players: getFilteredPlayers(game),
|
players: getFilteredPlayers(game),
|
||||||
|
participants: getParticipants(game),
|
||||||
unselected: getFilteredUnselected(game),
|
unselected: getFilteredUnselected(game),
|
||||||
chat: game.chat,
|
chat: game.chat,
|
||||||
});
|
});
|
||||||
@ -1282,6 +1283,7 @@ const setPlayerColor = (game: Game, session: Session, color: string): string | u
|
|||||||
|
|
||||||
const update: any = {
|
const update: any = {
|
||||||
players: getFilteredPlayers(game),
|
players: getFilteredPlayers(game),
|
||||||
|
participants: getParticipants(game),
|
||||||
chat: game.chat,
|
chat: game.chat,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3407,19 +3409,79 @@ const resetDisconnectCheck = (_game: any, req: any): void => {
|
|||||||
//req.disconnectCheck = setTimeout(() => { wsInactive(game, req) }, 20000);
|
//req.disconnectCheck = setTimeout(() => { wsInactive(game, req) }, 20000);
|
||||||
};
|
};
|
||||||
|
|
||||||
const join = (peers: any, session: any, { hasVideo, hasAudio }: { hasVideo?: boolean; hasAudio?: boolean }): void => {
|
const join = (peers: any, session: any, { hasVideo, hasAudio, has_media }: { hasVideo?: boolean; hasAudio?: boolean; has_media?: boolean }): void => {
|
||||||
const ws = session.ws;
|
const ws = session.ws;
|
||||||
|
|
||||||
if (!session.name) {
|
if (!session.name) {
|
||||||
console.error(`${session.id}: <- join - No name set yet. Audio not available.`);
|
console.error(`${session.id}: <- join - No name set yet. Audio not available.`);
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
type: "join_status",
|
||||||
|
status: "Error",
|
||||||
|
message: "No name set yet. Audio not available."
|
||||||
|
}));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`${session.id}: <- join - ${session.name}`);
|
console.log(`${session.id}: <- join - ${session.name}`);
|
||||||
console.log(`${all}: -> addPeer - ${session.name}`);
|
console.log(`${all}: -> addPeer - ${session.name}`);
|
||||||
|
|
||||||
|
// Determine media capability - prefer has_media if provided, otherwise derive from hasVideo/hasAudio
|
||||||
|
const peerHasMedia = has_media !== undefined ? has_media : (hasVideo || hasAudio);
|
||||||
|
|
||||||
if (session.name in peers) {
|
if (session.name in peers) {
|
||||||
console.log(`${session.id}:${session.name} - Already joined to Audio.`);
|
console.log(`${session.id}:${session.name} - Already joined to Audio, updating WebSocket reference.`);
|
||||||
|
|
||||||
|
// Update the WebSocket reference in case of reconnection
|
||||||
|
peers[session.name].ws = ws;
|
||||||
|
peers[session.name].has_media = peerHasMedia;
|
||||||
|
peers[session.name].hasAudio = hasAudio;
|
||||||
|
peers[session.name].hasVideo = hasVideo;
|
||||||
|
|
||||||
|
// Send join status to reconnected client
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
type: "join_status",
|
||||||
|
status: "Joined",
|
||||||
|
message: "Reconnected"
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Notify the reconnected client about all existing peers
|
||||||
|
for (const peer in peers) {
|
||||||
|
if (peer === session.name) continue; // Skip self
|
||||||
|
|
||||||
|
ws.send(
|
||||||
|
JSON.stringify({
|
||||||
|
type: "addPeer",
|
||||||
|
data: {
|
||||||
|
peer_id: peer,
|
||||||
|
peer_name: peer,
|
||||||
|
has_media: peers[peer].has_media,
|
||||||
|
should_create_offer: true,
|
||||||
|
hasAudio: peers[peer].hasAudio,
|
||||||
|
hasVideo: peers[peer].hasVideo,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify all other peers about the reconnected peer (with updated connection)
|
||||||
|
for (const peer in peers) {
|
||||||
|
if (peer === session.name) continue; // Skip self
|
||||||
|
|
||||||
|
peers[peer].ws.send(
|
||||||
|
JSON.stringify({
|
||||||
|
type: "addPeer",
|
||||||
|
data: {
|
||||||
|
peer_id: session.name,
|
||||||
|
peer_name: session.name,
|
||||||
|
has_media: peerHasMedia,
|
||||||
|
should_create_offer: false,
|
||||||
|
hasAudio,
|
||||||
|
hasVideo,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3430,6 +3492,8 @@ const join = (peers: any, session: any, { hasVideo, hasAudio }: { hasVideo?: boo
|
|||||||
type: "addPeer",
|
type: "addPeer",
|
||||||
data: {
|
data: {
|
||||||
peer_id: session.name,
|
peer_id: session.name,
|
||||||
|
peer_name: session.name,
|
||||||
|
has_media: peers[session.name]?.has_media ?? peerHasMedia,
|
||||||
should_create_offer: false,
|
should_create_offer: false,
|
||||||
hasAudio,
|
hasAudio,
|
||||||
hasVideo,
|
hasVideo,
|
||||||
@ -3443,6 +3507,8 @@ const join = (peers: any, session: any, { hasVideo, hasAudio }: { hasVideo?: boo
|
|||||||
type: "addPeer",
|
type: "addPeer",
|
||||||
data: {
|
data: {
|
||||||
peer_id: peer,
|
peer_id: peer,
|
||||||
|
peer_name: peer,
|
||||||
|
has_media: peers[peer].has_media,
|
||||||
should_create_offer: true,
|
should_create_offer: true,
|
||||||
hasAudio: peers[peer].hasAudio,
|
hasAudio: peers[peer].hasAudio,
|
||||||
hasVideo: peers[peer].hasVideo,
|
hasVideo: peers[peer].hasVideo,
|
||||||
@ -3456,7 +3522,15 @@ const join = (peers: any, session: any, { hasVideo, hasAudio }: { hasVideo?: boo
|
|||||||
ws,
|
ws,
|
||||||
hasAudio,
|
hasAudio,
|
||||||
hasVideo,
|
hasVideo,
|
||||||
|
has_media: peerHasMedia,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Send join success status */
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
type: "join_status",
|
||||||
|
status: "Joined",
|
||||||
|
message: "Successfully joined"
|
||||||
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
const part = (peers: any, session: any): void => {
|
const part = (peers: any, session: any): void => {
|
||||||
@ -3483,13 +3557,19 @@ const part = (peers: any, session: any): void => {
|
|||||||
peers[peer].ws.send(
|
peers[peer].ws.send(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
type: "removePeer",
|
type: "removePeer",
|
||||||
data: { peer_id: session.name },
|
data: {
|
||||||
|
peer_id: session.name,
|
||||||
|
peer_name: session.name
|
||||||
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
ws.send(
|
ws.send(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
type: "removePeer",
|
type: "removePeer",
|
||||||
data: { peer_id: session.name },
|
data: {
|
||||||
|
peer_id: peer,
|
||||||
|
peer_name: peer
|
||||||
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -3856,6 +3936,49 @@ const getFilteredPlayers = (game: any): Record<string, any> => {
|
|||||||
return filtered;
|
return filtered;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get participants list for the game room
|
||||||
|
* Uses the reusable room helper and adds game-specific data (color)
|
||||||
|
*
|
||||||
|
* This demonstrates how to extend the base participant list with app-specific data
|
||||||
|
*/
|
||||||
|
const getParticipants = (game: any): any[] => {
|
||||||
|
// Use the reusable room helper for base participant data
|
||||||
|
// If you were using the new architecture, this would be:
|
||||||
|
// import { getParticipants as getBaseParticipants } from './room/helpers';
|
||||||
|
// const baseParticipants = getBaseParticipants(game.sessions);
|
||||||
|
|
||||||
|
const participants: any[] = [];
|
||||||
|
for (let id in game.sessions) {
|
||||||
|
const session = game.sessions[id];
|
||||||
|
if (!session) continue;
|
||||||
|
|
||||||
|
// Base participant data (reusable across any application)
|
||||||
|
const baseParticipant = {
|
||||||
|
name: session.name || null,
|
||||||
|
session_id: session.id,
|
||||||
|
live: session.live || false,
|
||||||
|
protected: session.protected || false,
|
||||||
|
has_media: session.has_media !== false,
|
||||||
|
bot_run_id: session.bot_run_id || null,
|
||||||
|
bot_provider_id: session.bot_provider_id || null,
|
||||||
|
bot_instance_id: session.bot_instance_id || null,
|
||||||
|
muted: session.muted || false,
|
||||||
|
video_on: session.video_on !== false,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Game-specific data (in metadata layer)
|
||||||
|
// This is the ONLY game-specific code in this function
|
||||||
|
const gameSpecific = {
|
||||||
|
color: session.color || null, // Game-specific: player color
|
||||||
|
// In the new architecture, this would be: session.metadata?.color
|
||||||
|
};
|
||||||
|
|
||||||
|
participants.push({ ...baseParticipant, ...gameSpecific });
|
||||||
|
}
|
||||||
|
return participants;
|
||||||
|
};
|
||||||
|
|
||||||
const calculatePoints = (game: any, update: any): void => {
|
const calculatePoints = (game: any, update: any): void => {
|
||||||
if (game.state === "winner") {
|
if (game.state === "winner") {
|
||||||
return;
|
return;
|
||||||
@ -4225,6 +4348,16 @@ router.ws("/ws/:id", async (ws, req) => {
|
|||||||
// If there was a previous websocket and it's a different object, try to
|
// If there was a previous websocket and it's a different object, try to
|
||||||
// close it to avoid stale sockets lingering in memory.
|
// close it to avoid stale sockets lingering in memory.
|
||||||
if (previousWs && previousWs !== ws) {
|
if (previousWs && previousWs !== ws) {
|
||||||
|
// Clean up peer from audio registry before replacing WebSocket
|
||||||
|
if (gameId in audio) {
|
||||||
|
try {
|
||||||
|
part(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
previousWs.close();
|
previousWs.close();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -4282,7 +4415,11 @@ router.ws("/ws/:id", async (ws, req) => {
|
|||||||
|
|
||||||
message = JSON.stringify({
|
message = JSON.stringify({
|
||||||
type: "iceCandidate",
|
type: "iceCandidate",
|
||||||
data: { peer_id: getName(session), candidate: candidate },
|
data: {
|
||||||
|
peer_id: getName(session),
|
||||||
|
peer_name: getName(session),
|
||||||
|
candidate: candidate
|
||||||
|
},
|
||||||
}) as any;
|
}) as any;
|
||||||
|
|
||||||
if (peer_id in audio[gameId]) {
|
if (peer_id in audio[gameId]) {
|
||||||
@ -4312,7 +4449,11 @@ router.ws("/ws/:id", async (ws, req) => {
|
|||||||
);
|
);
|
||||||
message = JSON.stringify({
|
message = JSON.stringify({
|
||||||
type: "sessionDescription",
|
type: "sessionDescription",
|
||||||
data: { peer_id: getName(session), session_description: session_description },
|
data: {
|
||||||
|
peer_id: getName(session),
|
||||||
|
peer_name: getName(session),
|
||||||
|
session_description: session_description
|
||||||
|
},
|
||||||
}) as any;
|
}) as any;
|
||||||
if (peer_id in audio[gameId]) {
|
if (peer_id in audio[gameId]) {
|
||||||
try {
|
try {
|
||||||
@ -4350,7 +4491,12 @@ router.ws("/ws/:id", async (ws, req) => {
|
|||||||
|
|
||||||
const messagePayload = JSON.stringify({
|
const messagePayload = JSON.stringify({
|
||||||
type: "peer_state_update",
|
type: "peer_state_update",
|
||||||
data: { peer_id: session.name, muted, video_on },
|
data: {
|
||||||
|
peer_id: session.name,
|
||||||
|
peer_name: session.name,
|
||||||
|
muted,
|
||||||
|
video_on
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// Send to all other peers
|
// Send to all other peers
|
||||||
@ -4488,6 +4634,9 @@ router.ws("/ws/:id", async (ws, req) => {
|
|||||||
case "players":
|
case "players":
|
||||||
batchedUpdate.players = getFilteredPlayers(game);
|
batchedUpdate.players = getFilteredPlayers(game);
|
||||||
break;
|
break;
|
||||||
|
case "participants":
|
||||||
|
batchedUpdate.participants = getParticipants(game);
|
||||||
|
break;
|
||||||
case "color":
|
case "color":
|
||||||
console.log(`${session.id}: -> Returning color as ${session.color} for ${getName(session)}`);
|
console.log(`${session.id}: -> Returning color as ${session.color} for ${getName(session)}`);
|
||||||
batchedUpdate.color = session.color;
|
batchedUpdate.color = session.color;
|
||||||
@ -4771,6 +4920,7 @@ router.ws("/ws/:id", async (ws, req) => {
|
|||||||
if (session.name) {
|
if (session.name) {
|
||||||
sendUpdateToPlayers(game, {
|
sendUpdateToPlayers(game, {
|
||||||
players: getFilteredPlayers(game),
|
players: getFilteredPlayers(game),
|
||||||
|
participants: getParticipants(game),
|
||||||
unselected: getFilteredUnselected(game),
|
unselected: getFilteredUnselected(game),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -5326,7 +5476,13 @@ router.get("/", (req, res /*, next*/) => {
|
|||||||
|
|
||||||
// Mark this response as coming from the backend API to aid debugging
|
// Mark this response as coming from the backend API to aid debugging
|
||||||
res.setHeader("X-Backend", "games");
|
res.setHeader("X-Backend", "games");
|
||||||
return res.status(200).send({ player: playerId });
|
return res.status(200).send({
|
||||||
|
id: playerId,
|
||||||
|
player: playerId,
|
||||||
|
name: null,
|
||||||
|
lobbies: [],
|
||||||
|
has_media: true // Default to true for regular users
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
router.post("/:id?", async (req, res /*, next*/) => {
|
router.post("/:id?", async (req, res /*, next*/) => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user