async def join_channel(self, c: Channel) -> bool: """Attempt to add `self` to `c`.""" if self in c: # user already in the channel. if glob.config.debug: log(f'{self} was double-added to {c}.') return False if not self.priv & c.read: log(f'{self} tried to join {c} but lacks privs.') return False # lobby can only be interacted with while in mp lobby. if c._name == '#lobby' and not self.in_lobby: return False c.append(self) # Add to channels self.channels.append(c) # Add to player self.enqueue(packets.channelJoin(c.name)) # update channel usercounts for all clients that can see. # for instanced channels, enqueue update to only players # in the instance; for normal channels, enqueue to all. targets = c.players if c.instance else glob.players for p in targets: p.enqueue(packets.channelInfo(*c.basic_info)) if glob.config.debug: log(f'{self} joined {c}.') return True
def channelJoin(p: Player, pr: PacketReader) -> None: chan_name = pr.read(osuTypes.string)[0] c = glob.channels.get(chan_name) if not c or not p.join_channel(c): printlog(f'{p} failed to join {chan_name}.', Ansi.YELLOW) return # Enqueue new channelinfo (playercount) to all players. glob.players.enqueue(packets.channelInfo(*c.basic_info)) # Enqueue channelJoin to our player. p.enqueue(packets.channelJoin(c.name))
async def leave_channel(self, c: Channel) -> None: if self not in c: log(f'{self} tried to leave {c} but is not in it.') return await c.remove(self) # remove from channels self.channels.remove(c) # remove from player self.enqueue(packets.channelKick(c.name)) # update channel usercounts for all clients that can see. # for instanced channels, enqueue update to only players # in the instance; for normal channels, enqueue to all. targets = c.players if c.instance else glob.players for p in targets: p.enqueue(packets.channelInfo(*c.basic_info)) if glob.config.debug: log(f'{self} left {c}.')
def remove_spectator(self, p) -> None: self.spectators.remove(p) p.spectating = None c = glob.channels.get(f'#spec_{self.id}') p.leave_channel(c) if not self.spectators: # Remove host from channel, deleting it. self.leave_channel(c) else: fellow = packets.fellowSpectatorLeft(p.id) c_info = packets.channelInfo(*c.basic_info) # new playercount self.enqueue(c_info) for s in self.spectators: s.enqueue(fellow + c_info) self.enqueue(packets.spectatorLeft(p.id)) printlog(f'{p} is no longer spectating {self}.')
async def remove_spectator(self, p: 'Player') -> None: """Attempt to remove `p` from `self`'s spectators.""" self.spectators.remove(p) p.spectating = None c = glob.channels[f'#spec_{self.id}'] await p.leave_channel(c) if not self.spectators: # remove host from channel, deleting it. await self.leave_channel(c) else: fellow = packets.fellowSpectatorLeft(p.id) c_info = packets.channelInfo(*c.basic_info) # new playercount self.enqueue(c_info) for s in self.spectators: s.enqueue(fellow + c_info) self.enqueue(packets.spectatorLeft(p.id)) log(f'{p} is no longer spectating {self}.')
# tells osu! to load channels from config, i believe? data += packets.channelInfoEnd() # channels for c in glob.channels: if p.priv & c.read_priv != c.read_priv: continue # no priv to read # autojoinable channels if c.auto_join and await p.join_channel(c): # NOTE: p.join_channel enqueues channelJoin, but # if we don't send this back in this specific request, # the client will attempt to join the channel again. data += packets.channelJoin(c.name) data += packets.channelInfo(*c.basic_info) # fetch some of the player's # information from sql to be cached. await p.achievements_from_sql() await p.stats_from_sql_full() await p.friends_from_sql() if glob.config.server_build: # update their country data with # the IP from the login request. await p.fetch_geoloc(ip) # update our new player's stats, and broadcast them. user_data = (packets.userPresence(p) + packets.userStats(p))
# tells osu! to load channels from config, i believe? packets.channelInfoEnd()) # channels for c in glob.channels: if not p.priv & c.read: continue # no priv to read # autojoinable channels if c.auto_join and await p.join_channel(c): # NOTE: p.join_channel enqueues channelJoin, but # if we don't send this back in this specific request, # the client will attempt to join the channel again. data.extend(packets.channelJoin(c.name)) data.extend(packets.channelInfo(*c.basic_info)) # fetch some of the player's # information from sql to be cached. await p.stats_from_sql_full() await p.friends_from_sql() if glob.config.server_build: # update their country data with # the IP from the login request. await p.fetch_geoloc(ip) # update our new player's stats, and broadcast them. user_data = (packets.userPresence(p) + packets.userStats(p)) data.extend(user_data)
# Tells osu! to load channels from config, I believe? packets.channelInfoEnd()) # Channels for c in glob.channels: if not p.priv & c.read: continue # no priv to read # Autojoinable channels if c.auto_join and p.join_channel(c): data.extend(packets.channelJoin(c.name)) # Inform other client's that we've joined the channel. # XXX: Don't need to use `immune = {p}` here since # we're not added to glob.players yet :P.. glob.players.enqueue(packets.channelInfo(*c.basic_info)) data.extend(packets.channelInfo(*c.basic_info)) # Fetch some of the player's # information from sql to be cached. p.stats_from_sql_full() p.friends_from_sql() if glob.config.server_build: # Update their country data with # the IP from the login request. p.fetch_geoloc(ip) # Update our new player's stats, and broadcast them. user_data = packets.userPresence(p) + packets.userStats(p)