-
Notifications
You must be signed in to change notification settings - Fork 61
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
Merged
Merged
Changes from 1 commit
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,46 +1,305 @@ | ||
| # Netplay | ||
| # EmulatorJS Netplay Server Setup Guide | ||
|
|
||
| The old version of netplay that works versions prior to 4.0 (version 3.0) is really buggy and not recommended unless you need to. | ||
| Step-by-step instructions to set up your own EmulatorJS netplay server. | ||
|
|
||
| ::alert{type="danger"} | ||
| ::list{type="danger"} | ||
| - Netplay is currently **not supported**. Any bugs will not be fixed. A netplay re-write is being worked on. | ||
| :: | ||
| :: | ||
| ## Prerequisites | ||
|
|
||
| ## To add to your site | ||
| Before beginning, ensure you have **Node.js** installed on your system: | ||
|
|
||
| 1. Set a game id in the javascript config | ||
| ```js | ||
| EJS_gameID = 1; //Id needs to be unique per game in your website! | ||
| ``` | ||
| 1. Visit the [official Node.js website](https://nodejs.org/) | ||
| 2. Download the **LTS (Long-Term Support)** version for your operating system | ||
| 3. Run the installer and accept the default settings | ||
|
|
||
| 2. At the moment, netplay requires the old cores. To do this you must add this line to your code. | ||
| ```js | ||
| EJS_oldCores = true; | ||
| ``` | ||
| ## Server Implementation | ||
|
|
||
| **These 2 steps will add netplay to your website!** | ||
| ### Server Code | ||
|
|
||
| ## To host your own server: | ||
| 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}`)); | ||
| ``` | ||
|
|
||
| You can then set your netplay server with the `EJS_netplayUrl` setting. | ||
| ```js | ||
| EJS_netplayUrl = "URL HERE"; | ||
| ## Installation Instructions | ||
|
|
||
| ### Windows Setup | ||
|
|
||
| 1. **Create Server Directory** | ||
| - Create a new folder in an easily accessible location `(Example: D:\)` | ||
| - Name it something meaningful like `MyNetplayServer` | ||
|
|
||
| 2. **Create Server File** | ||
| - Right-click inside the folder → **New** → **Text Document** | ||
| - Rename the file to `server.js` (ensure you change the `.txt` extension) | ||
| - Open the file with a text editor and paste the server code above | ||
| - Save and close the file | ||
|
|
||
| 3. **Open Command Prompt** | ||
| - In the folder's address bar, type `cmd` and press **Enter** | ||
| - This opens Command Prompt in the correct directory | ||
|
|
||
| 4. **Install Dependencies** | ||
| ```bash | ||
| npm install express socket.io cors | ||
| ``` | ||
|
|
||
| 5. **Start the Server** | ||
| ```bash | ||
| node server.js | ||
| ``` | ||
|
|
||
| **Success message:** `Netplay server running on port 3000` | ||
|
|
||
| ### Linux Setup | ||
|
|
||
| 1. **Create Server Directory** | ||
| ```bash | ||
| mkdir MyNetplayServer && cd MyNetplayServer | ||
| ``` | ||
|
|
||
| 2. **Create Server File** | ||
| ```bash | ||
| nano server.js | ||
| ``` | ||
| - Paste the server code into the editor | ||
| - Press **Ctrl+X**, then **Y**, then **Enter** to save and exit | ||
|
|
||
| 3. **Install Dependencies** | ||
| ```bash | ||
| npm install express socket.io cors | ||
| ``` | ||
|
|
||
| 4. **Start the Server** | ||
| ```bash | ||
| node server.js | ||
| ``` | ||
|
|
||
| **Success message:** `Netplay server running on port 3000` | ||
|
|
||
| ## Website Integration | ||
|
|
||
| ### In your javascript config file | ||
|
|
||
| 1. **Set Unique Game ID** | ||
| ```javascript | ||
| EJS_gameID = 1; // Must be unique per game on your website | ||
| ``` | ||
|
|
||
| 2. **Configure Server Settings** | ||
| ```javascript | ||
| EJS_netplayServer: 'https://yourIP:port#', | ||
| EJS_netplayICEServers: [ | ||
| { urls: 'stun:stun.l.google.com:19302' }, | ||
| { urls: 'stun:stun1.l.google.com:19302' }, | ||
| { urls: 'stun:stun2.l.google.com:19302' }, | ||
| { urls: 'stun:stun.nextcloud.com:3478' }, | ||
| { urls: 'turn:openrelay.metered.ca:80', username: 'openrelayproject', credential: 'openrelayproject' }, | ||
| { urls: 'turn:openrelay.metered.ca:443', username: 'openrelayproject', credential: 'openrelayproject' } | ||
| ] | ||
| ``` | ||
|
|
||
| > **Note:** Add or remove ICE servers as needed for your specific requirements. | ||
| ## Network Configuration | ||
|
|
||
| To make your server accessible to friends over the internet, you need to configure both your firewall and router. | ||
|
|
||
| ### Firewall Configuration | ||
|
|
||
| #### Windows | ||
| 1. Search for **"Windows Defender Firewall with Advanced Security"** | ||
| 2. Navigate to **"Inbound Rules"** | ||
| 3. Click **"New Rule..."** | ||
| 4. Select **"Port"** and follow prompts to allow TCP traffic for port **3000** | ||
|
|
||
| #### Linux (using ufw) | ||
| ```bash | ||
| sudo ufw allow 3000/tcp | ||
| ``` | ||
| <!-- EJS_netplayServer --> | ||
|
|
||
| ### Port Forwarding | ||
|
|
||
| 1. **Find Your Local IP Address** | ||
| - **Windows:** Run `ipconfig` in Command Prompt, look for "IPv4 Address" (e.g., `192.168.1.15`) | ||
| - **Linux:** Run `hostname -I` in terminal | ||
|
|
||
| 2. **Access Router Admin Panel** | ||
| - Open web browser and navigate to router admin page (typically `192.168.1.1` or `192.168.0.1`) | ||
|
|
||
| 3. **Configure Port Forwarding** | ||
| - Locate **"Port Forwarding"** or **"Virtual Server"** section | ||
| - Create new rule with these settings: | ||
| - **Application Name:** Netplay Server | ||
| - **External/Start Port:** 3000 | ||
| - **Internal/End Port:** 3000 | ||
| - **Protocol:** TCP | ||
| - **Device IP:** Your computer's local IP address | ||
| - Save the configuration | ||
|
|
||
| ## Sharing Your Server | ||
|
|
||
| To allow friends to connect: | ||
S-Coding23 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| 1. **Find Your Public IP** | ||
| - Google search: "what is my IP" | ||
| - Copy the displayed IP address | ||
|
|
||
| 2. **Share Connection Details** | ||
| - Format: `[Your Public IP]:3000` | ||
| - Example: `123.45.67.89:3000` | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| - Ensure Node.js is properly installed | ||
| - Verify firewall rules are correctly configured | ||
| - Check that port forwarding is properly set up on your router | ||
| - Confirm your public IP address is current as it likely rotates | ||
| - Make sure the server is running before attempting connections | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.