works eventually, still shaky

This commit is contained in:
2026-02-23 15:13:16 -07:00
parent ffb0d9075b
commit 9dc6e9749c
6 changed files with 178 additions and 316 deletions

View File

@@ -11,106 +11,86 @@ interface GameState {
[playerId: string]: Player;
}
// List of WebSocket servers - we'll connect to all of them
const WS_SERVERS = [
"ws://localhost:4001/socket",
"ws://localhost:4002/socket",
"ws://localhost:4003/socket",
];
// Connect to nginx load balancer
const WS_SERVER = "ws://localhost:4000/socket";
function App() {
const [players, setPlayers] = useState<GameState>({});
const [myPlayerId, setMyPlayerId] = useState<string | null>(null);
const [connectionStatus, setConnectionStatus] =
useState<string>("connecting");
const socketsRef = useRef<Socket[]>([]);
const channelsRef = useRef<Channel[]>([]);
const socketRef = useRef<Socket | null>(null);
const channelRef = useRef<Channel | null>(null);
const keysPressed = useRef<Set<string>>(new Set());
useEffect(() => {
// Connect to all servers concurrently
const sockets = WS_SERVERS.map((serverUrl) => {
console.log(`Connecting to ${serverUrl}`);
// Connect to nginx load balancer
console.log(`Connecting to ${WS_SERVER}`);
const socket = new Socket(serverUrl, {
timeout: 3000,
reconnectAfterMs: () => 2000, // Keep trying to reconnect
});
// Handle connection events
socket.onOpen(() => {
console.log(`✓ Connected to ${serverUrl}`);
updateConnectionStatus();
});
socket.onError((error) => {
console.error(`✗ Error on ${serverUrl}:`, error);
updateConnectionStatus();
});
socket.onClose(() => {
console.log(`✗ Disconnected from ${serverUrl}`);
updateConnectionStatus();
});
socket.connect();
return socket;
const socket = new Socket(WS_SERVER, {
timeout: 3000,
reconnectAfterMs: (tries) =>
[1000, 2000, 5000, 10000][tries - 1] || 10000,
});
socketsRef.current = sockets;
socket.onOpen(() => {
console.log(`✓ Connected to load balancer`);
setConnectionStatus("Connected");
});
// Join game channel on all connected sockets
const channels = sockets.map((socket, index) => {
const channel = socket.channel("game:lobby", {});
socket.onError((error) => {
console.error(`✗ Connection error:`, error);
setConnectionStatus("Connection error");
});
channel
.join()
.receive("ok", () => {
console.log(`✓ Joined channel on ${WS_SERVERS[index]}`);
updateConnectionStatus();
})
.receive("error", (resp) => {
console.log(`✗ Failed to join on ${WS_SERVERS[index]}:`, resp);
})
.receive("timeout", () => {
console.log(`✗ Timeout joining on ${WS_SERVERS[index]}`);
});
socket.onClose(() => {
console.log(`✗ Disconnected from load balancer`);
setConnectionStatus("Disconnected - reconnecting...");
});
// Listen for game state updates from any server
channel.on("game_state", (payload: { players: GameState }) => {
setPlayers(payload.players);
socket.connect();
socketRef.current = socket;
// Set our player ID from the first state update if not set
if (!myPlayerId && Object.keys(payload.players).length > 0) {
const playerIds = Object.keys(payload.players);
if (playerIds.length > 0) {
setMyPlayerId(playerIds[playerIds.length - 1]);
}
// Join game channel
const channel = socket.channel("game:lobby", {});
channel
.join()
.receive("ok", () => {
console.log(`✓ Joined game channel`);
setConnectionStatus("Connected & playing");
})
.receive("error", (resp) => {
console.log(`✗ Failed to join:`, resp);
setConnectionStatus("Failed to join game");
})
.receive("timeout", () => {
console.log(`✗ Timeout joining`);
setConnectionStatus("Connection timeout");
});
// Listen for game state updates
channel.on("game_state", (payload: { players: GameState }) => {
setPlayers(payload.players);
if (!myPlayerId && Object.keys(payload.players).length > 0) {
const playerIds = Object.keys(payload.players);
if (playerIds.length > 0) {
setMyPlayerId(playerIds[playerIds.length - 1]);
}
});
return channel;
}
});
channelsRef.current = channels;
const updateConnectionStatus = () => {
const joined = channels.filter((c) => c.state === "joined").length;
setConnectionStatus(`${joined}/${WS_SERVERS.length} servers active`);
};
// Periodic status update
const statusInterval = setInterval(updateConnectionStatus, 1000);
channelRef.current = channel;
// Cleanup on unmount
return () => {
clearInterval(statusInterval);
channels.forEach((channel) => channel.leave());
sockets.forEach((socket) => socket.disconnect());
channel.leave();
socket.disconnect();
};
}, [myPlayerId]);
// Handle keyboard input - send to first available channel
// Handle keyboard input - send to active channel
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
const key = e.key.toLowerCase();
@@ -121,11 +101,9 @@ function App() {
if (!keysPressed.current.has(key)) {
keysPressed.current.add(key);
// Send to first joined channel (they all share same game state)
const activeChannel = channelsRef.current.find(
(c) => c.state === "joined",
);
if (activeChannel) {
// Send to active channel
const activeChannel = channelRef.current;
if (activeChannel && activeChannel.state === "joined") {
activeChannel.push("move", { direction: key });
}
}