6f24cfad30
- Server: Handle unready event to set player ready state to false - Client: Ready button toggles between READY and UNREADY - Client: Unready sends unready socket event to server Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
201 lines
4.9 KiB
JavaScript
201 lines
4.9 KiB
JavaScript
// Network module - Socket.io client handling
|
|
|
|
class NetworkManager {
|
|
constructor() {
|
|
this.socket = null;
|
|
this.currentPlayerId = null;
|
|
this.isSpectator = false;
|
|
this.players = {};
|
|
this.spectators = {};
|
|
this.gameState = {};
|
|
this.listeners = {
|
|
onPlayerJoined: null,
|
|
onPlayerLeft: null,
|
|
onGameStarted: null,
|
|
onStateUpdate: null,
|
|
onGameOver: null,
|
|
onSpectatorJoined: null,
|
|
onSpectatorLeft: null,
|
|
onForcedSpectator: null
|
|
};
|
|
}
|
|
|
|
connect() {
|
|
this.socket = io();
|
|
|
|
this.socket.on('connect', () => {
|
|
console.log('Connected to server');
|
|
this.currentPlayerId = this.socket.id;
|
|
});
|
|
|
|
this.socket.on('disconnect', () => {
|
|
console.log('Disconnected from server');
|
|
});
|
|
|
|
this.socket.on('player-joined', ({ player, players }) => {
|
|
this.updatePlayers(players);
|
|
if (this.listeners.onPlayerJoined) {
|
|
this.listeners.onPlayerJoined(player);
|
|
}
|
|
});
|
|
|
|
this.socket.on('player-left', ({ playerId, players }) => {
|
|
delete this.players[playerId];
|
|
this.updatePlayers(players);
|
|
if (this.listeners.onPlayerLeft) {
|
|
this.listeners.onPlayerLeft(playerId);
|
|
}
|
|
});
|
|
|
|
this.socket.on('game-started', ({ players, states }) => {
|
|
this.updatePlayers(players);
|
|
this.updateStates(states);
|
|
if (this.listeners.onGameStarted) {
|
|
this.listeners.onGameStarted(players, states);
|
|
}
|
|
});
|
|
|
|
this.socket.on('state-update', (states) => {
|
|
this.updateStates(states);
|
|
if (this.listeners.onStateUpdate) {
|
|
this.listeners.onStateUpdate(states);
|
|
}
|
|
});
|
|
|
|
this.socket.on('game-over', (data) => {
|
|
if (this.listeners.onGameOver) {
|
|
this.listeners.onGameOver(data);
|
|
}
|
|
});
|
|
|
|
// Forced spectator mode - game already in progress
|
|
this.socket.on('forced-spectator', ({ spectatorId, states, players }) => {
|
|
this.isSpectator = true;
|
|
this.updateStates(states);
|
|
this.updatePlayers(players);
|
|
if (this.listeners.onForcedSpectator) {
|
|
this.listeners.onForcedSpectator({ states, players });
|
|
}
|
|
});
|
|
|
|
// Spectator joined
|
|
this.socket.on('spectator-joined', ({ spectator, spectators }) => {
|
|
this.updateSpectators(spectators);
|
|
if (this.listeners.onSpectatorJoined) {
|
|
this.listeners.onSpectatorJoined(spectator);
|
|
}
|
|
});
|
|
|
|
// Spectator left
|
|
this.socket.on('spectator-left', ({ spectatorId, spectators }) => {
|
|
delete this.spectators[spectatorId];
|
|
this.updateSpectators(spectators);
|
|
if (this.listeners.onSpectatorLeft) {
|
|
this.listeners.onSpectatorLeft(spectatorId);
|
|
}
|
|
});
|
|
}
|
|
|
|
joinLobby(playerName) {
|
|
if (!this.socket) return;
|
|
this.socket.emit('join-lobby', { playerName });
|
|
}
|
|
|
|
leaveLobby() {
|
|
if (!this.socket) return;
|
|
}
|
|
|
|
ready() {
|
|
if (!this.socket) return;
|
|
this.socket.emit('ready');
|
|
}
|
|
|
|
unready() {
|
|
if (!this.socket) return;
|
|
this.socket.emit('unready');
|
|
}
|
|
|
|
sendMove(direction) {
|
|
if (!this.socket || !this.currentPlayerId) return;
|
|
this.socket.emit('player-move', { playerId: this.currentPlayerId, direction });
|
|
}
|
|
|
|
sendRotate() {
|
|
if (!this.socket || !this.currentPlayerId) return;
|
|
this.socket.emit('player-rotate', { playerId: this.currentPlayerId });
|
|
}
|
|
|
|
sendDrop() {
|
|
if (!this.socket || !this.currentPlayerId) return;
|
|
this.socket.emit('player-drop', { playerId: this.currentPlayerId, hard: false });
|
|
}
|
|
|
|
sendHardDrop() {
|
|
if (!this.socket || !this.currentPlayerId) return;
|
|
this.socket.emit('player-drop', { playerId: this.currentPlayerId, hard: true });
|
|
}
|
|
|
|
sendHold() {
|
|
if (!this.socket || !this.currentPlayerId) return;
|
|
this.socket.emit('player-hold', { playerId: this.currentPlayerId });
|
|
}
|
|
|
|
updatePlayers(players) {
|
|
this.players = {};
|
|
players.forEach(p => {
|
|
this.players[p.id] = p;
|
|
});
|
|
}
|
|
|
|
updateStates(states) {
|
|
states.forEach(s => {
|
|
this.gameState[s.playerId] = s;
|
|
});
|
|
}
|
|
|
|
updateSpectators(spectators) {
|
|
this.spectators = {};
|
|
spectators.forEach(s => {
|
|
this.spectators[s.id] = s;
|
|
});
|
|
}
|
|
|
|
getPlayer(playerId) {
|
|
return this.players[playerId];
|
|
}
|
|
|
|
getGameState(playerId) {
|
|
return this.gameState[playerId];
|
|
}
|
|
|
|
getAllPlayers() {
|
|
return this.players;
|
|
}
|
|
|
|
getAllGameStates() {
|
|
return this.gameState;
|
|
}
|
|
|
|
getAllSpectators() {
|
|
return this.spectators;
|
|
}
|
|
|
|
setListener(event, callback) {
|
|
const listenerMap = {
|
|
'player-joined': 'onPlayerJoined',
|
|
'player-left': 'onPlayerLeft',
|
|
'game-started': 'onGameStarted',
|
|
'state-update': 'onStateUpdate',
|
|
'game-over': 'onGameOver',
|
|
'forced-spectator': 'onForcedSpectator',
|
|
'spectator-joined': 'onSpectatorJoined',
|
|
'spectator-left': 'onSpectatorLeft'
|
|
};
|
|
if (callback) {
|
|
this.listeners[listenerMap[event]] = callback;
|
|
}
|
|
}
|
|
}
|
|
|
|
const network = new NetworkManager();
|