Implement main game mechanic
This commit is contained in:
117
client/src/common/contexts/SocketContext.jsx
Normal file
117
client/src/common/contexts/SocketContext.jsx
Normal file
@ -0,0 +1,117 @@
|
||||
import { createContext, useState, useEffect, useCallback, useRef } from 'react';
|
||||
import { io } from 'socket.io-client';
|
||||
|
||||
export const SocketContext = createContext();
|
||||
|
||||
export const SocketProvider = ({ children }) => {
|
||||
const [socket, setSocket] = useState(null);
|
||||
const [connected, setConnected] = useState(false);
|
||||
const connectAttempts = useRef(0);
|
||||
const maxAttempts = 3;
|
||||
const reconnectDelay = 2000; // ms
|
||||
|
||||
// Connect to socket server
|
||||
const connect = useCallback(() => {
|
||||
if (socket) return;
|
||||
|
||||
// Determine server URL based on environment
|
||||
const serverUrl = process.env.NODE_ENV === 'production'
|
||||
? window.location.origin
|
||||
: 'http://localhost:5287';
|
||||
|
||||
try {
|
||||
const newSocket = io(serverUrl, {
|
||||
reconnectionAttempts: 3,
|
||||
timeout: 10000,
|
||||
reconnectionDelay: 1000
|
||||
});
|
||||
|
||||
newSocket.on('connect', () => {
|
||||
console.log('Socket connected with ID:', newSocket.id);
|
||||
setConnected(true);
|
||||
connectAttempts.current = 0;
|
||||
|
||||
// Store player ID in localStorage for persistence
|
||||
localStorage.setItem('playerId', newSocket.id);
|
||||
});
|
||||
|
||||
newSocket.on('disconnect', (reason) => {
|
||||
console.log('Socket disconnected:', reason);
|
||||
setConnected(false);
|
||||
});
|
||||
|
||||
newSocket.on('connect_error', (error) => {
|
||||
console.error('Connection error:', error);
|
||||
connectAttempts.current += 1;
|
||||
|
||||
if (connectAttempts.current >= maxAttempts) {
|
||||
console.error('Max connection attempts reached, giving up');
|
||||
newSocket.disconnect();
|
||||
}
|
||||
});
|
||||
|
||||
setSocket(newSocket);
|
||||
} catch (err) {
|
||||
console.error('Error creating socket connection:', err);
|
||||
}
|
||||
}, [socket]);
|
||||
|
||||
// Disconnect socket
|
||||
const disconnect = useCallback(() => {
|
||||
if (socket) {
|
||||
socket.disconnect();
|
||||
setSocket(null);
|
||||
setConnected(false);
|
||||
console.log('Socket manually disconnected');
|
||||
}
|
||||
}, [socket]);
|
||||
|
||||
// Send event through socket
|
||||
const send = useCallback((event, data) => {
|
||||
if (!socket || !connected) {
|
||||
console.warn(`Cannot send event "${event}": socket not connected`);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
socket.emit(event, data);
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.error(`Error sending event "${event}":`, err);
|
||||
return false;
|
||||
}
|
||||
}, [socket, connected]);
|
||||
|
||||
// Register event listener
|
||||
const on = useCallback((event, callback) => {
|
||||
if (!socket) {
|
||||
console.warn(`Cannot listen for event "${event}": socket not initialized`);
|
||||
return () => {};
|
||||
}
|
||||
|
||||
socket.on(event, callback);
|
||||
return () => socket.off(event, callback);
|
||||
}, [socket]);
|
||||
|
||||
// Clean up socket on component unmount
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (socket) {
|
||||
socket.disconnect();
|
||||
}
|
||||
};
|
||||
}, [socket]);
|
||||
|
||||
return (
|
||||
<SocketContext.Provider value={{
|
||||
socket,
|
||||
connected,
|
||||
connect,
|
||||
disconnect,
|
||||
send,
|
||||
on
|
||||
}}>
|
||||
{children}
|
||||
</SocketContext.Provider>
|
||||
);
|
||||
};
|
Reference in New Issue
Block a user