mirror of
https://github.com/Lorenzooone/PokemonGB_Online_Trades.git
synced 2026-03-21 18:04:50 -05:00
Improve reliability of synchronous trades
This commit is contained in:
parent
c0b2eda976
commit
65e08438b6
69
serving.py
69
serving.py
|
|
@ -1,5 +1,6 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import datetime
|
||||
import asyncio
|
||||
import websockets
|
||||
import threading
|
||||
|
|
@ -9,6 +10,7 @@ import boto3
|
|||
import botocore
|
||||
from random import Random
|
||||
from time import sleep
|
||||
from utilities.trading_version import TradingVersion
|
||||
from utilities.high_level_listener import HighLevelListener
|
||||
from utilities.gsc_trading import GSCTradingClient
|
||||
from utilities.rby_trading import RBYTradingClient
|
||||
|
|
@ -113,6 +115,28 @@ class DataUploader(threading.Thread):
|
|||
except botocore.exceptions.NoCredentialsError:
|
||||
pass
|
||||
|
||||
class ServerSpecificTransfers:
|
||||
def __init__(self):
|
||||
self.prepare_random_data()
|
||||
|
||||
def prepare_random_data(self):
|
||||
rnd = Random()
|
||||
rnd.seed()
|
||||
self.random_data = []
|
||||
self.last_read = 0
|
||||
for i in range(10):
|
||||
self.random_data += [rnd.randint(0,0xFC)]
|
||||
|
||||
def handle_get_version(hll, version_transfer):
|
||||
return hll.prepare_send_data(version_transfer, TradingVersion.prepare_version_data())
|
||||
|
||||
def handle_get_random(self, hll, random_transfer):
|
||||
if self.last_read != 0:
|
||||
if (datetime.datetime.now() - self.last_read).total_seconds() > (2 * 60):
|
||||
self.prepare_random_data()
|
||||
self.last_read = datetime.datetime.now()
|
||||
return hll.prepare_send_data(random_transfer, self.random_data)
|
||||
|
||||
class PoolTradeServer:
|
||||
"""
|
||||
Class which handles the pool trading part.
|
||||
|
|
@ -155,7 +179,10 @@ class PoolTradeServer:
|
|||
self.get_handlers = {
|
||||
self.trading_client_class.pool_transfer: self.handle_get_pool,
|
||||
self.trading_client_class.accept_transfer: self.handle_get_accepted,
|
||||
self.trading_client_class.success_transfer: self.handle_get_success
|
||||
self.trading_client_class.success_transfer: self.handle_get_success,
|
||||
self.trading_client_class.version_client_transfer: self.handle_get_client_version,
|
||||
self.trading_client_class.version_server_transfer: self.handle_get_server_version,
|
||||
self.trading_client_class.random_data_transfer: self.handle_get_random_data
|
||||
}
|
||||
self.send_handlers = {
|
||||
self.trading_client_class.choice_transfer: self.handle_recv_mon,
|
||||
|
|
@ -177,7 +204,10 @@ class PoolTradeServer:
|
|||
self.trading_client_class.success_transfer[3]: self.handle_get_success3_3,
|
||||
self.trading_client_class.success_transfer[4]: self.handle_get_success3_4,
|
||||
self.trading_client_class.success_transfer[5]: self.handle_get_success3_5,
|
||||
self.trading_client_class.success_transfer[6]: self.handle_get_success3_6
|
||||
self.trading_client_class.success_transfer[6]: self.handle_get_success3_6,
|
||||
self.trading_client_class.version_client_transfer: self.handle_get_client_version,
|
||||
self.trading_client_class.version_server_transfer: self.handle_get_server_version,
|
||||
self.trading_client_class.random_data_transfer: self.handle_get_random_data
|
||||
}
|
||||
self.send_handlers = {
|
||||
self.trading_client_class.pool_transfer_out: self.handle_recv_mon3,
|
||||
|
|
@ -237,6 +267,19 @@ class PoolTradeServer:
|
|||
else:
|
||||
return self.hll.prepare_send_data(self.trading_client_class.pool_transfer, [self.own_id] + self.utils_class.single_mon_to_data(self.mon[0], self.mon[1]))
|
||||
|
||||
def handle_get_client_version(self):
|
||||
return ServerSpecificTransfers.handle_get_version(self.hll, self.trading_client_class.version_client_transfer)
|
||||
|
||||
def handle_get_server_version(self):
|
||||
return ServerSpecificTransfers.handle_get_version(self.hll, self.trading_client_class.version_server_transfer)
|
||||
|
||||
def handle_get_random_data(self):
|
||||
"""
|
||||
Maybe a bit wasteful, but whatever...
|
||||
"""
|
||||
i = ServerSpecificTransfers()
|
||||
return i.handle_get_random(self.hll, self.trading_client_class.random_data_transfer)
|
||||
|
||||
def handle_get_accepted(self):
|
||||
"""
|
||||
If the proper steps have been taken, it sends whether the data
|
||||
|
|
@ -547,6 +590,7 @@ class ProxyLinkServer:
|
|||
checks_class = RSESPChecks
|
||||
self.trading_client_class = RSESPTradingClient
|
||||
self.utils_class = RSESPUtils
|
||||
self.server_data = ServerSpecificTransfers()
|
||||
self.other = None
|
||||
self.other_ws = None
|
||||
self.own_ws = ws
|
||||
|
|
@ -559,12 +603,21 @@ class ProxyLinkServer:
|
|||
"""
|
||||
request = self.hll.is_received_valid(data)
|
||||
if request is not None:
|
||||
if (self.other is not None) and (self.other.other == self):
|
||||
await self.other_ws.send(data)
|
||||
else:
|
||||
self.other = None
|
||||
self.other_ws = None
|
||||
await self.own_ws.close()
|
||||
processed = False
|
||||
if request[0] == GSCTradingStrings.get_request:
|
||||
if request[1] == self.trading_client_class.version_server_transfer:
|
||||
await self.own_ws.send(ServerSpecificTransfers.handle_get_version(self.hll, self.trading_client_class.version_server_transfer))
|
||||
processed = True
|
||||
elif request[1] == self.trading_client_class.random_data_transfer:
|
||||
await self.own_ws.send(self.server_data.handle_get_random(self.hll, self.trading_client_class.random_data_transfer))
|
||||
processed = True
|
||||
if not processed:
|
||||
if (self.other is not None) and (self.other.other == self):
|
||||
await self.other_ws.send(data)
|
||||
else:
|
||||
self.other = None
|
||||
self.other_ws = None
|
||||
await self.own_ws.close()
|
||||
|
||||
class WebsocketServer (threading.Thread):
|
||||
'''
|
||||
|
|
|
|||
1
useful_data/gsc/base_random_section.bin
Normal file
1
useful_data/gsc/base_random_section.bin
Normal file
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -1,2 +1,2 @@
|
|||
|
||||
!&(*,.029:<=>?@ABCDEFGHINQVXZ\^`bijlmnopqrstuvwxy~<7E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>、<EFBFBD>ウЖ<EFBFBD>蔚減湿逝品麺力佰厶壞嶐慵渝肆裲鉋鴒燁
|
||||
!&(*,.029:<=>?@ABCDEFGHINPQVXZ\^`bijlmnopqrstuvwxy~<7E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>、<EFBFBD>ウЖ<EFBFBD>葦狂瑳樟舵別洋椀冫嘖孛忤掵珀肆裲鉋鴒燁
|
||||
|
|
@ -1,2 +1,2 @@
|
|||
|
||||
"$&
|
||||
"$&
|
||||
1
useful_data/rby/base_random_section.bin
Normal file
1
useful_data/rby/base_random_section.bin
Normal file
|
|
@ -0,0 +1 @@
|
|||
|
||||
1
useful_data/rse/base_random_section.bin
Normal file
1
useful_data/rse/base_random_section.bin
Normal file
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
import time
|
||||
import datetime
|
||||
from random import Random
|
||||
from .trading_version import TradingVersion
|
||||
from .gsc_trading_data_utils import *
|
||||
from .gsc_trading_menu import GSCBufferedNegotiator
|
||||
from .gsc_trading_strings import GSCTradingStrings
|
||||
|
|
@ -21,18 +23,24 @@ class GSCTradingClient:
|
|||
success_transfer = "SUC2"
|
||||
buffered_transfer = "BUF2"
|
||||
negotiation_transfer = "NEG2"
|
||||
version_client_transfer = "VEC2"
|
||||
version_server_transfer = "VES2"
|
||||
random_data_transfer = "RAN2"
|
||||
need_data_transfer = "ASK2"
|
||||
possible_transfers = {
|
||||
full_transfer: {0x412, 0x40C}, # Sum of special_sections_len - Ver 1.0 and 2.0
|
||||
single_transfer: {7},
|
||||
full_transfer: {0x412, 0x40C}, # Sum of special_sections_len - Ver 1.0, 2.0 - 4.0
|
||||
single_transfer: {7, 32}, # Ver 1.0 - 3.0 and 4.0
|
||||
pool_transfer: {1 + 0x75 + 1, 1 + 1}, # Counter + Single Pokémon + Egg OR Counter + Fail
|
||||
moves_transfer: {1 + 8}, # Counter + Moves
|
||||
mail_transfer : {1 + 0x24C}, # Counter + Mail - Ver 1.0
|
||||
mail_transfer : {1 + 0x24C, 1 + 0x24B}, # Counter + Mail - Ver 1.0 - 3.0 and 4.0
|
||||
choice_transfer : {1 + 1 + 0x75 + 1, 1 + 1}, # Counter + Choice + Single Pokémon + Egg OR Counter + Stop
|
||||
accept_transfer : {1 + 1}, # Counter + Accept
|
||||
success_transfer : {1 + 1}, # Counter + Success
|
||||
buffered_transfer : {1 + 1}, # Counter + Buffered or not
|
||||
negotiation_transfer : {1 + 1}, # Counter + Convergence value
|
||||
version_client_transfer : {6}, # Client's version value
|
||||
version_server_transfer : {6}, # Server's version value
|
||||
random_data_transfer : {10}, # Random values from server
|
||||
need_data_transfer : {1 + 1} # Counter + Whether it needs the other player's data
|
||||
}
|
||||
buffered_value = 0x85
|
||||
|
|
@ -68,6 +76,36 @@ class GSCTradingClient:
|
|||
"""
|
||||
GSCUtilsMisc.verbose_print(to_print, self.verbose, end=end)
|
||||
|
||||
def get_server_version(self):
|
||||
"""
|
||||
Handles getting the server's version.
|
||||
"""
|
||||
ret = self.connection.recv_data(self.version_server_transfer)
|
||||
if ret is not None:
|
||||
ret = TradingVersion.read_version_data(ret)
|
||||
return ret
|
||||
|
||||
def get_client_version(self):
|
||||
"""
|
||||
Handles getting the other's version.
|
||||
"""
|
||||
ret = self.connection.recv_data(self.version_client_transfer)
|
||||
if ret is not None:
|
||||
ret = TradingVersion.read_version_data(ret)
|
||||
return ret
|
||||
|
||||
def send_client_version(self):
|
||||
"""
|
||||
Handles sending my own version.
|
||||
"""
|
||||
self.connection.send_data(self.version_client_transfer, TradingVersion.prepare_version_data())
|
||||
|
||||
def get_random(self):
|
||||
"""
|
||||
Handles getting the RNG values.
|
||||
"""
|
||||
return self.connection.recv_data(self.random_data_transfer)
|
||||
|
||||
def get_success(self):
|
||||
"""
|
||||
Handles getting the success trade confirmation value.
|
||||
|
|
@ -405,6 +443,11 @@ class GSCTrading:
|
|||
no_input = 0xFE
|
||||
no_input_alternative = 0xFF
|
||||
no_data = 0
|
||||
total_send_buf_old_bytes = 2
|
||||
bytes_per_send_buf_old_byte = 3
|
||||
total_send_buf_new_bytes = 8
|
||||
bytes_per_send_buf_new_byte = 4
|
||||
max_tolerance_bytes = 3
|
||||
special_sections_len = [0xA, 0x1BC, 0xC5, 0x181]
|
||||
special_sections_starter = [next_section, next_section, next_section, mail_next_section]
|
||||
special_sections_sync = [True, True, True, False]
|
||||
|
|
@ -423,6 +466,8 @@ class GSCTrading:
|
|||
self.kill_function = kill_function
|
||||
self.extremely_verbose = False
|
||||
self.utils_class = self.get_and_init_utils_class()
|
||||
self.is_running_compat_3_mode = False
|
||||
self.max_seconds_between_transfers = 0.8
|
||||
self.pre_sleep = pre_sleep
|
||||
|
||||
def get_and_init_utils_class(self):
|
||||
|
|
@ -489,12 +534,19 @@ class GSCTrading:
|
|||
or an error depending on kill_on_byte_drops.
|
||||
"""
|
||||
if self.has_transfer_failed(byte, byte_index, section_index):
|
||||
if self.menu.kill_on_byte_drops:
|
||||
print(GSCTradingStrings.error_byte_dropped_str)
|
||||
self.kill_function()
|
||||
elif not self.printed_warning_drop:
|
||||
self.verbose_print(GSCTradingStrings.warning_byte_dropped_str)
|
||||
self.printed_warning_drop = True
|
||||
self.act_on_bad_data()
|
||||
|
||||
def act_on_bad_data(self):
|
||||
"""
|
||||
If any byte was dropped, either drop a warning
|
||||
or an error depending on kill_on_byte_drops.
|
||||
"""
|
||||
if self.menu.kill_on_byte_drops:
|
||||
print(GSCTradingStrings.error_byte_dropped_str)
|
||||
self.kill_function()
|
||||
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 3
|
||||
|
|
@ -522,7 +574,7 @@ class GSCTrading:
|
|||
return self.no_input_alternative
|
||||
return val
|
||||
|
||||
def read_section(self, index, send_data, buffered):
|
||||
def read_section(self, index, send_data, buffered, last_sent, last_index):
|
||||
"""
|
||||
Reads a data section and sends it to the device.
|
||||
"""
|
||||
|
|
@ -536,26 +588,10 @@ class GSCTrading:
|
|||
self.checks.prepare_species_buffer()
|
||||
|
||||
if not buffered:
|
||||
# Wait for a connection to be established if it's synchronous
|
||||
send_buf = [[0xFFFF,0xFF],[0xFFFF,0xFF],[index]]
|
||||
self.comms.send_trading_data(self.write_entire_data(send_buf))
|
||||
found = False
|
||||
if index == 0:
|
||||
self.verbose_print(GSCTradingStrings.waiting_synchro_str)
|
||||
while not found:
|
||||
received = self.comms.get_trading_data()
|
||||
if received is not None:
|
||||
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)
|
||||
if index == 0:
|
||||
self.verbose_print(GSCTradingStrings.arrived_synchro_str)
|
||||
if self.is_running_compat_3_mode:
|
||||
self.synch_synch_section_old(index)
|
||||
else:
|
||||
send_buf = self.synch_synch_section_new(index, last_sent, last_index)
|
||||
|
||||
if self.special_sections_sync[index]:
|
||||
next = self.no_input
|
||||
|
|
@ -603,63 +639,229 @@ class GSCTrading:
|
|||
self.swap_byte(self.no_data)
|
||||
other_buf = send_data
|
||||
else:
|
||||
# If the trade is synchronous, prepare small send buffers
|
||||
self.printed_warning_drop = False
|
||||
buf = [next]
|
||||
other_buf = []
|
||||
send_buf = [[0,next],[0xFFFF,0xFF],[index]]
|
||||
recv_data = {}
|
||||
i = 0
|
||||
while i < (length + 1):
|
||||
found = False
|
||||
# Send the current byte (and the previous one) to the
|
||||
# other client
|
||||
self.comms.send_trading_data(self.write_entire_data(send_buf))
|
||||
while not found:
|
||||
received = self.comms.get_trading_data()
|
||||
if received is not None:
|
||||
if i not in recv_data.keys():
|
||||
recv_buf = self.read_entire_data(received)
|
||||
# Get all the bytes we can consecutively send to the device
|
||||
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.prevent_no_input(checker[i](recv_data[i]))
|
||||
next_i = i+1
|
||||
# Handle fillers
|
||||
if next_i in self.fillers[index].keys():
|
||||
filler_len = self.fillers[index][next_i][0]
|
||||
filler_val = self.fillers[index][next_i][1]
|
||||
send_buf[(next_i)&1][0] = self.filler_value + filler_len
|
||||
send_buf[(next_i)&1][1] = filler_val
|
||||
buf += ([filler_val] * filler_len)
|
||||
for j in range(filler_len):
|
||||
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=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
|
||||
# the other client needs
|
||||
send_buf[(next_i)&1][0] = next_i
|
||||
send_buf[(next_i)&1][1] = next
|
||||
other_buf += [cleaned_byte]
|
||||
# Check for "bad transfer" clues
|
||||
self.check_bad_data(cleaned_byte, i, index)
|
||||
self.check_bad_data(next, next_i, index)
|
||||
buf += [next]
|
||||
found = True
|
||||
# Handle the last byte differently
|
||||
elif i in recv_data.keys() and (i >= length):
|
||||
found = True
|
||||
if not found:
|
||||
self.sleep_func()
|
||||
i += 1
|
||||
if self.is_running_compat_3_mode:
|
||||
buf, other_buf = self.synch_exchange_section_old(next, index, length, checker)
|
||||
else:
|
||||
buf, other_buf, last_sent = self.synch_exchange_section_new(next, index, length, checker, send_buf)
|
||||
|
||||
self.verbose_print(GSCTradingStrings.separate_section_str, end='')
|
||||
return buf, other_buf
|
||||
return buf, other_buf, last_sent
|
||||
|
||||
def synch_synch_section_old(self, index):
|
||||
# Wait for a connection to be established if it's synchronous
|
||||
send_buf = [[0xFFFF,0xFF],[0xFFFF,0xFF],[index]]
|
||||
self.comms.send_trading_data(self.write_entire_data(send_buf))
|
||||
found = False
|
||||
if index == 0:
|
||||
self.verbose_print(GSCTradingStrings.waiting_synchro_str)
|
||||
while not found:
|
||||
received = self.comms.get_trading_data()
|
||||
if received is not None:
|
||||
recv_buf = self.read_entire_data(received)
|
||||
if recv_buf[1] is not None and recv_buf[1][0] == 0xFFFF and recv_buf[2] == 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)
|
||||
if index == 0:
|
||||
self.verbose_print(GSCTradingStrings.arrived_synchro_str)
|
||||
|
||||
def synch_synch_section_new(self, index, last_sent, last_index):
|
||||
# Wait for a connection to be established if it's synchronous
|
||||
if last_sent is None:
|
||||
send_buf = []
|
||||
for i in range(self.total_send_buf_new_bytes):
|
||||
send_buf += [[0xFFFF,0xFF, index, False, 0]]
|
||||
else:
|
||||
min_index = 0
|
||||
for i in range(self.total_send_buf_new_bytes):
|
||||
if(last_sent[i][0] < last_sent[min_index][0]):
|
||||
min_index = i
|
||||
last_sent[min_index] = last_sent[self.total_send_buf_new_bytes - 1]
|
||||
last_sent[self.total_send_buf_new_bytes - 1] = [0xFFFF,0xFF, index, False, 0]
|
||||
send_buf = last_sent
|
||||
|
||||
self.comms.send_trading_data(self.write_entire_data_new(send_buf))
|
||||
found = False
|
||||
if index == 1:
|
||||
self.verbose_print(GSCTradingStrings.waiting_synchro_str)
|
||||
while not found:
|
||||
received = self.comms.get_trading_data()
|
||||
if received is not None:
|
||||
recv_buf = self.read_entire_data_new(received)
|
||||
if recv_buf[self.total_send_buf_new_bytes - 1] is not None and recv_buf[self.total_send_buf_new_bytes - 1][0] == 0xFFFF:
|
||||
if recv_buf[self.total_send_buf_new_bytes - 1][2] == index:
|
||||
found = True
|
||||
elif recv_buf[self.total_send_buf_new_bytes - 1][2] != last_index:
|
||||
self.verbose_print(GSCTradingStrings.incompatible_trade_str)
|
||||
self.kill_function()
|
||||
if not found:
|
||||
self.sleep_func()
|
||||
self.swap_byte(self.no_input)
|
||||
if index == 1:
|
||||
self.verbose_print(GSCTradingStrings.arrived_synchro_str)
|
||||
return send_buf
|
||||
|
||||
def synch_exchange_section_old(self, next, index, length, checker):
|
||||
# If the trade is synchronous, prepare small send buffers
|
||||
self.printed_warning_drop = False
|
||||
buf = [next]
|
||||
other_buf = []
|
||||
send_buf = [[0,next],[0xFFFF,0xFF],[index]]
|
||||
recv_data = {}
|
||||
i = 0
|
||||
while i < (length + 1):
|
||||
found = False
|
||||
# Send the current byte (and the previous one) to the
|
||||
# other client
|
||||
self.comms.send_trading_data(self.write_entire_data(send_buf))
|
||||
while not found:
|
||||
received = self.comms.get_trading_data()
|
||||
if received is not None:
|
||||
if i not in recv_data.keys():
|
||||
recv_buf = self.read_entire_data(received)
|
||||
# Get all the bytes we can consecutively send to the device
|
||||
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.prevent_no_input(checker[i](recv_data[i]))
|
||||
next_i = i+1
|
||||
# Handle fillers
|
||||
if next_i in self.fillers[index].keys():
|
||||
filler_len = self.fillers[index][next_i][0]
|
||||
filler_val = self.fillers[index][next_i][1]
|
||||
send_buf[(next_i)&1][0] = self.filler_value + filler_len
|
||||
send_buf[(next_i)&1][1] = filler_val
|
||||
buf += ([filler_val] * filler_len)
|
||||
for j in range(filler_len):
|
||||
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=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
|
||||
# the other client needs
|
||||
send_buf[(next_i)&1][0] = next_i
|
||||
send_buf[(next_i)&1][1] = next
|
||||
other_buf += [cleaned_byte]
|
||||
# Check for "bad transfer" clues
|
||||
self.check_bad_data(cleaned_byte, i, index)
|
||||
self.check_bad_data(next, next_i, index)
|
||||
buf += [next]
|
||||
found = True
|
||||
# Handle the last byte differently
|
||||
elif i in recv_data.keys() and (i >= length):
|
||||
found = True
|
||||
if not found:
|
||||
self.sleep_func()
|
||||
i += 1
|
||||
return buf, other_buf
|
||||
|
||||
def synch_exchange_section_new(self, next, index, length, checker, send_buf):
|
||||
# If the trade is synchronous, prepare small send buffers
|
||||
self.printed_warning_drop = False
|
||||
buf = [next]
|
||||
other_buf = []
|
||||
recv_data = {}
|
||||
safety_transfer_amount = self.max_tolerance_bytes - 2
|
||||
pos_recv = 0
|
||||
i = 0
|
||||
pos_send = 0
|
||||
send_index = 0
|
||||
bytes_offset = 1
|
||||
bytes_offset_target = self.max_tolerance_bytes
|
||||
send_buf[send_index] = [pos_send, next, index, False, 0]
|
||||
pos_send += 1
|
||||
send_index = (send_index + 1) % self.total_send_buf_new_bytes
|
||||
last_transfer_time = datetime.datetime.now()
|
||||
self.comms.send_trading_data(self.write_entire_data_new(send_buf))
|
||||
while i < (length - self.max_tolerance_bytes):
|
||||
received = self.comms.get_trading_data()
|
||||
if received is not None:
|
||||
recv_buf = self.read_entire_data_new(received)
|
||||
# Get all the bytes we can consecutively send to the device
|
||||
recv_data = self.get_swappable_bytes_new(recv_buf, length, index)
|
||||
while pos_recv in recv_data.keys():
|
||||
if pos_recv >= length:
|
||||
break
|
||||
cleaned_byte = self.prevent_no_input(checker[pos_recv](recv_data[pos_recv]))
|
||||
other_buf += [cleaned_byte]
|
||||
pos_recv += 1
|
||||
|
||||
if pos_recv in self.fillers[index].keys():
|
||||
filler_len = self.fillers[index][pos_send][0]
|
||||
filler_val = self.fillers[index][pos_send][1]
|
||||
added_len = 0
|
||||
for j in range(filler_len):
|
||||
if (pos_recv + j) >= length:
|
||||
break
|
||||
other_buf += [checker[pos_recv + j](filler_val)]
|
||||
added_len += 1
|
||||
pos_recv += added_len
|
||||
byte_to_console = self.no_input
|
||||
schedule_console = False
|
||||
time_diff = datetime.datetime.now() - last_transfer_time
|
||||
if time_diff.total_seconds() >= self.max_seconds_between_transfers:
|
||||
schedule_console = True
|
||||
if bytes_offset < bytes_offset_target:
|
||||
schedule_console = True
|
||||
elif pos_recv > i:
|
||||
byte_to_console = other_buf[i]
|
||||
if pos_recv > (i + safety_transfer_amount):
|
||||
schedule_console = True
|
||||
if schedule_console:
|
||||
i += 1
|
||||
if i in self.fillers[index].keys():
|
||||
filler_len = self.fillers[index][pos_send][0]
|
||||
i += filler_len
|
||||
|
||||
if schedule_console:
|
||||
if byte_to_console == self.no_input:
|
||||
bytes_offset += 1
|
||||
if bytes_offset > self.max_tolerance_bytes:
|
||||
self.act_on_bad_data()
|
||||
next = self.swap_byte(byte_to_console)
|
||||
self.verbose_print(GSCTradingStrings.transfer_to_hardware_str.format(index=self.get_printable_index(index), completion=GSCTradingStrings.x_out_of_y_str(i, length)), end='')
|
||||
last_transfer_time = datetime.datetime.now()
|
||||
send_buf[send_index] = [pos_send, next, index, False, 0]
|
||||
send_index = (send_index + 1) % self.total_send_buf_new_bytes
|
||||
buf += [next]
|
||||
pos_send += 1
|
||||
if pos_send in self.fillers[index].keys():
|
||||
filler_len = self.fillers[index][pos_send][0]
|
||||
filler_val = self.fillers[index][pos_send][1]
|
||||
send_buf[send_index] = [pos_send, filler_val, index, True, filler_len]
|
||||
send_index = (send_index + 1) % self.total_send_buf_new_bytes
|
||||
buf += ([filler_val] * filler_len)
|
||||
pos_send += filler_len
|
||||
self.comms.send_trading_data(self.write_entire_data_new(send_buf))
|
||||
self.sleep_func()
|
||||
|
||||
while i < (length - (bytes_offset)):
|
||||
byte_to_console = self.no_data
|
||||
i += 1
|
||||
schedule_console = True
|
||||
|
||||
if schedule_console:
|
||||
next = self.swap_byte(byte_to_console)
|
||||
self.verbose_print(GSCTradingStrings.transfer_to_hardware_str.format(index=self.get_printable_index(index), completion=GSCTradingStrings.x_out_of_y_str(i, length)), end='')
|
||||
send_buf[send_index] = [pos_send, next, index, False, 0]
|
||||
send_index = (send_index + 1) % self.total_send_buf_new_bytes
|
||||
pos_send += 1
|
||||
self.comms.send_trading_data(self.write_entire_data_new(send_buf))
|
||||
self.sleep_func()
|
||||
while len(buf) < length:
|
||||
buf += [self.no_data]
|
||||
while len(other_buf) < length:
|
||||
other_buf += [self.no_data]
|
||||
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='')
|
||||
return buf, other_buf, send_buf
|
||||
|
||||
def swap_byte(self, send_data):
|
||||
"""
|
||||
Swaps a byte with the device. First send, and then receives.
|
||||
|
|
@ -688,7 +890,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] >= (index + 1):
|
||||
ret[length] = 0
|
||||
else:
|
||||
byte_num = recv_buf[scanning_index][0]
|
||||
|
|
@ -701,17 +903,33 @@ class GSCTrading:
|
|||
byte_num = recv_buf[previous_scanning_index][0]
|
||||
for j in range(total_bytes):
|
||||
ret[byte_num + 1 + j] = recv_buf[scanning_index][1]
|
||||
|
||||
def prepare_single_entry_new(self, recv_buf, scanning_index, length, index, ret):
|
||||
"""
|
||||
Tries to read a single synchronous entry.
|
||||
"""
|
||||
if recv_buf[scanning_index] is not None:
|
||||
if recv_buf[scanning_index][2] > index:
|
||||
ret[length] = 0
|
||||
else:
|
||||
byte_num = recv_buf[scanning_index][0]
|
||||
if byte_num <= length:
|
||||
if recv_buf[scanning_index][3]:
|
||||
for j in range(recv_buf[scanning_index][4]):
|
||||
ret[byte_num + j] = recv_buf[scanning_index][1]
|
||||
else:
|
||||
ret[byte_num] = recv_buf[scanning_index][1]
|
||||
|
||||
def remove_filler(self, send_buf, curr_byte_num):
|
||||
"""
|
||||
Removes the filler from the send buffer when a new byte is read.
|
||||
Also prevents desyncs.
|
||||
"""
|
||||
for i in range(2):
|
||||
for i in range(self.total_send_buf_old_bytes):
|
||||
byte_num = send_buf[i][0]
|
||||
byte_val = send_buf[i][1]
|
||||
if byte_num > self.filler_value and byte_num <= self.last_filler_value:
|
||||
for j in range(2):
|
||||
for j in range(self.total_send_buf_old_bytes):
|
||||
send_buf[j][0] = curr_byte_num
|
||||
send_buf[j][1] = byte_val
|
||||
|
||||
|
|
@ -721,15 +939,33 @@ class GSCTrading:
|
|||
Tries to speedup the transfer a bit.
|
||||
"""
|
||||
ret = {}
|
||||
for i in range(2):
|
||||
for i in range(self.total_send_buf_old_bytes):
|
||||
self.prepare_single_entry(recv_buf, i, length, index, ret)
|
||||
return ret
|
||||
|
||||
def get_swappable_bytes_new(self, recv_buf, length, index):
|
||||
"""
|
||||
Returns the maximum amount of bytes we can swap freely.
|
||||
Tries to speedup the transfer a bit.
|
||||
"""
|
||||
ret = {}
|
||||
for i in range(self.total_send_buf_new_bytes):
|
||||
self.prepare_single_entry_new(recv_buf, i, length, index, ret)
|
||||
return ret
|
||||
|
||||
def read_entire_data(self, data):
|
||||
return [self.read_sync_data(data, 0), self.read_sync_data(data, 3), [data[6]]]
|
||||
final_product = []
|
||||
for i in range(self.total_send_buf_old_bytes):
|
||||
final_product += [self.read_sync_data(data, i * self.bytes_per_send_buf_old_byte)]
|
||||
final_product += [data[self.total_send_buf_old_bytes * self.bytes_per_send_buf_old_byte]]
|
||||
return final_product
|
||||
|
||||
def write_entire_data(self, data):
|
||||
return self.write_sync_data(data[0]) + self.write_sync_data(data[1]) + data[2]
|
||||
final_product = []
|
||||
for i in range(self.total_send_buf_old_bytes):
|
||||
final_product += self.write_sync_data(data[i])
|
||||
final_product += data[self.total_send_buf_old_bytes]
|
||||
return final_product
|
||||
|
||||
def read_sync_data(self, data, pos):
|
||||
if data is not None and len(data) > 0:
|
||||
|
|
@ -739,6 +975,41 @@ class GSCTrading:
|
|||
def write_sync_data(self, data):
|
||||
return [(data[0]>>8)&0xFF, data[0]&0xFF, data[1]]
|
||||
|
||||
def read_entire_data_new(self, data):
|
||||
final_product = []
|
||||
for i in range(self.total_send_buf_new_bytes):
|
||||
final_product += [self.read_sync_data_new(data, i * self.bytes_per_send_buf_new_byte)]
|
||||
return final_product
|
||||
|
||||
def write_entire_data_new(self, data):
|
||||
final_product = []
|
||||
for i in range(self.total_send_buf_new_bytes):
|
||||
final_product += self.write_sync_data_new(data[i])
|
||||
return final_product
|
||||
|
||||
def read_sync_data_new(self, data, pos):
|
||||
if data is not None and len(data) > 0:
|
||||
ret_val = [((data[pos]&0x01)<<8) + data[pos+1], data[pos+2], data[pos+3], self.read_is_filler(data[pos]), (data[pos] >> 1) & 0x3F]
|
||||
if ret_val[0] == (0xFFFF & 0x1FF):
|
||||
ret_val[0] = 0xFFFF
|
||||
ret_val[3] = False
|
||||
ret_val[4] = 0
|
||||
return ret_val
|
||||
return None
|
||||
|
||||
def read_is_filler(self, value):
|
||||
if (value >> 7) == 1:
|
||||
return True
|
||||
return False
|
||||
|
||||
def write_is_filler(self, value):
|
||||
if value == True:
|
||||
return 1 << 7
|
||||
return 0 << 7
|
||||
|
||||
def write_sync_data_new(self, data):
|
||||
return [((data[0]>>8)&0x01) | ((data[4] & 0x3F) << 1) | self.write_is_filler(data[3]), data[0]&0xFF, data[1], data[2]]
|
||||
|
||||
def end_trade(self):
|
||||
"""
|
||||
Forces a currently open trade menu to be closed.
|
||||
|
|
@ -853,6 +1124,21 @@ class GSCTrading:
|
|||
received = fun()
|
||||
self.swap_byte(self.no_input)
|
||||
return received
|
||||
|
||||
def attempt_receive(self, fun, max_seconds):
|
||||
"""
|
||||
Blocking wait for the requested data, with timeout
|
||||
It also keeps the device clock running properly.
|
||||
"""
|
||||
received = None
|
||||
start = datetime.datetime.now()
|
||||
while received is None:
|
||||
self.sleep_func()
|
||||
received = fun()
|
||||
self.swap_byte(self.no_input)
|
||||
if (datetime.datetime.now() - start).total_seconds() > max_seconds:
|
||||
break
|
||||
return received
|
||||
|
||||
def reset_trade(self):
|
||||
"""
|
||||
|
|
@ -1028,10 +1314,24 @@ class GSCTrading:
|
|||
# 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)
|
||||
send_data[0] = self.utils_class.base_random_section
|
||||
just_sent = None
|
||||
self.is_running_compat_3_mode = True
|
||||
self.comms.send_client_version()
|
||||
server_version = self.attempt_receive(self.comms.get_server_version, 5)
|
||||
if server_version is not None:
|
||||
send_data[0] = self.force_receive(self.comms.get_random)
|
||||
other_client_version = self.attempt_receive(self.comms.get_client_version, 5)
|
||||
if other_client_version is not None:
|
||||
self.is_running_compat_3_mode = False
|
||||
|
||||
if self.is_running_compat_3_mode:
|
||||
random_data, random_data_other, just_sent = self.read_section(0, send_data[0], buffered, just_sent, 0)
|
||||
else:
|
||||
random_data, random_data_other, just_sent = self.read_section(0, send_data[0], True, just_sent, 0)
|
||||
pokemon_data, pokemon_data_other, just_sent = self.read_section(1, send_data[1], buffered, just_sent, 0)
|
||||
# Get and apply patches for the Pokémon data
|
||||
patches_data, patches_data_other = self.read_section(2, send_data[2], buffered)
|
||||
patches_data, patches_data_other, just_sent = self.read_section(2, send_data[2], buffered, just_sent, 1)
|
||||
self.utils_class.apply_patches(pokemon_data, patches_data, self.utils_class)
|
||||
self.utils_class.apply_patches(pokemon_data_other, patches_data_other, self.utils_class)
|
||||
|
||||
|
|
@ -1043,7 +1343,7 @@ class GSCTrading:
|
|||
# Trade mail data only if needed
|
||||
if (pokemon_own_mail or pokemon_other_mail) or buffered:
|
||||
send_data[3] = self.convert_mail_data(send_data[3], True)
|
||||
mail_data, mail_data_other = self.read_section(self.get_mail_section_id(), send_data[3], buffered)
|
||||
mail_data, mail_data_other, just_sent = self.read_section(self.get_mail_section_id(), send_data[3], buffered, just_sent, 2)
|
||||
mail_data = self.convert_mail_data(mail_data, False)
|
||||
else:
|
||||
send_data[3] = self.utils_class.no_mail_section
|
||||
|
|
@ -1051,7 +1351,7 @@ class GSCTrading:
|
|||
|
||||
# Exchange mail data with the device
|
||||
send_data[3] = self.convert_mail_data(send_data[3], True)
|
||||
mail_data, mail_data_other = self.read_section(self.get_mail_section_id(), send_data[3], True)
|
||||
mail_data, mail_data_other, just_sent = self.read_section(self.get_mail_section_id(), send_data[3], True, just_sent, 2)
|
||||
mail_data = self.convert_mail_data(mail_data, False)
|
||||
|
||||
# Apply patches for the mail data
|
||||
|
|
|
|||
|
|
@ -115,6 +115,7 @@ class GSCUtils:
|
|||
evolution_ids_path = "evolution_ids.bin"
|
||||
mail_ids_path = "ids_mail.bin"
|
||||
no_mail_path = "no_mail_section.bin"
|
||||
base_random_path = "base_random_section.bin"
|
||||
base_stats_path = "stats.bin"
|
||||
text_conv_path = "text_conv.txt"
|
||||
pokemon_names_path = "pokemon_names.txt"
|
||||
|
|
@ -156,6 +157,7 @@ class GSCUtils:
|
|||
curr_class.evolution_ids = GSCUtilsLoaders.prepare_evolution_check_list(GSCUtilsMisc.read_data(self.get_path(curr_class.evolution_ids_path)))
|
||||
curr_class.mail_ids = GSCUtilsLoaders.prepare_check_list(GSCUtilsMisc.read_data(self.get_path(curr_class.mail_ids_path)))
|
||||
curr_class.no_mail_section = GSCUtilsMisc.read_data(self.get_path(curr_class.no_mail_path))
|
||||
curr_class.base_random_section = GSCUtilsMisc.read_data(self.get_path(curr_class.base_random_path))
|
||||
curr_class.base_stats = GSCUtilsLoaders.prepare_stats(GSCUtilsMisc.read_data(self.get_path(curr_class.base_stats_path)), curr_class.num_stats, curr_class.num_entries)
|
||||
curr_class.pokemon_names = GSCUtilsLoaders.text_to_bytes(self.get_path(curr_class.pokemon_names_path), self.get_path(curr_class.text_conv_path))
|
||||
curr_class.moves_pp_list = GSCUtilsMisc.read_data(self.get_path(curr_class.moves_pp_list_path))
|
||||
|
|
@ -1177,9 +1179,10 @@ class GSCChecks:
|
|||
current_pp = pp & 0x3F
|
||||
pp_ups = (pp >> 6) & 3
|
||||
max_base_pp = self.utils_class.moves_pp_list[self.moves[self.curr_pp]]
|
||||
max_pp = max_base_pp + (math.floor(max_base_pp/5) * pp_ups)
|
||||
if max_pp > 61:
|
||||
max_pp = 61
|
||||
pp_increment = math.floor(max_base_pp/5)
|
||||
if max_base_pp == 40:
|
||||
pp_increment -= 1
|
||||
max_pp = max_base_pp + (pp_increment * pp_ups)
|
||||
final_pp = pp
|
||||
if current_pp > max_pp:
|
||||
final_pp = (pp_ups << 6) | max_pp
|
||||
|
|
|
|||
|
|
@ -135,20 +135,24 @@ class GSCTradingJP(GSCTrading):
|
|||
end_of_line = 0x50
|
||||
single_text_len = 0xB
|
||||
mail_sender_len = 0xE
|
||||
end_of_player_name_pos = 6
|
||||
end_of_gsc_data_pos = 0x13B
|
||||
player_name_len_diff = 5
|
||||
pokemon_name_len_diff = 5
|
||||
fillers = [{}, {
|
||||
6: [5, end_of_line],
|
||||
0x13B + (single_text_len * 0): [5, end_of_line],
|
||||
0x13B + (single_text_len * 1): [5, end_of_line],
|
||||
0x13B + (single_text_len * 2): [5, end_of_line],
|
||||
0x13B + (single_text_len * 3): [5, end_of_line],
|
||||
0x13B + (single_text_len * 4): [5, end_of_line],
|
||||
0x13B + (single_text_len * 5): [5, end_of_line],
|
||||
0x13B + (single_text_len * 6): [5, end_of_line],
|
||||
0x13B + (single_text_len * 7): [5, end_of_line],
|
||||
0x13B + (single_text_len * 8): [5, end_of_line],
|
||||
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]
|
||||
end_of_player_name_pos: [player_name_len_diff, end_of_line],
|
||||
end_of_gsc_data_pos + (single_text_len * 0): [player_name_len_diff, end_of_line],
|
||||
end_of_gsc_data_pos + (single_text_len * 1): [player_name_len_diff, end_of_line],
|
||||
end_of_gsc_data_pos + (single_text_len * 2): [player_name_len_diff, end_of_line],
|
||||
end_of_gsc_data_pos + (single_text_len * 3): [player_name_len_diff, end_of_line],
|
||||
end_of_gsc_data_pos + (single_text_len * 4): [player_name_len_diff, end_of_line],
|
||||
end_of_gsc_data_pos + (single_text_len * 5): [player_name_len_diff, end_of_line],
|
||||
end_of_gsc_data_pos + (single_text_len * 6): [pokemon_name_len_diff, end_of_line],
|
||||
end_of_gsc_data_pos + (single_text_len * 7): [pokemon_name_len_diff, end_of_line],
|
||||
end_of_gsc_data_pos + (single_text_len * 8): [pokemon_name_len_diff, end_of_line],
|
||||
end_of_gsc_data_pos + (single_text_len * 9): [pokemon_name_len_diff, end_of_line],
|
||||
end_of_gsc_data_pos + (single_text_len * 10): [pokemon_name_len_diff, end_of_line],
|
||||
end_of_gsc_data_pos + (single_text_len * 11): [pokemon_name_len_diff, end_of_line]
|
||||
}, {}, {}, {}]
|
||||
special_sections_starter = [next_section, next_section, next_section, mail_next_section, mail_next_section]
|
||||
special_sections_sync = [True, True, True, False, False]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import threading
|
||||
from random import Random
|
||||
from .trading_version import TradingVersion
|
||||
from .gsc_trading_strings import GSCTradingStrings
|
||||
from argparse import ArgumentParser
|
||||
|
||||
|
|
@ -93,7 +94,7 @@ class GSCTradingMenu:
|
|||
ret_val = ret_val()
|
||||
|
||||
def handle_menu(self):
|
||||
GSCTradingStrings.version_print()
|
||||
GSCTradingStrings.version_print(TradingVersion.version_major, TradingVersion.version_minor, TradingVersion.version_build)
|
||||
if self.multiboot:
|
||||
self.start_pool_trading()
|
||||
elif self.trade_type is None or ((self.trade_type != GSCTradingStrings.two_player_trade_str) and (self.trade_type != GSCTradingStrings.pool_trade_str)):
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ class GSCTradingStrings:
|
|||
Class which collects all the text used by the program
|
||||
and methods connected to that.
|
||||
"""
|
||||
version_str = "Version: 3.0.2"
|
||||
version_str = "Version: {major}.{minor}.{build}"
|
||||
buffered_str = "Buffered"
|
||||
synchronous_str = "Synchronous"
|
||||
send_request = "S"
|
||||
|
|
@ -144,8 +144,8 @@ class GSCTradingStrings:
|
|||
print(GSCTradingStrings.buffered_negotiation_str.format(other_buffered=GSCTradingStrings.get_buffered_str(not buffered)))
|
||||
print(GSCTradingStrings.yes_no_str, end = '')
|
||||
|
||||
def version_print():
|
||||
print(GSCTradingStrings.version_str)
|
||||
def version_print(major, minor, build):
|
||||
print(GSCTradingStrings.version_str.format(major=major, minor=minor, build=build))
|
||||
|
||||
def buffered_other_negotiation_print(buffered):
|
||||
print(GSCTradingStrings.buffered_other_negotiation_str.format(own_buffered = GSCTradingStrings.get_buffered_str(buffered)))
|
||||
|
|
|
|||
|
|
@ -18,10 +18,13 @@ class RBYTradingClient(GSCTradingClient):
|
|||
success_transfer = "SUC1"
|
||||
buffered_transfer = "BUF1"
|
||||
negotiation_transfer = "NEG1"
|
||||
version_client_transfer = "VEC1"
|
||||
version_server_transfer = "VES1"
|
||||
random_data_transfer = "RAN1"
|
||||
need_data_transfer = "ASK1"
|
||||
possible_transfers = {
|
||||
full_transfer: {0x271}, # Sum of special_sections_len
|
||||
single_transfer: {7},
|
||||
single_transfer: {7, 32},
|
||||
pool_transfer: {1 + 0x42, 1 + 1}, # Counter + Single Pokémon OR Counter + Fail
|
||||
moves_transfer: {1 + 1 + 8}, # Counter + Species + Moves
|
||||
choice_transfer : {1 + 1 + 0x42, 1 + 1}, # Counter + Choice + Single Pokémon OR Counter + Stop
|
||||
|
|
@ -29,6 +32,9 @@ class RBYTradingClient(GSCTradingClient):
|
|||
success_transfer : {1 + 1}, # Counter + Success
|
||||
buffered_transfer : {1 + 1}, # Counter + Buffered or not
|
||||
negotiation_transfer : {1 + 1}, # Counter + Convergence value
|
||||
version_client_transfer : {6}, # Client's version value
|
||||
version_server_transfer : {6}, # Server's version value
|
||||
random_data_transfer : {10}, # Random values from server
|
||||
need_data_transfer : {1 + 1} # Counter + Whether it needs the other player's data
|
||||
}
|
||||
|
||||
|
|
@ -127,9 +133,22 @@ class RBYTrading(GSCTrading):
|
|||
# Prepare checks
|
||||
self.checks.reset_species_item_list()
|
||||
# Send and get the 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)
|
||||
patches_data, patches_data_other = self.read_section(2, send_data[2], buffered)
|
||||
send_data[0] = self.utils_class.base_random_section
|
||||
just_sent = None
|
||||
self.is_running_compat_3_mode = True
|
||||
self.comms.send_client_version()
|
||||
server_version = self.attempt_receive(self.comms.get_server_version, 5)
|
||||
if server_version is not None:
|
||||
send_data[0] = self.force_receive(self.comms.get_random)
|
||||
other_client_version = self.attempt_receive(self.comms.get_client_version, 5)
|
||||
if other_client_version is not None:
|
||||
self.is_running_compat_3_mode = False
|
||||
if self.is_running_compat_3_mode:
|
||||
random_data, random_data_other, just_sent = self.read_section(0, send_data[0], buffered, just_sent, 0)
|
||||
else:
|
||||
random_data, random_data_other, just_sent = self.read_section(0, send_data[0], True, just_sent, 0)
|
||||
pokemon_data, pokemon_data_other, just_sent = self.read_section(1, send_data[1], buffered, just_sent, 0)
|
||||
patches_data, patches_data_other, just_sent = self.read_section(2, send_data[2], buffered, just_sent, 1)
|
||||
|
||||
self.utils_class.apply_patches(pokemon_data, patches_data, self.utils_class)
|
||||
self.utils_class.apply_patches(pokemon_data_other, patches_data_other, self.utils_class)
|
||||
|
|
|
|||
|
|
@ -6,22 +6,26 @@ class RBYTradingJP(RBYTrading):
|
|||
"""
|
||||
end_of_line = 0x50
|
||||
single_text_len = 0xB
|
||||
end_of_player_name_pos = 6
|
||||
end_of_rby_data_pos = 0x121
|
||||
player_name_len_diff = 5
|
||||
pokemon_name_len_diff = 5
|
||||
fillers = [{}, {
|
||||
6: [5, end_of_line],
|
||||
0x121 + (single_text_len * 0): [5, end_of_line],
|
||||
0x121 + (single_text_len * 1): [5, end_of_line],
|
||||
0x121 + (single_text_len * 2): [5, end_of_line],
|
||||
0x121 + (single_text_len * 3): [5, end_of_line],
|
||||
0x121 + (single_text_len * 4): [5, end_of_line],
|
||||
0x121 + (single_text_len * 5): [5, end_of_line],
|
||||
0x121 + (single_text_len * 6): [5, end_of_line],
|
||||
0x121 + (single_text_len * 7): [5, end_of_line],
|
||||
0x121 + (single_text_len * 8): [5, end_of_line],
|
||||
0x121 + (single_text_len * 9): [5, end_of_line],
|
||||
0x121 + (single_text_len * 10): [5, end_of_line],
|
||||
0x121 + (single_text_len * 11): [5, end_of_line]
|
||||
end_of_player_name_pos: [player_name_len_diff, end_of_line],
|
||||
end_of_rby_data_pos + (single_text_len * 0): [player_name_len_diff, end_of_line],
|
||||
end_of_rby_data_pos + (single_text_len * 1): [player_name_len_diff, end_of_line],
|
||||
end_of_rby_data_pos + (single_text_len * 2): [player_name_len_diff, end_of_line],
|
||||
end_of_rby_data_pos + (single_text_len * 3): [player_name_len_diff, end_of_line],
|
||||
end_of_rby_data_pos + (single_text_len * 4): [player_name_len_diff, end_of_line],
|
||||
end_of_rby_data_pos + (single_text_len * 5): [player_name_len_diff, end_of_line],
|
||||
end_of_rby_data_pos + (single_text_len * 6): [pokemon_name_len_diff, end_of_line],
|
||||
end_of_rby_data_pos + (single_text_len * 7): [pokemon_name_len_diff, end_of_line],
|
||||
end_of_rby_data_pos + (single_text_len * 8): [pokemon_name_len_diff, end_of_line],
|
||||
end_of_rby_data_pos + (single_text_len * 9): [pokemon_name_len_diff, end_of_line],
|
||||
end_of_rby_data_pos + (single_text_len * 10): [pokemon_name_len_diff, end_of_line],
|
||||
end_of_rby_data_pos + (single_text_len * 11): [pokemon_name_len_diff, end_of_line]
|
||||
}, {}]
|
||||
|
||||
def __init__(self, sending_func, receiving_func, connection, menu, kill_function, pre_sleep):
|
||||
super(RBYTradingJP, self).__init__(sending_func, receiving_func, connection, menu, kill_function, pre_sleep)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ class RSESPTradingClient(GSCTradingClient):
|
|||
pool_transfer = "P3SI"
|
||||
pool_transfer_out = "P3SO"
|
||||
choice_transfer = "CH3S"
|
||||
version_client_transfer = "VEC3"
|
||||
version_server_transfer = "VES3"
|
||||
accept_transfer = ["A3S1", "A3S2"]
|
||||
success_transfer = ["S3S1", "S3S2", "S3S3", "S3S4", "S3S5", "S3S6", "S3S7"]
|
||||
possible_transfers = {
|
||||
|
|
@ -31,6 +33,8 @@ class RSESPTradingClient(GSCTradingClient):
|
|||
success_transfer[4] : {1 + 3}, # Counter + Success
|
||||
success_transfer[5] : {1 + 3}, # Counter + Success
|
||||
success_transfer[6] : {1 + 3}, # Counter + Success
|
||||
version_client_transfer : {6}, # Client's version value
|
||||
version_server_transfer : {6}, # Server's version value
|
||||
}
|
||||
|
||||
def __init__(self, trader, connection, verbose, stop_trade, party_reader, base_no_trade = base_folder + "base.bin", base_pool = base_folder + "base_pool.bin"):
|
||||
|
|
|
|||
22
utilities/trading_version.py
Normal file
22
utilities/trading_version.py
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
class TradingVersion:
|
||||
"""
|
||||
Class which contains the version and the version's helper methods.
|
||||
"""
|
||||
|
||||
version_major = 4
|
||||
version_minor = 0
|
||||
version_build = 0
|
||||
|
||||
def read_version_data(data):
|
||||
ret = []
|
||||
for i in range(3):
|
||||
ret += [data[i * 2] + (data[(i * 2) + 1] << 8)]
|
||||
return ret
|
||||
|
||||
def prepare_version_data():
|
||||
ret = []
|
||||
ret += [TradingVersion.version_major & 0xFF, (TradingVersion.version_major >> 8) & 0xFF]
|
||||
ret += [TradingVersion.version_minor & 0xFF, (TradingVersion.version_minor >> 8) & 0xFF]
|
||||
ret += [TradingVersion.version_build & 0xFF, (TradingVersion.version_build >> 8) & 0xFF]
|
||||
return ret
|
||||
|
||||
Loading…
Reference in New Issue
Block a user