diff --git a/constants/fokabotCommands.py b/constants/fokabotCommands.py index 7cad3a8..f2fb024 100644 --- a/constants/fokabotCommands.py +++ b/constants/fokabotCommands.py @@ -757,6 +757,32 @@ def report(fro, chan, message): token.enqueue(serverPackets.notification(msg)) return False +def multiplayer(fro, chan, message): + def mpMake(): + return "Not implemented yet." + + def mpClose(): + myToken = glob.tokens.getTokenFromUsername(fro) + if myToken.matchID == -1: + return "You're not in a multiplayer match" + glob.matches.disposeMatch(myToken.matchID) + return "Multiplayer match #{} disposed successfully".format(myToken.matchID) + + try: + subcommands = { + "make": mpMake, + "clear": mpClose + } + requestedSubcommand = message[0].lower().strip() + if requestedSubcommand not in subcommands: + raise exceptions.invalidArgumentsException("Invalid subcommand") + return subcommands[requestedSubcommand]() + except exceptions.invalidArgumentsException as e: + return str(e) + except: + raise + + """ Commands list @@ -891,6 +917,11 @@ commands = [ }, { "trigger": "!update", "callback": updateBeatmap + }, { + "trigger": "!mp", + "privileges": privileges.ADMIN_MANAGE_SERVERS, # TODO: replace with admin tournament privilege + "syntax": "", + "callback": multiplayer } # # "trigger": "!acc", diff --git a/objects/fokabot.py b/objects/fokabot.py index 8597a12..faee27a 100644 --- a/objects/fokabot.py +++ b/objects/fokabot.py @@ -41,7 +41,7 @@ def fokabotResponse(fro, chan, message): """ for i in fokabotCommands.commands: # Loop though all commands - if generalUtils.strContains(message, i["trigger"]): + if message.strip().startswith(i["trigger"]): # message has triggered a command # Make sure the user has right permissions diff --git a/objects/match.py b/objects/match.py index be84336..3f05b82 100644 --- a/objects/match.py +++ b/objects/match.py @@ -440,11 +440,12 @@ class match: return False - def userLeft(self, user): + def userLeft(self, user, disposeMatch=True): """ Remove someone from users in match :param user: user object of the user + :param disposeMatch: if `True`, will try to dispose match if there are no users in the room :return: """ # Make sure the user is in room @@ -456,10 +457,10 @@ class match: self.setSlot(slotID, slotStatuses.FREE, 0, None, 0) # Check if everyone left - if self.countUsers() == 0: + if self.countUsers() == 0 and disposeMatch: # Dispose match glob.matches.disposeMatch(self.matchID) - log.info("MPROOM{}: Room disposed".format(self.matchID)) + log.info("MPROOM{}: Room disposed because all users left".format(self.matchID)) return # Check if host left diff --git a/objects/matchList.py b/objects/matchList.py index f82f755..df811e8 100644 --- a/objects/matchList.py +++ b/objects/matchList.py @@ -1,6 +1,7 @@ from objects import match from objects import glob from constants import serverPackets +from common.log import logUtils as log class matchList: def __init__(self): @@ -38,12 +39,24 @@ class matchList: if matchID not in self.matches: return - # Remove match object and stream - _match = self.matches.pop(matchID) + # Get match and disconnect all players + _match = self.matches[matchID] + for slot in _match.slots: + _token = glob.tokens.getTokenFromUserID(slot.userID, ignoreIRC=True) + if _token is None: + continue + _match.userLeft(_token, disposeMatch=False) # don't dispose the match twice when we remove all players + + # Send matchDisposed packet before disposing streams + glob.streams.broadcast(_match.streamName, serverPackets.disposeMatch(_match.matchID)) + + # Dispose all streams glob.streams.dispose(_match.streamName) glob.streams.dispose(_match.playingStreamName) glob.streams.remove(_match.streamName) glob.streams.remove(_match.playingStreamName) # Send match dispose packet to everyone in lobby - glob.streams.broadcast("lobby", serverPackets.disposeMatch(matchID)) \ No newline at end of file + glob.streams.broadcast("lobby", serverPackets.disposeMatch(matchID)) + del self.matches[matchID] + log.info("MPROOM{}: Room disposed manually".format(_match.matchID)) \ No newline at end of file diff --git a/objects/osuToken.py b/objects/osuToken.py index 8123a84..176c13c 100644 --- a/objects/osuToken.py +++ b/objects/osuToken.py @@ -323,19 +323,20 @@ class token: self.leaveStream("multi/{}".format(self.matchID)) self.leaveStream("multi/{}/playing".format(self.matchID)) # optional + # Set usertoken match to -1 + leavingMatchID = self.matchID + self.matchID = -1 + # Make sure the match exists - if self.matchID not in glob.matches.matches: + if leavingMatchID not in glob.matches.matches: return # The match exists, get object - match = glob.matches.matches[self.matchID] + match = glob.matches.matches[leavingMatchID] # Set slot to free match.userLeft(self) - # Set usertoken match to -1 - self.matchID = -1 - def kick(self, message="You have been kicked from the server. Please login again.", reason="kick"): """ Kick this user from the server