Fixing dulicate calls
This commit is contained in:
parent
4218177bc7
commit
0d1024ff61
@ -20,9 +20,9 @@
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
width: 5rem;
|
width: 5rem;
|
||||||
min-width: 5rem;
|
|
||||||
height: 3.75rem;
|
height: 3.75rem;
|
||||||
min-height: 3.75rem;
|
min-height: 3.75rem;
|
||||||
|
min-width: 5rem;
|
||||||
background-color: #444;
|
background-color: #444;
|
||||||
border-radius: 0.25rem;
|
border-radius: 0.25rem;
|
||||||
border: 2px dashed #666; /* Visual indicator for drop zone */
|
border: 2px dashed #666; /* Visual indicator for drop zone */
|
||||||
@ -31,8 +31,8 @@
|
|||||||
.MediaControlSpacer.Medium {
|
.MediaControlSpacer.Medium {
|
||||||
width: 11.5em;
|
width: 11.5em;
|
||||||
height: 8.625em;
|
height: 8.625em;
|
||||||
min-width: 11.5em;
|
/* min-width: 11.5em;
|
||||||
min-height: 8.625em;
|
min-height: 8.625em; */
|
||||||
}
|
}
|
||||||
|
|
||||||
.MediaControl {
|
.MediaControl {
|
||||||
@ -42,8 +42,8 @@
|
|||||||
left: 0; /* Start at left of container */
|
left: 0; /* Start at left of container */
|
||||||
width: 5rem;
|
width: 5rem;
|
||||||
height: 3.75rem;
|
height: 3.75rem;
|
||||||
min-width: 5rem;
|
min-width: 1.25rem;
|
||||||
min-height: 3.75rem;
|
min-height: 0.9375rem;
|
||||||
z-index: 1200;
|
z-index: 1200;
|
||||||
border-radius: 0.25rem;
|
border-radius: 0.25rem;
|
||||||
}
|
}
|
||||||
@ -63,8 +63,8 @@
|
|||||||
.MediaControl.Medium {
|
.MediaControl.Medium {
|
||||||
width: 11.5em;
|
width: 11.5em;
|
||||||
height: 8.625em;
|
height: 8.625em;
|
||||||
min-width: 11.5em;
|
/* min-width: 11.5em;
|
||||||
min-height: 8.625em;
|
min-height: 8.625em; */
|
||||||
}
|
}
|
||||||
|
|
||||||
.MediaControl .Controls {
|
.MediaControl .Controls {
|
||||||
|
@ -193,15 +193,10 @@ const PlayerList: React.FC = () => {
|
|||||||
<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) => (
|
||||||
{ label: "Orange", value: "orange" },
|
<Box
|
||||||
{ label: "Red", value: "red" },
|
key={c}
|
||||||
{ label: "White", value: "white" },
|
sx={{
|
||||||
{ label: "Blue", value: "blue" },
|
|
||||||
].map((c) => (
|
|
||||||
<button
|
|
||||||
key={c.value}
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
gap: 8,
|
gap: 8,
|
||||||
@ -213,12 +208,11 @@ const PlayerList: React.FC = () => {
|
|||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (!sendJsonMessage) return;
|
if (!sendJsonMessage) return;
|
||||||
sendJsonMessage({ type: "set", field: "color", value: c.value });
|
sendJsonMessage({ type: "set", field: "color", value: c[0].toUpperCase() });
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<PlayerColor color={c.value} />
|
<PlayerColor color={c} />
|
||||||
<div style={{ fontSize: "0.9em" }}>{c.label}</div>
|
</Box>
|
||||||
</button>
|
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -93,7 +93,6 @@
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
width: 25rem;
|
width: 25rem;
|
||||||
max-width: 25rem;
|
max-width: 25rem;
|
||||||
overflow: hidden;
|
|
||||||
z-index: 5000;
|
z-index: 5000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +99,9 @@ const processTies = (players: Player[]): boolean => {
|
|||||||
const rev = slots.slice().reverse();
|
const rev = slots.slice().reverse();
|
||||||
for (const slot of rev) {
|
for (const slot of rev) {
|
||||||
const s = slot || [];
|
const s = slot || [];
|
||||||
if (s.length !== 1) {
|
// Only consider actual populated slots. Empty slots (holes) should be skipped.
|
||||||
|
if (s.length > 1) {
|
||||||
|
// real tie among multiple players in this slot
|
||||||
ties = true;
|
ties = true;
|
||||||
s.forEach((player: Player) => {
|
s.forEach((player: Player) => {
|
||||||
player.orderRoll = 0; /* Ties have to be re-rolled */
|
player.orderRoll = 0; /* Ties have to be re-rolled */
|
||||||
@ -107,12 +109,17 @@ const processTies = (players: Player[]): boolean => {
|
|||||||
player.orderStatus = `Tied for ${irstify(position)}`;
|
player.orderStatus = `Tied for ${irstify(position)}`;
|
||||||
player.tied = true;
|
player.tied = true;
|
||||||
});
|
});
|
||||||
} else if (s[0]) {
|
position += s.length;
|
||||||
|
} else if (s.length === 1 && s[0]) {
|
||||||
|
// single player in this slot - clear tie and record position
|
||||||
s[0].tied = false;
|
s[0].tied = false;
|
||||||
s[0].position = irstify(position);
|
s[0].position = irstify(position);
|
||||||
s[0].orderStatus = `Placed in ${irstify(position)}.`;
|
s[0].orderStatus = `Placed in ${irstify(position)}.`;
|
||||||
|
position += 1;
|
||||||
|
} else {
|
||||||
|
// empty slot - skip
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
position += s.length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ties;
|
return ties;
|
||||||
@ -155,10 +162,16 @@ const processGameOrder = (game: Game, player: Player, dice: number): any => {
|
|||||||
return B.order - A.order;
|
return B.order - A.order;
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`Pre process ties: `, players);
|
console.log(
|
||||||
|
`${info}: Pre process ties: `,
|
||||||
|
players.reduce((acc, p) => ({ ...acc, [p.color as string]: p.orderRoll }), {})
|
||||||
|
);
|
||||||
|
|
||||||
if (processTies(players)) {
|
if (processTies(players)) {
|
||||||
console.log(`${info}: There are ties in player rolls:`, players);
|
console.log(
|
||||||
|
`${info}: There are ties in player rolls:`,
|
||||||
|
players.reduce((acc, p) => ({ ...acc, [p.color as string]: p.orderRoll }), {})
|
||||||
|
);
|
||||||
sendUpdateToPlayers(game, {
|
sendUpdateToPlayers(game, {
|
||||||
players: getFilteredPlayers(game),
|
players: getFilteredPlayers(game),
|
||||||
chat: game.chat,
|
chat: game.chat,
|
||||||
@ -3380,14 +3393,33 @@ const ping = (session: Session) => {
|
|||||||
|
|
||||||
// Add new function to schedule recurring pings
|
// Add new function to schedule recurring pings
|
||||||
const schedulePing = (session: Session) => {
|
const schedulePing = (session: Session) => {
|
||||||
|
// Diagnostic logging to help detect multiple intervals being created
|
||||||
|
try {
|
||||||
|
console.log(
|
||||||
|
`${session.short}: schedulePing called for ${getName(session)} - existing pingInterval? ${!!session.pingInterval}`
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
/* ignore logging errors */
|
||||||
|
}
|
||||||
|
|
||||||
if (session.pingInterval) {
|
if (session.pingInterval) {
|
||||||
clearInterval(session.pingInterval);
|
// Clear any previous interval before creating a new one
|
||||||
|
try {
|
||||||
|
clearInterval(session.pingInterval);
|
||||||
|
} catch (e) {
|
||||||
|
console.warn(`${session.short}: Failed to clear previous pingInterval:`, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send ping every 10 seconds
|
// Send ping every 10 seconds
|
||||||
session.pingInterval = setInterval(() => {
|
session.pingInterval = setInterval(() => {
|
||||||
ping(session);
|
ping(session);
|
||||||
}, 10000);
|
}, 10000);
|
||||||
|
try {
|
||||||
|
console.log(`${session.short}: pingInterval started for ${getName(session)}`);
|
||||||
|
} catch (e) {
|
||||||
|
/* ignore logging errors */
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// wsInactive not present in this refactor; no-op placeholder removed
|
// wsInactive not present in this refactor; no-op placeholder removed
|
||||||
@ -3764,6 +3796,7 @@ const sendError = (session: any, error: string): void => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const sendWarning = (session: any, warning: string): void => {
|
const sendWarning = (session: any, warning: string): void => {
|
||||||
|
console.warn(`${session.short}: Warning: ${warning}`);
|
||||||
try {
|
try {
|
||||||
session?.ws?.send(JSON.stringify({ type: "warning", warning }));
|
session?.ws?.send(JSON.stringify({ type: "warning", warning }));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -4220,6 +4253,22 @@ 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) {
|
||||||
|
// Clear any existing ping/keepAlive timers associated with the old socket
|
||||||
|
try {
|
||||||
|
if (session.pingInterval) {
|
||||||
|
clearInterval(session.pingInterval);
|
||||||
|
session.pingInterval = undefined;
|
||||||
|
console.log(`${short}: Cleared old pingInterval during reconnection for ${getName(session)}`);
|
||||||
|
}
|
||||||
|
if (session.keepAlive) {
|
||||||
|
clearTimeout(session.keepAlive);
|
||||||
|
session.keepAlive = undefined;
|
||||||
|
console.log(`${short}: Cleared old keepAlive during reconnection for ${getName(session)}`);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.warn(`${short}: Error clearing old timers during reconnection:`, e);
|
||||||
|
}
|
||||||
|
|
||||||
// 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 {
|
||||||
@ -4249,11 +4298,10 @@ router.ws("/ws/:id", async (ws, req) => {
|
|||||||
let warning: string | void | undefined;
|
let warning: string | void | undefined;
|
||||||
let processed = true;
|
let processed = true;
|
||||||
|
|
||||||
// If this is the first time the session attached a WebSocket, or if the
|
// The initial-game snapshot is sent from the connection attach path to
|
||||||
// websocket was just replaced (reconnect), send an initial consolidated
|
// ensure it is only sent once per websocket lifecycle. Avoid sending it
|
||||||
// snapshot so clients can render deterministically without needing to
|
// here from the message handler to prevent duplicate snapshots when a
|
||||||
// wait for a flurry of incremental game-update events.
|
// client sends messages during the attach/reconnect sequence.
|
||||||
sendInitialGameSnapshot(game, session);
|
|
||||||
|
|
||||||
switch (incoming.type) {
|
switch (incoming.type) {
|
||||||
case "join":
|
case "join":
|
||||||
|
@ -15,6 +15,7 @@ export const debug = {
|
|||||||
export const all = `[ all ]`;
|
export const all = `[ all ]`;
|
||||||
export const info = `[ info ]`;
|
export const info = `[ info ]`;
|
||||||
export const todo = `[ todo ]`;
|
export const todo = `[ todo ]`;
|
||||||
|
export const warn = `[ warn ]`;
|
||||||
|
|
||||||
export const SEND_THROTTLE_MS = 50;
|
export const SEND_THROTTLE_MS = 50;
|
||||||
export const INCOMING_GET_BATCH_MS = 20;
|
export const INCOMING_GET_BATCH_MS = 20;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user