mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2025-07-04 00:36:14 +00:00
346 lines
11 KiB
JavaScript
346 lines
11 KiB
JavaScript
// Server Settings!
|
|
var map = "";
|
|
let _VERSION = "0.0.3"
|
|
let UDPExpireTime = 30// In Seconds
|
|
|
|
const net = require('net');
|
|
const uuidv4 = require('uuid/v4');
|
|
const args = require('minimist')(process.argv.slice(2));
|
|
const chalk = require("chalk")
|
|
|
|
//console.log(args.port)
|
|
if (args.port) {
|
|
var tcpport = args.port;
|
|
} else {
|
|
var tcpport = 30813;
|
|
}
|
|
|
|
var udpport = tcpport + 1;
|
|
var wsport = tcpport + 2;
|
|
const host = '0.0.0.0';
|
|
|
|
//==========================================================
|
|
// WebSocket Server
|
|
//==========================================================
|
|
|
|
const WebSocket = require('ws');
|
|
|
|
const wss = new WebSocket.Server({ port: wsport });
|
|
|
|
wss.on('connection', function connection(ws) {
|
|
ws.on('message', function incoming(message) {
|
|
console.log('[WS] received: %s', message);
|
|
wss.clients.forEach(function each(client) {
|
|
if (client.readyState === WebSocket.OPEN) {
|
|
client.send(message);
|
|
}
|
|
});
|
|
});
|
|
|
|
ws.send('Welcome!');
|
|
});
|
|
console.log(chalk.cyan('[WS]')+' Server listening on 0.0.0.0:' + wsport);
|
|
|
|
//==========================================================
|
|
// TCP Server
|
|
//==========================================================
|
|
|
|
const TCPserver = net.createServer();
|
|
TCPserver.listen(tcpport, () => {
|
|
console.log(chalk.green('[TCP]')+' Server listening on 0.0.0.0:' + tcpport);
|
|
});
|
|
|
|
let sockets = [];
|
|
let players = [];
|
|
let names = [];
|
|
let vehicles = [];
|
|
|
|
TCPserver.on('connection', function(sock) {
|
|
console.log(chalk.green('[TCP]')+' CONNECTED: ' + sock.remoteAddress + ':' + sock.remotePort);
|
|
sockets.push(sock);
|
|
|
|
var player = {};
|
|
player.remoteAddress = sock.remoteAddress;
|
|
player.remotePort = sock.remotePort;
|
|
player.nickname = "New User, Loading...";
|
|
player.id = uuidv4();
|
|
player.currentVehID = 0;
|
|
players.push(player);
|
|
|
|
sock.write('HOLA'+player.id+'\n');
|
|
if (map == "") {
|
|
sock.write("MAPS\n");
|
|
} else {
|
|
sock.write("MAPC"+map+'\n')
|
|
}
|
|
sock.write("VCHK"+_VERSION+'\n')
|
|
|
|
sock.on('data', function(data) {
|
|
// Write the data back to all the connected, the client will receive it as data from the server
|
|
var str = data.toString();
|
|
data = str.trim(); //replace(/\r?\n|\r/g, "");
|
|
var code = data.substring(0, 4);
|
|
var message = data.substr(4);
|
|
|
|
if (code != "PING") {
|
|
//console.log(code)
|
|
}
|
|
//if (data.length > 4) {
|
|
//console.log(data.length)
|
|
//}
|
|
|
|
switch (code) {
|
|
case "PING":
|
|
//console.log("Ping Received")
|
|
sock.write('PONG\n');
|
|
break;
|
|
case "CHAT":
|
|
sockets.forEach(function(socket, index, array) { // Send update to all clients
|
|
socket.write(data+'\n');
|
|
});
|
|
break;
|
|
case "MAPS":
|
|
map = message;
|
|
console.log("Setting map to: "+map);
|
|
sock.write("MAPC"+map+'\n');
|
|
break;
|
|
case "USER":
|
|
players.forEach(function(player, index, array) {
|
|
if (player.remoteAddress == sock.remoteAddress && player.remotePort == sock.remotePort) {
|
|
console.log("Player Found ("+player.id+"), setting nickname("+data.substr(4)+")");
|
|
player.nickname = ""+data.substr(4)+"";
|
|
sockets.forEach(function(socket, index, array) { // Send update to all clients
|
|
socket.write('PLST'+JSON.stringify(players)+'\n');
|
|
socket.write('SMSG'+data.substr(4)+' Just Joined the Session.\n');
|
|
});
|
|
}
|
|
});
|
|
break;
|
|
case "QUIT":
|
|
case "2001":
|
|
let index = sockets.findIndex(function(o) {
|
|
return o.remoteAddress === sock.remoteAddress && o.remotePort === sock.remotePort;
|
|
})
|
|
if (index !== -1) sockets.splice(index, 1);
|
|
console.log('CLOSED: ' + sock.remoteAddress + ' ' + sock.remotePort);
|
|
break;
|
|
case "U-VI":
|
|
case "U-VE":
|
|
case "U-VN":
|
|
case "U-VP":
|
|
case "U-VL":
|
|
case "U-VR":
|
|
case "U-VV":
|
|
//console.log(data)
|
|
//players.forEach(function(player, index, array) {
|
|
//if (player.remoteAddress != sock.remoteAddress) {
|
|
//console.log(player.remoteAddress+' != '+sock.remoteAddress+' Is not the same so we should send?')
|
|
//console.log("Got Update to send!")
|
|
sockets.forEach(function(socket, index, array) { // Send update to all clients
|
|
//console.log(socket.remotePort+' != '+sock.remotePort+' Is not the same so we should send?')
|
|
if ((sock.remoteAddress != socket.remoteAddress && sock.remotePort != socket.remotePort) || (sock.remoteAddress == socket.remoteAddress && sock.remotePort != socket.remotePort)) {
|
|
socket.write(data+'\n');
|
|
}
|
|
});
|
|
//}
|
|
//});
|
|
break;
|
|
case "U-VC":
|
|
sockets.forEach(function(socket, index, array) { // Send update to all clients
|
|
socket.write(data+'\n');
|
|
});
|
|
break;
|
|
case "U-NV":
|
|
console.log(message)
|
|
var vid = uuidv4();
|
|
|
|
break;
|
|
case "C-VS": // Client has changed vehicle. lets update our records.
|
|
console.log(message)
|
|
players.forEach(function(player, index, array) {
|
|
if (player.currentVehID != message && player.remoteAddress == sock.remoteAddress && player.remotePort == sock.remotePort) {
|
|
console.log(chalk.green('[TCP]')+" Player Found ("+player.id+"), updating current vehile("+message+")");
|
|
player.currentVehID = message;
|
|
}
|
|
});
|
|
break;
|
|
default:
|
|
console.log(chalk.green('[TCP]')+' Unknown / unhandled data from:' + sock.remoteAddress);
|
|
console.log(chalk.green('[TCP]')+' Data -> ' + data);
|
|
sockets.forEach(function(socket, index, array) { // Send update to all clients
|
|
//if ((sock.remoteAddress != socket.remoteAddress && sock.remotePort != socket.remotePort) || (sock.remoteAddress == socket.remoteAddress && sock.remotePort != socket.remotePort)) {
|
|
socket.write(data+'\n');
|
|
//}
|
|
});
|
|
break;
|
|
}
|
|
sockets.forEach(function(sock, index, array) {
|
|
//sock.write(sock.remoteAddress + ':' + sock.remotePort + " said " + data + '\n');
|
|
});
|
|
});
|
|
|
|
// Add a 'close' event handler to this instance of socket
|
|
sock.on('close', function(data) {
|
|
var index = players.findIndex(function(o) {
|
|
return o.remoteAddress === sock.remoteAddress && o.remotePort === sock.remotePort;
|
|
})
|
|
if (index !== -1) sockets.splice(index, 1);
|
|
index = sockets.findIndex(function(o) {
|
|
return o.remoteAddress === sock.remoteAddress && o.remotePort === sock.remotePort;
|
|
})
|
|
if (index !== -1) sockets.splice(index, 1);
|
|
console.log('CLOSED: ' + sock.remoteAddress + ' ' + sock.remotePort);
|
|
players = removePlayer(players, sock.remoteAddress);
|
|
console.log("Player list now holds: "+JSON.stringify(players));
|
|
sockets.forEach(function(socket, index, array) { // Send update to all clients
|
|
socket.write('PLST'+JSON.stringify(players)+'\n');
|
|
});
|
|
});
|
|
|
|
sock.on('error', (err) => {
|
|
// handle errors here
|
|
if (err.code == "ECONNRESET") {
|
|
console.error(chalk.red("ERROR ")+"Connection Reset for player: ");
|
|
players.forEach(function(player, index, array) {
|
|
if (player.remoteAddress == sock.remoteAddress && player.remotePort == sock.remotePort) {
|
|
console.error(+player.nickname+" ("+player.id+")");
|
|
console.error(chalk.red("ERROR ")+"End Error.");
|
|
}
|
|
});
|
|
} else {
|
|
console.error("Sock Error");
|
|
console.error(err);
|
|
throw err;
|
|
}
|
|
});
|
|
});
|
|
|
|
TCPserver.on('error', (err) => {
|
|
// handle errors here
|
|
console.error("TCPserver Error");
|
|
console.error(err);
|
|
throw err;
|
|
});
|
|
|
|
function removePlayer(array, ip) {
|
|
return array.filter(player => player.remoteAddress != ip);
|
|
}
|
|
|
|
//==========================================================
|
|
// UDP Server
|
|
//==========================================================
|
|
|
|
var clients = {};
|
|
var intervalTime = UDPExpireTime*2*1000;
|
|
|
|
setInterval(function() {
|
|
console.log(clients);
|
|
for (var client in clients) {
|
|
var lastupdate = clients[client];
|
|
var millis = Date.now() - lastupdate;
|
|
var t = Math.floor(millis/1000)
|
|
if (t > UDPExpireTime) {
|
|
console.warn("Found Old Client: "+client)
|
|
delete clients[client];
|
|
}
|
|
}
|
|
}, intervalTime);
|
|
|
|
function updateClient (rinfo) {
|
|
for (var client in clients) {
|
|
client = JSON.parse(client);
|
|
var address = client[0];
|
|
var port = client[1];
|
|
if (port == rinfo.port && address == rinfo.address) {
|
|
client
|
|
}
|
|
}
|
|
}
|
|
|
|
var dgram = require('dgram');
|
|
var UDPserver = dgram.createSocket('udp4');
|
|
|
|
function UDPsend(message, info) {
|
|
UDPserver.send(message, 0, message.length, info.port, info.address, function(error){
|
|
if (error) {
|
|
console.log("ERROR");
|
|
console.log(error);
|
|
client.close();
|
|
};
|
|
});
|
|
}
|
|
|
|
UDPserver.on('listening', function() {
|
|
var address = UDPserver.address();
|
|
console.log(chalk.rgb(123, 45, 67)('[UDP]')+' Server listening on ' + address.address + ':' + address.port);
|
|
});
|
|
|
|
UDPserver.on('message',function(msg,rinfo){
|
|
clients[JSON.stringify([rinfo.address, rinfo.port])] = Date.now();
|
|
//sending msg
|
|
var str = msg.toString();
|
|
data = str.trim(); //replace(/\r?\n|\r/g, "");
|
|
var code = data.substring(0, 4);
|
|
//if (code != "PING") {
|
|
//console.log(msg.toString());
|
|
//}
|
|
switch (code) {
|
|
case "PING":
|
|
UDPsend("PONG", rinfo)
|
|
break;
|
|
case "U-VC":
|
|
for (var client in clients) {
|
|
client = JSON.parse(client);
|
|
var port = client[1];
|
|
var address = client[0];
|
|
UDPserver.send(msg, 0, msg.length, port, address, function(error){
|
|
if (error) {
|
|
console.log("ERROR");
|
|
console.log(error);
|
|
client.close();
|
|
};
|
|
});
|
|
}
|
|
break;
|
|
case "U-VR":
|
|
case "U-VL":
|
|
case "U-VP":
|
|
case "U-VN":
|
|
case "U-VE":
|
|
case "U-VI":
|
|
for (var client in clients) {
|
|
client = JSON.parse(client);
|
|
var port = client[1];
|
|
var address = client[0];
|
|
if (port != rinfo.port && address != rinfo.address) {
|
|
UDPserver.send(msg, 0, msg.length, port, address, function(error){
|
|
if (error) {
|
|
console.log("ERROR");
|
|
console.log(error);
|
|
client.close();
|
|
};
|
|
});
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
// Unhandled data, this at the moment includes the extra packets of vehicles so it needs to be here until it is handled correctly
|
|
for (var client in clients) {
|
|
client = JSON.parse(client);
|
|
var port = client[1];
|
|
var address = client[0];
|
|
UDPserver.send(msg, 0, msg.length, port, address, function(error){
|
|
if (error) {
|
|
console.log("ERROR");
|
|
console.log(error);
|
|
client.close();
|
|
};
|
|
});
|
|
}
|
|
//console.log(chalk.rgb(123, 45, 67)('[UDP]')+' Data received from client : ' + msg.toString());
|
|
//console.log(chalk.rgb(123, 45, 67)('[UDP]')+' Received %d bytes from %s:%d\n',msg.length, rinfo.address, rinfo.port);
|
|
}
|
|
});
|
|
|
|
UDPserver.bind(Number(udpport));
|