async def update_action(user: Player, p: bytes) -> None: d = reader.handle_packet( p, ( ("actionid", osuTypes.u8), ("base_info", osuTypes.string), ("md5", osuTypes.string), ("mods", osuTypes.u32), ("mode", osuTypes.u8), ("mid", osuTypes.i32), ), ) if d["actionid"] == 0 and d["mods"] & Mods.RELAX: d["base_info"] = "on Relax" elif d["actionid"] == 0 and d["mods"] & Mods.AUTOPILOT: d["base_info"] = "on Autopilot" user.action = d["actionid"] user.base_info = d["base_info"] user.map_md5 = d["md5"] user.mods = d["mods"] m = lbModes(d["mode"], d["mods"]) user.mode = m.value user.mode_vn = m.as_vn user.map_id = d["mid"] if d["actionid"] == 2: user.base_info += f" +{(Mods(user.mods))!r}" # ugly and i dont care! if not user.restricted: glob.players.enqueue(writer.userStats(user))
async def join_chan(user: Player, p: bytes) -> None: name = (reader.handle_packet(p, (('chan', osuTypes.string),)))['chan'] if name == '#spectator': if user.spectating is not None: uid = user.spectating.id elif user.spectators: uid = user.id else: return # not spectating chan = glob.channels.get(f'#spec_{uid}') elif name == '#multiplayer': if not user.match: return m = user.match.id chan = glob.channels.get(f'#multi_{m}') elif name == '#clan': if not user.clan: return chan = user.clan.chan else: chan = glob.channels.get(name) if not chan: return user.join_chan(chan)
async def join_match(user: Player, p: bytes) -> None: d = reader.handle_packet(p, (('id', osuTypes.i32), ('pw', osuTypes.string),)) _id = d['id'] pw = d['pw'] if _id >= 1000: if not (menu := glob.menus.get(_id)): # TODO: use pw instead of id return user.enqueue(writer.matchJoinFail()) ret = await menu.handle(user) # if we don't return a join failure also, its gonna think we are still in lobby if isinstance(ret, str): # return string message? user.enqueue( writer.sendMessage( fromname = glob.bot.name, msg = ret, tarname = user.name, fromid = glob.bot.id ) ) return user.enqueue(writer.matchJoinFail()) user.enqueue(writer.matchJoinFail()) return ret
async def send_msg(user: Player, p: bytes) -> None: d = reader.handle_packet(p, (('msg', osuTypes.message),)) msg = d['msg'].msg chan = d['msg'].tarname if chan == '#spectator': if user.spectating: sid = user.spectating.id elif user.spectators: sid = user.id else: return c = glob.channels.get(f'#spec_{sid}') elif chan == '#multiplayer': if not user.match: return m = user.match.id c = glob.channels.get(f'#multi_{m}') if msg.startswith(glob.config.prefix) and (cmd := await commands.process_multiplayer(user, msg)): msg = cmd user = glob.bot
async def update_action(user: Player, p: bytes) -> None: d = reader.handle_packet(p, ( ('actionid', osuTypes.u8), ('info', osuTypes.string), ('md5', osuTypes.string), ('mods', osuTypes.u32), ('mode', osuTypes.u8), ('mid', osuTypes.i32) )) if d['actionid'] == 0 and d['mods'] & Mods.RELAX: d['info'] = 'on Relax' elif d['actionid'] == 0 and d['mods'] & Mods.AUTOPILOT: d['info'] = 'on Autopilot' user.action = d['actionid'] user.info = d['info'] user.map_md5 = d['md5'] user.mods = d['mods'] m = lbModes(d['mode'], d['mods']) user.mode = m.value user.mode_vn = m.as_vn user.map_id = d['mid'] if d['actionid'] == 2: user.info += f' +{(Mods(user.mods))!r}' # ugly and i dont care! if not user.restricted: glob.players.enqueue(writer.userStats(user))
async def start_spec(user: Player, p: bytes) -> None: tid = (reader.handle_packet(p, (('tid', osuTypes.i32),)))['tid'] if tid == 1: return if not (target := await glob.players.get(id=tid)): return
async def send_pm(user: Player, p: bytes) -> None: d = reader.handle_packet(p, (('msg', osuTypes.message),)) msg = d['msg'].msg tarname = d['msg'].tarname if not (target := await glob.players.get(name=tarname)): log(f'{user.name} tried to send message to offline user {tarname}', Ansi.LRED) return
async def match_invite(user: Player, p: bytes) -> None: uid = (reader.handle_packet(p, (("uid", osuTypes.i32),)))["uid"] if ( not user.match or not (target := await glob.players.get(id=uid)) or target is glob.bot ): return
async def send_pm(user: Player, p: bytes) -> None: d = reader.handle_packet(p, (("msg", osuTypes.message),)) msg = d["msg"].msg tarname = d["msg"].tarname if not (target := await glob.players.get(name=tarname)): warning(f"{user.name} tried to send message to offline user {tarname}") return
async def match_host(user: Player, p: bytes) -> None: slot = (reader.handle_packet(p, (("slot", osuTypes.i32),)))["slot"] if ( not (match := user.match) or user is not match.host or not (host := match.slots[slot].player) or match.clan_battle ): return
async def friend_remove(user: Player, p: bytes) -> None: tar = (reader.handle_packet(p, (('uid', osuTypes.i32),)))['uid'] if tar not in user.friends: return user.friends.remove(tar) await glob.db.execute('DELETE FROM friends WHERE user1 = %s AND user2 = %s', [user.id, tar]) log(f"{user.name} removed UID {tar} from their friends list.", Ansi.LCYAN)
async def friend_add(user: Player, p: bytes) -> None: tar = (reader.handle_packet(p, (('uid', osuTypes.i32),)))['uid'] if tar in user.friends: return user.friends.append(tar) await glob.db.execute('INSERT INTO friends (user1, user2) VALUES (%s, %s)', [user.id, tar]) log(f"{user.name} added UID {tar} into their friends list.", Ansi.LCYAN)
async def friend_remove(user: Player, p: bytes) -> None: tar = (reader.handle_packet(p, (("uid", osuTypes.i32),)))["uid"] if tar not in user.friends: return user.friends.remove(tar) await glob.db.execute( "DELETE FROM friends WHERE user1 = %s AND user2 = %s", [user.id, tar], ) base_info(f"{user.name} removed UID {tar} from their friends list.")
async def create_match(user: Player, p: bytes) -> None: match = (reader.handle_packet(p, (('match', osuTypes.match),)))['match'] glob.matches[match.id] = match if not glob.matches.get(match.id): return user.enqueue(writer.matchJoinFail()) mp_chan = Channel(name='#multiplayer', desc=f'Multiplayer channel for match ID {match.id}', auto=False, perm=False) glob.channels[f'#multi_{match.id}'] = mp_chan match.chat = mp_chan user.join_match(match, match.pw) log(f'{user.name} created a new multiplayer lobby.', Ansi.LBLUE)
async def friend_add(user: Player, p: bytes) -> None: tar = (reader.handle_packet(p, (("uid", osuTypes.i32),)))["uid"] if tar in user.friends: return user.friends.append(tar) await glob.db.execute( "INSERT INTO friends (user1, user2) VALUES (%s, %s)", [user.id, tar], ) base_info(f"{user.name} added UID {tar} into their friends list.")
async def leave_chan(user: Player, p: bytes) -> None: name = (reader.handle_packet(p, (("chan", osuTypes.string),)))["chan"] if name in ["#highlight", "#userlog"] or not name.startswith("#"): # osu why!!! return if name == "#spectator": if user.spectating is not None: uid = user.spectating.id elif user.spectators: uid = user.id else: return # not spectating chan = glob.channels.get(f"#spec_{uid}") elif name == "#multiplayer": if not user.match: return m = user.match.id chan = glob.channels.get(f"#multi_{m}") elif name == "#clan": if not user.clan: return chan = user.clan.chan else: chan = glob.channels.get(name) if not chan: return if user not in chan.players: return user.leave_chan(chan) chan_leave = writer.channelInfo(chan) for ( o ) in ( chan.players ): # TODO: playerlist instances for channels/multiplayer rooms etc..? o.enqueue(chan_leave)
async def create_match(user: Player, p: bytes) -> None: match = (reader.handle_packet(p, (("match", osuTypes.match),)))["match"] glob.matches[match.id] = match if not glob.matches.get(match.id): return user.enqueue(writer.matchJoinFail()) mp_chan = Channel( name="#multiplayer", desc=f"Multiplayer channel for match ID {match.id}", auto=False, perm=False, ) glob.channels[f"#multi_{match.id}"] = mp_chan match.chat = mp_chan user.join_match(match, match.pw) base_info(f"{user.name} created a new multiplayer lobby.")
async def leave_chan(user: Player, p: bytes) -> None: name = (reader.handle_packet(p, (('chan', osuTypes.string),)))['chan'] if name in ['#highlight', '#userlog'] or not name.startswith('#'): # osu why!!! return if name == '#spectator': if user.spectating is not None: uid = user.spectating.id elif user.spectators: uid = user.id else: return # not spectating chan = glob.channels.get(f'#spec_{uid}') elif name == '#multiplayer': if not user.match: return m = user.match.id chan = glob.channels.get(f'#multi_{m}') elif name == '#clan': if not user.clan: return chan = user.clan.chan else: chan = glob.channels.get(name) if not chan: return if user not in chan.players: return user.leave_chan(chan) chan_leave = writer.channelInfo(chan) for o in chan.players: #TODO: playerlist instances for channels/multiplayer rooms etc..? o.enqueue(chan_leave)
async def match_pw(user: Player, p: bytes) -> None: m = (reader.handle_packet(p, (('m', osuTypes.match),)))['m'] if not (match := user.match) or user is not match.host: return
async def presence_request(user: Player, p: bytes) -> None: uids = (reader.handle_packet(p, (('uids', osuTypes.i32_list),)))['uids'] for u in uids: if o := await glob.players.get(id=u): user.enqueue(writer.userPresence(o))
async def match_mods(user: Player, p: bytes) -> None: mods = (reader.handle_packet(p, (('mods', osuTypes.i32),)))['mods'] if not (match := user.match): return
async def request_stats(user: Player, p: bytes) -> None: uids = (reader.handle_packet(p, (('uids', osuTypes.i32_list),)))['uids'] for o in glob.players.unrestricted_users: if o.id != user.id and o.id in uids: user.enqueue(writer.userStats(o))
async def match_score(user: Player, p: bytes) -> None: data = (reader.handle_packet(p, (('data', osuTypes.raw),)))['data'] if not (match := user.match): return
async def lock_slot(user: Player, p: bytes) -> None: _id = (reader.handle_packet(p, (('id', osuTypes.i32),)))['id'] if not (match := user.match) or match.clan_battle or user is not match.host: return
async def change_slot(user: Player, p: bytes) -> None: _id = (reader.handle_packet(p, (('id', osuTypes.i32),)))['id'] if not (match := user.match): return
async def spec_frames(user: Player, p: bytes) -> None: frames = (reader.handle_packet(p, (('frames', osuTypes.raw),)))['frames'] frames_packet = writer.spectateFrames(frames) for u in user.spectators: # playerlist instances for spectators? u.enqueue(frames_packet)
async def match_settings(user: Player, p: bytes) -> None: m = (reader.handle_packet(p, (("m", osuTypes.match),)))["m"] if not (match := user.match) or user is not match.host: return