diff --git a/Binato.js b/Binato.js index 3477662..8616a66 100644 --- a/Binato.js +++ b/Binato.js @@ -1,86 +1,87 @@ console.clear(); // Globals -global.consoleHelper = require("./consoleHelper.js"); global.protocolVersion = 19; const app = require("express")(), - prometheusApp = require("express")(), - compression = require("compression"), - fs = require("fs"), - prom = require("prom-client"), - serverHandler = require("./server/serverHandler.js"), - config = require("./config.json"); + consoleHelper = require("./consoleHelper.js"), + prometheusApp = require("express")(), + fs = require("fs"), + serverHandler = require("./server/serverHandler.js"), + config = require("./config.json"); const debugMode = true; if (config.prometheusEnabled) { - const register = new prom.Registry(); + // We only need to require this if prom metrics are on. + const prom = require("prom-client"); - register.setDefaultLabels({ app: "nodejs_binato" }); - - prom.collectDefaultMetrics({ register }); - - prometheusApp.get("*", async (req, res) => { - if (req.url.split("?")[0] != "/metrics") return res.status(404).end(""); - - res.end(await register.metrics()); - }); - - prometheusApp.listen(config.prometheusPort, () => global.consoleHelper.printBancho(`Prometheus metrics listening at port ${config.prometheusPort}`)); -} else global.consoleHelper.printWarn("Prometheus is disabled!"); + const register = new prom.Registry(); + + register.setDefaultLabels({ app: "nodejs_binato" }); + + prom.collectDefaultMetrics({ register }); + + prometheusApp.get("*", async (req, res) => { + if (req.url.split("?")[0] != "/metrics") return res.status(404).end(""); + + res.end(await register.metrics()); + }); + + prometheusApp.listen(config.prometheusPort, () => consoleHelper.printBancho(`Prometheus metrics listening at port ${config.prometheusPort}`)); +} else consoleHelper.printWarn("Prometheus is disabled!"); if (config.compression) { - app.use(compression()); - global.consoleHelper.printBancho("Gzip Compression is enabled."); -} else global.consoleHelper.printWarn("Gzip Compression is disabled!"); + app.use(require("compression")()); + consoleHelper.printBancho("Gzip Compression is enabled."); +} else consoleHelper.printWarn("Gzip Compression is disabled!"); app.use((req, res) => { - req.packet = new Buffer.alloc(0); - req.on("data", (chunk) => req.packet = Buffer.concat([req.packet, chunk], req.packet.length + chunk.length)); - req.on("end", () => { - switch (req.method) { - case "GET": - if (req.url == "/" || req.url == "/index.html" || req.url == "/index.html") { - fs.readFile("./web/serverPage.html", (err, data) => { - if (err) throw err; - - if (debugMode) data = data.toString().replace("|isdebug?|", 'DEBUG'); - else data = data.toString().replace("|isdebug?|", ''); - res.send(data); - }); - } else if (req.url == "/chat") { - fs.readFile("./web/chatPageTemplate.html", (err, data) => { - if (err) throw err; + req.packet = new Buffer.alloc(0); + req.on("data", (chunk) => req.packet = Buffer.concat([req.packet, chunk], req.packet.length + chunk.length)); + req.on("end", () => { + switch (req.method) { + case "GET": + if (req.url == "/" || req.url == "/index.html" || req.url == "/index.html") { + fs.readFile("./web/serverPage.html", (err, data) => { + if (err) throw err; + + if (debugMode) data = data.toString().replace("|isdebug?|", 'DEBUG'); + else data = data.toString().replace("|isdebug?|", ''); + res.send(data); + }); + } else if (req.url == "/chat") { + fs.readFile("./web/chatPageTemplate.html", (err, data) => { + if (err) throw err; - let lines = "", flip = false; - const limit = global.chatHistory.length < 10 ? 10 : global.chatHistory.length; - for (let i = global.chatHistory.length - 10; i < limit; i++) { - if (i < 0) i = 0; - lines += `
${global.chatHistory[i] == null ? "blank" : global.chatHistory[i]}
` - flip = !flip; - } - - res.send(data.toString().replace("|content|", lines)); - }); - } - break; + let lines = "", flip = false; + const limit = global.chatHistory.length < 10 ? 10 : global.chatHistory.length; + for (let i = global.chatHistory.length - 10; i < limit; i++) { + if (i < 0) i = 0; + lines += `
${global.chatHistory[i] == null ? "blank" : global.chatHistory[i]}
` + flip = !flip; + } + + res.send(data.toString().replace("|content|", lines)); + }); + } + break; - case "POST": - // Make sure this address should respond to bancho requests - // Bancho addresses: c, c1, c2, c3, c4, c5, c6, ce - // Just looking for the first character being "c" *should* be enough - if (req.headers["host"].split(".")[0][0] == "c") - serverHandler(req, res); - else - res.status(400).send("400 | Bad Request!
Binato only accepts post requests on bancho subdomains.
Binato"); - break; + case "POST": + // Make sure this address should respond to bancho requests + // Bancho addresses: c, c1, c2, c3, c4, c5, c6, ce + // Just looking for the first character being "c" *should* be enough + if (req.headers["host"].split(".")[0][0] == "c") + serverHandler(req, res); + else + res.status(400).send("400 | Bad Request!
Binato only accepts post requests on bancho subdomains.
Binato"); + break; - default: - res.status(405).send("405 | Method not allowed!
Binato"); - break; - } - }); + default: + res.status(405).send("405 | Method not allowed!
Binato"); + break; + } + }); }); -app.listen(config.port, () => global.consoleHelper.printBancho(`Binato is up! Listening at port ${config.port}`)); \ No newline at end of file +app.listen(config.port, () => consoleHelper.printBancho(`Binato is up! Listening at port ${config.port}`)); \ No newline at end of file diff --git a/consoleHelper.js b/consoleHelper.js index 70f54fe..cf89a90 100644 --- a/consoleHelper.js +++ b/consoleHelper.js @@ -1,33 +1,33 @@ const chalk = require("chalk"); module.exports = { - printWebReq:function(s) { - console.log(`${this.getTime()} ${chalk.bgGreen(chalk.black(" WEBREQ "))} ${s}`); - }, - - printBancho:function(s) { - console.log(`${this.getTime()} ${chalk.bgMagenta(chalk.black(" BANCHO "))} ${s}`); - }, + printWebReq:function(s) { + console.log(`${this.getTime()} ${chalk.bgGreen(chalk.black(" WEBREQ "))} ${s}`); + }, + + printBancho:function(s) { + console.log(`${this.getTime()} ${chalk.bgMagenta(chalk.black(" BANCHO "))} ${s}`); + }, - printChat:function(s) { - console.log(`${this.getTime()} ${chalk.bgCyan(chalk.black(" CHATTO "))} ${s}`); - }, + printChat:function(s) { + console.log(`${this.getTime()} ${chalk.bgCyan(chalk.black(" CHATTO "))} ${s}`); + }, - printWarn:function(s) { - console.warn(`${this.getTime()} ${chalk.bgYellow(chalk.black(" WARNIN "))} ${chalk.yellow(s)}`); - }, - - printError:function(s) { - console.error(`${this.getTime()} ${chalk.bgRed((" ERROR! "))} ${chalk.red(s)}`); - }, + printWarn:function(s) { + console.warn(`${this.getTime()} ${chalk.bgYellow(chalk.black(" WARNIN "))} ${chalk.yellow(s)}`); + }, + + printError:function(s) { + console.error(`${this.getTime()} ${chalk.bgRed((" ERROR! "))} ${chalk.red(s)}`); + }, - getTime:function() { - const time = new Date(); - return chalk.green(`[${correctValue(time.getHours())}:${correctValue(time.getMinutes())}:${correctValue(time.getSeconds())}]`); - } + getTime:function() { + const time = new Date(); + return chalk.green(`[${correctValue(time.getHours())}:${correctValue(time.getMinutes())}:${correctValue(time.getSeconds())}]`); + } } function correctValue(i) { - if (i <= 9) return "0"+i; - else return i; + if (i <= 9) return "0"+i; + else return i; } \ No newline at end of file diff --git a/server/BotCommandHandler.js b/server/BotCommandHandler.js index 4c85c61..5972fa9 100644 --- a/server/BotCommandHandler.js +++ b/server/BotCommandHandler.js @@ -1,211 +1,211 @@ const osu = require("osu-packet"), - maths = require("./util/Maths.js"), - OsuBattleRoyale = require("./MultiplayerExtras/OsuBattleRoyale.js"); + maths = require("./util/Maths.js"), + OsuBattleRoyale = require("./MultiplayerExtras/OsuBattleRoyale.js"); module.exports = function(User, Message, Stream, IsCalledFromMultiplayer = false) { - if (Message[0] != "!") return; - const command = Message.split(" ")[0]; - const args = Message.split(" "); + if (Message[0] != "!") return; + const command = Message.split(" ")[0]; + const args = Message.split(" "); - let responseMessage = ""; + let responseMessage = ""; - let commandBanchoPacketWriter = null; + let commandBanchoPacketWriter = null; - switch (command) { - case "!help": - // This is terrible - if (args.length == 1) { - responseMessage = "Commands with an * next to them have a sub help section" + - "\n!help - Shows this message" + - "\n!roll - Rolls a random number or a number between 0 and a given number" + - "\n!ranking* - Sets your perfered ranking type" + - "\n!mp* - Shows information about all multiplayer commands" + - "\n!admin* - Shows information about all admin commands"; - } else { - switch (args[1]) { - case "ranking": - responseMessage = "Ranking Commands:" + - "\n!ranking pp - Sets your ranking type to pp" + - "\n!ranking score - Sets your ranking type to score" + - "\n!ranking acc - Sets your ranking type to accuracy"; - break; + switch (command) { + case "!help": + // This is terrible + if (args.length == 1) { + responseMessage = "Commands with an * next to them have a sub help section" + + "\n!help - Shows this message" + + "\n!roll - Rolls a random number or a number between 0 and a given number" + + "\n!ranking* - Sets your perfered ranking type" + + "\n!mp* - Shows information about all multiplayer commands" + + "\n!admin* - Shows information about all admin commands"; + } else { + switch (args[1]) { + case "ranking": + responseMessage = "Ranking Commands:" + + "\n!ranking pp - Sets your ranking type to pp" + + "\n!ranking score - Sets your ranking type to score" + + "\n!ranking acc - Sets your ranking type to accuracy"; + break; - case "mp": - responseMessage = "Multiplayer Commands:" + - "\n!mp start - Starts a multiplayer match with a delay" + - "\n!mp abort - Aborts the currently running multiplayer match" + - "\n!mp obr - Enables Battle Royale mode"; - break; + case "mp": + responseMessage = "Multiplayer Commands:" + + "\n!mp start - Starts a multiplayer match with a delay" + + "\n!mp abort - Aborts the currently running multiplayer match" + + "\n!mp obr - Enables Battle Royale mode"; + break; - case "admin": - responseMessage = "Admin Commands:" + - "\n!lock - Locks/Unlocks a channel and limits conversation to mods and above only"; - break; + case "admin": + responseMessage = "Admin Commands:" + + "\n!lock - Locks/Unlocks a channel and limits conversation to mods and above only"; + break; - default: - break; - } - } - break; + default: + break; + } + } + break; - case "!ranking": - if (args.length == 1) { - responseMessage = "You need to select a ranking mode! use \"!help ranking\" to see the options."; - } else { - switch (args[1]) { - case "pp": - responseMessage = "Set ranking mode to pp"; - User.rankingMode = 0; - User.getNewUserInformationFromDatabase(); - break; + case "!ranking": + if (args.length == 1) { + responseMessage = "You need to select a ranking mode! use \"!help ranking\" to see the options."; + } else { + switch (args[1]) { + case "pp": + responseMessage = "Set ranking mode to pp"; + User.rankingMode = 0; + User.getNewUserInformationFromDatabase(); + break; - case "score": - responseMessage = "Set ranking mode to score"; - User.rankingMode = 1; - User.getNewUserInformationFromDatabase(); - break; + case "score": + responseMessage = "Set ranking mode to score"; + User.rankingMode = 1; + User.getNewUserInformationFromDatabase(); + break; - case "acc": - responseMessage = "Set ranking mode to accuracy"; - User.rankingMode = 2; - User.getNewUserInformationFromDatabase(); - break; - } - } - break; + case "acc": + responseMessage = "Set ranking mode to accuracy"; + User.rankingMode = 2; + User.getNewUserInformationFromDatabase(); + break; + } + } + break; - case "!roll": - if (args.length == 1) { - responseMessage = User.username + " rolled " + maths.randInt(0, 65535); - } else { - if (`${parseInt(args[1])}` == "NaN") responseMessage = User.username + " rolled " + maths.randInt(0, 65535); - else responseMessage = User.username + " rolled " + maths.randInt(0, parseInt(args[1])); - } - break; + case "!roll": + if (args.length == 1) { + responseMessage = User.username + " rolled " + maths.randInt(0, 65535); + } else { + if (`${parseInt(args[1])}` == "NaN") responseMessage = User.username + " rolled " + maths.randInt(0, 65535); + else responseMessage = User.username + " rolled " + maths.randInt(0, parseInt(args[1])); + } + break; - case "!lock": - if (!Stream.includes("#")) responseMessage = "Multiplayer channels and private channels cannot be locked!"; - else { - for (let i = 0; i < global.channels.length; i++) { - // Find the channel that pertains to this stream - if (global.channels[i].channelName == Stream) { - if (global.channels[i].locked) { - global.channels[i].locked = false; - responseMessage = "Channel is now unlocked."; - } else { - global.channels[i].locked = true; - responseMessage = "Channel is now locked, chat restricted to mods and above."; - } - break; - } - } - } - break; + case "!lock": + if (!Stream.includes("#")) responseMessage = "Multiplayer channels and private channels cannot be locked!"; + else { + for (let i = 0; i < global.channels.length; i++) { + // Find the channel that pertains to this stream + if (global.channels[i].channelName == Stream) { + if (global.channels[i].locked) { + global.channels[i].locked = false; + responseMessage = "Channel is now unlocked."; + } else { + global.channels[i].locked = true; + responseMessage = "Channel is now locked, chat restricted to mods and above."; + } + break; + } + } + } + break; - case "!mp": - if (!IsCalledFromMultiplayer) return; - if (User.currentMatch.matchStartCountdownActive) return; - if (args.length == 1) return; - switch (args[1]) { - case "start": - if (args.length > 3) return; - if (`${parseInt(args[2])}` != "NaN") { - User.currentMatch.matchStartCountdownActive = true; - let countdown = parseInt(args[2]); - let intervalRef = setInterval(() => { - let local_osuPacketWriter = new osu.Bancho.Writer; - if (countdown != 0 && countdown > 0) countdown--; - if (countdown <= 10 && countdown > 0) { - local_osuPacketWriter.SendMessage({ - sendingClient: global.users["bot"].username, - message: "Starting in " + countdown, - target: "#multiplayer", - senderId: global.users["bot"].id - }); - global.StreamsHandler.sendToStream(Stream, local_osuPacketWriter.toBuffer, null); - } else if (countdown == 0) { - local_osuPacketWriter.SendMessage({ - sendingClient: global.users["bot"].username, - message: "Good luck, have fun!", - target: "#multiplayer", - senderId: global.users["bot"].id - }); - global.StreamsHandler.sendToStream(Stream, local_osuPacketWriter.toBuffer, null); - User.currentMatch.matchStartCountdownActive = false; - setTimeout(() => User.currentMatch.startMatch(), 1000); - clearInterval(intervalRef); - } - }, 1000); - } else { - responseMessage = "Good luck, have fun!"; - setTimeout(() => User.currentMatch.startMatch(), 1000); - } - break; + case "!mp": + if (!IsCalledFromMultiplayer) return; + if (User.currentMatch.matchStartCountdownActive) return; + if (args.length == 1) return; + switch (args[1]) { + case "start": + if (args.length > 3) return; + if (`${parseInt(args[2])}` != "NaN") { + User.currentMatch.matchStartCountdownActive = true; + let countdown = parseInt(args[2]); + let intervalRef = setInterval(() => { + let local_osuPacketWriter = new osu.Bancho.Writer; + if (countdown != 0 && countdown > 0) countdown--; + if (countdown <= 10 && countdown > 0) { + local_osuPacketWriter.SendMessage({ + sendingClient: global.users["bot"].username, + message: "Starting in " + countdown, + target: "#multiplayer", + senderId: global.users["bot"].id + }); + global.StreamsHandler.sendToStream(Stream, local_osuPacketWriter.toBuffer, null); + } else if (countdown == 0) { + local_osuPacketWriter.SendMessage({ + sendingClient: global.users["bot"].username, + message: "Good luck, have fun!", + target: "#multiplayer", + senderId: global.users["bot"].id + }); + global.StreamsHandler.sendToStream(Stream, local_osuPacketWriter.toBuffer, null); + User.currentMatch.matchStartCountdownActive = false; + setTimeout(() => User.currentMatch.startMatch(), 1000); + clearInterval(intervalRef); + } + }, 1000); + } else { + responseMessage = "Good luck, have fun!"; + setTimeout(() => User.currentMatch.startMatch(), 1000); + } + break; - case "abort": - //if (args.length > 2) return; - User.currentMatch.finishMatch(); - break; + case "abort": + //if (args.length > 2) return; + User.currentMatch.finishMatch(); + break; - case "obr": - if (User.currentMatch.multiplayerExtras != null) { - if (User.currentMatch.multiplayerExtras.name == "osu! Battle Royale") { - commandBanchoPacketWriter = new osu.Bancho.Writer; - commandBanchoPacketWriter.SendMessage({ - sendingClient: global.users["bot"].username, - message: "osu! Battle Royale has been disabled!", - target: "#multiplayer", - senderId: global.users["bot"].id - }); - User.currentMatch.multiplayerExtras = null; - global.StreamsHandler.sendToStream(Stream, commandBanchoPacketWriter.toBuffer, null); - } - else enableOBR(User, Stream, commandBanchoPacketWriter); - } - else enableOBR(User, Stream, commandBanchoPacketWriter); - break; + case "obr": + if (User.currentMatch.multiplayerExtras != null) { + if (User.currentMatch.multiplayerExtras.name == "osu! Battle Royale") { + commandBanchoPacketWriter = new osu.Bancho.Writer; + commandBanchoPacketWriter.SendMessage({ + sendingClient: global.users["bot"].username, + message: "osu! Battle Royale has been disabled!", + target: "#multiplayer", + senderId: global.users["bot"].id + }); + User.currentMatch.multiplayerExtras = null; + global.StreamsHandler.sendToStream(Stream, commandBanchoPacketWriter.toBuffer, null); + } + else enableOBR(User, Stream, commandBanchoPacketWriter); + } + else enableOBR(User, Stream, commandBanchoPacketWriter); + break; - default: - break; - } - break; - } + default: + break; + } + break; + } - const osuPacketWriter = new osu.Bancho.Writer; - if (responseMessage != "") { - if (Stream.includes("#")) { - osuPacketWriter.SendMessage({ - sendingClient: global.users["bot"].username, - message: responseMessage, - target: Stream, - senderId: global.users["bot"].id - }); - } else { - osuPacketWriter.SendMessage({ - sendingClient: global.users["bot"].username, - message: responseMessage, - target: "#multiplayer", - senderId: global.users["bot"].id - }); - } - } - global.StreamsHandler.sendToStream(Stream, osuPacketWriter.toBuffer, null); + const osuPacketWriter = new osu.Bancho.Writer; + if (responseMessage != "") { + if (Stream.includes("#")) { + osuPacketWriter.SendMessage({ + sendingClient: global.users["bot"].username, + message: responseMessage, + target: Stream, + senderId: global.users["bot"].id + }); + } else { + osuPacketWriter.SendMessage({ + sendingClient: global.users["bot"].username, + message: responseMessage, + target: "#multiplayer", + senderId: global.users["bot"].id + }); + } + } + global.StreamsHandler.sendToStream(Stream, osuPacketWriter.toBuffer, null); } function enableOBR(User, Stream, commandBanchoPacketWriter) { - User.currentMatch.multiplayerExtras = new OsuBattleRoyale(User.currentMatch); - commandBanchoPacketWriter = new osu.Bancho.Writer; - commandBanchoPacketWriter.SendMessage({ - sendingClient: global.users["bot"].username, - message: "osu! Battle Royale has been enabled!", - target: "#multiplayer", - senderId: global.users["bot"].id - }); - commandBanchoPacketWriter.SendMessage({ - sendingClient: global.users["bot"].username, - message: "New Multiplayer Rules Added:\n - Players that are in a failed state by the end of the map get eliminated\n - The player(s) with the lowest score get eliminated", - target: "#multiplayer", - senderId: global.users["bot"].id - }); - global.StreamsHandler.sendToStream(Stream, commandBanchoPacketWriter.toBuffer, null); + User.currentMatch.multiplayerExtras = new OsuBattleRoyale(User.currentMatch); + commandBanchoPacketWriter = new osu.Bancho.Writer; + commandBanchoPacketWriter.SendMessage({ + sendingClient: global.users["bot"].username, + message: "osu! Battle Royale has been enabled!", + target: "#multiplayer", + senderId: global.users["bot"].id + }); + commandBanchoPacketWriter.SendMessage({ + sendingClient: global.users["bot"].username, + message: "New Multiplayer Rules Added:\n - Players that are in a failed state by the end of the map get eliminated\n - The player(s) with the lowest score get eliminated", + target: "#multiplayer", + senderId: global.users["bot"].id + }); + global.StreamsHandler.sendToStream(Stream, commandBanchoPacketWriter.toBuffer, null); } \ No newline at end of file diff --git a/server/DatabaseHelper.js b/server/DatabaseHelper.js index a2f2b2f..253369b 100644 --- a/server/DatabaseHelper.js +++ b/server/DatabaseHelper.js @@ -1,36 +1,36 @@ const mysql = require("mysql"); module.exports = class { - constructor(databaseAddress, databasePort = 3306, databaseUsername, databasePassword, databaseName) { - this.connectionPool = mysql.createPool({ - connectionLimit: 128, - host: databaseAddress, - port: databasePort, - user: databaseUsername, - password: databasePassword, - database: databaseName - }); - } + constructor(databaseAddress, databasePort = 3306, databaseUsername, databasePassword, databaseName) { + this.connectionPool = mysql.createPool({ + connectionLimit: 128, + host: databaseAddress, + port: databasePort, + user: databaseUsername, + password: databasePassword, + database: databaseName + }); + } - async query(sqlQuery) { - return new Promise((resolve, reject) => { - this.connectionPool.getConnection((err, connection) => { - if (err) { - reject(err); - connection.release(); - } else { - connection.query(sqlQuery, (err, data) => { - if (err) { - reject(err); - connection.release(); - } else { - if (sqlQuery.includes("LIMIT 1")) resolve(data[0]); - else resolve(data); - connection.release(); - } - }); - } - }); - }); - } + async query(sqlQuery) { + return new Promise((resolve, reject) => { + this.connectionPool.getConnection((err, connection) => { + if (err) { + reject(err); + connection.release(); + } else { + connection.query(sqlQuery, (err, data) => { + if (err) { + reject(err); + connection.release(); + } else { + if (sqlQuery.includes("LIMIT 1")) resolve(data[0]); + else resolve(data); + connection.release(); + } + }); + } + }); + }); + } } \ No newline at end of file diff --git a/server/MultiplayerExtras/OsuBattleRoyale.js b/server/MultiplayerExtras/OsuBattleRoyale.js index 9fc35b4..1f703cc 100644 --- a/server/MultiplayerExtras/OsuBattleRoyale.js +++ b/server/MultiplayerExtras/OsuBattleRoyale.js @@ -1,130 +1,130 @@ const osu = require("osu-packet"), - MultiplayerMatch = require("../MultiplayerMatch.js"), - getUserById = require("../util/getUserById.js"); + MultiplayerMatch = require("../MultiplayerMatch.js"), + getUserById = require("../util/getUserById.js"); module.exports = class { - constructor(MultiplayerMatchClass = new MultiplayerMatch()) { - this.name = "osu! Battle Royale"; - this.MultiplayerMatch = MultiplayerMatchClass; - } + constructor(MultiplayerMatchClass = new MultiplayerMatch()) { + this.name = "osu! Battle Royale"; + this.MultiplayerMatch = MultiplayerMatchClass; + } - onMatchFinished(playerScores = [{playerId:0,slotId:0,score:0,isCurrentlyFailed:false}]) { - let lowestScore = 9999999999999999; - for (let i = 0; i < playerScores.length; i++) { - const playerScore = playerScores[i]; - if (playerScore.score < lowestScore) lowestScore = playerScore.score; - } + onMatchFinished(playerScores = [{playerId:0,slotId:0,score:0,isCurrentlyFailed:false}]) { + let lowestScore = 9999999999999999; + for (let i = 0; i < playerScores.length; i++) { + const playerScore = playerScores[i]; + if (playerScore.score < lowestScore) lowestScore = playerScore.score; + } - let everyoneHasTheSameScore = true; - for (let i = 0; i < playerScores.length; i++) { - if (playerScores[i].score != lowestScore) { - everyoneHasTheSameScore = false; - break; - } - } + let everyoneHasTheSameScore = true; + for (let i = 0; i < playerScores.length; i++) { + if (playerScores[i].score != lowestScore) { + everyoneHasTheSameScore = false; + break; + } + } - // Everyone has the same score, we don't need to kick anyone - if (everyoneHasTheSameScore) return; + // Everyone has the same score, we don't need to kick anyone + if (everyoneHasTheSameScore) return; - // Kick everyone with the lowest score - for (let i = 0; i < playerScores.length; i++) { - // Kick players if they have the lowest score or they are in a failed state - if (playerScores[i].score == lowestScore || playerScores[i].isCurrentlyFailed) { - let osuPacketWriter = new osu.Bancho.Writer; - // Get the slot this player is in - const slot = this.MultiplayerMatch.slots[playerScores[i].slotId]; - // Get the kicked player's user class - const kickedPlayer = getUserById(slot.playerId); - // Remove the kicked player's referance to the slot they were in - kickedPlayer.matchSlotId = -1; - // Lock the slot the kicked player was in - slot.playerId = -1; - slot.status = 2; - // Remove the kicked player from the match's stream - global.StreamsHandler.removeUserFromStream(this.MultiplayerMatch.matchStreamName, kickedPlayer.uuid); - global.StreamsHandler.removeUserFromStream(this.MultiplayerMatch.matchChatStreamName, kickedPlayer.uuid); - // Remove the kicked player's referance this this match - kickedPlayer.currentMatch = null; + // Kick everyone with the lowest score + for (let i = 0; i < playerScores.length; i++) { + // Kick players if they have the lowest score or they are in a failed state + if (playerScores[i].score == lowestScore || playerScores[i].isCurrentlyFailed) { + let osuPacketWriter = new osu.Bancho.Writer; + // Get the slot this player is in + const slot = this.MultiplayerMatch.slots[playerScores[i].slotId]; + // Get the kicked player's user class + const kickedPlayer = getUserById(slot.playerId); + // Remove the kicked player's referance to the slot they were in + kickedPlayer.matchSlotId = -1; + // Lock the slot the kicked player was in + slot.playerId = -1; + slot.status = 2; + // Remove the kicked player from the match's stream + global.StreamsHandler.removeUserFromStream(this.MultiplayerMatch.matchStreamName, kickedPlayer.uuid); + global.StreamsHandler.removeUserFromStream(this.MultiplayerMatch.matchChatStreamName, kickedPlayer.uuid); + // Remove the kicked player's referance this this match + kickedPlayer.currentMatch = null; - // Inform the kicked user's client that they were kicked - osuPacketWriter.MatchUpdate(this.MultiplayerMatch.createOsuMatchJSON()); - osuPacketWriter.SendMessage({ - sendingClient: global.users["bot"].username, - message: "You were eliminated from the match!", - target: global.users["bot"].username, - senderId: global.users["bot"].id - }); + // Inform the kicked user's client that they were kicked + osuPacketWriter.MatchUpdate(this.MultiplayerMatch.createOsuMatchJSON()); + osuPacketWriter.SendMessage({ + sendingClient: global.users["bot"].username, + message: "You were eliminated from the match!", + target: global.users["bot"].username, + senderId: global.users["bot"].id + }); - kickedPlayer.addActionToQueue(osuPacketWriter.toBuffer); + kickedPlayer.addActionToQueue(osuPacketWriter.toBuffer); - osuPacketWriter = new osu.Bancho.Writer; - - osuPacketWriter.SendMessage({ - sendingClient: global.users["bot"].username, - message: `${kickedPlayer.username} was eliminated from the match!`, - target: "#multiplayer", - senderId: global.users["bot"].id - }); + osuPacketWriter = new osu.Bancho.Writer; + + osuPacketWriter.SendMessage({ + sendingClient: global.users["bot"].username, + message: `${kickedPlayer.username} was eliminated from the match!`, + target: "#multiplayer", + senderId: global.users["bot"].id + }); - global.StreamsHandler.sendToStream(this.MultiplayerMatch.matchChatStreamName, osuPacketWriter.toBuffer, null); - } - } + global.StreamsHandler.sendToStream(this.MultiplayerMatch.matchChatStreamName, osuPacketWriter.toBuffer, null); + } + } - let numberOfPlayersRemaining = 0; - for (let i = 0; i < playerScores.length; i++) { - const slot = this.MultiplayerMatch.slots[playerScores[i].slotId]; + let numberOfPlayersRemaining = 0; + for (let i = 0; i < playerScores.length; i++) { + const slot = this.MultiplayerMatch.slots[playerScores[i].slotId]; - if (slot.playerId !== -1 && slot.status !== 2) { - numberOfPlayersRemaining++; - } - } + if (slot.playerId !== -1 && slot.status !== 2) { + numberOfPlayersRemaining++; + } + } - let playerClassContainer = null; - let remainingWriterContainer = null; - let i = 0; + let playerClassContainer = null; + let remainingWriterContainer = null; + let i = 0; - if (numberOfPlayersRemaining == 1) { - for (let i1 = 0; i1 < playerScores.length; i++) { - const slot = this.MultiplayerMatch.slots[playerScores[i].slotId]; - if (slot.playerId !== -1 && slot.status !== 2) { - playerClassContainer = getUserById(slot.playerId); - break; - } - } - } + if (numberOfPlayersRemaining == 1) { + for (let i1 = 0; i1 < playerScores.length; i++) { + const slot = this.MultiplayerMatch.slots[playerScores[i].slotId]; + if (slot.playerId !== -1 && slot.status !== 2) { + playerClassContainer = getUserById(slot.playerId); + break; + } + } + } - switch (numberOfPlayersRemaining) { - case 0: - remainingWriterContainer = new osu.Bancho.Writer; - remainingWriterContainer.SendMessage({ - sendingClient: global.users["bot"].username, - message: "Everyone was eliminated from the match! Nobody wins.", - target: global.users["bot"].username, - senderId: global.users["bot"].id - }); - for (i = 0; i < playerScores.length; i++) { - playerClassContainer = getUserById(playerScores[i].playerId); - playerClassContainer.addActionToQueue(remainingWriterContainer.toBuffer); - } - break; + switch (numberOfPlayersRemaining) { + case 0: + remainingWriterContainer = new osu.Bancho.Writer; + remainingWriterContainer.SendMessage({ + sendingClient: global.users["bot"].username, + message: "Everyone was eliminated from the match! Nobody wins.", + target: global.users["bot"].username, + senderId: global.users["bot"].id + }); + for (i = 0; i < playerScores.length; i++) { + playerClassContainer = getUserById(playerScores[i].playerId); + playerClassContainer.addActionToQueue(remainingWriterContainer.toBuffer); + } + break; - case 1: - remainingWriterContainer = new osu.Bancho.Writer; - remainingWriterContainer.SendMessage({ - sendingClient: global.users["bot"].username, - message: "You are the last one remaining, you win!", - target: global.users["bot"].username, - senderId: global.users["bot"].id - }); - playerClassContainer.addActionToQueue(remainingWriterContainer.toBuffer); - break; + case 1: + remainingWriterContainer = new osu.Bancho.Writer; + remainingWriterContainer.SendMessage({ + sendingClient: global.users["bot"].username, + message: "You are the last one remaining, you win!", + target: global.users["bot"].username, + senderId: global.users["bot"].id + }); + playerClassContainer.addActionToQueue(remainingWriterContainer.toBuffer); + break; - default: - break; - } + default: + break; + } - this.MultiplayerMatch.sendMatchUpdate(); - // Update the match listing for users in the multiplayer lobby - global.MultiplayerManager.updateMatchListing(); - } + this.MultiplayerMatch.sendMatchUpdate(); + // Update the match listing for users in the multiplayer lobby + global.MultiplayerManager.updateMatchListing(); + } } \ No newline at end of file diff --git a/server/MultiplayerManager.js b/server/MultiplayerManager.js index 7bb028c..304a533 100644 --- a/server/MultiplayerManager.js +++ b/server/MultiplayerManager.js @@ -1,220 +1,220 @@ const osu = require("osu-packet"), - UserPresenceBundle = require("./Packets/UserPresenceBundle.js"), - UserPresence = require("./Packets/UserPresence.js"), - StatusUpdate = require("./Packets/StatusUpdate.js"), - MultiplayerMatch = require("./MultiplayerMatch.js"); + UserPresenceBundle = require("./Packets/UserPresenceBundle.js"), + UserPresence = require("./Packets/UserPresence.js"), + StatusUpdate = require("./Packets/StatusUpdate.js"), + MultiplayerMatch = require("./MultiplayerMatch.js"); module.exports = class { - constructor() { - this.matches = []; - } + constructor() { + this.matches = []; + } - userEnterLobby(currentUser) { - // If the user is currently already in a match force them to leave - if (currentUser.currentMatch != null) - currentUser.currentMatch.leaveMatch(currentUser); + userEnterLobby(currentUser) { + // If the user is currently already in a match force them to leave + if (currentUser.currentMatch != null) + currentUser.currentMatch.leaveMatch(currentUser); - // Add user to the stream for the lobby - global.StreamsHandler.addUserToStream("multiplayer_lobby", currentUser.uuid); + // Add user to the stream for the lobby + global.StreamsHandler.addUserToStream("multiplayer_lobby", currentUser.uuid); - // Send user ids of all online users to all users in the lobby - global.StreamsHandler.sendToStream("multiplayer_lobby", UserPresenceBundle(currentUser, false), null); + // Send user ids of all online users to all users in the lobby + global.StreamsHandler.sendToStream("multiplayer_lobby", UserPresenceBundle(currentUser, false), null); - // Loop through all matches - for (let i = 0; i < this.matches.length; i++) { - // Loop through all the users in this match - for (let i1 = 0; i1 < this.matches[i].slots.length; i1++) { - const slot = this.matches[i].slots[i1]; - // Make sure there is a player / the slot is not locked - if (slot.playerId == -1 || slot.status == 2) continue; + // Loop through all matches + for (let i = 0; i < this.matches.length; i++) { + // Loop through all the users in this match + for (let i1 = 0; i1 < this.matches[i].slots.length; i1++) { + const slot = this.matches[i].slots[i1]; + // Make sure there is a player / the slot is not locked + if (slot.playerId == -1 || slot.status == 2) continue; - // Send information for this user to all users in the lobby - global.StreamsHandler.sendToStream("multiplayer_lobby", UserPresence(currentUser, slot.playerId, false), null); - global.StreamsHandler.sendToStream("multiplayer_lobby", StatusUpdate(currentUser, slot.playerId, false), null); - } - const osuPacketWriter = new osu.Bancho.Writer; + // Send information for this user to all users in the lobby + global.StreamsHandler.sendToStream("multiplayer_lobby", UserPresence(currentUser, slot.playerId, false), null); + global.StreamsHandler.sendToStream("multiplayer_lobby", StatusUpdate(currentUser, slot.playerId, false), null); + } + const osuPacketWriter = new osu.Bancho.Writer; - // List the match on the client - osuPacketWriter.MatchNew(this.matches[i].createOsuMatchJSON()); + // List the match on the client + osuPacketWriter.MatchNew(this.matches[i].createOsuMatchJSON()); - currentUser.addActionToQueue(osuPacketWriter.toBuffer); - } - const osuPacketWriter = new osu.Bancho.Writer; + currentUser.addActionToQueue(osuPacketWriter.toBuffer); + } + const osuPacketWriter = new osu.Bancho.Writer; - // Add the user to the #lobby channel - if (!global.StreamsHandler.isUserInStream("#lobby", currentUser.uuid)) { - global.StreamsHandler.addUserToStream("#lobby", currentUser.uuid); - osuPacketWriter.ChannelJoinSuccess("#lobby"); - } - - currentUser.addActionToQueue(osuPacketWriter.toBuffer); - } + // Add the user to the #lobby channel + if (!global.StreamsHandler.isUserInStream("#lobby", currentUser.uuid)) { + global.StreamsHandler.addUserToStream("#lobby", currentUser.uuid); + osuPacketWriter.ChannelJoinSuccess("#lobby"); + } + + currentUser.addActionToQueue(osuPacketWriter.toBuffer); + } - userLeaveLobby(currentUser) { - // Remove user from the stream for the multiplayer lobby if they are a part of it - if (global.StreamsHandler.isUserInStream("multiplayer_lobby", currentUser.uuid)) - global.StreamsHandler.removeUserFromStream("multiplayer_lobby", currentUser.uuid); - } - - updateMatchListing() { - // Send user ids of all online users to all users in the lobby - global.StreamsHandler.sendToStream("multiplayer_lobby", UserPresenceBundle(null, false), null); + userLeaveLobby(currentUser) { + // Remove user from the stream for the multiplayer lobby if they are a part of it + if (global.StreamsHandler.isUserInStream("multiplayer_lobby", currentUser.uuid)) + global.StreamsHandler.removeUserFromStream("multiplayer_lobby", currentUser.uuid); + } + + updateMatchListing() { + // Send user ids of all online users to all users in the lobby + global.StreamsHandler.sendToStream("multiplayer_lobby", UserPresenceBundle(null, false), null); - // List through all matches - for (let i = 0; i < this.matches.length; i++) { - // List through all users in the match - for (let i1 = 0; i1 < this.matches[i].slots.length; i1++) { - const slot = this.matches[i].slots[i1]; - // Make sure the slot has a user in it / isn't locked - if (slot.playerId == -1 || slot.status == 2) continue; + // List through all matches + for (let i = 0; i < this.matches.length; i++) { + // List through all users in the match + for (let i1 = 0; i1 < this.matches[i].slots.length; i1++) { + const slot = this.matches[i].slots[i1]; + // Make sure the slot has a user in it / isn't locked + if (slot.playerId == -1 || slot.status == 2) continue; - // Send information for this user to all users in the lobby - global.StreamsHandler.sendToStream("multiplayer_lobby", UserPresence(null, slot.playerId, false), null); - global.StreamsHandler.sendToStream("multiplayer_lobby", StatusUpdate(null, slot.playerId, false), null); - } - const osuPacketWriter = new osu.Bancho.Writer; + // Send information for this user to all users in the lobby + global.StreamsHandler.sendToStream("multiplayer_lobby", UserPresence(null, slot.playerId, false), null); + global.StreamsHandler.sendToStream("multiplayer_lobby", StatusUpdate(null, slot.playerId, false), null); + } + const osuPacketWriter = new osu.Bancho.Writer; - // List the match on the client - osuPacketWriter.MatchNew(this.matches[i].createOsuMatchJSON()); + // List the match on the client + osuPacketWriter.MatchNew(this.matches[i].createOsuMatchJSON()); - // Send this data back to every user in the lobby - global.StreamsHandler.sendToStream("multiplayer_lobby", osuPacketWriter.toBuffer, null); - } - } + // Send this data back to every user in the lobby + global.StreamsHandler.sendToStream("multiplayer_lobby", osuPacketWriter.toBuffer, null); + } + } - createMultiplayerMatch(MatchHost, MatchData) { - let matchClass = null; - this.matches.push(matchClass = new MultiplayerMatch(MatchHost, MatchData)); + createMultiplayerMatch(MatchHost, MatchData) { + let matchClass = null; + this.matches.push(matchClass = new MultiplayerMatch(MatchHost, MatchData)); - // Join the user to the newly created match - this.joinMultiplayerMatch(MatchHost, { - matchId: matchClass.matchId, - gamePassword: matchClass.gamePassword - }); - } + // Join the user to the newly created match + this.joinMultiplayerMatch(MatchHost, { + matchId: matchClass.matchId, + gamePassword: matchClass.gamePassword + }); + } - joinMultiplayerMatch(JoiningUser, JoinInfo) { - try { - let osuPacketWriter = new osu.Bancho.Writer; - const osuPacketWriter1 = new osu.Bancho.Writer; + joinMultiplayerMatch(JoiningUser, JoinInfo) { + try { + let osuPacketWriter = new osu.Bancho.Writer; + const osuPacketWriter1 = new osu.Bancho.Writer; - let matchIndex = 0; - for (let i = 0; i < this.matches.length; i++) { - if (this.matches[i].matchId == JoinInfo.matchId) { - matchIndex = i; - break; - } - } + let matchIndex = 0; + for (let i = 0; i < this.matches.length; i++) { + if (this.matches[i].matchId == JoinInfo.matchId) { + matchIndex = i; + break; + } + } - const streamName = this.matches[matchIndex].matchStreamName; - const chatStreamName = this.matches[matchIndex].matchChatStreamName; - const match = this.matches[matchIndex]; + const streamName = this.matches[matchIndex].matchStreamName; + const chatStreamName = this.matches[matchIndex].matchChatStreamName; + const match = this.matches[matchIndex]; - let full = true; - // Loop through all slots to find an empty one - for (let i = 0; i < match.slots.length; i++) { - const slot = match.slots[i]; - // Make sure the slot doesn't have a player in it / the slot is locked - if (slot.playerId !== -1 || slot.status === 2) continue; + let full = true; + // Loop through all slots to find an empty one + for (let i = 0; i < match.slots.length; i++) { + const slot = match.slots[i]; + // Make sure the slot doesn't have a player in it / the slot is locked + if (slot.playerId !== -1 || slot.status === 2) continue; - // Slot is empty and not locked, we can join the match! - full = false; - slot.playerId = JoiningUser.id; - JoiningUser.matchSlotId = i; - slot.status = 4; - break; - } + // Slot is empty and not locked, we can join the match! + full = false; + slot.playerId = JoiningUser.id; + JoiningUser.matchSlotId = i; + slot.status = 4; + break; + } - const matchJSON = match.createOsuMatchJSON(); - osuPacketWriter1.MatchUpdate(matchJSON); - osuPacketWriter.MatchJoinSuccess(matchJSON); + const matchJSON = match.createOsuMatchJSON(); + osuPacketWriter1.MatchUpdate(matchJSON); + osuPacketWriter.MatchJoinSuccess(matchJSON); - if (full) { - throw "MatchFullException"; - } + if (full) { + throw "MatchFullException"; + } - // Set the user's current match to this match - JoiningUser.currentMatch = match; + // Set the user's current match to this match + JoiningUser.currentMatch = match; - // Add user to the stream for the match - global.StreamsHandler.addUserToStream(streamName, JoiningUser.uuid); - global.StreamsHandler.addUserToStream(chatStreamName, JoiningUser.uuid); + // Add user to the stream for the match + global.StreamsHandler.addUserToStream(streamName, JoiningUser.uuid); + global.StreamsHandler.addUserToStream(chatStreamName, JoiningUser.uuid); - // Inform all users in the match that a new user has joined - global.StreamsHandler.sendToStream(streamName, osuPacketWriter1.toBuffer, null); + // Inform all users in the match that a new user has joined + global.StreamsHandler.sendToStream(streamName, osuPacketWriter1.toBuffer, null); - osuPacketWriter.ChannelJoinSuccess("#multiplayer"); + osuPacketWriter.ChannelJoinSuccess("#multiplayer"); - // Inform joining client they they have joined the match - JoiningUser.addActionToQueue(osuPacketWriter.toBuffer); + // Inform joining client they they have joined the match + JoiningUser.addActionToQueue(osuPacketWriter.toBuffer); - // Update the match listing for all users in the lobby since - // A user has joined a match - this.updateMatchListing(); - } catch (e) { - // Inform the client that there was an issue joining the match - const osuPacketWriter = new osu.Bancho.Writer; + // Update the match listing for all users in the lobby since + // A user has joined a match + this.updateMatchListing(); + } catch (e) { + // Inform the client that there was an issue joining the match + const osuPacketWriter = new osu.Bancho.Writer; - osuPacketWriter.MatchJoinFail(); + osuPacketWriter.MatchJoinFail(); - JoiningUser.addActionToQueue(osuPacketWriter.toBuffer); + JoiningUser.addActionToQueue(osuPacketWriter.toBuffer); - this.updateMatchListing(); - } - } + this.updateMatchListing(); + } + } - leaveMultiplayerMatch(MatchUser) { - // Make sure the user is in a match - if (MatchUser.currentMatch == null) return; + leaveMultiplayerMatch(MatchUser) { + // Make sure the user is in a match + if (MatchUser.currentMatch == null) return; - const mpLobby = MatchUser.currentMatch.leaveMatch(MatchUser); + const mpLobby = MatchUser.currentMatch.leaveMatch(MatchUser); - let empty = true; - // Check if the match is empty - for (let i = 0; i < mpLobby.slots.length; i++) { - const slot = mpLobby.slots[i]; - // Check if the slot is avaliable - if (slot.playerId === -1) continue; - - // There is a user in the match - empty = false; - break; - } + let empty = true; + // Check if the match is empty + for (let i = 0; i < mpLobby.slots.length; i++) { + const slot = mpLobby.slots[i]; + // Check if the slot is avaliable + if (slot.playerId === -1) continue; + + // There is a user in the match + empty = false; + break; + } - // The match is empty, proceed to remove it. - if (empty) { - let matchIndex; - // Loop through all matches - for (let i = 0; i < this.matches.length; i++) { - // If the match matches the match the user has left - if (this.matches[i].matchStreamName == MatchUser.currentMatch.matchStreamName) { - matchIndex = i; - break; - } - } + // The match is empty, proceed to remove it. + if (empty) { + let matchIndex; + // Loop through all matches + for (let i = 0; i < this.matches.length; i++) { + // If the match matches the match the user has left + if (this.matches[i].matchStreamName == MatchUser.currentMatch.matchStreamName) { + matchIndex = i; + break; + } + } - // Make sure we got a match index - if (matchIndex == null) return; + // Make sure we got a match index + if (matchIndex == null) return; - // Remove this match from the list of active matches - this.matches.splice(matchIndex, 1); - } + // Remove this match from the list of active matches + this.matches.splice(matchIndex, 1); + } - MatchUser.currentMatch = null; + MatchUser.currentMatch = null; - // Update the match listing to reflect this change (either removal or user leaving) - this.updateMatchListing(); + // Update the match listing to reflect this change (either removal or user leaving) + this.updateMatchListing(); - // Delay a 2nd match listing update - setTimeout(() => { - this.updateMatchListing(); - }, 1000); - } + // Delay a 2nd match listing update + setTimeout(() => { + this.updateMatchListing(); + }, 1000); + } - getMatch(MatchID) { - for (let match in this.matches) { - if (match.matchId == MatchID) return match; - } - return null; - } + getMatch(MatchID) { + for (let match in this.matches) { + if (match.matchId == MatchID) return match; + } + return null; + } } \ No newline at end of file diff --git a/server/MultiplayerMatch.js b/server/MultiplayerMatch.js index 143f792..1cc57b3 100644 --- a/server/MultiplayerMatch.js +++ b/server/MultiplayerMatch.js @@ -1,618 +1,618 @@ const osu = require("osu-packet"), - getUserById = require("./util/getUserById.js"), - StatusUpdate = require("./Packets/StatusUpdate.js"); + getUserById = require("./util/getUserById.js"), + StatusUpdate = require("./Packets/StatusUpdate.js"); // TODO: Cache the player's slot position in their user class for a small optimisation module.exports = class { - constructor(MatchHost, MatchData = {matchId: -1,inProgress: false,matchType: 0,activeMods: 0,gameName: "",gamePassword: '',beatmapName: '',beatmapId: 1250198,beatmapChecksum: '',slots: [],host: 0,playMode: 0,matchScoringType: 0,matchTeamType: 0,specialModes: 0,seed: 0}) { - this.matchId = global.getAndAddToHistoricalMultiplayerMatches(); - - this.inProgress = MatchData.inProgress; - this.matchStartCountdownActive = false; - - this.matchType = MatchData.matchType; - - this.activeMods = MatchData.activeMods; - - this.gameName = MatchData.gameName; - if (MatchData.gamePassword == '') MatchData.gamePassword == null; - this.gamePassword = MatchData.gamePassword; - - this.beatmapName = MatchData.beatmapName; - this.beatmapId = MatchData.beatmapId; - this.beatmapChecksum = MatchData.beatmapChecksum; - - this.slots = MatchData.slots; - for (let i = 0; i < this.slots.length; i++) { - this.slots[i].mods = 0; - } - - this.host = MatchData.host; - - this.playMode = MatchData.playMode; - - this.matchScoringType = MatchData.matchScoringType; - this.matchTeamType = MatchData.matchTeamType; - this.specialModes = MatchData.specialModes; - - this.seed = MatchData.seed; - - this.matchStreamName = `mp_${this.matchId}`; - this.matchChatStreamName = `mp_chat_${this.matchId}`; - - this.matchLoadSlots = null; - this.matchSkippedSlots = null; - - this.playerScores = null; - - this.multiplayerExtras = null; - - this.isTourneyMatch = false; - this.tourneyClientUsers = []; - - const osuPacketWriter = new osu.Bancho.Writer; - - // Update the status of the current user - StatusUpdate(MatchHost, MatchHost.id); - osuPacketWriter.MatchNew(this.createOsuMatchJSON()); - - // Queue match creation for user - MatchHost.addActionToQueue(osuPacketWriter.toBuffer); - - global.StreamsHandler.addStream(this.matchStreamName, true, this.matchId); - global.StreamsHandler.addStream(this.matchChatStreamName, true, this.matchId); - - // Update the match listing for users in the multiplayer lobby - global.MultiplayerManager.updateMatchListing(); - } - - createOsuMatchJSON() { - return { - matchId: this.matchId, - inProgress: this.inProgress, - matchType: this.matchType, - activeMods: this.activeMods, - gameName: this.gameName, - gamePassword: this.gamePassword, - beatmapName: this.beatmapName, - beatmapId: this.beatmapId, - beatmapChecksum: this.beatmapChecksum, - slots: this.slots, - host: this.host, - playMode: this.playMode, - matchScoringType: this.matchScoringType, - matchTeamType: this.matchTeamType, - specialModes: this.specialModes, - seed: this.seed - }; - } - - leaveMatch(MatchUser) { - try { - let userInMatch = false; - // Loop through all slots in the match - for (let i = 0; i < this.slots.length; i++) { - const slot = this.slots[i]; - // Check if the user is in this slot - if (slot.playerId == MatchUser.id) { - userInMatch = true; - break; - } - } - - // Make sure we don't run more than once - // Again, client double firing packets. - if (!userInMatch) return; - - let osuPacketWriter = new osu.Bancho.Writer; - - // Loop through all slots in the match - for (let i = 0; i < this.slots.length; i++) { - const slot = this.slots[i]; - // Make sure the user is in this slot - if (slot.playerId != MatchUser.id) continue; - - // Set the slot's status to avaliable - slot.playerId = -1; - slot.status = 1; - - break; - } - - osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); - - // Remove the leaving user from the match's stream - global.StreamsHandler.removeUserFromStream(this.matchStreamName, MatchUser.uuid); - global.StreamsHandler.removeUserFromStream(this.matchChatStreamName, MatchUser.uuid); - - // Inform all users in the match that the leaving user has left - global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - - osuPacketWriter = new osu.Bancho.Writer; - - // Remove user from the multiplayer channel for the match - osuPacketWriter.ChannelRevoked("#multiplayer"); - - MatchUser.addActionToQueue(osuPacketWriter.toBuffer); - - return this; - } catch (e) { - console.error(e); - } - } - - updateMatch(MatchUser, MatchData) { - // Update match with new data - this.inProgress = MatchData.inProgress; - - this.matchType = MatchData.matchType; - - this.activeMods = MatchData.activeMods; - - this.gameName = MatchData.gameName; - if (MatchData.gamePassword == '') MatchData.gamePassword == null; - this.gamePassword = MatchData.gamePassword; - - this.beatmapName = MatchData.beatmapName; - this.beatmapId = MatchData.beatmapId; - this.beatmapChecksum = MatchData.beatmapChecksum; - - this.host = MatchData.host; - - this.playMode = MatchData.playMode; - - this.matchScoringType = MatchData.matchScoringType; - this.matchTeamType = MatchData.matchTeamType; - this.specialModes = MatchData.specialModes; - - this.seed = MatchData.seed; - const osuPacketWriter = new osu.Bancho.Writer; - - osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); - - // Send this new match data to all users in the match - global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - - // Update the match listing in the lobby to reflect these changes - global.MultiplayerManager.updateMatchListing(); - } - - sendMatchUpdate() { - const osuPacketWriter = new osu.Bancho.Writer; - - osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); - - // Update all users in the match with new match information - global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - } - - moveToSlot(MatchUser, SlotToMoveTo) { - const osuPacketWriter = new osu.Bancho.Writer; - const oldSlot = this.slots[MatchUser.matchSlotId]; - - // Set the new slot's data to the user's old slot data - this.slots[SlotToMoveTo].playerId = MatchUser.id; - MatchUser.matchSlotId = SlotToMoveTo; - this.slots[SlotToMoveTo].status = 4; - - // Set the old slot's data to open - oldSlot.playerId = -1; - oldSlot.status = 1; - - osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); - - // Send this change to all users in the match - global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - - // Update the match listing in the lobby to reflect this change - global.MultiplayerManager.updateMatchListing(); - } - - changeTeam(MatchUser) { - const slot = this.slots[MatchUser.matchSlotId]; - slot.team = slot.team == 0 ? 1 : 0; + constructor(MatchHost, MatchData = {matchId: -1,inProgress: false,matchType: 0,activeMods: 0,gameName: "",gamePassword: '',beatmapName: '',beatmapId: 1250198,beatmapChecksum: '',slots: [],host: 0,playMode: 0,matchScoringType: 0,matchTeamType: 0,specialModes: 0,seed: 0}) { + this.matchId = global.getAndAddToHistoricalMultiplayerMatches(); + + this.inProgress = MatchData.inProgress; + this.matchStartCountdownActive = false; + + this.matchType = MatchData.matchType; + + this.activeMods = MatchData.activeMods; + + this.gameName = MatchData.gameName; + if (MatchData.gamePassword == '') MatchData.gamePassword == null; + this.gamePassword = MatchData.gamePassword; + + this.beatmapName = MatchData.beatmapName; + this.beatmapId = MatchData.beatmapId; + this.beatmapChecksum = MatchData.beatmapChecksum; + + this.slots = MatchData.slots; + for (let i = 0; i < this.slots.length; i++) { + this.slots[i].mods = 0; + } + + this.host = MatchData.host; + + this.playMode = MatchData.playMode; + + this.matchScoringType = MatchData.matchScoringType; + this.matchTeamType = MatchData.matchTeamType; + this.specialModes = MatchData.specialModes; + + this.seed = MatchData.seed; + + this.matchStreamName = `mp_${this.matchId}`; + this.matchChatStreamName = `mp_chat_${this.matchId}`; + + this.matchLoadSlots = null; + this.matchSkippedSlots = null; + + this.playerScores = null; + + this.multiplayerExtras = null; + + this.isTourneyMatch = false; + this.tourneyClientUsers = []; + + const osuPacketWriter = new osu.Bancho.Writer; + + // Update the status of the current user + StatusUpdate(MatchHost, MatchHost.id); + osuPacketWriter.MatchNew(this.createOsuMatchJSON()); + + // Queue match creation for user + MatchHost.addActionToQueue(osuPacketWriter.toBuffer); + + global.StreamsHandler.addStream(this.matchStreamName, true, this.matchId); + global.StreamsHandler.addStream(this.matchChatStreamName, true, this.matchId); + + // Update the match listing for users in the multiplayer lobby + global.MultiplayerManager.updateMatchListing(); + } + + createOsuMatchJSON() { + return { + matchId: this.matchId, + inProgress: this.inProgress, + matchType: this.matchType, + activeMods: this.activeMods, + gameName: this.gameName, + gamePassword: this.gamePassword, + beatmapName: this.beatmapName, + beatmapId: this.beatmapId, + beatmapChecksum: this.beatmapChecksum, + slots: this.slots, + host: this.host, + playMode: this.playMode, + matchScoringType: this.matchScoringType, + matchTeamType: this.matchTeamType, + specialModes: this.specialModes, + seed: this.seed + }; + } + + leaveMatch(MatchUser) { + try { + let userInMatch = false; + // Loop through all slots in the match + for (let i = 0; i < this.slots.length; i++) { + const slot = this.slots[i]; + // Check if the user is in this slot + if (slot.playerId == MatchUser.id) { + userInMatch = true; + break; + } + } + + // Make sure we don't run more than once + // Again, client double firing packets. + if (!userInMatch) return; + + let osuPacketWriter = new osu.Bancho.Writer; + + // Loop through all slots in the match + for (let i = 0; i < this.slots.length; i++) { + const slot = this.slots[i]; + // Make sure the user is in this slot + if (slot.playerId != MatchUser.id) continue; + + // Set the slot's status to avaliable + slot.playerId = -1; + slot.status = 1; + + break; + } + + osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); + + // Remove the leaving user from the match's stream + global.StreamsHandler.removeUserFromStream(this.matchStreamName, MatchUser.uuid); + global.StreamsHandler.removeUserFromStream(this.matchChatStreamName, MatchUser.uuid); + + // Inform all users in the match that the leaving user has left + global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); + + osuPacketWriter = new osu.Bancho.Writer; + + // Remove user from the multiplayer channel for the match + osuPacketWriter.ChannelRevoked("#multiplayer"); + + MatchUser.addActionToQueue(osuPacketWriter.toBuffer); + + return this; + } catch (e) { + console.error(e); + } + } + + updateMatch(MatchUser, MatchData) { + // Update match with new data + this.inProgress = MatchData.inProgress; + + this.matchType = MatchData.matchType; + + this.activeMods = MatchData.activeMods; + + this.gameName = MatchData.gameName; + if (MatchData.gamePassword == '') MatchData.gamePassword == null; + this.gamePassword = MatchData.gamePassword; + + this.beatmapName = MatchData.beatmapName; + this.beatmapId = MatchData.beatmapId; + this.beatmapChecksum = MatchData.beatmapChecksum; + + this.host = MatchData.host; + + this.playMode = MatchData.playMode; + + this.matchScoringType = MatchData.matchScoringType; + this.matchTeamType = MatchData.matchTeamType; + this.specialModes = MatchData.specialModes; + + this.seed = MatchData.seed; + const osuPacketWriter = new osu.Bancho.Writer; + + osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); + + // Send this new match data to all users in the match + global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); + + // Update the match listing in the lobby to reflect these changes + global.MultiplayerManager.updateMatchListing(); + } + + sendMatchUpdate() { + const osuPacketWriter = new osu.Bancho.Writer; + + osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); + + // Update all users in the match with new match information + global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); + } + + moveToSlot(MatchUser, SlotToMoveTo) { + const osuPacketWriter = new osu.Bancho.Writer; + const oldSlot = this.slots[MatchUser.matchSlotId]; + + // Set the new slot's data to the user's old slot data + this.slots[SlotToMoveTo].playerId = MatchUser.id; + MatchUser.matchSlotId = SlotToMoveTo; + this.slots[SlotToMoveTo].status = 4; + + // Set the old slot's data to open + oldSlot.playerId = -1; + oldSlot.status = 1; + + osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); + + // Send this change to all users in the match + global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); + + // Update the match listing in the lobby to reflect this change + global.MultiplayerManager.updateMatchListing(); + } + + changeTeam(MatchUser) { + const slot = this.slots[MatchUser.matchSlotId]; + slot.team = slot.team == 0 ? 1 : 0; - const osuPacketWriter = new osu.Bancho.Writer; + const osuPacketWriter = new osu.Bancho.Writer; - osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); + osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); - // Send this change to all users in the match - global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - } + // Send this change to all users in the match + global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); + } - setStateReady(MatchUser) { - // Get the match the user is in - const osuPacketWriter = new osu.Bancho.Writer; + setStateReady(MatchUser) { + // Get the match the user is in + const osuPacketWriter = new osu.Bancho.Writer; - // Loop though all slots in the match - for (let i = 0; i < this.slots.length; i++) { - const slot = this.slots[i]; - // Check if the player in this slot is this user - if (slot.playerId == MatchUser.id) { - // Turn on the user's ready state - slot.status = 8; // Ready - break; - } - } + // Loop though all slots in the match + for (let i = 0; i < this.slots.length; i++) { + const slot = this.slots[i]; + // Check if the player in this slot is this user + if (slot.playerId == MatchUser.id) { + // Turn on the user's ready state + slot.status = 8; // Ready + break; + } + } - osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); + osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); - // Send this update to all users in the stream - global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - } + // Send this update to all users in the stream + global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); + } - setStateNotReady(MatchUser) { - // Get the match the user is in - const osuPacketWriter = new osu.Bancho.Writer; + setStateNotReady(MatchUser) { + // Get the match the user is in + const osuPacketWriter = new osu.Bancho.Writer; - // Loop though all slots in the match - for (let i = 0; i < this.slots.length; i++) { - const slot = this.slots[i]; - // Check if the player in this slot is this user - if (slot.playerId == MatchUser.id) { - // Turn off the user's ready state - slot.status = 4; // Not Ready - break; - } - } + // Loop though all slots in the match + for (let i = 0; i < this.slots.length; i++) { + const slot = this.slots[i]; + // Check if the player in this slot is this user + if (slot.playerId == MatchUser.id) { + // Turn off the user's ready state + slot.status = 4; // Not Ready + break; + } + } - osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); + osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); - // Send this update to all users in the stream - global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - } + // Send this update to all users in the stream + global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); + } - lockMatchSlot(MatchUser, MatchUserToKick) { - const osuPacketWriter = new osu.Bancho.Writer; + lockMatchSlot(MatchUser, MatchUserToKick) { + const osuPacketWriter = new osu.Bancho.Writer; - // Make sure the user attempting to kick / lock is the host of the match - if (this.host != MatchUser.id) return; + // Make sure the user attempting to kick / lock is the host of the match + if (this.host != MatchUser.id) return; - // Make sure the user that is attempting to be kicked is not the host - if (this.slots[MatchUserToKick].playerId === this.host) return; + // Make sure the user that is attempting to be kicked is not the host + if (this.slots[MatchUserToKick].playerId === this.host) return; - // Get the data of the slot at the index sent by the client - const slot = this.slots[MatchUserToKick]; + // Get the data of the slot at the index sent by the client + const slot = this.slots[MatchUserToKick]; - let isSlotEmpty = true; + let isSlotEmpty = true; - // If the slot is empty lock/unlock instead of kicking - if (slot.playerId === -1) - slot.status = slot.status === 1 ? 2 : 1; - - // The slot isn't empty, kick the player - else { - const kickedPlayer = getUserById(slot.playerId); - kickedPlayer.matchSlotId = -1; - slot.playerId = -1; - slot.status = 1; - isSlotEmpty = false; - } + // If the slot is empty lock/unlock instead of kicking + if (slot.playerId === -1) + slot.status = slot.status === 1 ? 2 : 1; + + // The slot isn't empty, kick the player + else { + const kickedPlayer = getUserById(slot.playerId); + kickedPlayer.matchSlotId = -1; + slot.playerId = -1; + slot.status = 1; + isSlotEmpty = false; + } - osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); + osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); - // Inform all users in the match of the change - global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); + // Inform all users in the match of the change + global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - // Update the match listing in the lobby listing to reflect this change - global.MultiplayerManager.updateMatchListing(); + // Update the match listing in the lobby listing to reflect this change + global.MultiplayerManager.updateMatchListing(); - if (!isSlotEmpty) { - let cachedPlayerToken = getUserById(slot.playerId).uuid; + if (!isSlotEmpty) { + let cachedPlayerToken = getUserById(slot.playerId).uuid; - if (cachedPlayerToken !== null && cachedPlayerToken !== "") { - // Remove the kicked user from the match stream - global.StreamsHandler.removeUserFromStream(this.matchStreamName, cachedPlayerToken); - } - } - } + if (cachedPlayerToken !== null && cachedPlayerToken !== "") { + // Remove the kicked user from the match stream + global.StreamsHandler.removeUserFromStream(this.matchStreamName, cachedPlayerToken); + } + } + } - missingBeatmap(MatchUser) { - const osuPacketWriter = new osu.Bancho.Writer; + missingBeatmap(MatchUser) { + const osuPacketWriter = new osu.Bancho.Writer; - // User is missing the beatmap set the status to reflect it - this.slots[MatchUser.matchSlotId].status = 16; - - osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); - - // Inform all users in the match of this change - global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - } - - notMissingBeatmap(MatchUser) { - const osuPacketWriter = new osu.Bancho.Writer; - - // The user is not missing the beatmap, set the status to normal - this.slots[MatchUser.matchSlotId].status = 4; - - osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); - - // Inform all users in the match of this change - global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - } - - matchSkip(MatchUser) { - if (this.matchSkippedSlots == null) { - this.matchSkippedSlots = []; - - const skippedSlots = this.matchSkippedSlots; - - for (let i = 0; i < this.slots.length; i++) { - const slot = this.slots[i]; - // Make sure the slot has a user in it - if (slot.playerId === -1 || slot.status === 1 || slot.status === 2) continue; - - // Add the slot's user to the loaded checking array - skippedSlots.push({playerId: slot.playerId, skipped: false}); - } - } - - const skippedSlots = this.matchSkippedSlots; - - for (let i = 0; i < skippedSlots.length; i++) { - // If loadslot belongs to this user then set loaded to true - if (skippedSlots[i].playerId == MatchUser.id) { - skippedSlots[i].skipped = true; - } - } - - let allSkipped = true; - for (let i = 0; i < skippedSlots.length; i++) { - if (skippedSlots[i].skipped) continue; - - // A user hasn't finished playing - allSkipped = false; - } - - // All players have finished playing, finish the match - if (allSkipped) { - const osuPacketWriter = new osu.Bancho.Writer; - - osuPacketWriter.MatchPlayerSkipped(MatchUser.id); - osuPacketWriter.MatchSkip(); - - global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - - this.matchSkippedSlots = null; - } else { - const osuPacketWriter = new osu.Bancho.Writer; - - osuPacketWriter.MatchPlayerSkipped(MatchUser.id); - - global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - } - } - - transferHost(MatchUser, SlotIDToTransferTo) { - const osuPacketWriter = new osu.Bancho.Writer; - - // Set the lobby's host to the new user - this.host = this.slots[SlotIDToTransferTo].playerId; - - osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); - - // Inform all clients in the match of the change - global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - } - - // TODO: Fix not being able to add DT when freemod is active - updateMods(MatchUser, MatchMods) { - // Check if freemod is enabled - if (this.specialModes === 1) { - const osuPacketWriter = new osu.Bancho.Writer; - this.slots[MatchUser.matchSlotId].mods = MatchMods; - - osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); - - global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - } else { - // Make sure the person updating mods is the host of the match - if (this.host !== MatchUser.id) return; - const osuPacketWriter = new osu.Bancho.Writer; - - // Change the matches mods to these new mods - // TODO: Do this per user if freemod is enabled - this.activeMods = MatchMods; - - osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); - - // Inform all users in the match of the change - global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - } - - // Update match listing in the lobby to reflect this change - global.MultiplayerManager.updateMatchListing(); - } - - startMatch() { - // Make sure the match is not already in progress - // The client sometimes double fires the start packet - if (this.inProgress) return; - this.inProgress = true; - // Create array for monitoring users until they are ready to play - this.matchLoadSlots = []; - const loadedSlots = this.matchLoadSlots; - // Loop through all slots in the match - for (let i = 0; i < this.slots.length; i++) { - const slot = this.slots[i]; - // Make sure the slot has a user in it - if (slot.playerId === -1 || slot.status === 1 || slot.status === 2) continue; - - // Add the slot's user to the loaded checking array - loadedSlots.push({ - playerId: slot.playerId, - loaded: false - }); - } - const osuPacketWriter = new osu.Bancho.Writer; - - // Loop through all slots in the match - for (let i = 0; i < this.slots.length; i++) { - const slot = this.slots[i]; - // Make sure the slot has a user in it - if (slot.playerId === -1 || slot.status === 1 || slot.status === 2) continue; - - // Set the user's status to playing - slot.status = 32; - } - - osuPacketWriter.MatchStart(this.createOsuMatchJSON()); - - // Inform all users in the match that it has started - global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - - // Update all users in the match with new info - this.sendMatchUpdate(); - - // Update match listing in lobby to show the game is in progress - global.MultiplayerManager.updateMatchListing(); - } - - matchPlayerLoaded(MatchUser) { - const loadedSlots = this.matchLoadSlots; - - // Loop through all user load check items - for (let i = 0; i < loadedSlots.length; i++) { - // If loadslot belongs to this user then set loaded to true - if (loadedSlots[i].playerId == MatchUser.id) { - loadedSlots[i].loaded = true; - } - } - - // Loop through all loaded slots and check if all users are loaded - let allLoaded = true; - for (let i = 0; i < loadedSlots.length; i++) { - if (loadedSlots[i].loaded) continue; - - // A user wasn't loaded, keep waiting. - allLoaded = false; - break; - } - - // All players have loaded the beatmap, start playing. - if (allLoaded) { - let osuPacketWriter = new osu.Bancho.Writer; - osuPacketWriter.MatchAllPlayersLoaded(); - global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - - // Blank out user loading array - this.matchLoadSlots = null; - - this.playerScores = []; - for (let i = 0; i < this.slots.length; i++) { - const slot = this.slots[i]; - if (slot.playerId === -1 || slot.status === 1 || slot.status === 2) continue; - - this.playerScores.push({playerId: slot.playerId, slotId: i, score: 0, isCurrentlyFailed: false}); - } - } - } - - onPlayerFinishMatch(MatchUser) { - // If user loading slots do not exist - if (this.matchLoadSlots == null) { - this.matchLoadSlots = []; - // Repopulate user loading slots again - const loadedSlots = this.matchLoadSlots; - for (let i = 0; i < this.slots.length; i++) { - const slot = this.slots[i]; - // Make sure the slot has a user - if (slot.playerId === -1 || slot.status === 1 || slot.status === 2) continue; - - // Populate user loading slots with this user's id and load status - loadedSlots.push({ - playerId: slot.playerId, - loaded: false - }); - } - } - - const loadedSlots = this.matchLoadSlots; - - // Loop through all loaded slots to make sure all users have finished playing - for (let i = 0; i < loadedSlots.length; i++) { - if (loadedSlots[i].playerId == MatchUser.id) { - loadedSlots[i].loaded = true; - } - } - - let allLoaded = true; - for (let i = 0; i < loadedSlots.length; i++) { - if (loadedSlots[i].loaded) continue; - - // A user hasn't finished playing - allLoaded = false; - } - - // All players have finished playing, finish the match - if (allLoaded) this.finishMatch(); - } - - finishMatch() { - if (!this.inProgress) return; - this.matchLoadSlots = null; - this.inProgress = false; - let osuPacketWriter = new osu.Bancho.Writer; - - // Loop through all slots in the match - for (let i = 0; i < this.slots.length; i++) { - const slot = this.slots[i]; - // Make sure the slot has a user - if (slot.playerId === -1 || slot.status === 1 || slot.status === 2) continue; - - // Set the user's status back to normal from playing - slot.status = 4; - } - - osuPacketWriter.MatchComplete(); - - // Inform all users in the match that it is complete - global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - - // Update all users in the match with new info - this.sendMatchUpdate(); - - // Update match info in the lobby to reflect that the match has finished - global.MultiplayerManager.updateMatchListing(); - - if (this.multiplayerExtras != null) this.multiplayerExtras.onMatchFinished(JSON.parse(JSON.stringify(this.playerScores))); - - this.playerScores = null; - } - - updatePlayerScore(MatchPlayer, MatchScoreData) { - const osuPacketWriter = new osu.Bancho.Writer; - - // Make sure the user's slot ID is not invalid - if (this.matchSlotId == -1) return; - - // Get the user's current slotID and append it to the givien data, just incase. - MatchScoreData.id = MatchPlayer.matchSlotId; - - // Update the playerScores array accordingly - for (let i = 0; i < this.playerScores.length; i++) { - if (this.playerScores[i].playerId == MatchPlayer.id) { - this.playerScores[i].score = MatchScoreData.totalScore; - this.playerScores[i].isCurrentlyFailed = MatchScoreData.currentHp == 254; - break; - } - } - - osuPacketWriter.MatchScoreUpdate(MatchScoreData); - - // Send the newly updated score to all users in the match - global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - } - - matchFailed(MatchUser) { - const osuPacketWriter = new osu.Bancho.Writer; - - // Make sure the user's slot ID is not invalid - if (MatchUser.matchSlotId == -1) return; - - osuPacketWriter.MatchPlayerFailed(MatchUser.id); - - global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - } + // User is missing the beatmap set the status to reflect it + this.slots[MatchUser.matchSlotId].status = 16; + + osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); + + // Inform all users in the match of this change + global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); + } + + notMissingBeatmap(MatchUser) { + const osuPacketWriter = new osu.Bancho.Writer; + + // The user is not missing the beatmap, set the status to normal + this.slots[MatchUser.matchSlotId].status = 4; + + osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); + + // Inform all users in the match of this change + global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); + } + + matchSkip(MatchUser) { + if (this.matchSkippedSlots == null) { + this.matchSkippedSlots = []; + + const skippedSlots = this.matchSkippedSlots; + + for (let i = 0; i < this.slots.length; i++) { + const slot = this.slots[i]; + // Make sure the slot has a user in it + if (slot.playerId === -1 || slot.status === 1 || slot.status === 2) continue; + + // Add the slot's user to the loaded checking array + skippedSlots.push({playerId: slot.playerId, skipped: false}); + } + } + + const skippedSlots = this.matchSkippedSlots; + + for (let i = 0; i < skippedSlots.length; i++) { + // If loadslot belongs to this user then set loaded to true + if (skippedSlots[i].playerId == MatchUser.id) { + skippedSlots[i].skipped = true; + } + } + + let allSkipped = true; + for (let i = 0; i < skippedSlots.length; i++) { + if (skippedSlots[i].skipped) continue; + + // A user hasn't finished playing + allSkipped = false; + } + + // All players have finished playing, finish the match + if (allSkipped) { + const osuPacketWriter = new osu.Bancho.Writer; + + osuPacketWriter.MatchPlayerSkipped(MatchUser.id); + osuPacketWriter.MatchSkip(); + + global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); + + this.matchSkippedSlots = null; + } else { + const osuPacketWriter = new osu.Bancho.Writer; + + osuPacketWriter.MatchPlayerSkipped(MatchUser.id); + + global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); + } + } + + transferHost(MatchUser, SlotIDToTransferTo) { + const osuPacketWriter = new osu.Bancho.Writer; + + // Set the lobby's host to the new user + this.host = this.slots[SlotIDToTransferTo].playerId; + + osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); + + // Inform all clients in the match of the change + global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); + } + + // TODO: Fix not being able to add DT when freemod is active + updateMods(MatchUser, MatchMods) { + // Check if freemod is enabled + if (this.specialModes === 1) { + const osuPacketWriter = new osu.Bancho.Writer; + this.slots[MatchUser.matchSlotId].mods = MatchMods; + + osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); + + global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); + } else { + // Make sure the person updating mods is the host of the match + if (this.host !== MatchUser.id) return; + const osuPacketWriter = new osu.Bancho.Writer; + + // Change the matches mods to these new mods + // TODO: Do this per user if freemod is enabled + this.activeMods = MatchMods; + + osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); + + // Inform all users in the match of the change + global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); + } + + // Update match listing in the lobby to reflect this change + global.MultiplayerManager.updateMatchListing(); + } + + startMatch() { + // Make sure the match is not already in progress + // The client sometimes double fires the start packet + if (this.inProgress) return; + this.inProgress = true; + // Create array for monitoring users until they are ready to play + this.matchLoadSlots = []; + const loadedSlots = this.matchLoadSlots; + // Loop through all slots in the match + for (let i = 0; i < this.slots.length; i++) { + const slot = this.slots[i]; + // Make sure the slot has a user in it + if (slot.playerId === -1 || slot.status === 1 || slot.status === 2) continue; + + // Add the slot's user to the loaded checking array + loadedSlots.push({ + playerId: slot.playerId, + loaded: false + }); + } + const osuPacketWriter = new osu.Bancho.Writer; + + // Loop through all slots in the match + for (let i = 0; i < this.slots.length; i++) { + const slot = this.slots[i]; + // Make sure the slot has a user in it + if (slot.playerId === -1 || slot.status === 1 || slot.status === 2) continue; + + // Set the user's status to playing + slot.status = 32; + } + + osuPacketWriter.MatchStart(this.createOsuMatchJSON()); + + // Inform all users in the match that it has started + global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); + + // Update all users in the match with new info + this.sendMatchUpdate(); + + // Update match listing in lobby to show the game is in progress + global.MultiplayerManager.updateMatchListing(); + } + + matchPlayerLoaded(MatchUser) { + const loadedSlots = this.matchLoadSlots; + + // Loop through all user load check items + for (let i = 0; i < loadedSlots.length; i++) { + // If loadslot belongs to this user then set loaded to true + if (loadedSlots[i].playerId == MatchUser.id) { + loadedSlots[i].loaded = true; + } + } + + // Loop through all loaded slots and check if all users are loaded + let allLoaded = true; + for (let i = 0; i < loadedSlots.length; i++) { + if (loadedSlots[i].loaded) continue; + + // A user wasn't loaded, keep waiting. + allLoaded = false; + break; + } + + // All players have loaded the beatmap, start playing. + if (allLoaded) { + let osuPacketWriter = new osu.Bancho.Writer; + osuPacketWriter.MatchAllPlayersLoaded(); + global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); + + // Blank out user loading array + this.matchLoadSlots = null; + + this.playerScores = []; + for (let i = 0; i < this.slots.length; i++) { + const slot = this.slots[i]; + if (slot.playerId === -1 || slot.status === 1 || slot.status === 2) continue; + + this.playerScores.push({playerId: slot.playerId, slotId: i, score: 0, isCurrentlyFailed: false}); + } + } + } + + onPlayerFinishMatch(MatchUser) { + // If user loading slots do not exist + if (this.matchLoadSlots == null) { + this.matchLoadSlots = []; + // Repopulate user loading slots again + const loadedSlots = this.matchLoadSlots; + for (let i = 0; i < this.slots.length; i++) { + const slot = this.slots[i]; + // Make sure the slot has a user + if (slot.playerId === -1 || slot.status === 1 || slot.status === 2) continue; + + // Populate user loading slots with this user's id and load status + loadedSlots.push({ + playerId: slot.playerId, + loaded: false + }); + } + } + + const loadedSlots = this.matchLoadSlots; + + // Loop through all loaded slots to make sure all users have finished playing + for (let i = 0; i < loadedSlots.length; i++) { + if (loadedSlots[i].playerId == MatchUser.id) { + loadedSlots[i].loaded = true; + } + } + + let allLoaded = true; + for (let i = 0; i < loadedSlots.length; i++) { + if (loadedSlots[i].loaded) continue; + + // A user hasn't finished playing + allLoaded = false; + } + + // All players have finished playing, finish the match + if (allLoaded) this.finishMatch(); + } + + finishMatch() { + if (!this.inProgress) return; + this.matchLoadSlots = null; + this.inProgress = false; + let osuPacketWriter = new osu.Bancho.Writer; + + // Loop through all slots in the match + for (let i = 0; i < this.slots.length; i++) { + const slot = this.slots[i]; + // Make sure the slot has a user + if (slot.playerId === -1 || slot.status === 1 || slot.status === 2) continue; + + // Set the user's status back to normal from playing + slot.status = 4; + } + + osuPacketWriter.MatchComplete(); + + // Inform all users in the match that it is complete + global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); + + // Update all users in the match with new info + this.sendMatchUpdate(); + + // Update match info in the lobby to reflect that the match has finished + global.MultiplayerManager.updateMatchListing(); + + if (this.multiplayerExtras != null) this.multiplayerExtras.onMatchFinished(JSON.parse(JSON.stringify(this.playerScores))); + + this.playerScores = null; + } + + updatePlayerScore(MatchPlayer, MatchScoreData) { + const osuPacketWriter = new osu.Bancho.Writer; + + // Make sure the user's slot ID is not invalid + if (this.matchSlotId == -1) return; + + // Get the user's current slotID and append it to the givien data, just incase. + MatchScoreData.id = MatchPlayer.matchSlotId; + + // Update the playerScores array accordingly + for (let i = 0; i < this.playerScores.length; i++) { + if (this.playerScores[i].playerId == MatchPlayer.id) { + this.playerScores[i].score = MatchScoreData.totalScore; + this.playerScores[i].isCurrentlyFailed = MatchScoreData.currentHp == 254; + break; + } + } + + osuPacketWriter.MatchScoreUpdate(MatchScoreData); + + // Send the newly updated score to all users in the match + global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); + } + + matchFailed(MatchUser) { + const osuPacketWriter = new osu.Bancho.Writer; + + // Make sure the user's slot ID is not invalid + if (MatchUser.matchSlotId == -1) return; + + osuPacketWriter.MatchPlayerFailed(MatchUser.id); + + global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); + } } \ No newline at end of file diff --git a/server/Packets/AddFriend.js b/server/Packets/AddFriend.js index e7389f8..64172e9 100644 --- a/server/Packets/AddFriend.js +++ b/server/Packets/AddFriend.js @@ -1,3 +1,3 @@ module.exports = function(CurrentUser, FriendToAdd) { - global.DatabaseHelper.query(`INSERT INTO friends (user, friendsWith) VALUES (${CurrentUser.id}, ${FriendToAdd});`); + global.DatabaseHelper.query(`INSERT INTO friends (user, friendsWith) VALUES (${CurrentUser.id}, ${FriendToAdd});`); } \ No newline at end of file diff --git a/server/Packets/ChangeAction.js b/server/Packets/ChangeAction.js index 357b2f3..f4d71a0 100644 --- a/server/Packets/ChangeAction.js +++ b/server/Packets/ChangeAction.js @@ -1,10 +1,10 @@ const StatusUpdate = require("./StatusUpdate.js"); module.exports = function(currentUser, data) { - currentUser.updatePresence(data); + currentUser.updatePresence(data); - if (global.StreamsHandler.doesStreamExist(`sp_${currentUser.username}`)) { - const statusUpdate = StatusUpdate(currentUser, currentUser.id, false); - global.StreamsHandler.sendToStream(`sp_${currentUser.username}`, statusUpdate, null); - } + if (global.StreamsHandler.doesStreamExist(`sp_${currentUser.username}`)) { + const statusUpdate = StatusUpdate(currentUser, currentUser.id, false); + global.StreamsHandler.sendToStream(`sp_${currentUser.username}`, statusUpdate, null); + } } \ No newline at end of file diff --git a/server/Packets/ChannelJoin.js b/server/Packets/ChannelJoin.js index 739d5c1..7e6a1d1 100644 --- a/server/Packets/ChannelJoin.js +++ b/server/Packets/ChannelJoin.js @@ -1,15 +1,16 @@ -const osu = require("osu-packet"); +const osu = require("osu-packet"), + consoleHelper = require("../../consoleHelper.js"); module.exports = function(CurrentUser, channelName = "") { - // Make sure the user is not already in the channel - if (global.StreamsHandler.isUserInStream(channelName, CurrentUser.uuid)) - return global.consoleHelper.printBancho(`Did not add user to channel ${channelName} because they are already in it`); + // Make sure the user is not already in the channel + if (global.StreamsHandler.isUserInStream(channelName, CurrentUser.uuid)) + return consoleHelper.printBancho(`Did not add user to channel ${channelName} because they are already in it`); - const osuPacketWriter = new osu.Bancho.Writer; + const osuPacketWriter = new osu.Bancho.Writer; - osuPacketWriter.ChannelJoinSuccess(channelName); - if (!global.StreamsHandler.isUserInStream(channelName, CurrentUser.uuid)) - global.StreamsHandler.addUserToStream(channelName, CurrentUser.uuid); + osuPacketWriter.ChannelJoinSuccess(channelName); + if (!global.StreamsHandler.isUserInStream(channelName, CurrentUser.uuid)) + global.StreamsHandler.addUserToStream(channelName, CurrentUser.uuid); - CurrentUser.addActionToQueue(osuPacketWriter.toBuffer); + CurrentUser.addActionToQueue(osuPacketWriter.toBuffer); } \ No newline at end of file diff --git a/server/Packets/ChannelPart.js b/server/Packets/ChannelPart.js index 38d6431..9632eca 100644 --- a/server/Packets/ChannelPart.js +++ b/server/Packets/ChannelPart.js @@ -1,5 +1,5 @@ module.exports = function(CurrentUser, data) { - if (data == "#multiplayer") return; // Ignore requests for multiplayer + if (data == "#multiplayer") return; // Ignore requests for multiplayer - global.StreamsHandler.removeUserFromStream(data, CurrentUser.uuid); + global.StreamsHandler.removeUserFromStream(data, CurrentUser.uuid); } \ No newline at end of file diff --git a/server/Packets/Logout.js b/server/Packets/Logout.js index ce022ee..2ad1e13 100644 --- a/server/Packets/Logout.js +++ b/server/Packets/Logout.js @@ -1,27 +1,28 @@ -const osu = require("osu-packet"); +const osu = require("osu-packet"), + consoleHelper = require("../../consoleHelper.js"); module.exports = function(CurrentUser) { - const logoutStartTime = new Date().getTime(); + const logoutStartTime = Date.now(); - const streamList = global.StreamsHandler.getStreams(); + const streamList = global.StreamsHandler.getStreams(); - for (let i = 0; i < streamList.length; i++) { - if (global.StreamsHandler.isUserInStream(streamList[i], CurrentUser.uuid)) { - global.StreamsHandler.removeUserFromStream(streamList[i], CurrentUser.uuid); - } - } + for (let i = 0; i < streamList.length; i++) { + if (global.StreamsHandler.isUserInStream(streamList[i], CurrentUser.uuid)) { + global.StreamsHandler.removeUserFromStream(streamList[i], CurrentUser.uuid); + } + } - // Remove user from user list - global.removeUser(CurrentUser); + // Remove user from user list + global.removeUser(CurrentUser); - const osuPacketWriter = new osu.Bancho.Writer(); - osuPacketWriter.SendMessage({ - sendingClient: global.users["bot"].username, - message: `User ${CurrentUser.username} has logged out.`, - target: "#userlog", - senderId: global.users["bot"].id - }); - global.StreamsHandler.sendToStream("#userlog", osuPacketWriter.toBuffer); + const osuPacketWriter = new osu.Bancho.Writer(); + osuPacketWriter.SendMessage({ + sendingClient: global.users["bot"].username, + message: `User ${CurrentUser.username} has logged out.`, + target: "#userlog", + senderId: global.users["bot"].id + }); + global.StreamsHandler.sendToStream("#userlog", osuPacketWriter.toBuffer); - global.consoleHelper.printBancho(`User logged out, took ${new Date().getTime() - logoutStartTime}ms. [User: ${CurrentUser.username}]`); + consoleHelper.printBancho(`User logged out, took ${Date.now() - logoutStartTime}ms. [User: ${CurrentUser.username}]`); } \ No newline at end of file diff --git a/server/Packets/MultiplayerInvite.js b/server/Packets/MultiplayerInvite.js index 14dda34..a113c68 100644 --- a/server/Packets/MultiplayerInvite.js +++ b/server/Packets/MultiplayerInvite.js @@ -1,17 +1,17 @@ const osu = require("osu-packet"), - getUserById = require("../util/getUserById.js"); + getUserById = require("../util/getUserById.js"); module.exports = function(CurrentUser, InvitedUser) { - let osuPacketWriter = new osu.Bancho.Writer; + let osuPacketWriter = new osu.Bancho.Writer; - const InvitedUserClass = getUserById(InvitedUser); + const InvitedUserClass = getUserById(InvitedUser); - osuPacketWriter.SendMessage({ - sendingClient: CurrentUser.username, - message: `Come join my multiplayer match: [osump://${CurrentUser.currentMatch.matchId}/ ${CurrentUser.currentMatch.gameName}]`, - target: CurrentUser.username, - senderId: CurrentUser.id - }); + osuPacketWriter.SendMessage({ + sendingClient: CurrentUser.username, + message: `Come join my multiplayer match: [osump://${CurrentUser.currentMatch.matchId}/ ${CurrentUser.currentMatch.gameName}]`, + target: CurrentUser.username, + senderId: CurrentUser.id + }); - InvitedUserClass.addActionToQueue(osuPacketWriter.toBuffer); + InvitedUserClass.addActionToQueue(osuPacketWriter.toBuffer); } \ No newline at end of file diff --git a/server/Packets/RemoveFriend.js b/server/Packets/RemoveFriend.js index 8e1137f..b3d0957 100644 --- a/server/Packets/RemoveFriend.js +++ b/server/Packets/RemoveFriend.js @@ -1,3 +1,3 @@ module.exports = function(CurrentUser, FriendToRemove) { - global.DatabaseHelper.query(`DELETE FROM friends WHERE user = ${CurrentUser.id} AND friendsWith = ${FriendToRemove} LIMIT 1`); -} \ No newline at end of file + global.DatabaseHelper.query(`DELETE FROM friends WHERE user = ${CurrentUser.id} AND friendsWith = ${FriendToRemove} LIMIT 1`); +} \ No newline at end of file diff --git a/server/Packets/SendPrivateMessage.js b/server/Packets/SendPrivateMessage.js index be039e9..b72c883 100644 --- a/server/Packets/SendPrivateMessage.js +++ b/server/Packets/SendPrivateMessage.js @@ -1,19 +1,19 @@ const osu = require("osu-packet"), - getUserByUsername = require("../util/getUserByUsername.js"); + getUserByUsername = require("../util/getUserByUsername.js"); module.exports = function(CurrentUser, CurrentPacket) { - const osuPacketWriter = new osu.Bancho.Writer; - const userSentTo = getUserByUsername(CurrentPacket.target); + const osuPacketWriter = new osu.Bancho.Writer; + const userSentTo = getUserByUsername(CurrentPacket.target); - if (userSentTo == null) return; + if (userSentTo == null) return; - osuPacketWriter.SendMessage({ - sendingClient: CurrentUser.username, - message: CurrentPacket.message, - target: CurrentUser.username, - senderId: CurrentUser.id - }); + osuPacketWriter.SendMessage({ + sendingClient: CurrentUser.username, + message: CurrentPacket.message, + target: CurrentUser.username, + senderId: CurrentUser.id + }); - // Write chat message to stream asociated with chat channel - return userSentTo.addActionToQueue(osuPacketWriter.toBuffer); + // Write chat message to stream asociated with chat channel + return userSentTo.addActionToQueue(osuPacketWriter.toBuffer); } \ No newline at end of file diff --git a/server/Packets/SendPublicMessage.js b/server/Packets/SendPublicMessage.js index 8e74bf7..137811f 100644 --- a/server/Packets/SendPublicMessage.js +++ b/server/Packets/SendPublicMessage.js @@ -1,56 +1,57 @@ const osu = require("osu-packet"), - botCommandHandler = require("../BotCommandHandler.js"); + botCommandHandler = require("../BotCommandHandler.js"), + consoleHelper = require("../../consoleHelper.js"); module.exports = function(CurrentUser, CurrentPacket) { - let isSendingChannelLocked = false; - for (let i = 0; i < global.channels.length; i++) { - if (!CurrentPacket.target.includes("#")) break; - if (global.channels[i].channelName == CurrentPacket.target) { - isSendingChannelLocked = global.channels[i].locked; - break; - } - } + let isSendingChannelLocked = false; + for (let i = 0; i < global.channels.length; i++) { + if (!CurrentPacket.target.includes("#")) break; + if (global.channels[i].channelName == CurrentPacket.target) { + isSendingChannelLocked = global.channels[i].locked; + break; + } + } - if (isSendingChannelLocked) { - if (CurrentPacket.message.includes("!")) { - botCommandHandler(CurrentUser, CurrentPacket.message, CurrentPacket.target); - } else { - const osuPacketWriter = new osu.Bancho.Writer; - osuPacketWriter.SendMessage({ - sendingClient: global.users["bot"].username, - message: "The channel you are currently trying to send to is locked, please check back later!", - target: CurrentPacket.target, - senderId: global.users["bot"].id - }); - CurrentUser.addActionToQueue(osuPacketWriter.toBuffer); - } - return; - } + if (isSendingChannelLocked) { + if (CurrentPacket.message.includes("!")) { + botCommandHandler(CurrentUser, CurrentPacket.message, CurrentPacket.target); + } else { + const osuPacketWriter = new osu.Bancho.Writer; + osuPacketWriter.SendMessage({ + sendingClient: global.users["bot"].username, + message: "The channel you are currently trying to send to is locked, please check back later!", + target: CurrentPacket.target, + senderId: global.users["bot"].id + }); + CurrentUser.addActionToQueue(osuPacketWriter.toBuffer); + } + return; + } - global.consoleHelper.printChat(`${CurrentUser.username} in ${CurrentPacket.target} sent: ${CurrentPacket.message}`); + consoleHelper.printChat(`${CurrentUser.username} in ${CurrentPacket.target} sent: ${CurrentPacket.message}`); - const osuPacketWriter = new osu.Bancho.Writer; - osuPacketWriter.SendMessage({ - sendingClient: CurrentUser.username, - message: CurrentPacket.message, - target: CurrentPacket.target, - senderId: CurrentUser.id - }); + const osuPacketWriter = new osu.Bancho.Writer; + osuPacketWriter.SendMessage({ + sendingClient: CurrentUser.username, + message: CurrentPacket.message, + target: CurrentPacket.target, + senderId: CurrentUser.id + }); - if (CurrentPacket.target == "#multiplayer") { - global.StreamsHandler.sendToStream(CurrentUser.currentMatch.matchChatStreamName, osuPacketWriter.toBuffer, CurrentUser.uuid); - botCommandHandler(CurrentUser, CurrentPacket.message, CurrentUser.currentMatch.matchChatStreamName, true); - return; - } + if (CurrentPacket.target == "#multiplayer") { + global.StreamsHandler.sendToStream(CurrentUser.currentMatch.matchChatStreamName, osuPacketWriter.toBuffer, CurrentUser.uuid); + botCommandHandler(CurrentUser, CurrentPacket.message, CurrentUser.currentMatch.matchChatStreamName, true); + return; + } - // Check the stream that we're sending to even exists - if (!global.StreamsHandler.doesStreamExist(CurrentPacket.target)) return; + // Check the stream that we're sending to even exists + if (!global.StreamsHandler.doesStreamExist(CurrentPacket.target)) return; - // Write chat message to stream asociated with chat channel - global.StreamsHandler.sendToStream(CurrentPacket.target, osuPacketWriter.toBuffer, CurrentUser.uuid); - if (CurrentPacket.target == "#osu") - global.addChatMessage(`${CurrentUser.username}: ${CurrentPacket.message}`); - - botCommandHandler(CurrentUser, CurrentPacket.message, CurrentPacket.target); - return; + // Write chat message to stream asociated with chat channel + global.StreamsHandler.sendToStream(CurrentPacket.target, osuPacketWriter.toBuffer, CurrentUser.uuid); + if (CurrentPacket.target == "#osu") + global.addChatMessage(`${CurrentUser.username}: ${CurrentPacket.message}`); + + botCommandHandler(CurrentUser, CurrentPacket.message, CurrentPacket.target); + return; } \ No newline at end of file diff --git a/server/Packets/StatusUpdate.js b/server/Packets/StatusUpdate.js index b2cbc9a..fa9ef80 100644 --- a/server/Packets/StatusUpdate.js +++ b/server/Packets/StatusUpdate.js @@ -1,36 +1,36 @@ const osu = require("osu-packet"), - getUserById = require("../util/getUserById.js"); + getUserById = require("../util/getUserById.js"); module.exports = function(currentUser, id = 0, sendImmidiate = true) { - if (id == 3) return; // Ignore Bot + if (id == 3) return; // Ignore Bot - // Create new osu packet writer - const osuPacketWriter = new osu.Bancho.Writer; + // Create new osu packet writer + const osuPacketWriter = new osu.Bancho.Writer; - // Get user's class - const User = getUserById(id); + // Get user's class + const User = getUserById(id); - if (User == null) return; + if (User == null) return; - let UserStatusObject = { - userId: User.id, - status: User.actionID, - statusText: User.actionText, - beatmapChecksum: User.beatmapChecksum, - currentMods: User.currentMods, - playMode: User.playMode, - beatmapId: User.beatmapID, - rankedScore: User.rankedScore, - accuracy: User.accuracy / 100, // Scale of 0 to 1 - playCount: User.playCount, - totalScore: User.totalScore, - rank: User.rank, - performance: (User.rankingMode == 0 ? User.pp : 0) - }; + let UserStatusObject = { + userId: User.id, + status: User.actionID, + statusText: User.actionText, + beatmapChecksum: User.beatmapChecksum, + currentMods: User.currentMods, + playMode: User.playMode, + beatmapId: User.beatmapID, + rankedScore: User.rankedScore, + accuracy: User.accuracy / 100, // Scale of 0 to 1 + playCount: User.playCount, + totalScore: User.totalScore, + rank: User.rank, + performance: (User.rankingMode == 0 ? User.pp : 0) + }; - osuPacketWriter.HandleOsuUpdate(UserStatusObject); + osuPacketWriter.HandleOsuUpdate(UserStatusObject); - // Send data to user's queue - if (sendImmidiate) currentUser.addActionToQueue(osuPacketWriter.toBuffer); - else return osuPacketWriter.toBuffer; + // Send data to user's queue + if (sendImmidiate) currentUser.addActionToQueue(osuPacketWriter.toBuffer); + else return osuPacketWriter.toBuffer; } \ No newline at end of file diff --git a/server/Packets/TourneyJoinMatchChannel.js b/server/Packets/TourneyJoinMatchChannel.js index a7a6099..72c80db 100644 --- a/server/Packets/TourneyJoinMatchChannel.js +++ b/server/Packets/TourneyJoinMatchChannel.js @@ -1,26 +1,27 @@ -const osu = require("osu-packet"); +const osu = require("osu-packet"), + consoleHelper = require("./consoleHelper.js"); module.exports = function(CurrentUser, MatchID) { - const match = global.MultiplayerManager.getMatch(MatchID); + const match = global.MultiplayerManager.getMatch(MatchID); - if (match != null) { + if (match != null) { - match.isTourneyMatch = true; - for (let i = 0; i < global.userKeys.length; i++) { - if (global.users[global.userKeys[i]].id == CurrentUser.id) { - match.tourneyClientUsers.push(global.users[global.userKeys[i]]); - } - } + match.isTourneyMatch = true; + for (let i = 0; i < global.userKeys.length; i++) { + if (global.users[global.userKeys[i]].id == CurrentUser.id) { + match.tourneyClientUsers.push(global.users[global.userKeys[i]]); + } + } - if (global.StreamsHandler.isUserInStream(match.matchChatStreamName, CurrentUser.uuid)) - return global.consoleHelper.printBancho(`Did not add user to channel ${match.matchChatStreamName} because they are already in it`); + if (global.StreamsHandler.isUserInStream(match.matchChatStreamName, CurrentUser.uuid)) + return consoleHelper.printBancho(`Did not add user to channel ${match.matchChatStreamName} because they are already in it`); - const osuPacketWriter = new osu.Bancho.Writer; + const osuPacketWriter = new osu.Bancho.Writer; - osuPacketWriter.ChannelJoinSuccess("#multiplayer"); - if (!global.StreamsHandler.isUserInStream(match.matchChatStreamName, CurrentUser.uuid)) - global.StreamsHandler.addUserToStream(match.matchChatStreamName, CurrentUser.uuid); + osuPacketWriter.ChannelJoinSuccess("#multiplayer"); + if (!global.StreamsHandler.isUserInStream(match.matchChatStreamName, CurrentUser.uuid)) + global.StreamsHandler.addUserToStream(match.matchChatStreamName, CurrentUser.uuid); - CurrentUser.addActionToQueue(osuPacketWriter.toBuffer); - } + CurrentUser.addActionToQueue(osuPacketWriter.toBuffer); + } } \ No newline at end of file diff --git a/server/Packets/TourneyLeaveMatchChannel.js b/server/Packets/TourneyLeaveMatchChannel.js index 6a409b5..8fed8e3 100644 --- a/server/Packets/TourneyLeaveMatchChannel.js +++ b/server/Packets/TourneyLeaveMatchChannel.js @@ -1,30 +1,31 @@ -const osu = require("osu-packet"); +const osu = require("osu-packet"), + consoleHelper = require("../../consoleHelper.js"); module.exports = function(CurrentUser, MatchID) { - const match = global.MultiplayerManager.getMatch(MatchID); + const match = global.MultiplayerManager.getMatch(MatchID); - if (match != null) { + if (match != null) { - match.isTourneyMatch = false; - match.tourneyClientUsers = []; + match.isTourneyMatch = false; + match.tourneyClientUsers = []; - if (global.StreamsHandler.isUserInStream(match.matchChatStreamName, CurrentUser.uuid)) - return global.consoleHelper.printBancho(`Did not add user to channel ${match.matchChatStreamName} because they are already in it`); + if (global.StreamsHandler.isUserInStream(match.matchChatStreamName, CurrentUser.uuid)) + return consoleHelper.printBancho(`Did not add user to channel ${match.matchChatStreamName} because they are already in it`); - const osuPacketWriter = new osu.Bancho.Writer; + const osuPacketWriter = new osu.Bancho.Writer; - osuPacketWriter.ChannelRevoked("#multiplayer"); - if (!global.StreamsHandler.isUserInStream(match.matchChatStreamName, CurrentUser.uuid)) - global.StreamsHandler.removeUserFromStream(match.matchChatStreamName, CurrentUser.uuid); + osuPacketWriter.ChannelRevoked("#multiplayer"); + if (!global.StreamsHandler.isUserInStream(match.matchChatStreamName, CurrentUser.uuid)) + global.StreamsHandler.removeUserFromStream(match.matchChatStreamName, CurrentUser.uuid); - CurrentUser.addActionToQueue(osuPacketWriter.toBuffer); - } else { - // Still provide feedback just in case - // TODO: Check if this has any effect, if not then remove this. - const osuPacketWriter = new osu.Bancho.Writer; + CurrentUser.addActionToQueue(osuPacketWriter.toBuffer); + } else { + // Still provide feedback just in case + // TODO: Check if this has any effect, if not then remove this. + const osuPacketWriter = new osu.Bancho.Writer; - osuPacketWriter.ChannelRevoked("#multiplayer"); + osuPacketWriter.ChannelRevoked("#multiplayer"); - CurrentUser.addActionToQueue(osuPacketWriter.toBuffer); - } + CurrentUser.addActionToQueue(osuPacketWriter.toBuffer); + } } \ No newline at end of file diff --git a/server/Packets/TourneyMatchSpecialInfo.js b/server/Packets/TourneyMatchSpecialInfo.js index d537a08..15d96bf 100644 --- a/server/Packets/TourneyMatchSpecialInfo.js +++ b/server/Packets/TourneyMatchSpecialInfo.js @@ -1,22 +1,22 @@ const osu = require("osu-packet"), - UserPresence = require("./UserPresence.js"), - StatusUpdate = require("./StatusUpdate.js"); + UserPresence = require("./UserPresence.js"), + StatusUpdate = require("./StatusUpdate.js"); module.exports = function(CurrentUser, MatchID) { - const matchData = global.MultiplayerManager.getMatch(MatchID); + const matchData = global.MultiplayerManager.getMatch(MatchID); - if (matchData != null) { - const osuPacketWriter = new osu.Bancho.Writer(); + if (matchData != null) { + const osuPacketWriter = new osu.Bancho.Writer(); - osuPacketWriter.MatchUpdate(matchData.createOsuMatchJSON()); + osuPacketWriter.MatchUpdate(matchData.createOsuMatchJSON()); - // Queue info on all the users in the match to the client - for (let slot in matchData.slots) { - CurrentUser.addActionToQueue(UserPresence(CurrentUser, slot.playerId, false)); - CurrentUser.addActionToQueue(StatusUpdate(CurrentUser, slot.playerId, false)); - } + // Queue info on all the users in the match to the client + for (let slot in matchData.slots) { + CurrentUser.addActionToQueue(UserPresence(CurrentUser, slot.playerId, false)); + CurrentUser.addActionToQueue(StatusUpdate(CurrentUser, slot.playerId, false)); + } - // Queue data - CurrentUser.addActionToQueue(osuPacketWriter.toBuffer); - } + // Queue data + CurrentUser.addActionToQueue(osuPacketWriter.toBuffer); + } } \ No newline at end of file diff --git a/server/Packets/UserPresence.js b/server/Packets/UserPresence.js index d84d85c..d9c5e3a 100644 --- a/server/Packets/UserPresence.js +++ b/server/Packets/UserPresence.js @@ -1,24 +1,24 @@ const osu = require("osu-packet"), - getUserById = require("../util/getUserById.js"); + getUserById = require("../util/getUserById.js"); module.exports = function(currentUser, id = 0, sendImmidiate = true) { - const osuPacketWriter = new osu.Bancho.Writer; + const osuPacketWriter = new osu.Bancho.Writer; - const User = getUserById(id); + const User = getUserById(id); - if (User == null) return; + if (User == null) return; - osuPacketWriter.UserPresence({ - userId: id, - username: User.username, - timezone: 0, - countryId: User.countryID, - permissions: 4, - longitude: User.location[1], - latitude: User.location[0], - rank: User.rank - }); + osuPacketWriter.UserPresence({ + userId: id, + username: User.username, + timezone: 0, + countryId: User.countryID, + permissions: 4, + longitude: User.location[1], + latitude: User.location[0], + rank: User.rank + }); - if (sendImmidiate) currentUser.addActionToQueue(osuPacketWriter.toBuffer); - else return osuPacketWriter.toBuffer; + if (sendImmidiate) currentUser.addActionToQueue(osuPacketWriter.toBuffer); + else return osuPacketWriter.toBuffer; } \ No newline at end of file diff --git a/server/Packets/UserPresenceBundle.js b/server/Packets/UserPresenceBundle.js index 4db3bdd..21a226d 100644 --- a/server/Packets/UserPresenceBundle.js +++ b/server/Packets/UserPresenceBundle.js @@ -1,16 +1,16 @@ const osu = require("osu-packet"); module.exports = function(currentUser, sendImmidiate = true) { - const osuPacketWriter = new osu.Bancho.Writer; + const osuPacketWriter = new osu.Bancho.Writer; - let userIds = []; + let userIds = []; - for (let i = 0; i < global.userKeys.length; i++) { - userIds.push(global.users[global.userKeys[i]].id); - } + for (let i = 0; i < global.userKeys.length; i++) { + userIds.push(global.users[global.userKeys[i]].id); + } - osuPacketWriter.UserPresenceBundle(userIds); + osuPacketWriter.UserPresenceBundle(userIds); - if (sendImmidiate) currentUser.addActionToQueue(osuPacketWriter.toBuffer); - else return osuPacketWriter.toBuffer; + if (sendImmidiate) currentUser.addActionToQueue(osuPacketWriter.toBuffer); + else return osuPacketWriter.toBuffer; } \ No newline at end of file diff --git a/server/Packets/UserStatsRequest.js b/server/Packets/UserStatsRequest.js index 6b9d4ce..8291be7 100644 --- a/server/Packets/UserStatsRequest.js +++ b/server/Packets/UserStatsRequest.js @@ -1,14 +1,14 @@ const UserPresenceBundle = require("./UserPresenceBundle.js"), - UserPresence = require("./UserPresence.js"), - StatusUpdate = require("./StatusUpdate.js"); + UserPresence = require("./UserPresence.js"), + StatusUpdate = require("./StatusUpdate.js"); module.exports = function (currentUser, data = [0]) { - UserPresenceBundle(currentUser); + UserPresenceBundle(currentUser); - for (let i1 = 0; i1 < data.length; i1++) { - const CurrentUserID = data[i1]; + for (let i1 = 0; i1 < data.length; i1++) { + const CurrentUserID = data[i1]; - UserPresence(currentUser, CurrentUserID); - StatusUpdate(currentUser, CurrentUserID); - } + UserPresence(currentUser, CurrentUserID); + StatusUpdate(currentUser, CurrentUserID); + } } \ No newline at end of file diff --git a/server/Spectator.js b/server/Spectator.js index b8a28b7..5989cf1 100644 --- a/server/Spectator.js +++ b/server/Spectator.js @@ -1,75 +1,75 @@ const osu = require("osu-packet"), - getUserById = require("./util/getUserById.js"); + getUserById = require("./util/getUserById.js"); module.exports = { - startSpectatingUser:function(currentUser, spectatedId) { - // Get the user this user is trying to spectate - const User = getUserById(spectatedId); - if (global.StreamsHandler.doesStreamExist(`sp_${User.id}`)) { - // Just add user to stream since it already exists - global.StreamsHandler.addUserToStream(`sp_${User.id}`, currentUser.uuid); - } else { - // Stream doesn't exist, create it and add the spectator - global.StreamsHandler.addStream(`sp_${User.id}`, true, spectatedId); - global.StreamsHandler.addUserToStream(`sp_${User.id}`, currentUser.uuid); - } + startSpectatingUser:function(currentUser, spectatedId) { + // Get the user this user is trying to spectate + const User = getUserById(spectatedId); + if (global.StreamsHandler.doesStreamExist(`sp_${User.id}`)) { + // Just add user to stream since it already exists + global.StreamsHandler.addUserToStream(`sp_${User.id}`, currentUser.uuid); + } else { + // Stream doesn't exist, create it and add the spectator + global.StreamsHandler.addStream(`sp_${User.id}`, true, spectatedId); + global.StreamsHandler.addUserToStream(`sp_${User.id}`, currentUser.uuid); + } - // We want to do this stuff regardless - // Create a new osu packet writer - let osuPacketWriter = new osu.Bancho.Writer; + // We want to do this stuff regardless + // Create a new osu packet writer + let osuPacketWriter = new osu.Bancho.Writer; - // Set the user requesting to be spectating this user - currentUser.spectating = spectatedId; - - // Tell the client of the user being spectated that they are being spectated - osuPacketWriter.SpectatorJoined(currentUser.id); + // Set the user requesting to be spectating this user + currentUser.spectating = spectatedId; + + // Tell the client of the user being spectated that they are being spectated + osuPacketWriter.SpectatorJoined(currentUser.id); - // Send the packet to the spectated user's queue - User.addActionToQueue(osuPacketWriter.toBuffer); + // Send the packet to the spectated user's queue + User.addActionToQueue(osuPacketWriter.toBuffer); - // Make a new clear osu packet writer - osuPacketWriter = new osu.Bancho.Writer; + // Make a new clear osu packet writer + osuPacketWriter = new osu.Bancho.Writer; - // Tell everyone spectating this user that another user has started spectating - osuPacketWriter.FellowSpectatorJoined(currentUser.id); + // Tell everyone spectating this user that another user has started spectating + osuPacketWriter.FellowSpectatorJoined(currentUser.id); - // Send this packet to all the spectators - global.StreamsHandler.sendToStream(`sp_${User.id}`, osuPacketWriter.toBuffer); - }, + // Send this packet to all the spectators + global.StreamsHandler.sendToStream(`sp_${User.id}`, osuPacketWriter.toBuffer); + }, - sendSpectatorFrames(currentUser, data) { - // Create new osu packet writer - const osuPacketWriter = new osu.Bancho.Writer; + sendSpectatorFrames(currentUser, data) { + // Create new osu packet writer + const osuPacketWriter = new osu.Bancho.Writer; - // Data containing the user's actions - osuPacketWriter.SpectateFrames(data); + // Data containing the user's actions + osuPacketWriter.SpectateFrames(data); - // Send the frames to all the spectators - global.StreamsHandler.sendToStream(`sp_${currentUser.id}`, osuPacketWriter.toBuffer, null); - }, + // Send the frames to all the spectators + global.StreamsHandler.sendToStream(`sp_${currentUser.id}`, osuPacketWriter.toBuffer, null); + }, - stopSpectatingUser(currentUser) { - // Get the user this user is spectating - const spectatedUser = getUserById(currentUser.spectating); - // Create new osu packet writer - let osuPacketWriter = new osu.Bancho.Writer; + stopSpectatingUser(currentUser) { + // Get the user this user is spectating + const spectatedUser = getUserById(currentUser.spectating); + // Create new osu packet writer + let osuPacketWriter = new osu.Bancho.Writer; - // Inform the client being spectated that this user has stopped spectating - osuPacketWriter.SpectatorLeft(currentUser.id); + // Inform the client being spectated that this user has stopped spectating + osuPacketWriter.SpectatorLeft(currentUser.id); - // Add this packet to the spectated user's queue - spectatedUser.addActionToQueue(osuPacketWriter.toBuffer); + // Add this packet to the spectated user's queue + spectatedUser.addActionToQueue(osuPacketWriter.toBuffer); - // Remove this user from the spectator stream - global.StreamsHandler.removeUserFromStream(`sp_${spectatedUser.id}`, currentUser.uuid); + // Remove this user from the spectator stream + global.StreamsHandler.removeUserFromStream(`sp_${spectatedUser.id}`, currentUser.uuid); - // Make a new clear osu packet writer - osuPacketWriter = new osu.Bancho.Writer; + // Make a new clear osu packet writer + osuPacketWriter = new osu.Bancho.Writer; - // Inform other users spectating that this spectator has left - osuPacketWriter.FellowSpectatorLeft(currentUser.id); + // Inform other users spectating that this spectator has left + osuPacketWriter.FellowSpectatorLeft(currentUser.id); - // Send this packet to all spectators - global.StreamsHandler.sendToStream(`sp_${spectatedUser.id}`, osuPacketWriter.toBuffer); - } + // Send this packet to all spectators + global.StreamsHandler.sendToStream(`sp_${spectatedUser.id}`, osuPacketWriter.toBuffer); + } } \ No newline at end of file diff --git a/server/Streams.js b/server/Streams.js index d0fb3a2..ee7669b 100644 --- a/server/Streams.js +++ b/server/Streams.js @@ -1,135 +1,136 @@ -const getUserByToken = require("./util/getUserByToken.js"); +const getUserByToken = require("./util/getUserByToken.js"), + consoleHelper = require("../consoleHelper.js"); module.exports = class { - constructor() { - this.avaliableStreams = {}; - this.avaliableStreamKeys = []; - } + constructor() { + this.avaliableStreams = {}; + this.avaliableStreamKeys = []; + } - addStream(streamName = "", removeIfEmpty = false, spectatorHostId = null) { - // Make sure a stream with the same name doesn't exist already - if (this.avaliableStreamKeys.includes(streamName)) - return global.consoleHelper.printBancho(`Did not add stream [${streamName}] A stream with the same name already exists`); - // Add new stream to the list of streams - this.avaliableStreams[streamName] = { - streamUsers: [], // An array containing a list of user tokens of the users in a given stream - streamSpectatorHost: spectatorHostId, // null unless stream is for spectating - removeIfEmpty: removeIfEmpty - } - this.avaliableStreamKeys = Object.keys(this.avaliableStreams); - global.consoleHelper.printBancho(`Added stream [${streamName}]`); - } + addStream(streamName = "", removeIfEmpty = false, spectatorHostId = null) { + // Make sure a stream with the same name doesn't exist already + if (this.avaliableStreamKeys.includes(streamName)) + return consoleHelper.printBancho(`Did not add stream [${streamName}] A stream with the same name already exists`); + // Add new stream to the list of streams + this.avaliableStreams[streamName] = { + streamUsers: [], // An array containing a list of user tokens of the users in a given stream + streamSpectatorHost: spectatorHostId, // null unless stream is for spectating + removeIfEmpty: removeIfEmpty + } + this.avaliableStreamKeys = Object.keys(this.avaliableStreams); + consoleHelper.printBancho(`Added stream [${streamName}]`); + } - // Checks if a stream has no users in it - streamChecker(interval = 5000) { - setInterval(() => { - // Get the names of all currently avaliable streams - const streams = global.StreamsHandler.getStreams(); - // Loop through all streams - for (let i = 0; i < streams.length; i++) { - // Get the current stream - const currentStream = global.StreamsHandler.avaliableStreams[streams[i]]; - // Check if the stream should be removed if there are no users in it - // And if the stream has no users in it - if (currentStream.removeIfEmpty && currentStream.streamUsers.length == 0) { - global.StreamsHandler.removeStream(streams[i]); - global.consoleHelper.printBancho(`Removed stream [${streams[i]}] There were no users in stream`); - } - } - }, interval); - global.consoleHelper.printBancho(`BinatoStream is running! Checks running at a ${interval}ms interval`); - } + // Checks if a stream has no users in it + streamChecker(interval = 5000) { + setInterval(() => { + // Get the names of all currently avaliable streams + const streams = global.StreamsHandler.getStreams(); + // Loop through all streams + for (let i = 0; i < streams.length; i++) { + // Get the current stream + const currentStream = global.StreamsHandler.avaliableStreams[streams[i]]; + // Check if the stream should be removed if there are no users in it + // And if the stream has no users in it + if (currentStream.removeIfEmpty && currentStream.streamUsers.length == 0) { + global.StreamsHandler.removeStream(streams[i]); + consoleHelper.printBancho(`Removed stream [${streams[i]}] There were no users in stream`); + } + } + }, interval); + consoleHelper.printBancho(`BinatoStream is running! Checks running at a ${interval}ms interval`); + } - sendToStream(streamName, streamData, initUser = null) { - // Make sure the stream we are attempting to send to even exists - if (!this.doesStreamExist(streamName)) - return global.consoleHelper.printBancho(`Did not send to stream [${streamName}] because it does not exist!`); + sendToStream(streamName, streamData, initUser = null) { + // Make sure the stream we are attempting to send to even exists + if (!this.doesStreamExist(streamName)) + return consoleHelper.printBancho(`Did not send to stream [${streamName}] because it does not exist!`); - // Get the stream to send the data to - const currentStream = this.avaliableStreams[streamName]; + // Get the stream to send the data to + const currentStream = this.avaliableStreams[streamName]; - // Loop through the users in this stream - for (let i = 0; i < currentStream.streamUsers.length; i++) { - // Get the user token of the user in the queue - const currentUserToken = currentStream.streamUsers[i]; - // Make sure we don't send this data back to the user requesting this data to be sent - if (initUser != null && currentUserToken == initUser && (streamName[0] == "#" || streamName.includes("mp_"))) continue; - if (currentUserToken == 3) continue; // Skip if user is bot + // Loop through the users in this stream + for (let i = 0; i < currentStream.streamUsers.length; i++) { + // Get the user token of the user in the queue + const currentUserToken = currentStream.streamUsers[i]; + // Make sure we don't send this data back to the user requesting this data to be sent + if (initUser != null && currentUserToken == initUser && (streamName[0] == "#" || streamName.includes("mp_"))) continue; + if (currentUserToken == 3) continue; // Skip if user is bot - // Get user object - const currentUser = getUserByToken(currentUserToken); - // Skip if user is nonexistant - if (currentUser == null) continue; + // Get user object + const currentUser = getUserByToken(currentUserToken); + // Skip if user is nonexistant + if (currentUser == null) continue; - // Send stream data to user's own queue - currentUser.addActionToQueue(streamData); - } - } + // Send stream data to user's own queue + currentUser.addActionToQueue(streamData); + } + } - addUserToStream(streamName, userToken) { - // Make sure the stream we are attempting to add this user to even exists - if (!this.doesStreamExist(streamName)) - return global.consoleHelper.printBancho(`Did not add user to stream [${streamName}] because it does not exist!`); + addUserToStream(streamName, userToken) { + // Make sure the stream we are attempting to add this user to even exists + if (!this.doesStreamExist(streamName)) + return consoleHelper.printBancho(`Did not add user to stream [${streamName}] because it does not exist!`); - // Make sure the user isn't already in the stream - if (this.avaliableStreams[streamName].streamUsers.includes(userToken)) - return global.consoleHelper.printBancho(`Did not add user to stream [${streamName}] because they are already in it!`); + // Make sure the user isn't already in the stream + if (this.avaliableStreams[streamName].streamUsers.includes(userToken)) + return consoleHelper.printBancho(`Did not add user to stream [${streamName}] because they are already in it!`); - // Make sure this isn't an invalid user (userId can't be lower than 1) - if (userToken == "" || userToken == null) - return global.consoleHelper.printBancho(`Did not add user to stream [${streamName}] because their token is invalid!`); + // Make sure this isn't an invalid user (userId can't be lower than 1) + if (userToken == "" || userToken == null) + return consoleHelper.printBancho(`Did not add user to stream [${streamName}] because their token is invalid!`); - // Add user's token to the stream's user list - this.avaliableStreams[streamName].streamUsers.push(userToken); - global.consoleHelper.printBancho(`Added user [${userToken}] to stream ${streamName}`); - } + // Add user's token to the stream's user list + this.avaliableStreams[streamName].streamUsers.push(userToken); + consoleHelper.printBancho(`Added user [${userToken}] to stream ${streamName}`); + } - removeUserFromStream(streamName, userToken) { - // Make sure the stream we are attempting to add this user to even exists - if (!this.doesStreamExist(streamName)) - return global.consoleHelper.printBancho(`Did not remove user from stream [${streamName}] because it does not exist!`); + removeUserFromStream(streamName, userToken) { + // Make sure the stream we are attempting to add this user to even exists + if (!this.doesStreamExist(streamName)) + return consoleHelper.printBancho(`Did not remove user from stream [${streamName}] because it does not exist!`); - // Make sure the user isn't already in the stream - if (!this.avaliableStreams[streamName].streamUsers.includes(userToken)) - return global.consoleHelper.printBancho(`Did not remove user from stream [${streamName}] because they are not in it!`); + // Make sure the user isn't already in the stream + if (!this.avaliableStreams[streamName].streamUsers.includes(userToken)) + return consoleHelper.printBancho(`Did not remove user from stream [${streamName}] because they are not in it!`); - // Make sure this isn't an invalid user (userId can't be lower than 1) - if (userToken == "" || userToken == null) - return global.consoleHelper.printBancho(`Did not remove user from stream [${streamName}] because their userId is invalid!`); - try { - // Find index of user to remove - let userCurrentIndex; - for (let i = 0; i < this.avaliableStreams[streamName].streamUsers.length; i++) { - if (userToken == this.avaliableStreams[streamName].streamUsers[i]) { - userCurrentIndex = i; - break; - } - } + // Make sure this isn't an invalid user (userId can't be lower than 1) + if (userToken == "" || userToken == null) + return consoleHelper.printBancho(`Did not remove user from stream [${streamName}] because their userId is invalid!`); + try { + // Find index of user to remove + let userCurrentIndex; + for (let i = 0; i < this.avaliableStreams[streamName].streamUsers.length; i++) { + if (userToken == this.avaliableStreams[streamName].streamUsers[i]) { + userCurrentIndex = i; + break; + } + } - // Remove user from stream's user list - this.avaliableStreams[streamName].streamUsers.splice(userCurrentIndex, 1); - global.consoleHelper.printBancho(`Removed user [${userToken}] from stream ${streamName}`); - } catch (e) { global.consoleHelper.printBancho(`Can't Remove user [${userToken}] from stream ${streamName}`); } - } + // Remove user from stream's user list + this.avaliableStreams[streamName].streamUsers.splice(userCurrentIndex, 1); + consoleHelper.printBancho(`Removed user [${userToken}] from stream ${streamName}`); + } catch (e) { consoleHelper.printBancho(`Can't Remove user [${userToken}] from stream ${streamName}`); } + } - doesStreamExist(streamName) { - return this.avaliableStreamKeys.includes(streamName); - } + doesStreamExist(streamName) { + return this.avaliableStreamKeys.includes(streamName); + } - getStreams() { - // Return the names of all avaliable streams - return this.avaliableStreamKeys; - } + getStreams() { + // Return the names of all avaliable streams + return this.avaliableStreamKeys; + } - isUserInStream(streamName, userToken) { - if (this.avaliableStreams[streamName].streamUsers.includes(userToken)) return true; - else return false; - } + isUserInStream(streamName, userToken) { + if (this.avaliableStreams[streamName].streamUsers.includes(userToken)) return true; + else return false; + } - removeStream(streamName) { - try { - delete this.avaliableStreams[streamName]; - this.avaliableStreamKeys = Object.keys(this.avaliableStreams); - } catch (e) { global.consoleHelper.printError(`Was not able to remove stream [${streamName}]`) } - } + removeStream(streamName) { + try { + delete this.avaliableStreams[streamName]; + this.avaliableStreamKeys = Object.keys(this.avaliableStreams); + } catch (e) { consoleHelper.printError(`Was not able to remove stream [${streamName}]`) } + } } \ No newline at end of file diff --git a/server/bakedResponses.js b/server/bakedResponses.js index 9e58b15..e4cfff4 100644 --- a/server/bakedResponses.js +++ b/server/bakedResponses.js @@ -1,9 +1,9 @@ module.exports = function(s) { - switch (s) { - case "reconnect": - return "\u0005\u0000\u0000\u0004\u0000\u0000\u0000����\u0018\u0000\u0000\u0011\u0000\u0000\u0000\u000b\u000fReconnecting..."; + switch (s) { + case "reconnect": + return "\u0005\u0000\u0000\u0004\u0000\u0000\u0000����\u0018\u0000\u0000\u0011\u0000\u0000\u0000\u000b\u000fReconnecting..."; - default: - return Buffer.alloc(0); - } + default: + return Buffer.alloc(0); + } } \ No newline at end of file diff --git a/server/countryHelper.js b/server/countryHelper.js index 82438b2..b33a875 100644 --- a/server/countryHelper.js +++ b/server/countryHelper.js @@ -1,274 +1,274 @@ const countryCodes = { - "LV": 132, - "AD": 3, - "LT": 130, - "KM": 116, - "QA": 182, - "VA": 0, - "PK": 173, - "KI": 115, - "SS": 0, - "KH": 114, - "NZ": 166, - "TO": 215, - "KZ": 122, - "GA": 76, - "BW": 35, - "AX": 247, - "GE": 79, - "UA": 222, - "CR": 50, - "AE": 0, - "NE": 157, - "ZA": 240, - "SK": 196, - "BV": 34, - "SH": 0, - "PT": 179, - "SC": 189, - "CO": 49, - "GP": 86, - "GY": 93, - "CM": 47, - "TJ": 211, - "AF": 5, - "IE": 101, - "AL": 8, - "BG": 24, - "JO": 110, - "MU": 149, - "PM": 0, - "LA": 0, - "IO": 104, - "KY": 121, - "SA": 187, - "KN": 0, - "OM": 167, - "CY": 54, - "BQ": 0, - "BT": 33, - "WS": 236, - "ES": 67, - "LR": 128, - "RW": 186, - "AQ": 12, - "PW": 180, - "JE": 250, - "TN": 214, - "ZW": 243, - "JP": 111, - "BB": 20, - "VN": 233, - "HN": 96, - "KP": 0, - "WF": 235, - "EC": 62, - "HU": 99, - "GF": 80, - "GQ": 87, - "TW": 220, - "MC": 135, - "BE": 22, - "PN": 176, - "SZ": 205, - "CZ": 55, - "LY": 0, - "IN": 103, - "FM": 0, - "PY": 181, - "PH": 172, - "MN": 142, - "GG": 248, - "CC": 39, - "ME": 242, - "DO": 60, - "KR": 0, - "PL": 174, - "MT": 148, - "MM": 141, - "AW": 17, - "MV": 150, - "BD": 21, - "NR": 164, - "AT": 15, - "GW": 92, - "FR": 74, - "LI": 126, - "CF": 41, - "DZ": 61, - "MA": 134, - "VG": 0, - "NC": 156, - "IQ": 105, - "BN": 0, - "BF": 23, - "BO": 30, - "GB": 77, - "CU": 51, - "LU": 131, - "YT": 238, - "NO": 162, - "SM": 198, - "GL": 83, - "IS": 107, - "AO": 11, - "MH": 138, - "SE": 191, - "ZM": 241, - "FJ": 70, - "SL": 197, - "CH": 43, - "RU": 0, - "CW": 0, - "CX": 53, - "TF": 208, - "NL": 161, - "AU": 16, - "FI": 69, - "MS": 147, - "GH": 81, - "BY": 36, - "IL": 102, - "VC": 0, - "NG": 159, - "HT": 98, - "LS": 129, - "MR": 146, - "YE": 237, - "MP": 144, - "SX": 0, - "RE": 183, - "RO": 184, - "NP": 163, - "CG": 0, - "FO": 73, - "CI": 0, - "TH": 210, - "HK": 94, - "TK": 212, - "XK": 0, - "DM": 59, - "LC": 0, - "ID": 100, - "MG": 137, - "JM": 109, - "IT": 108, - "CA": 38, - "TZ": 221, - "GI": 82, - "KG": 113, - "NU": 165, - "TV": 219, - "LB": 124, - "SY": 0, - "PR": 177, - "NI": 160, - "KE": 112, - "MO": 0, - "SR": 201, - "VI": 0, - "SV": 203, - "HM": 0, - "CD": 0, - "BI": 26, - "BM": 28, - "MW": 151, - "TM": 213, - "GT": 90, - "AG": 0, - "UM": 0, - "US": 225, - "AR": 13, - "DJ": 57, - "KW": 120, - "MY": 153, - "FK": 71, - "EG": 64, - "BA": 0, - "CN": 48, - "GN": 85, - "PS": 178, - "SO": 200, - "IM": 249, - "GS": 0, - "BR": 31, - "GM": 84, - "PF": 170, - "PA": 168, - "PG": 171, - "BH": 25, - "TG": 209, - "GU": 91, - "CK": 45, - "MF": 252, - "VE": 230, - "CL": 46, - "TR": 217, - "UG": 223, - "GD": 78, - "TT": 218, - "TL": 0, - "MD": 0, - "MK": 0, - "ST": 202, - "CV": 52, - "MQ": 145, - "GR": 88, - "HR": 97, - "BZ": 37, - "UZ": 227, - "DK": 58, - "SN": 199, - "ET": 68, - "VU": 234, - "ER": 66, - "BJ": 27, - "LK": 127, - "NA": 155, - "AS": 14, - "SG": 192, - "PE": 169, - "IR": 0, - "MX": 152, - "TD": 207, - "AZ": 18, - "AM": 9, - "BL": 0, - "SJ": 195, - "SB": 188, - "NF": 158, - "RS": 239, - "DE": 56, - "EH": 65, - "EE": 63, - "SD": 190, - "ML": 140, - "TC": 206, - "MZ": 154, - "BS": 32, - "UY": 226, - "SI": 194, - "AI": 7 + "LV": 132, + "AD": 3, + "LT": 130, + "KM": 116, + "QA": 182, + "VA": 0, + "PK": 173, + "KI": 115, + "SS": 0, + "KH": 114, + "NZ": 166, + "TO": 215, + "KZ": 122, + "GA": 76, + "BW": 35, + "AX": 247, + "GE": 79, + "UA": 222, + "CR": 50, + "AE": 0, + "NE": 157, + "ZA": 240, + "SK": 196, + "BV": 34, + "SH": 0, + "PT": 179, + "SC": 189, + "CO": 49, + "GP": 86, + "GY": 93, + "CM": 47, + "TJ": 211, + "AF": 5, + "IE": 101, + "AL": 8, + "BG": 24, + "JO": 110, + "MU": 149, + "PM": 0, + "LA": 0, + "IO": 104, + "KY": 121, + "SA": 187, + "KN": 0, + "OM": 167, + "CY": 54, + "BQ": 0, + "BT": 33, + "WS": 236, + "ES": 67, + "LR": 128, + "RW": 186, + "AQ": 12, + "PW": 180, + "JE": 250, + "TN": 214, + "ZW": 243, + "JP": 111, + "BB": 20, + "VN": 233, + "HN": 96, + "KP": 0, + "WF": 235, + "EC": 62, + "HU": 99, + "GF": 80, + "GQ": 87, + "TW": 220, + "MC": 135, + "BE": 22, + "PN": 176, + "SZ": 205, + "CZ": 55, + "LY": 0, + "IN": 103, + "FM": 0, + "PY": 181, + "PH": 172, + "MN": 142, + "GG": 248, + "CC": 39, + "ME": 242, + "DO": 60, + "KR": 0, + "PL": 174, + "MT": 148, + "MM": 141, + "AW": 17, + "MV": 150, + "BD": 21, + "NR": 164, + "AT": 15, + "GW": 92, + "FR": 74, + "LI": 126, + "CF": 41, + "DZ": 61, + "MA": 134, + "VG": 0, + "NC": 156, + "IQ": 105, + "BN": 0, + "BF": 23, + "BO": 30, + "GB": 77, + "CU": 51, + "LU": 131, + "YT": 238, + "NO": 162, + "SM": 198, + "GL": 83, + "IS": 107, + "AO": 11, + "MH": 138, + "SE": 191, + "ZM": 241, + "FJ": 70, + "SL": 197, + "CH": 43, + "RU": 0, + "CW": 0, + "CX": 53, + "TF": 208, + "NL": 161, + "AU": 16, + "FI": 69, + "MS": 147, + "GH": 81, + "BY": 36, + "IL": 102, + "VC": 0, + "NG": 159, + "HT": 98, + "LS": 129, + "MR": 146, + "YE": 237, + "MP": 144, + "SX": 0, + "RE": 183, + "RO": 184, + "NP": 163, + "CG": 0, + "FO": 73, + "CI": 0, + "TH": 210, + "HK": 94, + "TK": 212, + "XK": 0, + "DM": 59, + "LC": 0, + "ID": 100, + "MG": 137, + "JM": 109, + "IT": 108, + "CA": 38, + "TZ": 221, + "GI": 82, + "KG": 113, + "NU": 165, + "TV": 219, + "LB": 124, + "SY": 0, + "PR": 177, + "NI": 160, + "KE": 112, + "MO": 0, + "SR": 201, + "VI": 0, + "SV": 203, + "HM": 0, + "CD": 0, + "BI": 26, + "BM": 28, + "MW": 151, + "TM": 213, + "GT": 90, + "AG": 0, + "UM": 0, + "US": 225, + "AR": 13, + "DJ": 57, + "KW": 120, + "MY": 153, + "FK": 71, + "EG": 64, + "BA": 0, + "CN": 48, + "GN": 85, + "PS": 178, + "SO": 200, + "IM": 249, + "GS": 0, + "BR": 31, + "GM": 84, + "PF": 170, + "PA": 168, + "PG": 171, + "BH": 25, + "TG": 209, + "GU": 91, + "CK": 45, + "MF": 252, + "VE": 230, + "CL": 46, + "TR": 217, + "UG": 223, + "GD": 78, + "TT": 218, + "TL": 0, + "MD": 0, + "MK": 0, + "ST": 202, + "CV": 52, + "MQ": 145, + "GR": 88, + "HR": 97, + "BZ": 37, + "UZ": 227, + "DK": 58, + "SN": 199, + "ET": 68, + "VU": 234, + "ER": 66, + "BJ": 27, + "LK": 127, + "NA": 155, + "AS": 14, + "SG": 192, + "PE": 169, + "IR": 0, + "MX": 152, + "TD": 207, + "AZ": 18, + "AM": 9, + "BL": 0, + "SJ": 195, + "SB": 188, + "NF": 158, + "RS": 239, + "DE": 56, + "EH": 65, + "EE": 63, + "SD": 190, + "ML": 140, + "TC": 206, + "MZ": 154, + "BS": 32, + "UY": 226, + "SI": 194, + "AI": 7 } const countryCodeKeys = Object.keys(countryCodes); module.exports = { - getCountryID:function(code = "") { - // Get id of a country from a 2 char code - code = code.toUpperCase(); - if (countryCodes[code] != null) return countryCodes[code]; - else return 0; - }, + getCountryID:function(code = "") { + // Get id of a country from a 2 char code + code = code.toUpperCase(); + if (countryCodes[code] != null) return countryCodes[code]; + else return 0; + }, - getCountryLetters:function(code) { - // Get country char code from id - for (var i = 0; i < countryCodes.length; i++) { - const countryId = countryCodes[countryCodeKeys[i]]; - if (countryId === code) return countryId; - } - return "XX"; - } + getCountryLetters:function(code) { + // Get country char code from id + for (var i = 0; i < countryCodes.length; i++) { + const countryId = countryCodes[countryCodeKeys[i]]; + if (countryId === code) return countryId; + } + return "XX"; + } } module.exports.countryCodes = countryCodes; \ No newline at end of file diff --git a/server/loginHandler.js b/server/loginHandler.js index 319919a..f3dcd15 100644 --- a/server/loginHandler.js +++ b/server/loginHandler.js @@ -1,158 +1,160 @@ const osu = require("osu-packet"), - User = require("./User.js"), - uuid = require("./util/shortUUID.js"), - ahttp = require("./util/AsyncHttpRequest.js"), - RequestType = require("./util/RequestType.json"), - - getUserByUsername = require("./util/getUserByUsername.js"), - getUserByToken = require("./util/getUserByToken.js"), - countryHelper = require("./countryHelper.js"), - loginHelper = require("./loginHelper.js"), - UserPresenceBundle = require("./Packets/UserPresenceBundle.js"), - UserPresence = require("./Packets/UserPresence.js"), - StatusUpdate = require("./Packets/StatusUpdate.js"); + User = require("./User.js"), + uuid = require("./util/shortUUID.js"), + ahttp = require("./util/AsyncHttpRequest.js"), + RequestType = require("./util/RequestType.json"), + consoleHelper = require("../consoleHelper.js"), + + // Packets + getUserByUsername = require("./util/getUserByUsername.js"), + getUserByToken = require("./util/getUserByToken.js"), + countryHelper = require("./countryHelper.js"), + loginHelper = require("./loginHelper.js"), + UserPresenceBundle = require("./Packets/UserPresenceBundle.js"), + UserPresence = require("./Packets/UserPresence.js"), + StatusUpdate = require("./Packets/StatusUpdate.js"); module.exports = async function(req, res, loginInfo) { - // Get time at the start of login - const loginStartTime = new Date().getTime(), - isTourneyClient = loginInfo.osuversion.includes("tourney"); + // Get time at the start of login + const loginStartTime = Date.now(), + isTourneyClient = loginInfo.osuversion.includes("tourney"); - // Check login - const loginCheck = await loginHelper.checkLogin(loginInfo); - if (loginCheck != null) { - res.writeHead(200, loginCheck[1]); - return res.end(loginCheck[0]); - } + // Check login + const loginCheck = await loginHelper.checkLogin(loginInfo); + if (loginCheck != null) { + res.writeHead(200, loginCheck[1]); + return res.end(loginCheck[0]); + } - // Get users IP for getting location - // Get cloudflare requestee IP first - let requestIP = req.get("cf-connecting-ip"); + // Get users IP for getting location + // Get cloudflare requestee IP first + let requestIP = req.get("cf-connecting-ip"); - // Get IP of requestee since we are probably behind a reverse proxy - if (requestIP == null) - requestIP = req.get("X-Real-IP"); + // Get IP of requestee since we are probably behind a reverse proxy + if (requestIP == null) + requestIP = req.get("X-Real-IP"); - // Just get the requestee IP (we are not behind a reverse proxy) - if (requestIP == null) - requestIP = req.remote_addr; + // Just get the requestee IP (we are not behind a reverse proxy) + if (requestIP == null) + requestIP = req.remote_addr; - // Make sure requestIP is never null - if (requestIP == null) - requestIP = ""; + // Make sure requestIP is never null + if (requestIP == null) + requestIP = ""; - - let userLocationData = [], userLocation; - // Check if it is a local or null IP - if (requestIP.includes("192.168.") || requestIP.includes("127.0.") || requestIP == "") { - // Set location to null island - userLocationData.country = "XX"; - userLocation = [0, 0]; - } else { - // Get user's location using zxq - userLocationData = await ahttp(`http://ip.zxq.co/${requestIP}`, RequestType.JSON); - userLocation = userLocationData.loc.split(","); - } + + let userLocationData = [], userLocation; + // Check if it is a local or null IP + if (requestIP.includes("192.168.") || requestIP.includes("127.0.") || requestIP == "") { + // Set location to null island + userLocationData.country = "XX"; + userLocation = [0, 0]; + } else { + // Get user's location using zxq + userLocationData = await ahttp(`http://ip.zxq.co/${requestIP}`, RequestType.JSON); + userLocation = userLocationData.loc.split(","); + } - // Get information about the user from the database - const userDB = await global.DatabaseHelper.query(`SELECT id FROM users_info WHERE username = "${loginInfo.username}" LIMIT 1`); + // Get information about the user from the database + const userDB = await global.DatabaseHelper.query(`SELECT id FROM users_info WHERE username = "${loginInfo.username}" LIMIT 1`); - // Create a token for the client - const newClientToken = uuid(); + // Create a token for the client + const newClientToken = uuid(); - // Make sure user is not already connected, kick off if so. - const checkForPreexistingUser = getUserByUsername(loginInfo.username); - if (checkForPreexistingUser != null && !isTourneyClient) { - for (let i = 0; i < global.userKeys.length; i++) { - const user = global.users[global.userKeys[i]]; - // Make sure they are not a tourney user - if (!user.isTourneyUser && user.uuid != newClientToken) { - global.removeUser(user); - } - } - } + // Make sure user is not already connected, kick off if so. + const checkForPreexistingUser = getUserByUsername(loginInfo.username); + if (checkForPreexistingUser != null && !isTourneyClient) { + for (let i = 0; i < global.userKeys.length; i++) { + const user = global.users[global.userKeys[i]]; + // Make sure they are not a tourney user + if (!user.isTourneyUser && user.uuid != newClientToken) { + global.removeUser(user); + } + } + } - // Create user object - global.addUser(newClientToken, new User(userDB.id, loginInfo.username, newClientToken, new Date().getTime(), isTourneyClient)); + // Create user object + global.addUser(newClientToken, new User(userDB.id, loginInfo.username, newClientToken, Date.now(), isTourneyClient)); - // Retreive the newly created user - const NewUser = getUserByToken(newClientToken); + // Retreive the newly created user + const NewUser = getUserByToken(newClientToken); - // Get user's data from the database - NewUser.getNewUserInformationFromDatabase(); + // Get user's data from the database + NewUser.getNewUserInformationFromDatabase(); - try { - // Save the user's location to their class for later use - NewUser.location[0] = parseFloat(userLocation[0]); - NewUser.location[1] = parseFloat(userLocation[1]); + try { + // Save the user's location to their class for later use + NewUser.location[0] = parseFloat(userLocation[0]); + NewUser.location[1] = parseFloat(userLocation[1]); - // Save the country id for the same reason as above - NewUser.countryID = countryHelper.getCountryID(userLocationData.country); + // Save the country id for the same reason as above + NewUser.countryID = countryHelper.getCountryID(userLocationData.country); - // We're ready to start putting together a login packet - // Create an osu! Packet writer - let osuPacketWriter = new osu.Bancho.Writer; + // We're ready to start putting together a login packet + // Create an osu! Packet writer + let osuPacketWriter = new osu.Bancho.Writer; - // The reply id is the user's id in any other case than an error in which case negative numbers are used - osuPacketWriter.LoginReply(NewUser.id); - // Current bancho protocol version. Defined in Binato.js - osuPacketWriter.ProtocolNegotiation(global.protocolVersion); - // Permission level 4 is osu!supporter - osuPacketWriter.LoginPermissions(4); + // The reply id is the user's id in any other case than an error in which case negative numbers are used + osuPacketWriter.LoginReply(NewUser.id); + // Current bancho protocol version. Defined in Binato.js + osuPacketWriter.ProtocolNegotiation(global.protocolVersion); + // Permission level 4 is osu!supporter + osuPacketWriter.LoginPermissions(4); - // After sending the user their friends list send them the online users - UserPresenceBundle(NewUser); + // After sending the user their friends list send them the online users + UserPresenceBundle(NewUser); - // Set title screen image - //osuPacketWriter.TitleUpdate("http://puu.sh/jh7t7/20c04029ad.png|https://osu.ppy.sh/news/123912240253"); + // Set title screen image + //osuPacketWriter.TitleUpdate("http://puu.sh/jh7t7/20c04029ad.png|https://osu.ppy.sh/news/123912240253"); - // Add user panel data packets - UserPresence(NewUser, NewUser.id); - StatusUpdate(NewUser, NewUser.id); + // Add user panel data packets + UserPresence(NewUser, NewUser.id); + StatusUpdate(NewUser, NewUser.id); - // peppy pls, why - osuPacketWriter.ChannelListingComplete(); + // peppy pls, why + osuPacketWriter.ChannelListingComplete(); - // Add user to chat channels - osuPacketWriter.ChannelJoinSuccess("#osu"); - if (!global.StreamsHandler.isUserInStream("#osu", NewUser.uuid)) - global.StreamsHandler.addUserToStream("#osu", NewUser.uuid); + // Add user to chat channels + osuPacketWriter.ChannelJoinSuccess("#osu"); + if (!global.StreamsHandler.isUserInStream("#osu", NewUser.uuid)) + global.StreamsHandler.addUserToStream("#osu", NewUser.uuid); - osuPacketWriter.ChannelJoinSuccess("#userlog"); - if (!global.StreamsHandler.isUserInStream("#userlog", NewUser.uuid)) - global.StreamsHandler.addUserToStream("#userlog", NewUser.uuid); + osuPacketWriter.ChannelJoinSuccess("#userlog"); + if (!global.StreamsHandler.isUserInStream("#userlog", NewUser.uuid)) + global.StreamsHandler.addUserToStream("#userlog", NewUser.uuid); - // List all channels out to the client - for (let i = 0; i < global.channels.length; i++) { - osuPacketWriter.ChannelAvailable({ - channelName: global.channels[i].channelName, - channelTopic: global.channels[i].channelTopic, - channelUserCount: global.channels[i].channelUserCount - }); - } + // List all channels out to the client + for (let i = 0; i < global.channels.length; i++) { + osuPacketWriter.ChannelAvailable({ + channelName: global.channels[i].channelName, + channelTopic: global.channels[i].channelTopic, + channelUserCount: global.channels[i].channelUserCount + }); + } - // Construct user's friends list - const userFriends = await global.DatabaseHelper.query(`SELECT friendsWith FROM friends WHERE user = ${NewUser.id}`); - let friendsArray = []; - for (let i = 0; i < userFriends.length; i++) { - friendsArray.push(userFriends[i].friendsWith); - } - // Send user's friends list - osuPacketWriter.FriendsList(friendsArray); + // Construct user's friends list + const userFriends = await global.DatabaseHelper.query(`SELECT friendsWith FROM friends WHERE user = ${NewUser.id}`); + let friendsArray = []; + for (let i = 0; i < userFriends.length; i++) { + friendsArray.push(userFriends[i].friendsWith); + } + // Send user's friends list + osuPacketWriter.FriendsList(friendsArray); - osuPacketWriter.Announce(`Welcome back ${loginInfo.username}!`); + osuPacketWriter.Announce(`Welcome back ${loginInfo.username}!`); - // Complete login - res.writeHead(200, { - "cho-token": NewUser.uuid, - "cho-protocol": global.protocolVersion, - "Connection": "keep-alive", - "Keep-Alive": "timeout=5, max=100", - "Content-Type": "text/html; charset=UTF-8" - }); - res.end(osuPacketWriter.toBuffer, () => { - global.consoleHelper.printBancho(`User login finished, took ${new Date().getTime() - loginStartTime}ms. [User: ${loginInfo.username}]`); - }); - } catch (err) { - console.error(err); - } + // Complete login + res.writeHead(200, { + "cho-token": NewUser.uuid, + "cho-protocol": global.protocolVersion, + "Connection": "keep-alive", + "Keep-Alive": "timeout=5, max=100", + "Content-Type": "text/html; charset=UTF-8" + }); + res.end(osuPacketWriter.toBuffer, () => { + consoleHelper.printBancho(`User login finished, took ${Date.now() - loginStartTime}ms. [User: ${loginInfo.username}]`); + }); + } catch (err) { + console.error(err); + } } \ No newline at end of file diff --git a/server/loginHelper.js b/server/loginHelper.js index 59b263b..42425ce 100644 --- a/server/loginHelper.js +++ b/server/loginHelper.js @@ -1,59 +1,59 @@ const osu = require("osu-packet"), - aes256 = require("aes256"), - config = require("../config.json"); + aes256 = require("aes256"), + config = require("../config.json"); module.exports = { - checkLogin:async function(loginInfo) { - // Check if there is any login information provided - if (loginInfo == null) return incorrectLoginResponse(); + checkLogin:async function(loginInfo) { + // Check if there is any login information provided + if (loginInfo == null) return incorrectLoginResponse(); - const userDBData = await global.DatabaseHelper.query(`SELECT * FROM users_info WHERE username = "${loginInfo.username}" LIMIT 1`); + const userDBData = await global.DatabaseHelper.query(`SELECT * FROM users_info WHERE username = "${loginInfo.username}" LIMIT 1`); - // Make sure a user was found in the database - if (Object.keys(userDBData).length < 1) return incorrectLoginResponse(); - // Make sure the username is the same as the login info - if (userDBData.username !== loginInfo.username) return incorrectLoginResponse(); - // If the user has an old md5 password - if (userDBData.has_old_password == 1) { - // Make sure the password is the same as the login info - if (userDBData.password !== loginInfo.password) return incorrectLoginResponse(); - - return requiredPWChangeResponse(); - } else { - if (aes256.decrypt(config.databaseKey, userDBData.password) !== loginInfo.password) return incorrectLoginResponse(); - } + // Make sure a user was found in the database + if (Object.keys(userDBData).length < 1) return incorrectLoginResponse(); + // Make sure the username is the same as the login info + if (userDBData.username !== loginInfo.username) return incorrectLoginResponse(); + // If the user has an old md5 password + if (userDBData.has_old_password == 1) { + // Make sure the password is the same as the login info + if (userDBData.password !== loginInfo.password) return incorrectLoginResponse(); + + return requiredPWChangeResponse(); + } else { + if (aes256.decrypt(config.databaseKey, userDBData.password) !== loginInfo.password) return incorrectLoginResponse(); + } - return null; - } + return null; + } } function incorrectLoginResponse() { - const osuPacketWriter = new osu.Bancho.Writer; - osuPacketWriter.LoginReply(-1); - return [ - osuPacketWriter.toBuffer, - { - 'cho-token': 'No', - 'cho-protocol': global.protocolVersion, - 'Connection': 'keep-alive', - 'Keep-Alive': 'timeout=5, max=100', - 'Content-Type': 'text/html; charset=UTF-8' - } - ]; + const osuPacketWriter = new osu.Bancho.Writer; + osuPacketWriter.LoginReply(-1); + return [ + osuPacketWriter.toBuffer, + { + 'cho-token': 'No', + 'cho-protocol': global.protocolVersion, + 'Connection': 'keep-alive', + 'Keep-Alive': 'timeout=5, max=100', + 'Content-Type': 'text/html; charset=UTF-8' + } + ]; } function requiredPWChangeResponse() { - const osuPacketWriter = new osu.Bancho.Writer; - osuPacketWriter.Announce("As part of migration to a new password system you are required to change your password. Please login on the website and change your password."); - osuPacketWriter.LoginReply(-1); - return [ - osuPacketWriter.toBuffer, - { - 'cho-token': 'No', - 'cho-protocol': global.protocolVersion, - 'Connection': 'keep-alive', - 'Keep-Alive': 'timeout=5, max=100', - 'Content-Type': 'text/html; charset=UTF-8' - } - ]; + const osuPacketWriter = new osu.Bancho.Writer; + osuPacketWriter.Announce("As part of migration to a new password system you are required to change your password. Please login on the website and change your password."); + osuPacketWriter.LoginReply(-1); + return [ + osuPacketWriter.toBuffer, + { + 'cho-token': 'No', + 'cho-protocol': global.protocolVersion, + 'Connection': 'keep-alive', + 'Keep-Alive': 'timeout=5, max=100', + 'Content-Type': 'text/html; charset=UTF-8' + } + ]; } \ No newline at end of file diff --git a/server/packetIDs.js b/server/packetIDs.js index 5b357e6..631cca9 100644 --- a/server/packetIDs.js +++ b/server/packetIDs.js @@ -1,111 +1,111 @@ module.exports = { - "client_changeAction":0, - "client_sendPublicMessage":1, - "client_logout":2, - "client_requestStatusUpdate":3, - "client_pong":4, - "server_userID":5, - "server_commandError":6, - "server_sendMessage":7, - "server_ping":8, - "server_handleIRCUsernameChange":9, - "server_handleIRCQuit":10, - "server_userStats":11, - "server_userLogout":12, - "server_spectatorJoined":13, - "server_spectatorLeft":14, - "server_spectateFrames":15, - "client_startSpectating":16, - "client_stopSpectating":17, - "client_spectateFrames":18, - "server_versionUpdate":19, - "client_errorReport":20, - "client_cantSpectate":21, - "server_spectatorCantSpectate":22, - "server_getAttention":23, - "server_notification":24, - "client_sendPrivateMessage":25, - "server_updateMatch":26, - "server_newMatch":27, - "server_disposeMatch":28, - "client_partLobby":29, - "client_joinLobby":30, - "client_createMatch":31, - "client_joinMatch":32, - "client_partMatch":33, - "server_lobbyJoin_obsolete":34, - "server_lobbyPart_obsolete":35, - "server_matchJoinSuccess":36, - "server_matchJoinFail":37, - "client_matchChangeSlot":38, - "client_matchReady":39, - "client_matchLock":40, - "client_matchChangeSettings":41, - "server_fellowSpectatorJoined":42, - "server_fellowSpectatorLeft":43, - "client_matchStart":44, - "AllPlayersLoaded":45, - "server_matchStart":46, - "client_matchScoreUpdate":47, - "server_matchScoreUpdate":48, - "client_matchComplete":49, - "server_matchTransferHost":50, - "client_matchChangeMods":51, - "client_matchLoadComplete":52, - "server_matchAllPlayersLoaded":53, - "client_matchNoBeatmap":54, - "client_matchNotReady":55, - "client_matchFailed":56, - "server_matchComplete":58, - "client_matchHasBeatmap":59, - "client_matchSkipRequest":60, - "server_matchSkip":61, - "server_unauthorised":62, - "client_channelJoin":63, - "server_channelJoinSuccess":64, - "server_channelInfo":65, - "server_channelKicked":66, - "server_channelAvailableAutojoin":67, - "client_beatmapInfoRequest":68, - "server_beatmapInfoReply":69, - "client_matchTransferHost":70, - "server_supporterGMT":71, - "server_friendsList":72, - "client_friendAdd":73, - "client_friendRemove":74, - "server_protocolVersion":75, - "server_mainMenuIcon":76, - "client_matchChangeTeam":77, - "client_channelPart":78, - "client_receiveUpdates":79, - "server_topBotnet":80, - "server_matchPlayerSkipped":81, - "client_setAwayMessage":82, - "server_userPanel":83, - "IRC_only":84, - "client_userStatsRequest":85, - "server_restart":86, - "client_invite":87, - "server_invite":88, - "server_channelInfoEnd":89, - "client_matchChangePassword":90, - "server_matchChangePassword":91, - "server_silenceEnd":92, - "client_specialMatchInfoRequest":93, - "server_userSilenced":94, - "server_userPresenceSingle":95, - "server_userPresenceBundle":96, - "client_userPresenceRequest":97, - "client_userPresenceRequestAll":98, - "client_userToggleBlockNonFriendPM":99, - "server_userPMBlocked":100, - "server_targetIsSilenced":101, - "server_versionUpdateForced":102, - "server_switchServer":103, - "server_accountRestricted":104, - "server_jumpscare":105, - "client_matchAbort":106, - "server_switchTourneyServer":107, - "client_specialJoinMatchChannel":108, - "client_specialLeaveMatchChannel":109 + "client_changeAction":0, + "client_sendPublicMessage":1, + "client_logout":2, + "client_requestStatusUpdate":3, + "client_pong":4, + "server_userID":5, + "server_commandError":6, + "server_sendMessage":7, + "server_ping":8, + "server_handleIRCUsernameChange":9, + "server_handleIRCQuit":10, + "server_userStats":11, + "server_userLogout":12, + "server_spectatorJoined":13, + "server_spectatorLeft":14, + "server_spectateFrames":15, + "client_startSpectating":16, + "client_stopSpectating":17, + "client_spectateFrames":18, + "server_versionUpdate":19, + "client_errorReport":20, + "client_cantSpectate":21, + "server_spectatorCantSpectate":22, + "server_getAttention":23, + "server_notification":24, + "client_sendPrivateMessage":25, + "server_updateMatch":26, + "server_newMatch":27, + "server_disposeMatch":28, + "client_partLobby":29, + "client_joinLobby":30, + "client_createMatch":31, + "client_joinMatch":32, + "client_partMatch":33, + "server_lobbyJoin_obsolete":34, + "server_lobbyPart_obsolete":35, + "server_matchJoinSuccess":36, + "server_matchJoinFail":37, + "client_matchChangeSlot":38, + "client_matchReady":39, + "client_matchLock":40, + "client_matchChangeSettings":41, + "server_fellowSpectatorJoined":42, + "server_fellowSpectatorLeft":43, + "client_matchStart":44, + "AllPlayersLoaded":45, + "server_matchStart":46, + "client_matchScoreUpdate":47, + "server_matchScoreUpdate":48, + "client_matchComplete":49, + "server_matchTransferHost":50, + "client_matchChangeMods":51, + "client_matchLoadComplete":52, + "server_matchAllPlayersLoaded":53, + "client_matchNoBeatmap":54, + "client_matchNotReady":55, + "client_matchFailed":56, + "server_matchComplete":58, + "client_matchHasBeatmap":59, + "client_matchSkipRequest":60, + "server_matchSkip":61, + "server_unauthorised":62, + "client_channelJoin":63, + "server_channelJoinSuccess":64, + "server_channelInfo":65, + "server_channelKicked":66, + "server_channelAvailableAutojoin":67, + "client_beatmapInfoRequest":68, + "server_beatmapInfoReply":69, + "client_matchTransferHost":70, + "server_supporterGMT":71, + "server_friendsList":72, + "client_friendAdd":73, + "client_friendRemove":74, + "server_protocolVersion":75, + "server_mainMenuIcon":76, + "client_matchChangeTeam":77, + "client_channelPart":78, + "client_receiveUpdates":79, + "server_topBotnet":80, + "server_matchPlayerSkipped":81, + "client_setAwayMessage":82, + "server_userPanel":83, + "IRC_only":84, + "client_userStatsRequest":85, + "server_restart":86, + "client_invite":87, + "server_invite":88, + "server_channelInfoEnd":89, + "client_matchChangePassword":90, + "server_matchChangePassword":91, + "server_silenceEnd":92, + "client_specialMatchInfoRequest":93, + "server_userSilenced":94, + "server_userPresenceSingle":95, + "server_userPresenceBundle":96, + "client_userPresenceRequest":97, + "client_userPresenceRequestAll":98, + "client_userToggleBlockNonFriendPM":99, + "server_userPMBlocked":100, + "server_targetIsSilenced":101, + "server_versionUpdateForced":102, + "server_switchServer":103, + "server_accountRestricted":104, + "server_jumpscare":105, + "client_matchAbort":106, + "server_switchTourneyServer":107, + "client_specialJoinMatchChannel":108, + "client_specialLeaveMatchChannel":109 } diff --git a/server/serverHandler.js b/server/serverHandler.js index bc4f808..2cd55f6 100644 --- a/server/serverHandler.js +++ b/server/serverHandler.js @@ -1,34 +1,35 @@ const osu = require("osu-packet"), - fs = require("fs"), - packetIDs = require("./packetIDs.js"), - loginHandler = require("./loginHandler.js"), - parseUserData = require("./util/parseUserData.js"), - User = require("./User.js"), - getUserFromToken = require("./util/getUserByToken.js"), - bakedResponses = require("./bakedResponses.js"), - Streams = require("./Streams.js"), - DatabaseHelperClass = require("./DatabaseHelper.js"), - config = require("../config.json"); + fs = require("fs"), + consoleHelper = require("../consoleHelper.js"), + packetIDs = require("./packetIDs.js"), + loginHandler = require("./loginHandler.js"), + parseUserData = require("./util/parseUserData.js"), + User = require("./User.js"), + getUserFromToken = require("./util/getUserByToken.js"), + bakedResponses = require("./bakedResponses.js"), + Streams = require("./Streams.js"), + DatabaseHelperClass = require("./DatabaseHelper.js"), + config = require("../config.json"); global.users = {}; global.userKeys = Object.keys(global.users); global.addUser = function(uuid, userToAdd) { - global.users[uuid] = userToAdd; - global.refreshUserKeys(); + global.users[uuid] = userToAdd; + global.refreshUserKeys(); } global.removeUser = function(userToRemove) { - delete userToRemove; - global.refreshUserKeys(); + delete userToRemove; + global.refreshUserKeys(); } global.refreshUserKeys = function() { - global.userKeys = Object.keys(global.users); + global.userKeys = Object.keys(global.users); } // Add the bot user -global.addUser("bot", new User(3, "SillyBot", "bot", new Date().getTime())); +global.addUser("bot", new User(3, "SillyBot", "bot", Date.now())); // Set the bot's position on the map global.users["bot"].location[0] = 50; global.users["bot"].location[1] = -32; @@ -40,25 +41,25 @@ global.DatabaseHelper = new DatabaseHelperClass(config.databaseAddress, config.d // TODO: Some way of informing bancho that a user has set a score so details can be pulled down quickly // Possible solution, TCP socket between the score submit server and bancho? redis? (score submit is on a different server, redis probably wouldn't work) setInterval(() => { - for (let i = 0; i < global.userKeys.length; i++) { - const User = global.users[global.userKeys[i]]; - if (User.id == 3) continue; // Ignore the bot - // Bot: :( + for (let i = 0; i < global.userKeys.length; i++) { + const User = global.users[global.userKeys[i]]; + if (User.id == 3) continue; // Ignore the bot + // Bot: :( - User.getNewUserInformationFromDatabase(); - } + User.getNewUserInformationFromDatabase(); + } }, 10000); // An array containing the last 15 messages in chat // TODO: Bother making this global.chatHistory = []; global.addChatMessage = function(msg) { - if (global.chatHistory.length == 15) { - global.chatHistory.splice(0, 1); - global.chatHistory.push(msg); - } else { - global.chatHistory.push(msg); - } + if (global.chatHistory.length == 15) { + global.chatHistory.splice(0, 1); + global.chatHistory.push(msg); + } else { + global.chatHistory.push(msg); + } } global.StreamsHandler = new Streams(); @@ -66,16 +67,16 @@ global.StreamsHandler = new Streams(); // An array containing all chat channels // TODO: Send user chat channels and not have osu! crash global.channels = [ - { channelName:"#osu", channelTopic:"The main channel", channelUserCount: 0, locked: false }, - { channelName:"#userlog", channelTopic:"Log about stuff doing go on yes very", channelUserCount: 0, locked: false }, - { channelName:"#lobby", channelTopic:"Talk about multiplayer stuff", channelUserCount: 0, locked: false }, - { channelName:"#english", channelTopic:"Talk in exclusively English", channelUserCount: 0, locked: false }, - { channelName:"#japanese", channelTopic:"Talk in exclusively Japanese", channelUserCount: 0, locked: false }, + { channelName:"#osu", channelTopic:"The main channel", channelUserCount: 0, locked: false }, + { channelName:"#userlog", channelTopic:"Log about stuff doing go on yes very", channelUserCount: 0, locked: false }, + { channelName:"#lobby", channelTopic:"Talk about multiplayer stuff", channelUserCount: 0, locked: false }, + { channelName:"#english", channelTopic:"Talk in exclusively English", channelUserCount: 0, locked: false }, + { channelName:"#japanese", channelTopic:"Talk in exclusively Japanese", channelUserCount: 0, locked: false }, ]; // Create a stream for each chat channel for (let i = 0; i < global.channels.length; i++) { - global.StreamsHandler.addStream(global.channels[i].channelName, false); + global.StreamsHandler.addStream(global.channels[i].channelName, false); } // Add a stream for the multiplayer lobby @@ -92,44 +93,44 @@ global.httpRequestsPerLogInterval = 0; const logInterval = 10; // Secs setInterval(() => { - global.usersOnline = (global.userKeys.length - 1); - global.multiplayerMatches = [global.MultiplayerManager.matches.length, 0]; // TODO: Respect private matches + global.usersOnline = (global.userKeys.length - 1); + global.multiplayerMatches = [global.MultiplayerManager.matches.length, 0]; // TODO: Respect private matches - fs.appendFile( - "server-stats.log", - `${global.usersOnline}|${global.multiplayerMatches[0]},${global.multiplayerMatches[1]}|${global.httpRequestsPerLogInterval}|${new Date().getTime()}@`, - () => {} - ); + fs.appendFile( + "server-stats.log", + `${global.usersOnline}|${global.multiplayerMatches[0]},${global.multiplayerMatches[1]}|${global.httpRequestsPerLogInterval}|${Date.now()}@`, + () => {} + ); - global.httpRequestsPerLogInterval = 0; + global.httpRequestsPerLogInterval = 0; }, logInterval * 1000); if (!fs.existsSync("tHMM.ds")) fs.writeFileSync("tHMM.ds", "0"); global.totalHistoricalMultiplayerMatches = parseInt(fs.readFileSync("tHMM.ds").toString()); global.getAndAddToHistoricalMultiplayerMatches = function() { - global.totalHistoricalMultiplayerMatches++; - fs.writeFile("tHMM.ds", `${global.totalHistoricalMultiplayerMatches}`, () => {}); - return global.totalHistoricalMultiplayerMatches; + global.totalHistoricalMultiplayerMatches++; + fs.writeFile("tHMM.ds", `${global.totalHistoricalMultiplayerMatches}`, () => {}); + return global.totalHistoricalMultiplayerMatches; } // Include packets const ChangeAction = require("./Packets/ChangeAction.js"), - SendPublicMessage = require("./Packets/SendPublicMessage.js"), - Logout = require("./Packets/Logout.js"), - Spectator = require("./Spectator.js"), - SendPrivateMessage = require("./Packets/SendPrivateMessage.js"), - MultiplayerManager = require("./MultiplayerManager.js"), - ChannelJoin = require("./Packets/ChannelJoin.js"), - ChannelPart = require("./Packets/ChannelPart.js"), - AddFriend = require("./Packets/AddFriend.js"), - RemoveFriend = require("./Packets/RemoveFriend.js"), - UserPresenceBundle = require("./Packets/UserPresenceBundle.js"), - UserPresence = require("./Packets/UserPresence.js"), - UserStatsRequest = require("./Packets/UserStatsRequest.js"), - MultiplayerInvite = require("./Packets/MultiplayerInvite.js"), - TourneyMatchSpecialInfo = require("./Packets/TourneyMatchSpecialInfo.js"), - TourneyMatchJoinChannel = require("./Packets/TourneyMatchSpecialInfo.js"), - TourneyMatchLeaveChannel = require("./Packets/TourneyLeaveMatchChannel.js"); + SendPublicMessage = require("./Packets/SendPublicMessage.js"), + Logout = require("./Packets/Logout.js"), + Spectator = require("./Spectator.js"), + SendPrivateMessage = require("./Packets/SendPrivateMessage.js"), + MultiplayerManager = require("./MultiplayerManager.js"), + ChannelJoin = require("./Packets/ChannelJoin.js"), + ChannelPart = require("./Packets/ChannelPart.js"), + AddFriend = require("./Packets/AddFriend.js"), + RemoveFriend = require("./Packets/RemoveFriend.js"), + UserPresenceBundle = require("./Packets/UserPresenceBundle.js"), + UserPresence = require("./Packets/UserPresence.js"), + UserStatsRequest = require("./Packets/UserStatsRequest.js"), + MultiplayerInvite = require("./Packets/MultiplayerInvite.js"), + TourneyMatchSpecialInfo = require("./Packets/TourneyMatchSpecialInfo.js"), + TourneyMatchJoinChannel = require("./Packets/TourneyMatchSpecialInfo.js"), + TourneyMatchLeaveChannel = require("./Packets/TourneyLeaveMatchChannel.js"); const emptyBuffer = Buffer.alloc(0); @@ -137,231 +138,231 @@ const emptyBuffer = Buffer.alloc(0); global.MultiplayerManager = new MultiplayerManager(); module.exports = async function(req, res) { - // Add to requests for logging - global.httpRequestsPerLogInterval++; + // Add to requests for logging + global.httpRequestsPerLogInterval++; - // Get the client's token string and request data - const requestTokenString = req.header("osu-token"), - requestData = req.packet; - - // Server's response & new client token - let responseData = emptyBuffer; + // Get the client's token string and request data + const requestTokenString = req.header("osu-token"), + requestData = req.packet; + + // Server's response & new client token + let responseData = emptyBuffer; - // Check if the user is logged in - if (requestTokenString == null) { - // Client doesn't have a token yet, let's auth them! - const userData = parseUserData(requestData); - global.consoleHelper.printBancho(`New client connection. [User: ${userData.username}]`); - await loginHandler(req, res, userData); - } else { - // Client has a token, let's see what they want. - try { - // Get the current user - const PacketUser = getUserFromToken(requestTokenString); + // Check if the user is logged in + if (requestTokenString == null) { + // Client doesn't have a token yet, let's auth them! + const userData = parseUserData(requestData); + consoleHelper.printBancho(`New client connection. [User: ${userData.username}]`); + await loginHandler(req, res, userData); + } else { + // Client has a token, let's see what they want. + try { + // Get the current user + const PacketUser = getUserFromToken(requestTokenString); - // Make sure the client's token isn't invalid - if (PacketUser != null) { - // Create a new osu! packet reader - const osuPacketReader = new osu.Client.Reader(requestData); - // Parse current bancho packet - const PacketData = osuPacketReader.Parse(); - // Loop through parsed packet data - for (let i = 0; i < PacketData.length; i++) { - // Get current packet - let CurrentPacket = PacketData[i]; + // Make sure the client's token isn't invalid + if (PacketUser != null) { + // Create a new osu! packet reader + const osuPacketReader = new osu.Client.Reader(requestData); + // Parse current bancho packet + const PacketData = osuPacketReader.Parse(); + // Loop through parsed packet data + for (let i = 0; i < PacketData.length; i++) { + // Get current packet + let CurrentPacket = PacketData[i]; - // This is getting a little big, swap this out for mapped functions? - // Would require some standardisation - switch (CurrentPacket.id) { - case packetIDs.client_changeAction: - ChangeAction(PacketUser, CurrentPacket.data); - break; + // This is getting a little big, swap this out for mapped functions? + // Would require some standardisation + switch (CurrentPacket.id) { + case packetIDs.client_changeAction: + ChangeAction(PacketUser, CurrentPacket.data); + break; - case packetIDs.client_sendPublicMessage: - SendPublicMessage(PacketUser, CurrentPacket.data); - break; + case packetIDs.client_sendPublicMessage: + SendPublicMessage(PacketUser, CurrentPacket.data); + break; - case packetIDs.client_logout: - Logout(PacketUser); - break; + case packetIDs.client_logout: + Logout(PacketUser); + break; - case packetIDs.client_requestStatusUpdate: - UserPresenceBundle(PacketUser); - break; + case packetIDs.client_requestStatusUpdate: + UserPresenceBundle(PacketUser); + break; - case packetIDs.client_pong: // Pretty sure this is just a client ping - // so we probably don't do anything here - break; // It's probably just the client wanting to pull data down. + case packetIDs.client_pong: // Pretty sure this is just a client ping + // so we probably don't do anything here + break; // It's probably just the client wanting to pull data down. - case packetIDs.client_startSpectating: - Spectator.startSpectatingUser(PacketUser, CurrentPacket.data); - break; + case packetIDs.client_startSpectating: + Spectator.startSpectatingUser(PacketUser, CurrentPacket.data); + break; - case packetIDs.client_spectateFrames: - Spectator.sendSpectatorFrames(PacketUser, CurrentPacket.data); - break; + case packetIDs.client_spectateFrames: + Spectator.sendSpectatorFrames(PacketUser, CurrentPacket.data); + break; - case packetIDs.client_stopSpectating: - Spectator.stopSpectatingUser(PacketUser); - break; + case packetIDs.client_stopSpectating: + Spectator.stopSpectatingUser(PacketUser); + break; - case packetIDs.client_sendPrivateMessage: - SendPrivateMessage(PacketUser, CurrentPacket.data); - break; + case packetIDs.client_sendPrivateMessage: + SendPrivateMessage(PacketUser, CurrentPacket.data); + break; - case packetIDs.client_joinLobby: - global.MultiplayerManager.userEnterLobby(PacketUser); - break; + case packetIDs.client_joinLobby: + global.MultiplayerManager.userEnterLobby(PacketUser); + break; - case packetIDs.client_partLobby: - global.MultiplayerManager.userLeaveLobby(PacketUser); - break; + case packetIDs.client_partLobby: + global.MultiplayerManager.userLeaveLobby(PacketUser); + break; - case packetIDs.client_createMatch: - global.MultiplayerManager.createMultiplayerMatch(PacketUser, CurrentPacket.data); - break; + case packetIDs.client_createMatch: + global.MultiplayerManager.createMultiplayerMatch(PacketUser, CurrentPacket.data); + break; - case packetIDs.client_joinMatch: - global.MultiplayerManager.joinMultiplayerMatch(PacketUser, CurrentPacket.data); - break; + case packetIDs.client_joinMatch: + global.MultiplayerManager.joinMultiplayerMatch(PacketUser, CurrentPacket.data); + break; - case packetIDs.client_matchChangeSlot: - PacketUser.currentMatch.moveToSlot(PacketUser, CurrentPacket.data); - break; + case packetIDs.client_matchChangeSlot: + PacketUser.currentMatch.moveToSlot(PacketUser, CurrentPacket.data); + break; - case packetIDs.client_matchReady: - PacketUser.currentMatch.setStateReady(PacketUser); - break; + case packetIDs.client_matchReady: + PacketUser.currentMatch.setStateReady(PacketUser); + break; - case packetIDs.client_matchChangeSettings: - PacketUser.currentMatch.updateMatch(PacketUser, CurrentPacket.data); - break; + case packetIDs.client_matchChangeSettings: + PacketUser.currentMatch.updateMatch(PacketUser, CurrentPacket.data); + break; - case packetIDs.client_matchNotReady: - PacketUser.currentMatch.setStateNotReady(PacketUser); - break; + case packetIDs.client_matchNotReady: + PacketUser.currentMatch.setStateNotReady(PacketUser); + break; - case packetIDs.client_partMatch: - global.MultiplayerManager.leaveMultiplayerMatch(PacketUser); - break; + case packetIDs.client_partMatch: + global.MultiplayerManager.leaveMultiplayerMatch(PacketUser); + break; - // Also handles user kick if the slot has a user - case packetIDs.client_matchLock: - PacketUser.currentMatch.lockMatchSlot(PacketUser, CurrentPacket.data); - break; + // Also handles user kick if the slot has a user + case packetIDs.client_matchLock: + PacketUser.currentMatch.lockMatchSlot(PacketUser, CurrentPacket.data); + break; - case packetIDs.client_matchNoBeatmap: - PacketUser.currentMatch.missingBeatmap(PacketUser); - break; + case packetIDs.client_matchNoBeatmap: + PacketUser.currentMatch.missingBeatmap(PacketUser); + break; - case packetIDs.client_matchSkipRequest: - PacketUser.currentMatch.matchSkip(PacketUser); - break; - - case packetIDs.client_matchHasBeatmap: - PacketUser.currentMatch.notMissingBeatmap(PacketUser); - break; + case packetIDs.client_matchSkipRequest: + PacketUser.currentMatch.matchSkip(PacketUser); + break; + + case packetIDs.client_matchHasBeatmap: + PacketUser.currentMatch.notMissingBeatmap(PacketUser); + break; - case packetIDs.client_matchTransferHost: - PacketUser.currentMatch.transferHost(PacketUser, CurrentPacket.data); - break; + case packetIDs.client_matchTransferHost: + PacketUser.currentMatch.transferHost(PacketUser, CurrentPacket.data); + break; - case packetIDs.client_matchChangeMods: - PacketUser.currentMatch.updateMods(PacketUser, CurrentPacket.data); - break; + case packetIDs.client_matchChangeMods: + PacketUser.currentMatch.updateMods(PacketUser, CurrentPacket.data); + break; - case packetIDs.client_matchStart: - PacketUser.currentMatch.startMatch(); - break; + case packetIDs.client_matchStart: + PacketUser.currentMatch.startMatch(); + break; - case packetIDs.client_matchLoadComplete: - PacketUser.currentMatch.matchPlayerLoaded(PacketUser); - break; + case packetIDs.client_matchLoadComplete: + PacketUser.currentMatch.matchPlayerLoaded(PacketUser); + break; - case packetIDs.client_matchComplete: - PacketUser.currentMatch.onPlayerFinishMatch(PacketUser); - break; + case packetIDs.client_matchComplete: + PacketUser.currentMatch.onPlayerFinishMatch(PacketUser); + break; - case packetIDs.client_matchScoreUpdate: - PacketUser.currentMatch.updatePlayerScore(PacketUser, CurrentPacket.data); - break; + case packetIDs.client_matchScoreUpdate: + PacketUser.currentMatch.updatePlayerScore(PacketUser, CurrentPacket.data); + break; - case packetIDs.client_matchFailed: - PacketUser.currentMatch.matchFailed(PacketUser); - break; + case packetIDs.client_matchFailed: + PacketUser.currentMatch.matchFailed(PacketUser); + break; - case packetIDs.client_matchChangeTeam: - PacketUser.currentMatch.changeTeam(PacketUser); - break; + case packetIDs.client_matchChangeTeam: + PacketUser.currentMatch.changeTeam(PacketUser); + break; - case packetIDs.client_channelJoin: - ChannelJoin(PacketUser, CurrentPacket.data); - break; + case packetIDs.client_channelJoin: + ChannelJoin(PacketUser, CurrentPacket.data); + break; - case packetIDs.client_channelPart: - ChannelPart(PacketUser, CurrentPacket.data); - break; + case packetIDs.client_channelPart: + ChannelPart(PacketUser, CurrentPacket.data); + break; - case packetIDs.client_friendAdd: - AddFriend(PacketUser, CurrentPacket.data); - break; + case packetIDs.client_friendAdd: + AddFriend(PacketUser, CurrentPacket.data); + break; - case packetIDs.client_friendRemove: - RemoveFriend(PacketUser, CurrentPacket.data); - break; + case packetIDs.client_friendRemove: + RemoveFriend(PacketUser, CurrentPacket.data); + break; - case packetIDs.client_userStatsRequest: - UserStatsRequest(PacketUser, CurrentPacket.data); - break; + case packetIDs.client_userStatsRequest: + UserStatsRequest(PacketUser, CurrentPacket.data); + break; - case packetIDs.client_specialMatchInfoRequest: - TourneyMatchSpecialInfo(PacketUser, CurrentPacket.data); - break; + case packetIDs.client_specialMatchInfoRequest: + TourneyMatchSpecialInfo(PacketUser, CurrentPacket.data); + break; - case packetIDs.client_specialJoinMatchChannel: - TourneyMatchJoinChannel(PacketUser, CurrentPacket.data); - break; + case packetIDs.client_specialJoinMatchChannel: + TourneyMatchJoinChannel(PacketUser, CurrentPacket.data); + break; - case packetIDs.client_specialLeaveMatchChannel: - TourneyMatchLeaveChannel(PacketUser, CurrentPacket.data); - break; + case packetIDs.client_specialLeaveMatchChannel: + TourneyMatchLeaveChannel(PacketUser, CurrentPacket.data); + break; - case packetIDs.client_invite: - MultiplayerInvite(PacketUser, CurrentPacket.data); - break; + case packetIDs.client_invite: + MultiplayerInvite(PacketUser, CurrentPacket.data); + break; - case packetIDs.client_userPresenceRequest: - UserPresence(PacketUser, PacketUser.id); // Can't really think of a way to generalize this? - break; + case packetIDs.client_userPresenceRequest: + UserPresence(PacketUser, PacketUser.id); // Can't really think of a way to generalize this? + break; - default: - // Ignore client_beatmapInfoRequest and client_receiveUpdates - if (CurrentPacket.id == 68 || CurrentPacket.id == 79) break; - // Print out unimplemented packet - console.dir(CurrentPacket); - break; - } + default: + // Ignore client_beatmapInfoRequest and client_receiveUpdates + if (CurrentPacket.id == 68 || CurrentPacket.id == 79) break; + // Print out unimplemented packet + console.dir(CurrentPacket); + break; + } - // Concat current user queue into response data - responseData = Buffer.concat([responseData, PacketUser.queue], responseData.length + PacketUser.queue.length); - PacketUser.clearQueue(); - } - } else { - // User's token is invlid, force a reconnect - global.consoleHelper.printBancho(`Forced client re-login (Token is invalid)`); - responseData = bakedResponses("reconnect"); - } - } catch (e) { - console.error(e); - } finally { - // Send the prepared packet to the client - res.writeHead(200, { - "cho-protocol": global.protocolVersion, - "Connection": "keep-alive", - "Keep-Alive": "timeout=5, max=100", - "Content-Type": "text/html; charset=UTF-8" - }); - res.end(responseData); - } - } + // Concat current user queue into response data + responseData = Buffer.concat([responseData, PacketUser.queue], responseData.length + PacketUser.queue.length); + PacketUser.clearQueue(); + } + } else { + // User's token is invlid, force a reconnect + consoleHelper.printBancho(`Forced client re-login (Token is invalid)`); + responseData = bakedResponses("reconnect"); + } + } catch (e) { + console.error(e); + } finally { + // Send the prepared packet to the client + res.writeHead(200, { + "cho-protocol": global.protocolVersion, + "Connection": "keep-alive", + "Keep-Alive": "timeout=5, max=100", + "Content-Type": "text/html; charset=UTF-8" + }); + res.end(responseData); + } + } }; diff --git a/server/util/AsyncHttpRequest.js b/server/util/AsyncHttpRequest.js index a2683bd..c774330 100644 --- a/server/util/AsyncHttpRequest.js +++ b/server/util/AsyncHttpRequest.js @@ -1,16 +1,16 @@ const request = require("request"), RequestType = require("./RequestType.json"); const functionMap = { - 0: (resolve, body) => resolve(body), - 1: (resolve, body) => resolve(JSON.parse(body)), - 2: null + 0: (resolve, body) => resolve(body), + 1: (resolve, body) => resolve(JSON.parse(body)), + 2: null }; module.exports = async function(url, reqType = RequestType.Text) { - return new Promise((resolve, reject) => { - request(url, (err, res, body) => { - if (err) reject(err); - else functionMap[reqType](resolve, body); - }); - }); + return new Promise((resolve, reject) => { + request(url, (err, res, body) => { + if (err) reject(err); + else functionMap[reqType](resolve, body); + }); + }); } \ No newline at end of file diff --git a/server/util/BitwiseModConverter.js b/server/util/BitwiseModConverter.js index 1b48143..c4ae162 100644 --- a/server/util/BitwiseModConverter.js +++ b/server/util/BitwiseModConverter.js @@ -1,3 +1,3 @@ module.exports = function(bitwiseMods = 0) { - + } \ No newline at end of file diff --git a/server/util/Maths.js b/server/util/Maths.js index 4692b9b..10600ec 100644 --- a/server/util/Maths.js +++ b/server/util/Maths.js @@ -1,15 +1,15 @@ module.exports = { - map:function(input, inputMin, inputMax, outputMin, outputMax) { - const newv = (input - inputMin) / (inputMax - inputMin) * (outputMax - outputMin) + outputMin; - if (outputMin < outputMax) return this.constrain(newv, outputMin, outputMax); - else return this.constrain(newv, outputMax, outputMin); - }, + map:function(input, inputMin, inputMax, outputMin, outputMax) { + const newv = (input - inputMin) / (inputMax - inputMin) * (outputMax - outputMin) + outputMin; + if (outputMin < outputMax) return this.constrain(newv, outputMin, outputMax); + else return this.constrain(newv, outputMax, outputMin); + }, - constrain:function(input, low, high) { - return Math.max(Math.min(input, high), low); - }, + constrain:function(input, low, high) { + return Math.max(Math.min(input, high), low); + }, - randInt:function(from, to) { - return Math.round(this.map(Math.random(), 0, 1, from, to)); - } + randInt:function(from, to) { + return Math.round(this.map(Math.random(), 0, 1, from, to)); + } } \ No newline at end of file diff --git a/server/util/getUserById.js b/server/util/getUserById.js index a132299..9f608f7 100644 --- a/server/util/getUserById.js +++ b/server/util/getUserById.js @@ -1,6 +1,6 @@ module.exports = function(id) { - for (let i = 0; i < global.userKeys.length; i++) { - if (global.users[global.userKeys[i]].id == id) - return global.users[userKeys[i]]; - } + for (let i = 0; i < global.userKeys.length; i++) { + if (global.users[global.userKeys[i]].id == id) + return global.users[userKeys[i]]; + } } \ No newline at end of file diff --git a/server/util/getUserByToken.js b/server/util/getUserByToken.js index 7ea76f4..6c871b1 100644 --- a/server/util/getUserByToken.js +++ b/server/util/getUserByToken.js @@ -1,4 +1,4 @@ module.exports = function(token) { - if (global.userKeys.includes(token)) return global.users[token]; - else return null; + if (global.userKeys.includes(token)) return global.users[token]; + else return null; } \ No newline at end of file diff --git a/server/util/getUserByUsername.js b/server/util/getUserByUsername.js index e4616fd..03e1f1b 100644 --- a/server/util/getUserByUsername.js +++ b/server/util/getUserByUsername.js @@ -1,6 +1,6 @@ module.exports = function(username) { - for (let i = 0; i < global.userKeys.length; i++) { - if (global.users[global.userKeys[i]].username == username) - return global.users[global.userKeys[i]]; - } + for (let i = 0; i < global.userKeys.length; i++) { + if (global.users[global.userKeys[i]].username == username) + return global.users[global.userKeys[i]]; + } } \ No newline at end of file diff --git a/server/util/parseUserData.js b/server/util/parseUserData.js index fe051ed..3339a39 100644 --- a/server/util/parseUserData.js +++ b/server/util/parseUserData.js @@ -1,33 +1,33 @@ module.exports = function(packet) { - try { - const p = packet.toString(); // Convert our buffer to a String - const s = p.split('\n'); // Split our Login Data to Username Password Osuversion|blabla|bla - const n = s[2].split('|'); // Split osuversion|blablabla|blablabla to a object. - const username = s[0]; // Username ofc - const password = s[1]; // Password ofc - const osuversion = n[0]; // OsuVersion ofc. - const TimeOffset = Number(n[1]); // Comeon, i dont realy have to tell you what this is. - const clientData = n[3].split(':')[2]; // Some system information. such as MacAdress or DiskID - - // If some data is not set OR is invailed throw errors - if (username == undefined) throw 'UserName'; - if (password == undefined) throw 'password'; - if (osuversion == undefined) throw 'osuversion'; - if (TimeOffset == undefined) throw 'offset'; - if (clientData == undefined) throw 'clientData'; - - // Everything alright? return parsed data. - const obj = { - username: String(username), - password: String(password), - osuversion: String(osuversion), - timeoffset: Number(TimeOffset), - clientdata: String(clientData) - }; - // Here is the return. - return obj; - } catch (ex) { - // Else return undefined, that the login request got broke. - return undefined; - } + try { + const p = packet.toString(); // Convert our buffer to a String + const s = p.split('\n'); // Split our Login Data to Username Password Osuversion|blabla|bla + const n = s[2].split('|'); // Split osuversion|blablabla|blablabla to a object. + const username = s[0]; // Username ofc + const password = s[1]; // Password ofc + const osuversion = n[0]; // OsuVersion ofc. + const TimeOffset = Number(n[1]); // Comeon, i dont realy have to tell you what this is. + const clientData = n[3].split(':')[2]; // Some system information. such as MacAdress or DiskID + + // If some data is not set OR is invailed throw errors + if (username == undefined) throw 'UserName'; + if (password == undefined) throw 'password'; + if (osuversion == undefined) throw 'osuversion'; + if (TimeOffset == undefined) throw 'offset'; + if (clientData == undefined) throw 'clientData'; + + // Everything alright? return parsed data. + const obj = { + username: String(username), + password: String(password), + osuversion: String(osuversion), + timeoffset: Number(TimeOffset), + clientdata: String(clientData) + }; + // Here is the return. + return obj; + } catch (ex) { + // Else return undefined, that the login request got broke. + return undefined; + } } \ No newline at end of file