From afbd8e7e8c4a3e1a66e0e1473a146f3723ca20c8 Mon Sep 17 00:00:00 2001 From: Nyo Date: Tue, 4 Oct 2016 22:10:07 +0200 Subject: [PATCH] .BANCHO. Implemented packet streams for spectator and lobby --- events/changeActionEvent.py | 16 ++---- events/createMatchEvent.py | 6 +-- events/joinLobbyEvent.py | 3 +- events/partLobbyEvent.py | 2 +- events/spectateFramesEvent.py | 5 +- events/startSpectatingEvent.py | 41 +-------------- helpers/chatHelper.py | 8 +-- objects/match.py | 5 +- objects/matchList.py | 14 ++--- objects/osuToken.py | 94 ++++++++++++++++++++++++---------- objects/stream.py | 4 ++ objects/streamList.py | 12 +++++ pep.py | 3 +- 13 files changed, 105 insertions(+), 108 deletions(-) diff --git a/events/changeActionEvent.py b/events/changeActionEvent.py index 81b27be..92c576d 100644 --- a/events/changeActionEvent.py +++ b/events/changeActionEvent.py @@ -48,22 +48,16 @@ if userToken.matchID != -1 and userToken.actionID != actions.MULTIPLAYING and us userToken.beatmapID = packetData["beatmapID"] # Enqueue our new user panel and stats to us and our spectators - recipients = [userID] + recipients = [userToken] if len(userToken.spectators) > 0: recipients += userToken.spectators for i in recipients: - if i == userID: - # Save some loops - token = userToken - else: - token = glob.tokens.getTokenFromUserID(i) - - if token is not None: + if i is not None: # Force our own packet - force = True if token.userID == userID else False - token.enqueue(serverPackets.userPanel(userID, force)) - token.enqueue(serverPackets.userStats(userID, force)) + force = True if i == userToken else False + i.enqueue(serverPackets.userPanel(userID, force)) + i.enqueue(serverPackets.userStats(userID, force)) # Console output log.info("{} changed action: {} [{}][{}][{}]".format(username, str(userToken.actionID), userToken.actionText, userToken.actionMd5, userToken.beatmapID)) diff --git a/events/createMatchEvent.py b/events/createMatchEvent.py index 4940ec2..e245a24 100644 --- a/events/createMatchEvent.py +++ b/events/createMatchEvent.py @@ -32,11 +32,7 @@ def handle(userToken, packetData): match.setHost(userID) # Send match create packet to everyone in lobby - for i in glob.matches.usersInLobby: - # Make sure this user is still connected - token = glob.tokens.getTokenFromUserID(i) - if token is not None: - token.enqueue(serverPackets.createMatch(matchID)) + glob.streams.broadcast("lobby", serverPackets.createMatch(matchID)) # Console output log.info("MPROOM{}: Room created!".format(matchID)) diff --git a/events/joinLobbyEvent.py b/events/joinLobbyEvent.py index c130f03..a5c4624 100644 --- a/events/joinLobbyEvent.py +++ b/events/joinLobbyEvent.py @@ -6,10 +6,9 @@ from objects import glob def handle(userToken, _): # Get userToken data username = userToken.username - userID = userToken.userID # Add user to users in lobby - glob.matches.lobbyUserJoin(userID) + userToken.joinStream("lobby") # Send matches data for key, _ in glob.matches.matches.items(): diff --git a/events/partLobbyEvent.py b/events/partLobbyEvent.py index a4367b5..e5b2a71 100644 --- a/events/partLobbyEvent.py +++ b/events/partLobbyEvent.py @@ -9,7 +9,7 @@ def handle(userToken, _): username = userToken.username # Remove user from users in lobby - glob.matches.lobbyUserPart(userID) + userToken.leaveStream("lobby") # Part lobby channel chat.partChannel(channel="#lobby", token=userToken, kick=True) diff --git a/events/spectateFramesEvent.py b/events/spectateFramesEvent.py index 3e4c680..6cb1495 100644 --- a/events/spectateFramesEvent.py +++ b/events/spectateFramesEvent.py @@ -7,7 +7,8 @@ def handle(userToken, packetData): userID = userToken.userID # Send spectator frames to every spectator - for i in userToken.spectators: + glob.streams.broadcast("spect/{}".format(userID), serverPackets.spectatorFrames(packetData[7:])) + '''for i in userToken.spectators: # Send to every user but host if i != userID: try: @@ -27,4 +28,4 @@ def handle(userToken, packetData): except exceptions.stopSpectating: # Remove this user from spectators userToken.removeSpectator(i) - userToken.enqueue(serverPackets.removeSpectator(i)) + userToken.enqueue(serverPackets.removeSpectator(i))''' diff --git a/events/startSpectatingEvent.py b/events/startSpectatingEvent.py index b67b3bf..495705d 100644 --- a/events/startSpectatingEvent.py +++ b/events/startSpectatingEvent.py @@ -1,57 +1,20 @@ from common.log import logUtils as log -from common.ripple import userUtils from constants import clientPackets from constants import exceptions -from constants import serverPackets -from helpers import chatHelper as chat from objects import glob - def handle(userToken, packetData): try: - # Get usertoken data - userID = userToken.userID - username = userToken.username - # Start spectating packet packetData = clientPackets.startSpectating(packetData) - # Stop spectating old user if needed - if userToken.spectating != 0: - oldTargetToken = glob.tokens.getTokenFromUserID(userToken.spectating) - oldTargetToken.enqueue(serverPackets.removeSpectator(userID)) - userToken.stopSpectating() - - # Start spectating new user - userToken.startSpectating(packetData["userID"]) - # Get host token targetToken = glob.tokens.getTokenFromUserID(packetData["userID"]) if targetToken is None: raise exceptions.tokenNotFoundException - # Add us to host's spectators - targetToken.addSpectator(userID) - - # Send spectator join packet to host - targetToken.enqueue(serverPackets.addSpectator(userID)) - - # Create and join #spectator (#spect_userid) channel - glob.channels.addTempChannel("#spect_{}".format(targetToken.userID)) - chat.joinChannel(token=userToken, channel="#spect_{}".format(targetToken.userID)) - if len(targetToken.spectators) == 1: - # First spectator, send #spectator join to host too - chat.joinChannel(token=targetToken, channel="#spect_{}".format(targetToken.userID)) - - # send fellowSpectatorJoined to all spectators - for spec in targetToken.spectators: - if spec is not userID: - c = glob.tokens.getTokenFromUserID(spec) - userToken.enqueue(serverPackets.fellowSpectatorJoined(c.userID)) - c.enqueue(serverPackets.fellowSpectatorJoined(userID)) - - # Console output - log.info("{} are spectating {}".format(username, userUtils.getUsername(packetData["userID"]))) + # Start spectating new user + userToken.startSpectating(targetToken) except exceptions.tokenNotFoundException: # Stop spectating if token not found log.warning("Spectator start: token not found") diff --git a/helpers/chatHelper.py b/helpers/chatHelper.py index feb3140..d9e7748 100644 --- a/helpers/chatHelper.py +++ b/helpers/chatHelper.py @@ -105,10 +105,10 @@ def partChannel(userID = 0, channel = "", token = None, toIRC = True, kick = Fal # (toclient is used clientwise for #multiplayer and #spectator channels) channelClient = channel if channel == "#spectator": - if token.spectating == 0: + if token.spectating is None: s = userID else: - s = token.spectating + s = token.spectating.userID channel = "#spect_{}".format(s) elif channel == "#multiplayer": channel = "#multi_{}".format(token.matchID) @@ -189,10 +189,10 @@ def sendMessage(fro = "", to = "", message = "", token = None, toIRC = True): # (toclient is used clientwise for #multiplayer and #spectator channels) toClient = to if to == "#spectator": - if token.spectating == 0: + if token.spectating is None: s = userID else: - s = token.spectating + s = token.spectating.userID to = "#spect_{}".format(s) elif to == "#multiplayer": to = "#multi_{}".format(token.matchID) diff --git a/objects/match.py b/objects/match.py index 15cd8fe..72ee488 100644 --- a/objects/match.py +++ b/objects/match.py @@ -633,10 +633,7 @@ class match: token.enqueue(serverPackets.updateMatch(self.matchID)) # Send to users in lobby - for i in glob.matches.usersInLobby: - token = glob.tokens.getTokenFromUserID(i) - if token is not None: - token.enqueue(serverPackets.updateMatch(self.matchID)) + glob.streams.broadcast("lobby", serverPackets.updateMatch(self.matchID)) def checkTeams(self): """ diff --git a/objects/matchList.py b/objects/matchList.py index cffee5a..80040a7 100644 --- a/objects/matchList.py +++ b/objects/matchList.py @@ -3,14 +3,9 @@ from objects import glob from constants import serverPackets class matchList: - matches = {} - usersInLobby = [] - lastID = 1 - def __init__(self): """Initialize a matchList object""" self.matches = {} - self.usersInLobby = [] self.lastID = 1 def createMatch(self, matchName, matchPassword, beatmapID, beatmapName, beatmapMD5, gameMode, hostUserID): @@ -32,7 +27,7 @@ class matchList: self.matches[matchID] = match.match(matchID, matchName, matchPassword, beatmapID, beatmapName, beatmapMD5, gameMode, hostUserID) return matchID - def lobbyUserJoin(self, userID): + '''def lobbyUserJoin(self, userID): """ Add userID to users in lobby @@ -52,7 +47,7 @@ class matchList: # Make sure the user is in mp lobby if userID in self.usersInLobby: # Part lobby and #lobby channel - self.usersInLobby.remove(userID) + self.usersInLobby.remove(userID)''' def disposeMatch(self, matchID): """ @@ -68,7 +63,4 @@ class matchList: self.matches.pop(matchID) # Send match dispose packet to everyone in lobby - for i in self.usersInLobby: - token = glob.tokens.getTokenFromUserID(i) - if token is not None: - token.enqueue(serverPackets.disposeMatch(matchID)) + glob.streams.broadcast("lobby", serverPackets.disposeMatch(matchID)) \ No newline at end of file diff --git a/objects/osuToken.py b/objects/osuToken.py index 00f0900..031927b 100644 --- a/objects/osuToken.py +++ b/objects/osuToken.py @@ -39,7 +39,7 @@ class token: # Default variables self.spectators = [] - self.spectating = 0 + self.spectating = None self.location = [0,0] self.joinedChannels = [] self.ip = ip @@ -141,42 +141,80 @@ class token: """ return self.location[1] - def startSpectating(self, userID): + def startSpectating(self, host): """ Set the spectating user to userID - userID -- target userID + user -- user object """ - self.spectating = userID + # Stop spectating old client + self.stopSpectating() + + # Set new spectator host + self.spectating = host + + # Add us to host's spectator list + host.spectators.append(self) + + # Create and join spectator stream + streamName = "spect/{}".format(self.spectating.userID) + glob.streams.add(streamName) + self.joinStream(streamName) + host.joinStream(streamName) + + # Send spectator join packet to host + host.enqueue(serverPackets.addSpectator(self.userID)) + + # Create and join #spectator (#spect_userid) channel + glob.channels.addTempChannel("#spect_{}".format(host.userID)) + chat.joinChannel(token=self, channel="#spect_{}".format(host.userID)) + if len(host.spectators) == 1: + # First spectator, send #spectator join to host too + chat.joinChannel(token=host, channel="#spect_{}".format(host.userID)) + + # Send fellow spectator join to all clients + glob.streams.broadcast(streamName, serverPackets.fellowSpectatorJoined(self.userID)) + + # Get current spectators list + for i in host.spectators: + if i != self: + self.enqueue(serverPackets.fellowSpectatorJoined(i.userID)) + + # Log + log.info("{} are spectating {}".format(self.username, userUtils.getUsername(host.username))) def stopSpectating(self): # Remove our userID from host's spectators - target = self.spectating - if self.spectating == 0: + if self.spectating == None: return - targetToken = glob.tokens.getTokenFromUserID(target) - if targetToken is not None: - # Remove us from host's spectators list - targetToken.removeSpectator(self.userID) + streamName = "spect/{}".format(self.spectating.userID) - # Send the spectator left packet to host - targetToken.enqueue(serverPackets.removeSpectator(self.userID)) - for c in targetToken.spectators: - spec = glob.tokens.getTokenFromUserID(c) - spec.enqueue(serverPackets.fellowSpectatorLeft(self.userID)) + # Remove us from host's spectators list + # and leave spectator stream + self.leaveStream(streamName) + self.spectating.spectators.remove(self) - # If nobody is spectating the host anymore, close #spectator channel - if len(targetToken.spectators) == 0: - chat.partChannel(token=targetToken, channel="#spect_{}".format(target), kick=True) + # Send the spectator left packet to host + self.spectating.enqueue(serverPackets.removeSpectator(self.userID)) + + # and to all other spectators + for i in self.spectating.spectators: + i.enqueue(serverPackets.fellowSpectatorLeft(self.userID)) + + # If nobody is spectating the host anymore, close #spectator channel + # and remove host from spect stream too + if len(self.spectating.spectators) == 0: + chat.partChannel(token=self.spectating, channel="#spect_{}".format(self.spectating.userID), kick=True) + self.spectating.leaveStream(streamName) # Part #spectator channel - chat.partChannel(token=self, channel="#spect_{}".format(target), kick=True) - - # Set our spectating user to 0 - self.spectating = 0 + chat.partChannel(token=self, channel="#spect_{}".format(self.spectating.userID), kick=True) # Console output - log.info("{} are no longer spectating {}".format(self.username, target)) + log.info("{} are no longer spectating {}".format(self.username, self.spectating.userID)) + + # Set our spectating user to 0 + self.spectating = None def partMatch(self): # Make sure we are in a match @@ -199,15 +237,15 @@ class token: # Set usertoken match to -1 self.matchID = -1 - def addSpectator(self, userID): + '''def addSpectator(self, user): """ Add userID to our spectators - userID -- new spectator userID + user -- user object """ # Add userID to spectators if not already in - if userID not in self.spectators: - self.spectators.append(userID) + if user not in self.spectators: + self.spectators.append(user) def removeSpectator(self, userID): """ @@ -217,7 +255,7 @@ class token: """ # Remove spectator if userID in self.spectators: - self.spectators.remove(userID) + self.spectators.remove(userID)''' def setCountry(self, countryID): """ diff --git a/objects/stream.py b/objects/stream.py index 4fca536..896027d 100644 --- a/objects/stream.py +++ b/objects/stream.py @@ -1,3 +1,5 @@ +from common.log import logUtils as log + class stream: def __init__(self, name): """ @@ -16,6 +18,7 @@ class stream: :return: """ if client not in self.clients: + log.info("{} has joined stream {}".format(client.username, self.name)) self.clients.append(client) def removeClient(self, client): @@ -26,6 +29,7 @@ class stream: :return: """ if client in self.clients: + log.info("{} has left stream {}".format(client.username, self.name)) self.clients.remove(client) def broadcast(self, data): diff --git a/objects/streamList.py b/objects/streamList.py index 85e1258..3d970d2 100644 --- a/objects/streamList.py +++ b/objects/streamList.py @@ -13,6 +13,7 @@ class streamList: """ if name not in self.streams: self.streams[name] = stream.stream(name) + print(str(self.streams)) def remove(self, name): """ @@ -38,6 +39,17 @@ class streamList: return self.streams[streamName].broadcast(data) + def getClients(self, streamName): + """ + Get all clients in a stream + + :param streamName: name of the stream + :return: + """ + if streamName not in self.streams: + return + return self.streams[streamName].clients + def join(self, streamName, client): """ Add a client to a stream diff --git a/pep.py b/pep.py index 271401d..20b9ebd 100644 --- a/pep.py +++ b/pep.py @@ -128,8 +128,9 @@ if __name__ == "__main__": consoleHelper.printDone() # Initialize stremas - consoleHelper.printNoNl("> Creating main stream... ") + consoleHelper.printNoNl("> Creating packets streams... ") glob.streams.add("main") + glob.streams.add("lobby") consoleHelper.printDone() # Start fokabot