diff --git a/package.json b/package.json index bedf743..e2159d7 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "express": "^4.17.1", "fs": "0.0.1-security", "osu-packet": "^4.1.2", + "python-struct": "^1.1.3", "request": "^2.88.2", "sync-request": "^6.1.0", "tcp-netx": "^1.2.11", diff --git a/server/ActionBuffer.js b/server/ActionBuffer.js new file mode 100644 index 0000000..1d6155f --- /dev/null +++ b/server/ActionBuffer.js @@ -0,0 +1,19 @@ +module.exports = class { + constructor(initialData = Buffer) { + this.actionBuffer; + if (initialData.length == 0) { + this.actionBuffer = Buffer.alloc(0); + } else { + this.actionBuffer = initialData; + } + } + + bufferAction(data = Buffer) { + if (data.length != 0) + this.actionBuffer = Buffer.concat([this.actionBuffer, data], this.actionBuffer.length + data.length); + } + + toBuffer() { + return this.actionBuffer; + } +} \ No newline at end of file diff --git a/server/MultiplayerExtras/OsuBattleRoyale.js b/server/MultiplayerExtras/OsuBattleRoyale.js index afa5bf6..61954f2 100644 --- a/server/MultiplayerExtras/OsuBattleRoyale.js +++ b/server/MultiplayerExtras/OsuBattleRoyale.js @@ -38,7 +38,7 @@ module.exports = class { slot.playerId = -1; slot.status = 2; // Remove the kicked player from the match's stream - global.StreamsHandler.removeUserFromStream(this.MultiplayerMatch.matchStreamName, kickedPlayer.id); + global.StreamsHandler.removeUserFromStream(this.MultiplayerMatch.matchStreamName, kickedPlayer.uuid); // Remove the kicked player's referance this this match kickedPlayer.currentMatch = null; diff --git a/server/MultiplayerManager.js b/server/MultiplayerManager.js index b6c4a03..5b975b4 100644 --- a/server/MultiplayerManager.js +++ b/server/MultiplayerManager.js @@ -16,7 +16,7 @@ module.exports = class { currentUser.currentMatch.leaveMatch(currentUser); // Add user to the stream for the lobby - global.StreamsHandler.addUserToStream("multiplayer_lobby", currentUser.id); + 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); @@ -43,8 +43,8 @@ module.exports = class { const osuPacketWriter = new osu.Bancho.Writer; // Add the user to the #lobby channel - if (!global.StreamsHandler.isUserInStream("#lobby", currentUser.id)) { - global.StreamsHandler.addUserToStream("#lobby", currentUser.id); + if (!global.StreamsHandler.isUserInStream("#lobby", currentUser.uuid)) { + global.StreamsHandler.addUserToStream("#lobby", currentUser.uuid); osuPacketWriter.ChannelJoinSuccess("#lobby"); } @@ -53,8 +53,8 @@ module.exports = class { 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.id)) - global.StreamsHandler.removeUserFromStream("multiplayer_lobby", currentUser.id); + if (global.StreamsHandler.isUserInStream("multiplayer_lobby", currentUser.uuid)) + global.StreamsHandler.removeUserFromStream("multiplayer_lobby", currentUser.uuid); } updateMatchListing() { @@ -141,7 +141,7 @@ module.exports = class { JoiningUser.currentMatch = match; // Add user to the stream for the match - global.StreamsHandler.addUserToStream(streamName, JoiningUser.id); + global.StreamsHandler.addUserToStream(streamName, JoiningUser.uuid); // Inform all users in the match that a new user has joined global.StreamsHandler.sendToStream(streamName, osuPacketWriter1.toBuffer, null); @@ -212,4 +212,26 @@ module.exports = class { this.updateMatchListing(); }, 1000); } + + getMatchInfoForTourneyClient(MatchID) { + let match = null; + for (let amatch in this.matches) { + if (amatch.matchId == MatchID) { + match = amatch; + } + } + if (match == null) return null; + else return match.createOsuMatchJSON(); + } + + getMatch(MatchID) { + let match = null; + for (let amatch in this.matches) { + if (amatch.matchId == MatchID) { + match = amatch; + } + } + if (match == null) return null; + else return match; + } } \ No newline at end of file diff --git a/server/MultiplayerMatch.js b/server/MultiplayerMatch.js index f0a779a..5548267 100644 --- a/server/MultiplayerMatch.js +++ b/server/MultiplayerMatch.js @@ -47,6 +47,9 @@ module.exports = class { this.multiplayerExtras = null; + this.isTourneyMatch = false; + this.tourneyClientUsers = []; + const osuPacketWriter = new osu.Bancho.Writer; // Update the status of the current user @@ -118,7 +121,7 @@ module.exports = class { osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); // Remove the leaving user from the match's stream - global.StreamsHandler.removeUserFromStream(this.matchStreamName, MatchUser.id); + global.StreamsHandler.removeUserFromStream(this.matchStreamName, MatchUser.uuid); // Inform all users in the match that the leaving user has left global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); @@ -212,6 +215,22 @@ module.exports = class { global.MultiplayerManager.updateMatchListing(); } + changeTeam(MatchUser) { + const slot = this.slots[MatchUser.matchSlotId]; + if (slot.team == 0) { + slot.team = 1; + } else { + slot.team = 0; + } + + const osuPacketWriter = new osu.Bancho.Writer; + + osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); + + // Send this change to all users in the match + global.StreamsHandler.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); + } + setReadyState(MatchUser, ReadyState) { // Get the match the user is in const osuPacketWriter = new osu.Bancho.Writer; @@ -245,7 +264,7 @@ module.exports = class { // Get the data of the slot at the index sent by the client const slot = this.slots[MatchUserToKick]; - let cachedPlayerId = slot.playerId; + let cachedPlayerToken = getUserById(slot.playerId).uuid; // If the slot is empty lock instead of kicking if (slot.playerId === -1) { // Slot is empty, lock it @@ -268,9 +287,9 @@ module.exports = class { // Update the match listing in the lobby listing to reflect this change global.MultiplayerManager.updateMatchListing(); - if (cachedPlayerId !== null && cachedPlayerId !== -1) { + if (cachedPlayerToken !== null && cachedPlayerToken !== "") { // Remove the kicked user from the match stream - global.StreamsHandler.removeUserFromStream(this.matchStreamName, cachedPlayerId); + global.StreamsHandler.removeUserFromStream(this.matchStreamName, cachedPlayerToken); } } diff --git a/server/Packets/ChangeAction.js b/server/Packets/ChangeAction.js index a80b351..357b2f3 100644 --- a/server/Packets/ChangeAction.js +++ b/server/Packets/ChangeAction.js @@ -2,6 +2,7 @@ const StatusUpdate = require("./StatusUpdate.js"); module.exports = function(currentUser, 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); diff --git a/server/Packets/ChannelJoin.js b/server/Packets/ChannelJoin.js index 4033992..739d5c1 100644 --- a/server/Packets/ChannelJoin.js +++ b/server/Packets/ChannelJoin.js @@ -2,14 +2,14 @@ const osu = require("osu-packet"); module.exports = function(CurrentUser, channelName = "") { // Make sure the user is not already in the channel - if (global.StreamsHandler.isUserInStream(channelName, CurrentUser.id)) + if (global.StreamsHandler.isUserInStream(channelName, CurrentUser.uuid)) return global.consoleHelper.printBancho(`Did not add user to channel ${channelName} because they are already in it`); const osuPacketWriter = new osu.Bancho.Writer; osuPacketWriter.ChannelJoinSuccess(channelName); - if (!global.StreamsHandler.isUserInStream(channelName, CurrentUser.id)) - global.StreamsHandler.addUserToStream(channelName, CurrentUser.id); + if (!global.StreamsHandler.isUserInStream(channelName, CurrentUser.uuid)) + global.StreamsHandler.addUserToStream(channelName, CurrentUser.uuid); CurrentUser.addActionToQueue(osuPacketWriter.toBuffer); } \ No newline at end of file diff --git a/server/Packets/ChannelPart.js b/server/Packets/ChannelPart.js index 3a39717..38d6431 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 - global.StreamsHandler.removeUserFromStream(data, CurrentUser.id); + 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 dd4e995..28cdf1f 100644 --- a/server/Packets/Logout.js +++ b/server/Packets/Logout.js @@ -6,8 +6,8 @@ module.exports = function(CurrentUser) { const streamList = global.StreamsHandler.getStreams(); for (let i = 0; i < streamList.length; i++) { - if (global.StreamsHandler.isUserInStream(streamList[i], CurrentUser.id)) { - global.StreamsHandler.removeUserFromStream(streamList[i], CurrentUser.id); + if (global.StreamsHandler.isUserInStream(streamList[i], CurrentUser.uuid)) { + global.StreamsHandler.removeUserFromStream(streamList[i], CurrentUser.uuid); } } diff --git a/server/Packets/SendPublicMessage.js b/server/Packets/SendPublicMessage.js index e98d346..9a5df66 100644 --- a/server/Packets/SendPublicMessage.js +++ b/server/Packets/SendPublicMessage.js @@ -36,7 +36,7 @@ module.exports = function(CurrentUser, CurrentPacket) { }); if (CurrentPacket.data.target == "#multiplayer") { - global.StreamsHandler.sendToStream(CurrentUser.currentMatch.matchStreamName, osuPacketWriter.toBuffer, CurrentUser.id); + global.StreamsHandler.sendToStream(CurrentUser.currentMatch.matchStreamName, osuPacketWriter.toBuffer, CurrentUser.uuid); botCommandHandler(CurrentUser, CurrentPacket.data.message, CurrentUser.currentMatch.matchStreamName, true); return; } @@ -45,7 +45,7 @@ module.exports = function(CurrentUser, CurrentPacket) { if (!global.StreamsHandler.doesStreamExist(CurrentPacket.data.target)) return; // Write chat message to stream asociated with chat channel - global.StreamsHandler.sendToStream(CurrentPacket.data.target, osuPacketWriter.toBuffer, CurrentUser.id); + global.StreamsHandler.sendToStream(CurrentPacket.data.target, osuPacketWriter.toBuffer, CurrentUser.uuid); if (CurrentPacket.data.target == "#osu") global.addChatMessage(`${CurrentUser.username}: ${CurrentPacket.data.message}`); botCommandHandler(CurrentUser, CurrentPacket.data.message, CurrentPacket.data.target); diff --git a/server/Packets/TourneyJoinMatchChannel.js b/server/Packets/TourneyJoinMatchChannel.js new file mode 100644 index 0000000..b50749c --- /dev/null +++ b/server/Packets/TourneyJoinMatchChannel.js @@ -0,0 +1,26 @@ +const osu = require("osu-packet"); + +module.exports = function(CurrentUser, MatchID) { + const match = global.MultiplayerManager.getMatch(MatchID); + + if (match != null) { + + match.isTourneyMatch = true; + for (let i = 0; i < global.users.length; i++) { + if (global.users[i].id == CurrentUser.id) { + match.tourneyClientUsers.push(global.users[i]); + } + } + + if (global.StreamsHandler.isUserInStream(match.matchStreamName, CurrentUser.uuid)) + return global.consoleHelper.printBancho(`Did not add user to channel ${match.matchStreamName} because they are already in it`); + + const osuPacketWriter = new osu.Bancho.Writer; + + osuPacketWriter.ChannelJoinSuccess("#multiplayer"); + if (!global.StreamsHandler.isUserInStream(match.matchStreamName, CurrentUser.uuid)) + global.StreamsHandler.addUserToStream(match.matchStreamName, CurrentUser.uuid); + + CurrentUser.addActionToQueue(osuPacketWriter.toBuffer); + } +} \ No newline at end of file diff --git a/server/Packets/TourneyMatchSpecialInfo.js b/server/Packets/TourneyMatchSpecialInfo.js new file mode 100644 index 0000000..922fdaf --- /dev/null +++ b/server/Packets/TourneyMatchSpecialInfo.js @@ -0,0 +1,24 @@ +const osu = require("osu-packet"), + ActionBuffer = require("../ActionBuffer.js"); +const UserPresence = require("./UserPresence.js"), + StatusUpdate = require("./StatusUpdate.js"); + +module.exports = function(CurrentUser, MatchID) { + const matchData = global.MultiplayerManager.getMatchInfoForTourneyClient(MatchID); + + if (matchData != null) { + const osuPacketWriter = new osu.Bancho.Writer(); + + osuPacketWriter.MatchUpdate(matchData); + + let actions = new ActionBuffer(osuPacketWriter.toBuffer); + + for (let i = 0; i < matchData.slots.length; i++) { + const slot = matchData.slots[i]; + actions.bufferAction(UserPresence(CurrentUser, slot.playerId, false)); + actions.bufferAction(StatusUpdate(CurrentUser, slot.playerId, false)); + } + + CurrentUser.addActionToQueue(actions.toBuffer()); + } +} \ No newline at end of file diff --git a/server/Spectator.js b/server/Spectator.js index a4bf653..ba631d4 100644 --- a/server/Spectator.js +++ b/server/Spectator.js @@ -7,11 +7,11 @@ module.exports = { const User = getUserById(spectatedId); if (global.StreamsHandler.doesStreamExist(`sp_${User.username}`)) { // Just add user to stream since it already exists - global.StreamsHandler.addUserToStream(`sp_${User.username}`, currentUser.id); + global.StreamsHandler.addUserToStream(`sp_${User.username}`, currentUser.uuid); } else { // Stream doesn't exist, create it and add the spectator global.StreamsHandler.addStream(`sp_${User.username}`, true, spectatedId); - global.StreamsHandler.addUserToStream(`sp_${User.username}`, currentUser.id); + global.StreamsHandler.addUserToStream(`sp_${User.username}`, currentUser.uuid); } // We want to do this stuff regardless @@ -61,7 +61,7 @@ module.exports = { spectatedUser.addActionToQueue(osuPacketWriter.toBuffer); // Remove this user from the spectator stream - global.StreamsHandler.removeUserFromStream(`sp_${spectatedUser.username}`, currentUser.id); + global.StreamsHandler.removeUserFromStream(`sp_${spectatedUser.username}`, currentUser.uuid); // Make a new clear osu packet writer osuPacketWriter = new osu.Bancho.Writer; diff --git a/server/Streams.js b/server/Streams.js index 0e89368..5aa203a 100644 --- a/server/Streams.js +++ b/server/Streams.js @@ -1,4 +1,4 @@ -const getUserById = require("./util/getUserById.js"); +const getUserByToken = require("./util/getUserByToken.js"); module.exports = class { constructor() { @@ -12,7 +12,7 @@ module.exports = class { 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 IDs of the users in a given stream + 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 } @@ -47,14 +47,14 @@ module.exports = class { try { // Loop through the users in this stream for (let i = 0; i < currentStream.streamUsers.length; i++) { - // Get the user id of the user in the queue - const currentUserId = currentStream.streamUsers[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 && currentUserId == initUser && (streamName[0] == "#" || streamName.includes("mp_"))) continue; - if (currentUserId == 3) continue; // Skip if user is bot + 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 = getUserById(currentUserId); + const currentUser = getUserByToken(currentUserToken); // Skip if user is nonexistant if (currentUser == null) continue; @@ -64,41 +64,41 @@ module.exports = class { } catch (e) {} } - addUserToStream(streamName, userId) { + 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!`); // Make sure the user isn't already in the stream - if (this.avaliableStreams[streamName].streamUsers.includes(userId)) + 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 this isn't an invalid user (userId can't be lower than 1) - if (userId <= 0 || userId == null) - return global.consoleHelper.printBancho(`Did not add user to stream [${streamName}] because their userId is invalid!`); + if (userToken == "" || userToken == null) + return global.consoleHelper.printBancho(`Did not add user to stream [${streamName}] because their token is invalid!`); - // Add user's id to the stream's user list - this.avaliableStreams[streamName].streamUsers.push(userId); - global.consoleHelper.printBancho(`Added user [${userId}] to stream ${streamName}`); + // 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}`); } - removeUserFromStream(streamName, userId) { + 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!`); // Make sure the user isn't already in the stream - if (!this.avaliableStreams[streamName].streamUsers.includes(userId)) + 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 this isn't an invalid user (userId can't be lower than 1) - if (userId <= 0 || userId == null) + 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 (userId == this.avaliableStreams[streamName].streamUsers[i]) { + if (userToken == this.avaliableStreams[streamName].streamUsers[i]) { userCurrentIndex = i; break; } @@ -106,8 +106,8 @@ module.exports = class { // Remove user from stream's user list this.avaliableStreams[streamName].streamUsers.splice(userCurrentIndex, 1); - global.consoleHelper.printBancho(`Removed user [${userId}] from stream ${streamName}`); - } catch (e) { global.consoleHelper.printBancho(`Can't Remove user [${userId}] from stream ${streamName}`); } + global.consoleHelper.printBancho(`Removed user [${userToken}] from stream ${streamName}`); + } catch (e) { global.consoleHelper.printBancho(`Can't Remove user [${userToken}] from stream ${streamName}`); } } doesStreamExist(streamName) { @@ -119,8 +119,8 @@ module.exports = class { return this.avaliableStreamKeys; } - isUserInStream(streamName, userId) { - if (this.avaliableStreams[streamName].streamUsers.includes(userId)) return true; + isUserInStream(streamName, userToken) { + if (this.avaliableStreams[streamName].streamUsers.includes(userToken)) return true; else return false; } diff --git a/server/User.js b/server/User.js index 34bb0cb..8867abb 100644 --- a/server/User.js +++ b/server/User.js @@ -1,7 +1,7 @@ const StatusUpdate = require("./Packets/StatusUpdate.js"); module.exports = class { - constructor(id, username, uuid, connectTime) { + constructor(id, username, uuid, connectTime, isTourneyUser = false) { this.id = id; this.username = username; this.uuid = uuid; @@ -34,6 +34,8 @@ module.exports = class { // Multiplayer data this.currentMatch = null; this.matchSlotId = -1; + + this.isTourneyUser = isTourneyUser; } // Adds new actions to the user's queue diff --git a/server/loginHandler.js b/server/loginHandler.js index 2402b6d..d3b22c7 100644 --- a/server/loginHandler.js +++ b/server/loginHandler.js @@ -47,23 +47,24 @@ module.exports = function(req, res, loginInfo) { // Make sure user is not already connected, kick off if so. const checkForPreexistingUser = getUserByUsername(loginInfo.username); - if (checkForPreexistingUser != null) { + if (checkForPreexistingUser != null && !loginInfo.osuversion.includes("tourney")) { if (checkForPreexistingUser.uuid != newClientToken) { - let userCurrentIndex; + let userCurrentIndex, isTourneyUser = false; // Find the index that the user's class is at for (let i = 0; i < global.users.length; i++) { - if (checkForPreexistingUser.uuid == global.users[i].uuid) { + if (checkForPreexistingUser.uuid == global.users[i].uuid && !global.users[i].isTourneyUser) { userCurrentIndex = i; + isTourneyUser = global.users[i].isTourneyUser; break; } } - global.users.splice(userCurrentIndex, 1); + if (!isTourneyUser) global.users.splice(userCurrentIndex, 1); } } // Create user object - global.users.push(new User(userDB.id, loginInfo.username, newClientToken, new Date().getTime())); + global.users.push(new User(userDB.id, loginInfo.username, newClientToken, new Date().getTime(), loginInfo.osuversion.includes("tourney"))); // Retreive the newly created user const NewUser = getUserByToken(newClientToken); @@ -113,12 +114,12 @@ module.exports = function(req, res, loginInfo) { // Add user to chat channels osuPacketWriter.ChannelJoinSuccess("#osu"); - if (!global.StreamsHandler.isUserInStream("#osu", NewUser.id)) - global.StreamsHandler.addUserToStream("#osu", NewUser.id); + if (!global.StreamsHandler.isUserInStream("#osu", NewUser.uuid)) + global.StreamsHandler.addUserToStream("#osu", NewUser.uuid); osuPacketWriter.ChannelJoinSuccess("#userlog"); - if (!global.StreamsHandler.isUserInStream("#userlog", NewUser.id)) - global.StreamsHandler.addUserToStream("#userlog", NewUser.id); + 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++) { diff --git a/server/serverHandler.js b/server/serverHandler.js index da7d0af..17fc1e6 100644 --- a/server/serverHandler.js +++ b/server/serverHandler.js @@ -112,7 +112,9 @@ const ChangeAction = require("./Packets/ChangeAction.js"), UserPresenceBundle = require("./Packets/UserPresenceBundle.js"), UserPresence = require("./Packets/UserPresence.js"), UserStatsRequest = require("./Packets/UserStatsRequest.js"), - MultiplayerInvite = require("./Packets/MultiplayerInvite.js"); + MultiplayerInvite = require("./Packets/MultiplayerInvite.js"), + TourneyMatchSpecialInfo = require("./Packets/TourneyMatchSpecialInfo.js"), + TourneyMatchJoinChannel = require("./Packets/TourneyMatchSpecialInfo.js"); // A class for managing everything multiplayer global.MultiplayerManager = new MultiplayerManager(); @@ -272,6 +274,10 @@ module.exports = function(req, res) { PacketUser.currentMatch.matchFailed(PacketUser); break; + case packetIDs.client_matchChangeTeam: + PacketUser.currentMatch.changeTeam(PacketUser); + break; + case packetIDs.client_channelJoin: ChannelJoin(PacketUser, CurrentPacket.data); break; @@ -292,6 +298,14 @@ module.exports = function(req, res) { UserStatsRequest(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_invite: MultiplayerInvite(PacketUser, CurrentPacket.data); break;