diff --git a/server/BotCommandHandler.js b/server/BotCommandHandler.js index 9f0066b..fc9251a 100644 --- a/server/BotCommandHandler.js +++ b/server/BotCommandHandler.js @@ -4,6 +4,7 @@ const osu = require("osu-packet"), module.exports = function(User, Message, Stream, IsCalledFromMultiplayer = false) { if (Message[0] != "!") return; + const command = Message.split(" ")[0]; const args = Message.split(" "); @@ -117,18 +118,18 @@ module.exports = function(User, Message, Stream, IsCalledFromMultiplayer = false if (countdown != 0 && countdown > 0) countdown--; if (countdown <= 10 && countdown > 0) { local_osuPacketWriter.SendMessage({ - sendingClient: global.users["bot"].username, + sendingClient: global.botUser.username, message: "Starting in " + countdown, target: "#multiplayer", - senderId: global.users["bot"].id + senderId: global.botUser.id }); global.StreamsHandler.sendToStream(Stream, local_osuPacketWriter.toBuffer, null); } else if (countdown == 0) { local_osuPacketWriter.SendMessage({ - sendingClient: global.users["bot"].username, + sendingClient: global.botUser.username, message: "Good luck, have fun!", target: "#multiplayer", - senderId: global.users["bot"].id + senderId: global.botUser.id }); global.StreamsHandler.sendToStream(Stream, local_osuPacketWriter.toBuffer, null); User.currentMatch.matchStartCountdownActive = false; @@ -152,10 +153,10 @@ module.exports = function(User, Message, Stream, IsCalledFromMultiplayer = false if (User.currentMatch.multiplayerExtras.name == "osu! Battle Royale") { commandBanchoPacketWriter = new osu.Bancho.Writer; commandBanchoPacketWriter.SendMessage({ - sendingClient: global.users["bot"].username, + sendingClient: global.botUser.username, message: "osu! Battle Royale has been disabled!", target: "#multiplayer", - senderId: global.users["bot"].id + senderId: global.botUser.id }); User.currentMatch.multiplayerExtras = null; global.StreamsHandler.sendToStream(Stream, commandBanchoPacketWriter.toBuffer, null); @@ -175,17 +176,17 @@ module.exports = function(User, Message, Stream, IsCalledFromMultiplayer = false if (responseMessage != "") { if (Stream.includes("#")) { osuPacketWriter.SendMessage({ - sendingClient: global.users["bot"].username, + sendingClient: global.botUser.username, message: responseMessage, target: Stream, - senderId: global.users["bot"].id + senderId: global.botUser.id }); } else { osuPacketWriter.SendMessage({ - sendingClient: global.users["bot"].username, + sendingClient: global.botUser.username, message: responseMessage, target: "#multiplayer", - senderId: global.users["bot"].id + senderId: global.botUser.id }); } } @@ -196,16 +197,16 @@ function enableOBR(User, Stream, commandBanchoPacketWriter) { User.currentMatch.multiplayerExtras = new OsuBattleRoyale(User.currentMatch); commandBanchoPacketWriter = new osu.Bancho.Writer; commandBanchoPacketWriter.SendMessage({ - sendingClient: global.users["bot"].username, + sendingClient: global.botUser.username, message: "osu! Battle Royale has been enabled!", target: "#multiplayer", - senderId: global.users["bot"].id + senderId: global.botUser.id }); commandBanchoPacketWriter.SendMessage({ - sendingClient: global.users["bot"].username, + sendingClient: global.botUser.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 + senderId: global.botUser.id }); global.StreamsHandler.sendToStream(Stream, commandBanchoPacketWriter.toBuffer, null); } \ No newline at end of file diff --git a/server/MultiplayerExtras/OsuBattleRoyale.js b/server/MultiplayerExtras/OsuBattleRoyale.js index e140a72..93d59b6 100644 --- a/server/MultiplayerExtras/OsuBattleRoyale.js +++ b/server/MultiplayerExtras/OsuBattleRoyale.js @@ -35,10 +35,10 @@ function kickLowScorers(playerScores = [{playerId:0,slotId:0,score:0,isCurrently // Inform the kicked user's client that they were kicked osuPacketWriter.MatchUpdate(MultiplayerMatch.createOsuMatchJSON()); osuPacketWriter.SendMessage({ - sendingClient: global.users["bot"].username, + sendingClient: global.botUser.username, message: "You were eliminated from the match!", - target: global.users["bot"].username, - senderId: global.users["bot"].id + target: global.botUser.username, + senderId: global.botUser.id }); kickedPlayer.addActionToQueue(osuPacketWriter.toBuffer); @@ -46,10 +46,10 @@ function kickLowScorers(playerScores = [{playerId:0,slotId:0,score:0,isCurrently osuPacketWriter = new osu.Bancho.Writer; osuPacketWriter.SendMessage({ - sendingClient: global.users["bot"].username, + sendingClient: global.botUser.username, message: `${kickedPlayer.username} was eliminated from the match!`, target: "#multiplayer", - senderId: global.users["bot"].id + senderId: global.botUser.id }); global.StreamsHandler.sendToStream(MultiplayerMatch.matchChatStreamName, osuPacketWriter.toBuffer, null); @@ -111,10 +111,10 @@ module.exports = class { case 0: remainingWriterContainer = new osu.Bancho.Writer; remainingWriterContainer.SendMessage({ - sendingClient: global.users["bot"].username, + sendingClient: global.botUser.username, message: "Everyone was eliminated from the match! Nobody wins.", - target: global.users["bot"].username, - senderId: global.users["bot"].id + target: global.botUser.username, + senderId: global.botUser.id }); for (i = 0; i < playerScores.length; i++) { playerClassContainer = getUserById(playerScores[i].playerId); @@ -125,10 +125,10 @@ module.exports = class { case 1: remainingWriterContainer = new osu.Bancho.Writer; remainingWriterContainer.SendMessage({ - sendingClient: global.users["bot"].username, + sendingClient: global.botUser.username, message: "You are the last one remaining, you win!", - target: global.users["bot"].username, - senderId: global.users["bot"].id + target: global.botUser.username, + senderId: global.botUser.id }); playerClassContainer.addActionToQueue(remainingWriterContainer.toBuffer); break; diff --git a/server/Packets/Logout.js b/server/Packets/Logout.js index 2ad1e13..4c36c3a 100644 --- a/server/Packets/Logout.js +++ b/server/Packets/Logout.js @@ -13,14 +13,14 @@ module.exports = function(CurrentUser) { } // Remove user from user list - global.removeUser(CurrentUser); + global.users.remove(CurrentUser.uuid); const osuPacketWriter = new osu.Bancho.Writer(); osuPacketWriter.SendMessage({ - sendingClient: global.users["bot"].username, + sendingClient: global.botUser.username, message: `User ${CurrentUser.username} has logged out.`, target: "#userlog", - senderId: global.users["bot"].id + senderId: global.botUser.id }); global.StreamsHandler.sendToStream("#userlog", osuPacketWriter.toBuffer); diff --git a/server/Packets/SendPublicMessage.js b/server/Packets/SendPublicMessage.js index 74264f4..f69c32b 100644 --- a/server/Packets/SendPublicMessage.js +++ b/server/Packets/SendPublicMessage.js @@ -18,10 +18,10 @@ module.exports = function(CurrentUser, CurrentPacket) { } else { const osuPacketWriter = new osu.Bancho.Writer; osuPacketWriter.SendMessage({ - sendingClient: global.users["bot"].username, + sendingClient: global.botUser.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 + senderId: global.botUser.id }); CurrentUser.addActionToQueue(osuPacketWriter.toBuffer); } diff --git a/server/Packets/TourneyJoinMatchChannel.js b/server/Packets/TourneyJoinMatchChannel.js index 72c80db..be7b9aa 100644 --- a/server/Packets/TourneyJoinMatchChannel.js +++ b/server/Packets/TourneyJoinMatchChannel.js @@ -7,9 +7,9 @@ module.exports = function(CurrentUser, MatchID) { 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]]); + for (let user of global.users.getIterableItems()) { + if (user.id == CurrentUser.id) { + match.tourneyClientUsers.push(user); } } diff --git a/server/Packets/UserPresenceBundle.js b/server/Packets/UserPresenceBundle.js index 21a226d..6d71175 100644 --- a/server/Packets/UserPresenceBundle.js +++ b/server/Packets/UserPresenceBundle.js @@ -5,8 +5,8 @@ module.exports = function(currentUser, sendImmidiate = true) { let userIds = []; - for (let i = 0; i < global.userKeys.length; i++) { - userIds.push(global.users[global.userKeys[i]].id); + for (let user of global.users.getIterableItems()) { + userIds.push(user.id); } osuPacketWriter.UserPresenceBundle(userIds); diff --git a/server/loginHandler.js b/server/loginHandler.js index 2b37ff4..c7c6684 100644 --- a/server/loginHandler.js +++ b/server/loginHandler.js @@ -9,6 +9,7 @@ const osu = require("osu-packet"), getUserByToken = require("./util/getUserByToken.js"), countryHelper = require("./countryHelper.js"), loginHelper = require("./loginHelper.js"), + Logout = require("./Packets/Logout.js"), UserPresenceBundle = require("./Packets/UserPresenceBundle.js"), UserPresence = require("./Packets/UserPresence.js"), StatusUpdate = require("./Packets/StatusUpdate.js"); @@ -65,20 +66,15 @@ module.exports = async function(req, res, loginInfo) { // 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); - } + for (let user of global.users.getIterableItems()) { + // Log them out if they are not a tourney user + if (!user.isTourneyUser && user.uuid != newClientToken) + Logout(user); } } - // Create user object - global.addUser(newClientToken, new User(userDB.id, loginInfo.username, newClientToken)); - // Retreive the newly created user - const NewUser = getUserByToken(newClientToken); + const NewUser = global.users.add(newClientToken, new User(userDB.id, loginInfo.username, newClientToken)); // Set tourney client flag NewUser.isTourneyUser = isTourneyClient; diff --git a/server/serverHandler.js b/server/serverHandler.js index add89c8..0af49e0 100644 --- a/server/serverHandler.js +++ b/server/serverHandler.js @@ -9,35 +9,17 @@ const osu = require("osu-packet"), bakedResponses = require("./bakedResponses.js"), Streams = require("./Streams.js"), DatabaseHelperClass = require("./DatabaseHelper.js"), + funkyArray = require("./util/funkyArray.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.removeUser = function(userToRemove) { - // This should be safe to do since we should be in a try-catch at all times - // I just want a trace of how this is happening. - if (userToRemove.uuid == "bot") - throw "Tried to remove the bot user!"; - - delete userToRemove; - global.refreshUserKeys(); -} - -global.refreshUserKeys = function() { - global.userKeys = Object.keys(global.users); -} +// Users funkyArray for session storage +global.users = new funkyArray(); // Add the bot user -global.addUser("bot", new User(3, "SillyBot", "bot")); +global.botUser = global.users.add("bot", new User(3, "SillyBot", "bot")); // Set the bot's position on the map -global.users["bot"].location[0] = 50; -global.users["bot"].location[1] = -32; +global.botUser.location[0] = 50; +global.botUser.location[1] = -32; global.DatabaseHelper = new DatabaseHelperClass(config.databaseAddress, config.databasePort, config.databaseUsername, config.databasePassword, config.databaseName); @@ -45,8 +27,7 @@ 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]]; + for (let User of global.users.getIterableItems()) { if (User.id == 3) continue; // Ignore the bot // Bot: :( diff --git a/server/util/funkyArray.js b/server/util/funkyArray.js new file mode 100644 index 0000000..04feeea --- /dev/null +++ b/server/util/funkyArray.js @@ -0,0 +1,75 @@ +class FunkyArray { + constructor() { + this.items = {}; + this.itemKeys = Object.keys(this.items); + + this.iterableArray = []; + } + + add(uuid, item, regenerate = true) { + this.items[uuid] = item; + + if (regenerate) { + this.itemKeys = Object.keys(this.items); + this.regenerateIterableArray(); + } + + return this.items[uuid]; + } + + remove(uuid, regenerate = true) { + delete this.items[uuid]; + if (regenerate) { + this.itemKeys = Object.keys(this.items); + this.regenerateIterableArray(); + } + } + + removeFirstItem(regenerate = true) { + delete this.items[this.itemKeys[0]]; + this.itemKeys = Object.keys(this.items); + if (regenerate) this.regenerateIterableArray(); + } + + regenerateIterableArray() { + this.iterableArray = new Array(); + for (let itemKey of this.itemKeys) { + this.iterableArray.push(this.items[itemKey]); + } + this.itemKeys = Object.keys(this.items); + } + + getFirstItem() { + return this.items[this.itemKeys[0]]; + } + + getLength() { + return this.itemKeys.length; + } + + getKeyById(id) { + return this.itemKeys[id]; + } + + getById(id) { + return this.items[this.itemKeys[id]]; + } + + getByKey(key) { + return this.items[key]; + } + + getKeys() { + return this.itemKeys; + } + + getItems() { + return this.items; + } + + getIterableItems() { + return this.iterableArray; + } +} + +module.exports = FunkyArray; \ No newline at end of file diff --git a/server/util/getUserById.js b/server/util/getUserById.js index 9f608f7..529dab7 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 user of global.users.getIterableItems()) { + if (user.id == id) + return user; } } \ No newline at end of file diff --git a/server/util/getUserByToken.js b/server/util/getUserByToken.js index 6c871b1..78d3683 100644 --- a/server/util/getUserByToken.js +++ b/server/util/getUserByToken.js @@ -1,4 +1,3 @@ module.exports = function(token) { - if (global.userKeys.includes(token)) return global.users[token]; - else return null; + return global.users.getByKey(token); } \ No newline at end of file diff --git a/server/util/getUserByUsername.js b/server/util/getUserByUsername.js index 03e1f1b..fb0a4bf 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 user of global.users.getIterableItems()) { + if (user.username == username) + return user; } } \ No newline at end of file