mirror of
https://github.com/Lorenzooone/PokemonGB_Online_Trades.git
synced 2026-04-27 00:42:07 -05:00
Add proper mail data handling
Closes #11 . Also adds proper egg handling (by making sure received eggs have 0 HPs).
This commit is contained in:
parent
4ce0f979bc
commit
a811470c94
Binary file not shown.
BIN
useful_data/gsc/mail_checks_jp.bin
Normal file
BIN
useful_data/gsc/mail_checks_jp.bin
Normal file
Binary file not shown.
BIN
useful_data/gsc/mail_conversion_table_en_to_jp.bin
Normal file
BIN
useful_data/gsc/mail_conversion_table_en_to_jp.bin
Normal file
Binary file not shown.
BIN
useful_data/gsc/mail_conversion_table_jp_to_en.bin
Normal file
BIN
useful_data/gsc/mail_conversion_table_jp_to_en.bin
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -98,6 +98,7 @@ class GSCTradingClient:
|
|||
if val is not None:
|
||||
updating_mon = self.trader.other_pokemon.pokemon[self.trader.other_pokemon.get_last_mon_index()]
|
||||
data = [updating_mon.get_species()] + val
|
||||
self.trader.checks.prepare_species_buffer()
|
||||
data = self.trader.checks.apply_checks_to_data(self.trader.checks.moves_checks_map, data)
|
||||
for i in range(4):
|
||||
updating_mon.set_move(i, data[i+1], max_pp=False)
|
||||
|
|
@ -437,7 +438,7 @@ class GSCTrading:
|
|||
Checks if the transfer dropped any bytes.
|
||||
"""
|
||||
if byte_index >= self.drop_bytes_checks[0][section_index]:
|
||||
if byte_index < self.special_sections_len[section_index]:
|
||||
if byte_index < self.get_section_length(section_index):
|
||||
if byte == self.drop_bytes_checks[1][section_index]:
|
||||
return True
|
||||
else:
|
||||
|
|
@ -461,13 +462,32 @@ class GSCTrading:
|
|||
elif not self.printed_warning_drop:
|
||||
self.verbose_print(GSCTradingStrings.warning_byte_dropped_str)
|
||||
self.printed_warning_drop = True
|
||||
|
||||
def get_mail_section_id(self):
|
||||
return 2
|
||||
|
||||
def get_printable_index(self, index):
|
||||
return index+1
|
||||
|
||||
def get_section_length(self, index):
|
||||
return self.special_sections_len[index]
|
||||
|
||||
def get_checker(self, index):
|
||||
return self.checks.checks_map[index]
|
||||
|
||||
def convert_mail_data(self, data, to_device):
|
||||
"""
|
||||
Handles converting the mail data.
|
||||
"""
|
||||
return data
|
||||
|
||||
def read_section(self, index, send_data, buffered):
|
||||
"""
|
||||
Reads a data section and sends it to the device.
|
||||
"""
|
||||
length = self.special_sections_len[index]
|
||||
length = self.get_section_length(index)
|
||||
next = self.next_section
|
||||
checker = self.get_checker(index)
|
||||
|
||||
# Prepare sanity checks stuff
|
||||
self.checks.prepare_text_buffer()
|
||||
|
|
@ -486,6 +506,9 @@ class GSCTrading:
|
|||
recv_buf = self.read_entire_data(received)
|
||||
if recv_buf[1] is not None and recv_buf[1][0] == 0xFFFF and recv_buf[2][0] == index:
|
||||
found = True
|
||||
elif recv_buf[1] is not None and recv_buf[1][0] == 0xFFFF:
|
||||
self.verbose_print(GSCTradingStrings.incompatible_trade_str)
|
||||
self.kill_function()
|
||||
if not found:
|
||||
self.sleep_func()
|
||||
self.swap_byte(self.no_input)
|
||||
|
|
@ -505,12 +528,12 @@ class GSCTrading:
|
|||
i = 0
|
||||
while i < (length-1):
|
||||
if send_data is not None:
|
||||
next = self.checks.checks_map[index][i](send_data[i])
|
||||
next = checker[i](send_data[i])
|
||||
send_data[i] = next
|
||||
next_i = i+1
|
||||
if next_i not in self.fillers[index].keys():
|
||||
next = self.swap_byte(next)
|
||||
self.verbose_print(GSCTradingStrings.transfer_to_hardware_str.format(index=index+1, completion=GSCTradingStrings.x_out_of_y_str(next_i, length)), end='')
|
||||
self.verbose_print(GSCTradingStrings.transfer_to_hardware_str.format(index=self.get_printable_index(index), completion=GSCTradingStrings.x_out_of_y_str(next_i, length)), end='')
|
||||
buf += [next]
|
||||
# Handle fillers
|
||||
else:
|
||||
|
|
@ -518,17 +541,17 @@ class GSCTrading:
|
|||
filler_val = self.fillers[index][next_i][1]
|
||||
if send_data is not None:
|
||||
for j in range(filler_len):
|
||||
send_data[next_i + j] = self.checks.checks_map[index][next_i + j](send_data[next_i + j])
|
||||
send_data[next_i + j] = checker[next_i + j](send_data[next_i + j])
|
||||
buf += ([filler_val] * filler_len)
|
||||
i += (filler_len - 1)
|
||||
i += 1
|
||||
|
||||
if send_data is not None:
|
||||
# Send the last byte too
|
||||
next = self.checks.checks_map[index][length-1](send_data[length-1])
|
||||
next = checker[length-1](send_data[length-1])
|
||||
send_data[length-1] = next
|
||||
self.swap_byte(next)
|
||||
self.verbose_print(GSCTradingStrings.transfer_to_hardware_str.format(index=index+1, completion=GSCTradingStrings.x_out_of_y_str(length, length)), end='')
|
||||
self.verbose_print(GSCTradingStrings.transfer_to_hardware_str.format(index=self.get_printable_index(index), completion=GSCTradingStrings.x_out_of_y_str(length, length)), end='')
|
||||
for j in range(self.drop_bytes_checks[2][index]):
|
||||
self.swap_byte(self.no_data)
|
||||
other_buf = send_data
|
||||
|
|
@ -554,7 +577,7 @@ class GSCTrading:
|
|||
recv_data = self.get_swappable_bytes(recv_buf, length, index)
|
||||
if i in recv_data.keys() and (i < length):
|
||||
# Clean it and send it
|
||||
cleaned_byte = self.checks.checks_map[index][i](recv_data[i])
|
||||
cleaned_byte = checker[i](recv_data[i])
|
||||
next_i = i+1
|
||||
# Handle fillers
|
||||
if next_i in self.fillers[index].keys():
|
||||
|
|
@ -564,11 +587,11 @@ class GSCTrading:
|
|||
send_buf[(next_i)&1][1] = filler_val
|
||||
buf += ([filler_val] * filler_len)
|
||||
for j in range(filler_len):
|
||||
other_buf += [self.checks.checks_map[index][next_i + j](filler_val)]
|
||||
other_buf += [checker[next_i + j](filler_val)]
|
||||
i += (filler_len - 1)
|
||||
else:
|
||||
next = self.swap_byte(cleaned_byte)
|
||||
self.verbose_print(GSCTradingStrings.transfer_to_hardware_str.format(index=index+1, completion=GSCTradingStrings.x_out_of_y_str(next_i, length)), end='')
|
||||
self.verbose_print(GSCTradingStrings.transfer_to_hardware_str.format(index=self.get_printable_index(index), completion=GSCTradingStrings.x_out_of_y_str(next_i, length)), end='')
|
||||
# Fillers aren't needed anymore, but their last byte may be needed
|
||||
self.remove_filler(send_buf, i)
|
||||
# This will, in turn, get the next byte
|
||||
|
|
@ -607,7 +630,7 @@ class GSCTrading:
|
|||
Tries to read a single synchronous entry.
|
||||
"""
|
||||
if recv_buf[scanning_index] is not None:
|
||||
if recv_buf[2][0] == (index + 1):
|
||||
if recv_buf[2][0] >= (index + 1):
|
||||
ret[length] = 0
|
||||
else:
|
||||
byte_num = recv_buf[scanning_index][0]
|
||||
|
|
@ -913,6 +936,8 @@ class GSCTrading:
|
|||
if necessary and in the way which requires less packet transfers.
|
||||
Returns the player's data and the other player's data.
|
||||
"""
|
||||
# Prepare checks
|
||||
self.checks.reset_species_item_list()
|
||||
# Send and get the first two sections
|
||||
random_data, random_data_other = self.read_section(0, send_data[0], buffered)
|
||||
pokemon_data, pokemon_data_other = self.read_section(1, send_data[1], buffered)
|
||||
|
|
@ -924,7 +949,9 @@ class GSCTrading:
|
|||
|
||||
# Trade mail data only if needed
|
||||
if (pokemon_own_mail and pokemon_other_mail) or buffered:
|
||||
mail_data, mail_data_other = self.read_section(2, send_data[2], buffered)
|
||||
send_data[2] = self.convert_mail_data(send_data[2], True)
|
||||
mail_data, mail_data_other = self.read_section(self.get_mail_section_id(), send_data[2], buffered)
|
||||
mail_data = self.convert_mail_data(mail_data, False)
|
||||
else:
|
||||
send_data[2] = self.utils_class.no_mail_section
|
||||
# Get mail data if only the other client has it
|
||||
|
|
@ -935,7 +962,9 @@ class GSCTrading:
|
|||
self.verbose_print(GSCTradingStrings.no_mail_other_data_str)
|
||||
|
||||
# Exchange mail data with the device
|
||||
mail_data, mail_data_other = self.read_section(2, send_data[2], True)
|
||||
send_data[2] = self.convert_mail_data(send_data[2], True)
|
||||
mail_data, mail_data_other = self.read_section(self.get_mail_section_id(), send_data[2], True)
|
||||
mail_data = self.convert_mail_data(mail_data, False)
|
||||
|
||||
# Send mail data if only this client has it
|
||||
if pokemon_own_mail:
|
||||
|
|
|
|||
|
|
@ -91,6 +91,12 @@ class GSCUtilsLoaders:
|
|||
ret[i] = data[(i)*num_stats:(i+1)*num_stats]
|
||||
return ret
|
||||
|
||||
def prepare_functions_map(data, functions):
|
||||
call_map = [None] * len(data)
|
||||
for i in range(len(data)):
|
||||
call_map[i] = functions[data[i]]
|
||||
return call_map
|
||||
|
||||
def load_trading_data(target, lengths):
|
||||
data = None
|
||||
try:
|
||||
|
|
@ -231,10 +237,25 @@ class GSCUtils:
|
|||
ret = None
|
||||
|
||||
# Prepare sanity checks stuff
|
||||
checks.reset_species_item_list()
|
||||
checks.set_single_team_size()
|
||||
checks.prepare_text_buffer()
|
||||
checks.prepare_species_buffer()
|
||||
checker = checks.single_pokemon_checks_map
|
||||
|
||||
if len(data) > len(checker):
|
||||
# Handle getting/sending eggs. That requires one extra byte
|
||||
is_egg = False
|
||||
if data[len(checker)] == GSCUtils.egg_value:
|
||||
is_egg = True
|
||||
|
||||
# Prepare for further checks
|
||||
if is_egg:
|
||||
checks.species_cleaner(GSCUtils.egg_id)
|
||||
else:
|
||||
checks.species_cleaner(data[0])
|
||||
checks.prepare_species_buffer()
|
||||
|
||||
# Applies the checks to the received data.
|
||||
# If the sanity checks are off, this will be a simple copy
|
||||
purified_data = checks.apply_checks_to_data(checker, data)
|
||||
|
|
@ -244,11 +265,6 @@ class GSCUtils:
|
|||
raw = GSCTradingPokémonInfo.set_data(data)
|
||||
mon = GSCTradingPokémonInfo.set_data(purified_data)
|
||||
|
||||
# Handle getting/sending eggs. That requires one extra byte
|
||||
is_egg = False
|
||||
if purified_data[len(checker)] == GSCUtils.egg_value:
|
||||
is_egg = True
|
||||
|
||||
# If the sanity checks are on, has the pokémon changed
|
||||
# too much from the cleaning?
|
||||
if not mon.has_changed_significantly(raw):
|
||||
|
|
@ -440,7 +456,7 @@ class GSCTradingPokémonInfo:
|
|||
self.mail = self.text_class(data, start, length=self.mail_len)
|
||||
|
||||
def add_mail_sender(self, data, start):
|
||||
self.mail_sender = self.text_class(data, start, length=self.sender_len, data_start=3)
|
||||
self.mail_sender = self.text_class(data, start, length=self.sender_len, data_start=0)
|
||||
|
||||
def is_nicknamed(self):
|
||||
return not self.nickname.values_equal(self.utils_class.pokemon_names[self.get_species()])
|
||||
|
|
@ -804,14 +820,24 @@ class GSCTradingData:
|
|||
"""
|
||||
Trades a pokémon between two parties.
|
||||
"""
|
||||
# Prepare checks
|
||||
checks.reset_species_item_list()
|
||||
checks.set_single_team_size()
|
||||
checks.prepare_text_buffer()
|
||||
checks.prepare_species_buffer()
|
||||
|
||||
# Apply checks
|
||||
own_id = checks.species_cleaner(self.party_info.get_id(own_index))
|
||||
checks.prepare_species_buffer()
|
||||
own = self.mon_generator_class().set_data(checks.apply_checks_to_data(checks.single_pokemon_checks_map, self.pokemon[own_index].get_data()))
|
||||
|
||||
# Actually trade the Pokémon
|
||||
self.reorder_party(own_index)
|
||||
other.reorder_party(other_index)
|
||||
own = self.mon_generator_class().set_data(checks.apply_checks_to_data(checks.single_pokemon_checks_map, self.pokemon[self.get_last_mon_index()].get_data()))
|
||||
self.pokemon[self.get_last_mon_index()] = other.pokemon[other.get_last_mon_index()]
|
||||
other.pokemon[other.get_last_mon_index()] = own
|
||||
checks.curr_species_pos = self.get_last_mon_index()
|
||||
checks.team_size = self.get_party_size()
|
||||
own_id = checks.species_cleaner(self.party_info.get_id(self.get_last_mon_index()))
|
||||
self.party_info.set_id(self.get_last_mon_index(), other.party_info.get_id(other.get_last_mon_index()))
|
||||
other.party_info.set_id(other.get_last_mon_index(), own_id)
|
||||
|
||||
|
|
@ -867,10 +893,12 @@ class GSCChecks:
|
|||
moves_checks_map_path = "moves_checks_map.bin"
|
||||
curr_exp_pos_masks = [0, 0xFF0000, 0xFFFF00]
|
||||
free_value_species = 0xFF
|
||||
empty_value_species = 0
|
||||
free_value_moves = 0
|
||||
tackle_id = 0x21
|
||||
rattata_id = 0x13
|
||||
question_mark = 0xE6
|
||||
newline = 0x4E
|
||||
|
||||
def __init__(self, section_sizes, do_sanity_checks):
|
||||
self.utils_class = self.get_utils_class()
|
||||
|
|
@ -896,11 +924,17 @@ class GSCChecks:
|
|||
self.clean_pp,
|
||||
self.clean_experience,
|
||||
self.clean_egg_cycles_friendship,
|
||||
self.clean_type
|
||||
self.clean_type,
|
||||
self.clean_text_newline,
|
||||
self.clean_text_final_no_end,
|
||||
self.clean_species_force_terminate,
|
||||
self.clean_mail_species,
|
||||
self.clean_mail_item,
|
||||
self.clean_mail_same_species
|
||||
]
|
||||
self.checks_map = self.prepare_checks_map(GSCUtilsMisc.read_data(self.get_path(self.checks_map_path)), section_sizes)
|
||||
self.single_pokemon_checks_map = self.prepare_basic_checks_map(GSCUtilsMisc.read_data(self.get_path(self.single_pokemon_checks_map_path)))
|
||||
self.moves_checks_map = self.prepare_basic_checks_map(GSCUtilsMisc.read_data(self.get_path(self.moves_checks_map_path)))
|
||||
self.checks_map = self.prepare_checks_map(GSCUtilsMisc.read_data(self.get_path(self.checks_map_path)), section_sizes, self.check_functions)
|
||||
self.single_pokemon_checks_map = GSCUtilsLoaders.prepare_functions_map(GSCUtilsMisc.read_data(self.get_path(self.single_pokemon_checks_map_path)), self.check_functions)
|
||||
self.moves_checks_map = GSCUtilsLoaders.prepare_functions_map(GSCUtilsMisc.read_data(self.get_path(self.moves_checks_map_path)), self.check_functions)
|
||||
self.species_cleaner = self.clean_species_sp
|
||||
|
||||
def get_path(self, target):
|
||||
|
|
@ -937,20 +971,27 @@ class GSCChecks:
|
|||
def prepare_text_buffer(self):
|
||||
self.curr_text = []
|
||||
|
||||
def reset_species_item_list(self):
|
||||
self.species_list = []
|
||||
self.species_list_size = 0
|
||||
self.item_list = []
|
||||
|
||||
def set_single_team_size(self):
|
||||
self.team_size = 1
|
||||
|
||||
def add_to_species_list(self, species):
|
||||
if (species != self.free_value_species) and (species != self.empty_value_species):
|
||||
self.species_list_size += 1
|
||||
self.species_list += [species]
|
||||
|
||||
def prepare_species_buffer(self):
|
||||
self.curr_species_pos = 0
|
||||
|
||||
def prepare_checks_map(self, data, lengths):
|
||||
def prepare_checks_map(self, data, lengths, functions_list):
|
||||
raw_data_sections = GSCUtilsMisc.divide_data(data, lengths)
|
||||
call_map = [[],[],[]]
|
||||
for i in range(len(raw_data_sections)):
|
||||
call_map[i] = self.prepare_basic_checks_map(raw_data_sections[i])
|
||||
return call_map
|
||||
|
||||
def prepare_basic_checks_map(self, data):
|
||||
call_map = [None] * len(data)
|
||||
for i in range(len(data)):
|
||||
call_map[i] = self.check_functions[data[i]]
|
||||
call_map[i] = GSCUtilsLoaders.prepare_functions_map(raw_data_sections[i], functions_list)
|
||||
return call_map
|
||||
|
||||
@clean_check_sanity_checks
|
||||
|
|
@ -987,7 +1028,9 @@ class GSCChecks:
|
|||
|
||||
@clean_check_sanity_checks
|
||||
def clean_item(self, item):
|
||||
return self.clean_value(item, self.is_item_valid, 0)
|
||||
cleaned_item = self.clean_value(item, self.is_item_valid, 0)
|
||||
self.item_list += [cleaned_item]
|
||||
return cleaned_item
|
||||
|
||||
@clean_check_sanity_checks
|
||||
def clean_pp(self, pp):
|
||||
|
|
@ -1017,6 +1060,7 @@ class GSCChecks:
|
|||
@clean_check_sanity_checks
|
||||
def clean_species(self, species):
|
||||
self.curr_species = self.clean_value(species, self.is_species_valid, self.rattata_id)
|
||||
self.curr_species_pos += 1
|
||||
self.curr_stat_id = 0
|
||||
self.iv = [0,0,0,0]
|
||||
self.stat_exp = [0,0,0,0,0]
|
||||
|
|
@ -1035,15 +1079,22 @@ class GSCChecks:
|
|||
|
||||
@clean_check_sanity_checks
|
||||
def clean_species_sp(self, species):
|
||||
if species == self.free_value_species or self.curr_species_pos >= self.team_size:
|
||||
if species == self.free_value_species or self.species_list_size >= self.team_size:
|
||||
self.add_to_species_list(self.free_value_species)
|
||||
self.curr_species_pos += 1
|
||||
return self.free_value_species
|
||||
found_species = self.clean_value(species, self.is_species_valid, self.rattata_id)
|
||||
if species == self.utils_class.egg_id:
|
||||
found_species = species
|
||||
self.add_to_species_list(found_species)
|
||||
self.curr_species_pos += 1
|
||||
return found_species
|
||||
|
||||
@clean_check_sanity_checks
|
||||
def clean_species_force_terminate(self, species):
|
||||
self.prepare_species_buffer()
|
||||
return self.free_value_species
|
||||
|
||||
@clean_check_sanity_checks
|
||||
def load_stat_exp(self, val):
|
||||
calc_val = val << (8 * self.curr_stat_exp_pos)
|
||||
|
|
@ -1064,6 +1115,19 @@ class GSCChecks:
|
|||
self.curr_iv_pos += 1
|
||||
return val
|
||||
|
||||
@clean_check_sanity_checks
|
||||
def clean_mail_species(self, species):
|
||||
self.curr_species_pos += 1
|
||||
return self.species_list[self.curr_species_pos-1]
|
||||
|
||||
@clean_check_sanity_checks
|
||||
def clean_mail_same_species(self, species):
|
||||
return self.species_list[self.curr_species_pos-1]
|
||||
|
||||
@clean_check_sanity_checks
|
||||
def clean_mail_item(self, item):
|
||||
return self.item_list[self.curr_species_pos-1]
|
||||
|
||||
@clean_check_sanity_checks
|
||||
def clean_text(self, char):
|
||||
char_val = self.clean_value(char, self.is_char_valid, self.question_mark)
|
||||
|
|
@ -1079,6 +1143,21 @@ class GSCChecks:
|
|||
self.prepare_text_buffer()
|
||||
return char_val
|
||||
|
||||
@clean_check_sanity_checks
|
||||
def clean_text_newline(self, char):
|
||||
char_val = self.newline
|
||||
self.curr_text += [char_val]
|
||||
# Possibility to put bad words filters here
|
||||
return char_val
|
||||
|
||||
@clean_check_sanity_checks
|
||||
def clean_text_final_no_end(self, char):
|
||||
char_val = self.clean_value(char, self.is_char_valid, self.question_mark)
|
||||
self.curr_text += [char_val]
|
||||
# Possibility to put bad words filters here
|
||||
self.prepare_text_buffer()
|
||||
return char_val
|
||||
|
||||
@clean_check_sanity_checks
|
||||
def clean_type(self, typing):
|
||||
return typing
|
||||
|
|
@ -1091,13 +1170,16 @@ class GSCChecks:
|
|||
return curr_stat
|
||||
|
||||
@clean_check_sanity_checks
|
||||
def check_stat(self, val, zero_min=False):
|
||||
def check_stat(self, val, zero_min=False, zero_max=False):
|
||||
if self.curr_pos == 0:
|
||||
self.stat = 0
|
||||
min_stat = self.utils_class.stat_calculation(self.curr_stat_id, self.curr_species, self.iv, self.stat_exp, self.level, self.utils_class, do_exp=False)
|
||||
if zero_min:
|
||||
max_stat = self.utils_class.stat_calculation(self.curr_stat_id, self.curr_species, self.iv, self.stat_exp, self.level, self.utils_class)
|
||||
if zero_min or zero_max:
|
||||
min_stat = 0
|
||||
self.stat_range = [min_stat, self.utils_class.stat_calculation(self.curr_stat_id, self.curr_species, self.iv, self.stat_exp, self.level, self.utils_class)]
|
||||
if zero_max:
|
||||
max_stat = 0
|
||||
self.stat_range = [min_stat, max_stat]
|
||||
curr_read_val = val << (8 * (1 - (self.curr_pos & 1)))
|
||||
self.stat = self.check_range(self.stat_range, (self.stat & 0xFF00) | curr_read_val)
|
||||
val = (self.stat >> (8 * (1 - (self.curr_pos & 1)))) & 0xFF
|
||||
|
|
@ -1107,12 +1189,19 @@ class GSCChecks:
|
|||
self.curr_pos = 0
|
||||
return val
|
||||
|
||||
def is_egg(self):
|
||||
if self.species_list[self.curr_species_pos-1] == self.utils_class.egg_id:
|
||||
return True
|
||||
return False
|
||||
|
||||
@clean_check_sanity_checks
|
||||
def check_hp(self, val):
|
||||
start_zero = False
|
||||
max_zero = False
|
||||
if self.curr_hp == 0:
|
||||
start_zero = True
|
||||
val = self.check_stat(val, zero_min=start_zero)
|
||||
max_zero = self.is_egg()
|
||||
val = self.check_stat(val, zero_min=start_zero, zero_max=max_zero)
|
||||
if self.curr_pos == 0:
|
||||
if self.curr_hp == 0:
|
||||
self.hps = [0,0]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,129 @@
|
|||
from .gsc_trading import GSCTrading
|
||||
from .gsc_trading_data_utils import GSCUtilsLoaders, GSCUtilsMisc
|
||||
|
||||
class GSCJPMailConverter:
|
||||
"""
|
||||
Class which handles converting the GSC Japanese mail data
|
||||
to the international format.
|
||||
"""
|
||||
base_folder = "useful_data/gsc/"
|
||||
table_to_jp_path = "mail_conversion_table_en_to_jp.bin"
|
||||
table_to_int_path = "mail_conversion_table_jp_to_en.bin"
|
||||
mail_jp_checks_path = "mail_checks_jp.bin"
|
||||
|
||||
end_of_line = 0x50
|
||||
|
||||
extra_distance_jp = 5
|
||||
extra_distance_int = 0xA
|
||||
full_mail_jp_len = 0x2A
|
||||
mail_len = 0x21
|
||||
sender_int_len = 0xE
|
||||
mail_pos_jp = [
|
||||
0xCB + (0*full_mail_jp_len),
|
||||
0xCB + (1*full_mail_jp_len),
|
||||
0xCB + (2*full_mail_jp_len),
|
||||
0xCB + (3*full_mail_jp_len),
|
||||
0xCB + (4*full_mail_jp_len),
|
||||
0xCB + (5*full_mail_jp_len)
|
||||
]
|
||||
mail_pos_int = [
|
||||
0xCB + (0*mail_len),
|
||||
0xCB + (1*mail_len),
|
||||
0xCB + (2*mail_len),
|
||||
0xCB + (3*mail_len),
|
||||
0xCB + (4*mail_len),
|
||||
0xCB + (5*mail_len)
|
||||
]
|
||||
sender_pos_jp = [
|
||||
0xEC + (0*full_mail_jp_len),
|
||||
0xEC + (1*full_mail_jp_len),
|
||||
0xEC + (2*full_mail_jp_len),
|
||||
0xEC + (3*full_mail_jp_len),
|
||||
0xEC + (4*full_mail_jp_len),
|
||||
0xEC + (5*full_mail_jp_len)
|
||||
]
|
||||
sender_pos_int = [
|
||||
0x191 + (0*sender_int_len),
|
||||
0x191 + (1*sender_int_len),
|
||||
0x191 + (2*sender_int_len),
|
||||
0x191 + (3*sender_int_len),
|
||||
0x191 + (4*sender_int_len),
|
||||
0x191 + (5*sender_int_len)
|
||||
]
|
||||
|
||||
def __init__(self, checks):
|
||||
self.conversion_functions = [
|
||||
self.do_zero,
|
||||
self.mail_conversion,
|
||||
self.sender_conversion,
|
||||
self.extra_conversion,
|
||||
self.do_ff,
|
||||
self.do_20,
|
||||
self.start_mail_conversion,
|
||||
self.do_eol,
|
||||
self.start_sender_conversion
|
||||
]
|
||||
self.mail_conversion_table_jp = GSCUtilsLoaders.prepare_functions_map(GSCUtilsMisc.read_data(self.get_path(self.table_to_jp_path)), self.conversion_functions)
|
||||
self.mail_conversion_table_int = GSCUtilsLoaders.prepare_functions_map(GSCUtilsMisc.read_data(self.get_path(self.table_to_int_path)), self.conversion_functions)
|
||||
self.mail_checker = GSCUtilsLoaders.prepare_functions_map(GSCUtilsMisc.read_data(self.get_path(self.mail_jp_checks_path)), checks.check_functions)
|
||||
|
||||
def get_path(self, target):
|
||||
return self.base_folder + target
|
||||
|
||||
def convert_to_jp(self, data):
|
||||
self.mail_converter_pos = self.mail_pos_int
|
||||
self.sender_converter_pos = self.sender_pos_int
|
||||
self.extra_distance = self.extra_distance_int
|
||||
return self.convert(data, self.mail_conversion_table_jp)
|
||||
|
||||
def convert_to_int(self, data):
|
||||
self.mail_converter_pos = self.mail_pos_jp
|
||||
self.sender_converter_pos = self.sender_pos_jp
|
||||
self.extra_distance = self.extra_distance_jp
|
||||
return self.convert(data, self.mail_conversion_table_int)
|
||||
|
||||
def convert(self, to_convert, converter):
|
||||
ret = [0] * len(converter)
|
||||
for i in range(len(converter)):
|
||||
ret[i] = converter[i](to_convert)
|
||||
return ret
|
||||
|
||||
def do_zero(self, data):
|
||||
return 0
|
||||
|
||||
def mail_conversion(self, data):
|
||||
self.single_mail_pos += 1
|
||||
return data[self.mail_converter_pos[self.mail_conv_pos] + self.single_mail_pos]
|
||||
|
||||
def sender_conversion(self, data):
|
||||
self.single_sender_pos += 1
|
||||
return data[self.sender_converter_pos[self.sender_conv_pos] + self.single_sender_pos]
|
||||
|
||||
def extra_conversion(self, data):
|
||||
self.extra_conversion_pos += 1
|
||||
return data[self.sender_converter_pos[self.sender_conv_pos] + self.extra_distance + self.extra_conversion_pos]
|
||||
|
||||
def start_mail_conversion(self, data):
|
||||
self.mail_conv_pos += 1
|
||||
self.single_mail_pos = 0
|
||||
return data[self.mail_converter_pos[self.mail_conv_pos] + self.single_mail_pos]
|
||||
|
||||
def start_sender_conversion(self, data):
|
||||
self.sender_conv_pos += 1
|
||||
self.single_sender_pos = 0
|
||||
self.extra_conversion_pos = -1
|
||||
return data[self.sender_converter_pos[self.sender_conv_pos] + self.single_sender_pos]
|
||||
|
||||
def do_ff(self, data):
|
||||
return 0xFF
|
||||
|
||||
def do_eol(self, data):
|
||||
return self.end_of_line
|
||||
|
||||
def do_20(self, data):
|
||||
self.mail_conv_pos = -1
|
||||
self.sender_conv_pos = -1
|
||||
return 0x20
|
||||
|
||||
class GSCTradingJP(GSCTrading):
|
||||
"""
|
||||
|
|
@ -23,17 +148,38 @@ class GSCTradingJP(GSCTrading):
|
|||
0x13B + (single_text_len * 9): [5, end_of_line],
|
||||
0x13B + (single_text_len * 10): [5, end_of_line],
|
||||
0x13B + (single_text_len * 11): [5, end_of_line]
|
||||
}, {
|
||||
0x19A + (mail_sender_len * 0): [5, end_of_line],
|
||||
0x19A + (mail_sender_len * 1): [5, end_of_line],
|
||||
0x19A + (mail_sender_len * 2): [5, end_of_line],
|
||||
0x19A + (mail_sender_len * 3): [5, end_of_line],
|
||||
0x19A + (mail_sender_len * 4): [5, end_of_line],
|
||||
0x19A + (mail_sender_len * 5): [5, end_of_line],
|
||||
0x205: [0x46, 0]
|
||||
}]
|
||||
drop_bytes_checks = [[0xA, 0x1B9, 0x1E6], [next_section, next_section, no_input], [0,4,0]]
|
||||
}, {}, {}]
|
||||
drop_bytes_checks = [[0xA, 0x1B9, 0x1E6, 0x1B8], [next_section, next_section, no_input, no_input], [0,4,0,0]]
|
||||
|
||||
def __init__(self, sending_func, receiving_func, connection, menu, kill_function):
|
||||
super(GSCTradingJP, self).__init__(sending_func, receiving_func, connection, menu, kill_function)
|
||||
|
||||
self.jp_mail_converter = GSCJPMailConverter(self.checks)
|
||||
|
||||
def get_mail_section_id(self):
|
||||
return 3
|
||||
|
||||
def get_printable_index(self, index):
|
||||
if index != self.get_mail_section_id():
|
||||
return index+1
|
||||
return index
|
||||
|
||||
def get_section_length(self, index):
|
||||
if index != self.get_mail_section_id():
|
||||
return self.special_sections_len[index]
|
||||
return len(self.jp_mail_converter.mail_checker)
|
||||
|
||||
def get_checker(self, index):
|
||||
if index != self.get_mail_section_id():
|
||||
return self.checks.checks_map[index]
|
||||
return self.jp_mail_converter.mail_checker
|
||||
|
||||
def convert_mail_data(self, data, to_device):
|
||||
"""
|
||||
Handles converting the mail data.
|
||||
"""
|
||||
if data is not None:
|
||||
if to_device:
|
||||
data = self.jp_mail_converter.convert_to_jp(data)
|
||||
else:
|
||||
data = self.jp_mail_converter.convert_to_int(data)
|
||||
return data
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ class GSCTradingStrings:
|
|||
arrived_synchro_str = "\nThe other player arrived. Starting party information trading..."
|
||||
transfer_to_hardware_str = "\rSection {index}: {completion}"
|
||||
restart_trade_str = "\nStarting a new trade."
|
||||
incompatible_trade_str = "\nIt looks like the requested trade is not possible.\nYou can't do a synchronous trade when both the International version and the Japanese version\nrequire Mail data from the other.\nEither do a Buffered trade, or remove mail from one of the two.\nShutting down..."
|
||||
separate_section_str = "\n"
|
||||
buffered_negotiation_str = '\nThe other player wants to do a {other_buffered} trade.\nWould you like to switch to a {other_buffered} trade?'
|
||||
buffered_other_negotiation_str = "\nAsking the other player whether they're willing to do a {own_buffered} trade..."
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ class RBYTradingClient(GSCTradingClient):
|
|||
val = self.get_with_counter(self.moves_transfer)
|
||||
if val is not None:
|
||||
updating_mon = self.trader.other_pokemon.pokemon[self.trader.other_pokemon.get_last_mon_index()]
|
||||
self.trader.checks.prepare_species_buffer()
|
||||
data = self.trader.checks.apply_checks_to_data(self.trader.checks.moves_checks_map, val)
|
||||
for i in range(4):
|
||||
updating_mon.set_move(i, data[i+1], max_pp=False)
|
||||
|
|
|
|||
|
|
@ -56,12 +56,17 @@ class RBYUtils(GSCUtils):
|
|||
ret = None
|
||||
|
||||
# Prepare sanity checks stuff
|
||||
checks.reset_species_item_list()
|
||||
checks.set_single_team_size()
|
||||
checks.prepare_text_buffer()
|
||||
checks.prepare_species_buffer()
|
||||
checker = checks.single_pokemon_checks_map
|
||||
|
||||
if len(data) >= len(checker):
|
||||
# Applies the checks to the received data.
|
||||
# If the sanity checks are off, this will be a simple copy
|
||||
checks.species_cleaner(data[0])
|
||||
checks.prepare_species_buffer()
|
||||
purified_data = checks.apply_checks_to_data(checker, data)
|
||||
|
||||
# Prepares the pokémon data. For both the cleaned one and
|
||||
|
|
@ -250,12 +255,17 @@ class RBYChecks(GSCChecks):
|
|||
self.level = self.utils_class.max_level
|
||||
return val
|
||||
|
||||
def is_egg(self):
|
||||
return False
|
||||
|
||||
@GSCChecks.clean_check_sanity_checks
|
||||
def clean_species_sp(self, species):
|
||||
if species == self.free_value_species or self.curr_species_pos >= self.team_size:
|
||||
if species == self.free_value_species or self.species_list_size >= self.team_size:
|
||||
self.add_to_species_list(self.free_value_species)
|
||||
self.curr_species_pos += 1
|
||||
return self.free_value_species
|
||||
found_species = self.clean_value(species, self.is_species_valid, self.rattata_id)
|
||||
self.add_to_species_list(found_species)
|
||||
self.curr_species_pos += 1
|
||||
return found_species
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user