async def read_match(data: bytes) -> TypedReadMatch: buffer = KurisoBuffer(None) await buffer.write_to_buffer(data) await buffer.read_int_16( ) # skip 3 bytes for id and inProgress because default is False await buffer.read_byte() match_type = MatchTypes(await buffer.read_byte()) mods = Mods(await buffer.read_int_32()) name = await buffer.read_osu_string() password = await buffer.read_osu_string() beatmap_name = await buffer.read_osu_string() beatmap_id = await buffer.read_int_32() beatmap_md5 = await buffer.read_osu_string() slots = [Slot() for _ in range(0, 16)] # make slots for slot in slots: slot.status = SlotStatus(await buffer.read_byte()) for slot in slots: slot.team = SlotTeams(await buffer.read_byte()) for slot in slots: if slot.status.value & SlotStatus.HasPlayer: await buffer.read_int_32() host_id = await buffer.read_int_32() play_mode = GameModes(await buffer.read_byte()) scoring_type = MatchScoringTypes(await buffer.read_byte()) team_type = MatchTeamTypes(await buffer.read_byte()) is_freemod = await buffer.read_bool() match_freemod = MultiSpecialModes(int(is_freemod)) if is_freemod: for slot in slots: slot.mods = Mods(await buffer.read_int_32()) seed = await buffer.read_int_32() t_dict = { 'match_type': match_type, 'mods': mods, 'name': name, 'password': password, 'beatmap_name': beatmap_name, 'beatmap_id': beatmap_id, 'beatmap_md5': beatmap_md5, 'slots': slots, 'host_id': host_id, 'play_mode': play_mode, 'scoring_type': scoring_type, 'team_type': team_type, 'match_freemod': match_freemod, 'seed': seed } return t_dict
async def tillerino_last(_, token: 'Player', message: 'Message'): if message.to.startswith("#") and ( token.privileges & KurikkuPrivileges.Donor) != KurikkuPrivileges.Donor: return False # don't allow run np commands in public channels! data = await Context.mysql.fetch( """SELECT beatmaps.song_name as sn, scores.*, beatmaps.beatmap_id as bid, beatmaps.difficulty_std, beatmaps.difficulty_taiko, beatmaps.difficulty_ctb, beatmaps.difficulty_mania, beatmaps.max_combo as fc FROM scores LEFT JOIN beatmaps ON beatmaps.beatmap_md5=scores.beatmap_md5 WHERE scores.userid = %s ORDER BY scores.time DESC LIMIT 1""", [token.id]) diffString = f"difficulty_{GameModes.resolve_to_str(GameModes(data['play_mode']))}" rank = legacy_utils.getRank(data["play_mode"], data["mods"], data["accuracy"], data["300_count"], data["100_count"], data["50_count"], data["misses_count"]) ifPlayer = f"{token.name if message.to != CrystalBot.bot_name else ''} | " ifFc = " (FC)" if data["max_combo"] == data[ "fc"] else f" {data['max_combo']}x/{data['fc']}x" beatmapLink = f"[http://osu.ppy.sh/b/{data['bid']} {data['sn']}]" hasPP = data["play_mode"] != GameModes.CTB.value msg = ifPlayer msg += beatmapLink if data["play_mode"] != GameModes.STD.value: msg += f" <{GameModes.resolve_to_str(GameModes(data['play_mode']))}>" if data["mods"]: msg += ' +' + new_utils.readable_mods(Mods(data["mods"])) if not hasPP: msg += " | {0:,}".format(data["score"]) msg += ifFc msg += f" | {round(data['accuracy'], 2)}%, {rank.upper()}" msg += f" {{ {data['300_count']} / {data['100_count']} / {data['50_count']} / {data['misses_count']} }}" msg += f" | {round(data[diffString], 2)} stars" return msg msg += f" | {round(data['accuracy'], 2)}%, {rank.upper()}" msg += ifFc msg += f" | {round(data['pp'], 2)}pp" stars = data[diffString] if data["mods"]: token.tillerino[0] = data["bid"] token.tillerino[1] = Mods(data["mods"]) peace_data = await get_pp_message(token, just_data=True) if "stars" in peace_data: stars = peace_data['stars'] msg += " | {0:.2f} stars".format(stars) return msg
def update(self, **kwargs): self.action = Action(kwargs.get('action', 0)) self.action_text = kwargs.get('action_text', '') self.map_md5 = kwargs.get('map_md5', '') self.mode = GameModes(kwargs.get('mode', 0)) self.mods = Mods(kwargs.get('mods', 0)) self.map_id = kwargs.get('map_id', 0)
async def tilleino_like(args: List[str], token: 'Player', message: 'Message'): if (token.privileges & KurikkuPrivileges.Donor) != KurikkuPrivileges.Donor: return False # don't allow run np commands in public channels! play_or_watch = "playing" in message.body or "watching" in message.body # Get URL from message beatmap_url = args[0][1:] modsEnum = Mods(0) if play_or_watch: mapping = { "-Easy": Mods.Easy, "-NoFail": Mods.NoFail, "+Hidden": Mods.Hidden, "+HardRock": Mods.HardRock, "+Nightcore": Mods.Nightcore, "+DoubleTime": Mods.DoubleTime, "-HalfTime": Mods.HalfTime, "+Flashlight": Mods.Flashlight, "-SpunOut": Mods.SpunOut } for part in args: part = part.replace("\x01", "") if part in mapping.keys(): modsEnum |= mapping[part] try: beatmap_id = NP_REGEX.search(beatmap_url).groups(0)[1] except Exception as e: traceback.print_exc() capture_exception(e) return "Can't find beatmap" token.tillerino = [int(beatmap_id), modsEnum] return await get_pp_message(token)
async def update_match_mods(packet_data: bytes, token: 'Player'): if not token.match: return False match = token.match newMods = Mods(await PacketResolver.read_mods(packet_data)) await match.change_mods(newMods, token) await match.update_match() return True
def __init__(self, user_id: Union[int], user_name: Union[str], privileges: Union[int], utc_offset: Optional[int] = 0, pm_private: bool = False, silence_end: int = 0, is_tourneymode: bool = False, is_bot: bool = False, ip: str = ''): self.token: str = self.generate_token() self.id: int = user_id self.name: str = user_name self.ip: str = ip self.privileges: int = privileges self.selected_game_mode: GameModes = GameModes.STD self.stats: Dict[GameModes, StatsMode] = { mode: StatsMode() for mode in GameModes } # setup dictionary with stats self.pr_status: Status = Status() self.spectators: List[Player] = [] self.spectating: Optional[Player] = None self.country: Tuple[int, str] = (0, 'XX') self.location: Tuple[float, float] = (0.0, 0.0) self.timezone: int = 24 + utc_offset self.timezone_offset: int = utc_offset self.pm_private: bool = pm_private # Как я понял, это типо только друзья могут писать self.friends: Union[List[int]] = [] self.away_msg: Optional[str] = None self.silence_end: int = silence_end self.presence_filter: PresenceFilter = PresenceFilter(1) self.bot_np: Optional[dict] = None # TODO: Beatmap self._match: Optional['Match'] = None self.friends: Union[List[int]] = [] # bot by default xd self.queue: bytearray = bytearray() # main thing self.login_time: int = int(time.time()) self.last_packet_unix: int = int(time.time()) self.is_tourneymode: bool = is_tourneymode self.id_tourney: int = -1 self.is_in_lobby: bool = False self.is_bot: bool = is_bot self.tillerino: List[Union[int, Mods]] = [ 0, Mods(0), -1.0 ] # 1 - map id, 2 - current_mods, 3 - acc <- legacy code self.user_chat_log: List['Message'] = []
async def mp_mods(args: List[str], player: 'Player', message: 'Message'): if not player.match: return 'You are not in any match' if not can_take_match(player, player.match, check_tourney_host=True): return 'You cant do anything with that match' if len(args) < 2: return "Wrong syntax: !mp mods <mod1> [<mod2>] ..." new_mods = Mods(0) freeMod = False for _mod in args[1:]: if _mod.lower().strip() == "hd": new_mods |= Mods.Hidden elif _mod.lower().strip() == "hr": new_mods |= Mods.HardRock elif _mod.lower().strip() == "dt": new_mods |= Mods.DoubleTime elif _mod.lower().strip() == "fl": new_mods |= Mods.Flashlight elif _mod.lower().strip() == "fi": new_mods |= Mods.FadeIn elif _mod.lower().strip() == "nf": new_mods |= Mods.NoFail elif _mod.lower().strip() == "ez": new_mods |= Mods.Easy if _mod.lower().strip() == "none" or _mod.lower().strip() == "nomod": new_mods = Mods(0) if _mod.lower().strip() == "freemod": freeMod = True await player.match.change_special_mods(MultiSpecialModes.Freemod if freeMod else MultiSpecialModes.Empty) await player.match.change_mods(new_mods, player) await player.match.unready_everyone() await player.match.update_match() return "Match mods have been updated!"
async def tillerino_mods(args: List[str], token: 'Player', _): if not args: return 'Enter mods as first argument' if (token.privileges & KurikkuPrivileges.Donor) != KurikkuPrivileges.Donor: return False # don't allow run np commands in public channels! if token.tillerino[0] == 0: return 'Please give me beatmap first with /np command' mods_list = [a.upper() for a in args] mods_enum = Mods(0) for mod in mods_list: if mod not in ALLOWED_MODS: return f"Invalid mods. Allowed mods: {', '.join(ALLOWED_MODS)} do not use spaces for multiple mods." mods_enum |= ALLOWED_MODS_MAPPING.get(mod, 0) token.tillerino[1] = mods_enum return await get_pp_message(token)