-
Notifications
You must be signed in to change notification settings - Fork 48
Update 9.netplay.md #68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Updated Netplay setup guide
✅ Deploy Preview for emulatorjs-org ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
This will be used later: | ||
|
||
1. Clone the EmulatorJS-netplay repository | ||
```sh | ||
git clone https://github.com/EmulatorJS/EmulatorJS-netplay-old.git | ||
``` | ||
```javascript | ||
const express = require('express'); | ||
const http = require('http'); | ||
const socketIo = require('socket.io'); | ||
const cors = require('cors'); | ||
|
||
2. Install nodejs dependencies | ||
```sh | ||
npm install | ||
``` | ||
const app = express(); | ||
const server = http.createServer(app); | ||
|
||
// Use CORS to allow connections from any origin | ||
app.use(cors()); | ||
|
||
const io = socketIo(server, { | ||
cors: { | ||
origin: "*", // Allows connections from any website or application. Update as needed. | ||
methods: ['GET', 'POST'], | ||
}, | ||
}); | ||
|
||
const PORT = 3000; // The default port for the server. Change as needed. | ||
let rooms = {}; | ||
|
||
setInterval(() => { | ||
for (const sessionId in rooms) { | ||
if (Object.keys(rooms[sessionId].players).length === 0) { | ||
delete rooms[sessionId]; | ||
console.log(`Cleaned up empty room ${sessionId}`); | ||
} | ||
} | ||
}, 60000); | ||
|
||
io.on('connection', (socket) => { | ||
console.log(`User connected: ${socket.id}`); | ||
|
||
socket.on('open-room', (data, callback) => { | ||
const { sessionid: sessionId, userid: playerId, room_name: roomName, game_id: gameId, player_name: playerName = 'Unknown' } = data.extra || {}; | ||
const maxPlayers = data.maxPlayers || 4; | ||
const roomPassword = data.password || null; | ||
|
||
if (!sessionId || !playerId) { | ||
return callback ? callback('Invalid data: sessionId and playerId required') : null; | ||
} | ||
if (rooms[sessionId]) { | ||
return callback ? callback('Room already exists') : null; | ||
} | ||
|
||
rooms[sessionId] = { | ||
owner: socket.id, | ||
players: { [playerId]: { ...data.extra, socketId: socket.id } }, | ||
roomName: roomName || `Room ${sessionId}`, | ||
gameId: gameId || 'default', | ||
password: roomPassword, | ||
maxPlayers: maxPlayers, | ||
}; | ||
|
||
socket.join(sessionId); | ||
socket.sessionId = sessionId; | ||
socket.playerId = playerId; | ||
|
||
console.log(`Room "${roomName}" (${sessionId}) created by ${playerName}.`); | ||
io.to(sessionId).emit('users-updated', rooms[sessionId].players); | ||
if (callback) callback(null); | ||
}); | ||
|
||
socket.on('join-room', (data, callback) => { | ||
const { sessionid: sessionId, userid: playerId, player_name: playerName = 'Unknown' } = data.extra || {}; | ||
|
||
if (!sessionId || !playerId) { | ||
return callback ? callback('Invalid data: sessionId and playerId required') : null; | ||
} | ||
|
||
3. start the server | ||
```sh | ||
npm run start | ||
const room = rooms[sessionId]; | ||
if (!room) { | ||
return callback ? callback('Room not found') : null; | ||
} | ||
if (room.password && room.password !== data.password) { | ||
return callback ? callback('Incorrect password') : null; | ||
} | ||
if (Object.keys(room.players).length >= room.maxPlayers) { | ||
return callback ? callback('Room full') : null; | ||
} | ||
|
||
room.players[playerId] = { ...data.extra, socketId: socket.id }; | ||
socket.join(sessionId); | ||
socket.sessionId = sessionId; | ||
socket.playerId = playerId; | ||
|
||
console.log(`${playerName} joined room "${room.roomName}" (${sessionId})`); | ||
io.to(sessionId).emit('users-updated', room.players); | ||
if (callback) callback(null, room.players); | ||
}); | ||
|
||
socket.on('leave-room', () => { | ||
handleDisconnect(socket); | ||
}); | ||
|
||
socket.on('disconnect', () => { | ||
handleDisconnect(socket); | ||
console.log(`User disconnected: ${socket.id}`); | ||
}); | ||
|
||
// Forwarding game and WebRTC data | ||
socket.on('webrtc-signal', (data) => { | ||
if (data.target) { | ||
io.to(data.target).emit('webrtc-signal', { ...data, sender: socket.id }); | ||
} | ||
}); | ||
|
||
socket.on('data-message', (data) => { | ||
if (socket.sessionId) { | ||
socket.to(socket.sessionId).emit('data-message', data); | ||
} | ||
}); | ||
|
||
socket.on('snapshot', (data) => { | ||
if (socket.sessionId) { | ||
socket.to(socket.sessionId).emit('snapshot', data); | ||
} | ||
}); | ||
|
||
socket.on('input', (data) => { | ||
if (socket.sessionId) { | ||
socket.to(socket.sessionId).emit('input', data); | ||
} | ||
}); | ||
}); | ||
|
||
function handleDisconnect(socket) { | ||
const { sessionId, playerId } = socket; | ||
if (sessionId && playerId && rooms[sessionId]) { | ||
const room = rooms[sessionId]; | ||
console.log(`Player ${playerId} left room ${sessionId}`); | ||
delete room.players[playerId]; | ||
|
||
if (Object.keys(room.players).length === 0) { | ||
delete rooms[sessionId]; | ||
console.log(`Room ${sessionId} closed - no players left`); | ||
} else { | ||
// If the owner left, assign a new owner | ||
if (socket.id === room.owner) { | ||
const newOwnerPlayerId = Object.keys(room.players)[0]; | ||
room.owner = room.players[newOwnerPlayerId].socketId; | ||
console.log(`New owner for room ${sessionId}: ${room.owner}`); | ||
} | ||
io.to(sessionId).emit('users-updated', room.players); | ||
} | ||
} | ||
} | ||
|
||
server.listen(PORT, '0.0.0.0', () => console.log(`Netplay server running on port ${PORT}`)); | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should paste this in here - or walk the user through installing dependencies manually. Could we go the route of cloning the repository (is the repository updated?) oh is it even public
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not believe its public, no. But we can make it public then go that route.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you send the link?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've made it public, you should be able to push to master I think
|
||
## Sharing Your Server | ||
|
||
To allow friends to connect: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we note this requires port forwarding
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It already does
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The "Sharing Your Server" has a bigger section header than the above "Port Forwarding" section header - I do believe this implies to the reader that these are different things
Updated Netplay setup guide