From 9bc76279f1c6867b554d8ab42486ef86f13812cd Mon Sep 17 00:00:00 2001 From: Kevin Trocolli Date: Sun, 12 Nov 2023 18:46:38 -0500 Subject: [PATCH] sao: fix episode_play_end --- titles/sao/base.py | 25 +--------------- titles/sao/handlers/base.py | 45 +++++++++++++++++++++++++++++ titles/sao/handlers/helpers.py | 53 +++++++++++++++++++++++++++------- 3 files changed, 89 insertions(+), 34 deletions(-) diff --git a/titles/sao/base.py b/titles/sao/base.py index b7d814e..facae40 100644 --- a/titles/sao/base.py +++ b/titles/sao/base.py @@ -563,30 +563,7 @@ class SaoBase: def handle_c914(self, header: SaoRequestHeader, request: bytes) -> bytes: #quest/trial_tower_play_start - req = bytes.fromhex(request)[24:] - - req_struct = Struct( - Padding(16), - "ticket_id_size" / Rebuild(Int32ub, len_(this.ticket_id) * 2), # calculates the length of the ticket_id - "ticket_id" / PaddedString(this.ticket_id_size, "utf_16_le"), # ticket_id is a (zero) padded string - "user_id_size" / Rebuild(Int32ub, len_(this.user_id) * 2), # calculates the length of the user_id - "user_id" / PaddedString(this.user_id_size, "utf_16_le"), # user_id is a (zero) padded string - "trial_tower_id" / Int32ub, # trial_tower_id is an int - "play_mode" / Int8ub, # play_mode is a byte - Padding(3), - "play_start_request_data_length" / Rebuild(Int8ub, len_(this.play_start_request_data)), # play_start_request_data_length is a byte, - "play_start_request_data" / Array(this.play_start_request_data_length, Struct( - "user_party_id_size" / Rebuild(Int32ub, len_(this.user_party_id) * 2), # calculates the length of the user_party_id - "user_party_id" / PaddedString(this.user_party_id_size, "utf_16_le"), # user_party_id is a (zero) padded string - "appoint_leader_resource_card_code_size" / Rebuild(Int32ub, len_(this.appoint_leader_resource_card_code) * 2), # calculates the length of the total_damage - "appoint_leader_resource_card_code" / PaddedString(this.appoint_leader_resource_card_code_size, "utf_16_le"), # total_damage is a (zero) padded string - "use_profile_card_code_size" / Rebuild(Int32ub, len_(this.use_profile_card_code) * 2), # calculates the length of the total_damage - "use_profile_card_code" / PaddedString(this.use_profile_card_code_size, "utf_16_le"), # use_profile_card_code is a (zero) padded string - "quest_drop_boost_apply_flag" / Int8ub, # quest_drop_boost_apply_flag is a byte - )), - ) - - req_data = req_struct.parse(req) + req_data = SaoTrialTowerPlayStartRequest(header, request) user_id = req_data.user_id floor_id = req_data.trial_tower_id diff --git a/titles/sao/handlers/base.py b/titles/sao/handlers/base.py index 836372b..c1453d0 100644 --- a/titles/sao/handlers/base.py +++ b/titles/sao/handlers/base.py @@ -1508,6 +1508,15 @@ class SaoEpisodePlayStartRequest(SaoBaseRequest): tmp = PlayStartRequestData(data, off) self.play_start_request_data.append(tmp) off += tmp.get_size() + + self.multi_play_start_request_data_count = decode_int(data, off) + off += INT_OFF + + self.multi_play_start_request_data: List[MultiPlayStartRequestData] = [] + for _ in range(self.multi_play_start_request_data_count): + tmp = MultiPlayStartRequestData(data, off) + off += tmp.get_size() + self.multi_play_start_request_data.append(tmp) class SaoEpisodePlayStartResponse(SaoBaseResponse): def __init__(self, cmd, profile_data) -> None: @@ -1669,6 +1678,42 @@ class SaoEpisodePlayEndResponse(SaoBaseResponse): self.length = len(resp_data) return super().make() + resp_data +class SaoTrialTowerPlayStartRequest(SaoBaseRequest): + def __init__(self, header: SaoRequestHeader, data: bytes) -> None: + super().__init__(header, data) + off = 0 + ticket_id = decode_str(data, off) + self.ticket_id = ticket_id[0] + off += ticket_id[1] + + user_id = decode_str(data, off) + self.user_id = user_id[0] + off += user_id[1] + + self.trial_tower_id = decode_int(data, off) + off += INT_OFF + + self.play_mode = decode_byte(data, off) + off += BYTE_OFF + + self.play_start_request_data_count = decode_int(data, off) + off += INT_OFF + + self.play_start_request_data: List[PlayStartRequestData] = [] + for _ in range(self.play_start_request_data_count): + tmp = PlayStartRequestData(data, off) + self.play_start_request_data.append(tmp) + off += tmp.get_size() + + self.multi_play_start_request_data_count = decode_int(data, off) + off += INT_OFF + + self.multi_play_start_request_data: List[MultiPlayStartRequestData] = [] + for _ in range(self.multi_play_start_request_data_count): + tmp = MultiPlayStartRequestData(data, off) + off += tmp.get_size() + self.multi_play_start_request_data.append(tmp) + class SaoTrialTowerPlayEndRequest(SaoBaseRequest): def __init__(self, header: SaoRequestHeader, data: bytes) -> None: super().__init__(header, data) diff --git a/titles/sao/handlers/helpers.py b/titles/sao/handlers/helpers.py index 9c5f25a..8706ca9 100644 --- a/titles/sao/handlers/helpers.py +++ b/titles/sao/handlers/helpers.py @@ -283,7 +283,7 @@ class PlayEndRequestData(BaseHelper): self.base_get_data_list: List[BaseGetData] = [] for _ in range(self.base_get_data_count): - tmp = BaseGetData(data, sz) + tmp = BaseGetData(data, offset + sz) sz += tmp.get_size() self.base_get_data_list.append(tmp) @@ -292,7 +292,7 @@ class PlayEndRequestData(BaseHelper): self.get_player_trace_data: List[GetPlayerTraceData] = [] for _ in range(self.get_player_trace_data_count): - tmp = GetPlayerTraceData(data, sz) + tmp = GetPlayerTraceData(data, offset + sz) sz += tmp.get_size() self.get_player_trace_data.append(tmp) @@ -301,7 +301,7 @@ class PlayEndRequestData(BaseHelper): self.get_rare_drop_data_list: List[RareDropData] = [] for _ in range(self.get_rare_drop_data_count): - tmp = RareDropData(data, sz) + tmp = RareDropData(data, offset + sz) sz += tmp.get_size() self.get_rare_drop_data_list.append(tmp) @@ -310,7 +310,7 @@ class PlayEndRequestData(BaseHelper): self.get_special_rare_drop_data_list: List[SpecialRareDropData] = [] for _ in range(self.get_special_rare_drop_data_count): - tmp = SpecialRareDropData(data, sz) + tmp = SpecialRareDropData(data, offset + sz) sz += tmp.get_size() self.get_special_rare_drop_data_list.append(tmp) @@ -319,7 +319,7 @@ class PlayEndRequestData(BaseHelper): self.get_unanalyzed_log_tmp_reward_data_list: List[UnanalyzedLogTmpRewardData] = [] for _ in range(self.get_unanalyzed_log_tmp_reward_data_count): - tmp = UnanalyzedLogTmpRewardData(data, sz) + tmp = UnanalyzedLogTmpRewardData(data, offset + sz) sz += tmp.get_size() self.get_unanalyzed_log_tmp_reward_data_list.append(tmp) @@ -328,7 +328,7 @@ class PlayEndRequestData(BaseHelper): self.get_event_item_data_list: List[EventItemData] = [] for _ in range(self.get_event_item_data_count): - tmp = EventItemData(data, sz) + tmp = EventItemData(data, offset + sz) sz += tmp.get_size() self.get_event_item_data_list.append(tmp) @@ -337,7 +337,7 @@ class PlayEndRequestData(BaseHelper): self.discovery_enemy_data_list: List[DiscoveryEnemyData] = [] for _ in range(self.discovery_enemy_data_count): - tmp = DiscoveryEnemyData(data, sz) + tmp = DiscoveryEnemyData(data, offset + sz) sz += tmp.get_size() self.discovery_enemy_data_list.append(tmp) @@ -346,7 +346,7 @@ class PlayEndRequestData(BaseHelper): self.destroy_boss_data_list: List[DestroyBossData] = [] for _ in range(self.destroy_boss_data_count): - tmp = DestroyBossData(data, sz) + tmp = DestroyBossData(data, offset + sz) sz += tmp.get_size() self.destroy_boss_data_list.append(tmp) @@ -355,7 +355,7 @@ class PlayEndRequestData(BaseHelper): self.mission_data_list: List[MissionData] = [] for _ in range(self.mission_data_count): - tmp = MissionData(data, sz) + tmp = MissionData(data, offset + sz) sz += tmp.get_size() self.mission_data_list.append(tmp) @@ -364,12 +364,45 @@ class PlayEndRequestData(BaseHelper): self.score_data_list: List[ScoreData] = [] for _ in range(self.score_data_count): - tmp = ScoreData(data, sz) + tmp = ScoreData(data, offset + sz) sz += tmp.get_size() self.score_data_list.append(tmp) self._sz = sz +class EntryUserData(BaseHelper): + def __init__(self, data: bytes, offset: int) -> None: + super().__init__(data, offset) + store_id = decode_str(data, offset + self._sz) + self.store_id = store_id[0] + self._sz += store_id[1] + + user_id = decode_str(data, offset + self._sz) + self.user_id = user_id[0] + self._sz += user_id[1] + + self.host_flag = decode_byte(data, offset + self._sz) + self._sz += BYTE_OFF + +class MultiPlayStartRequestData(BaseHelper): + def __init__(self, data: bytes, offset: int) -> None: + super().__init__(data, offset) + room_id = decode_str(data, offset + self._sz) + self.room_id = room_id[0] + self._sz += room_id[1] + + self.matching_mode = decode_byte(data, offset + self._sz) + self._sz += BYTE_OFF + + self.entry_user_data_count = decode_int(data, offset + self._sz) + self._sz += INT_OFF + + self.entry_user_data_list: List[EntryUserData] = [] + for _ in range(self.entry_user_data_count): + tmp = EntryUserData(data, offset + self._sz) + self._sz += tmp.get_size() + self.entry_user_data_list.append(tmp) + class MultiPlayEndRequestData(BaseHelper): def __init__(self, data: bytes, offset: int) -> None: super().__init__(data, offset)