PokemonGB_Online_Trades/utilities/gsc_trading_menu.py
2023-07-16 19:36:09 +02:00

304 lines
12 KiB
Python

import threading
from random import Random
from .trading_version import TradingVersion
from .gsc_trading_strings import GSCTradingStrings
from argparse import ArgumentParser
class GSCTradingMenu:
"""
Class used to handle the various possible menus.
"""
default_server = ["pokemon-gb-online-trades.herokuapp.com", None]
default_emulator = ["localhost", 8765]
default_max_level = 100
def __init__(self, kill_function, is_emulator=False):
try:
args = self.handle_args(is_emulator)
except SystemExit as e:
kill_function()
# Initialize the menu
self.server = [args.server_host, args.server_port]
self.buffered = args.buffered
self.japanese = args.japanese
self.max_level = args.max_level
self.egg = args.egg
self.is_emulator = is_emulator
self.multiboot = False
if is_emulator:
self.emulator = [args.emulator_host, args.emulator_port]
self.do_sanity_checks = args.do_sanity_checks
self.kill_on_byte_drops = args.kill_on_byte_drops
self.verbose = args.verbose
self.gen = args.gen_number
self.trade_type = args.trade_type
self.room = args.room
self.toppest_menu_handlers = {
"1": self.start_gen1_trading,
"2": self.start_gen2_trading,
"3": self.start_gen1_trading,
"4": self.start_gen3_trading,
"m": self.start_multiboot_gen3
}
self.top_menu_handlers = {
"0": self.start_2p_trading,
"1": self.start_2p_trading,
"2": self.start_pool_trading,
"3": self.handle_options
}
self.options_menu_handlers = {
"0": self.handle_exit_option,
"1": self.handle_server_option,
"2": self.handle_port_option,
"3": self.handle_japanese_option,
"4": self.handle_sanity_option,
"5": self.handle_verbose_option,
"6": self.handle_buffered_option,
"7": self.handle_kill_on_byte_drop_option,
"8": self.handle_max_level_option,
"9": self.handle_eggs_option
}
if is_emulator:
self.options_menu_handlers["10"] = self.handle_emulator_host_option
self.options_menu_handlers["11"] = self.handle_emulator_port_option
def get_int(self, default_value):
x = input()
try:
ret_val = int(x)
except ValueError:
ret_val = default_value
return ret_val
def handle_buffered_change_offer(self, buffered):
decided = False
while not decided:
GSCTradingStrings.buffered_negotiation_print(buffered)
x = input().lower()
if x == "y" or x == "yes":
buffered = not buffered
decided = True
elif x == "n" or x == "no":
decided = True
return buffered
def handle_game_selector(self):
if self.gen is None or ((self.gen != 1) and (self.gen != 2) and (self.gen != 3)):
ret_val = None
while ret_val is None:
GSCTradingStrings.game_selector_menu_print()
GSCTradingStrings.choice_print()
ret_val = self.toppest_menu_handlers.get(input(), None)
if ret_val is not None:
ret_val = ret_val()
def handle_menu(self):
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)):
self.handle_game_selector()
if not self.multiboot:
ret_val = False
while not ret_val:
GSCTradingStrings.top_menu_print()
GSCTradingStrings.choice_print()
ret_val = self.top_menu_handlers.get(input(), self.top_menu_handlers["0"])()
else:
if self.trade_type == GSCTradingStrings.two_player_trade_str:
self.start_2p_trading()
elif self.trade_type == GSCTradingStrings.pool_trade_str:
self.start_pool_trading()
def get_default_room(self):
r = Random()
return r.randint(0,99999)
def start_2p_trading(self):
self.trade_type = GSCTradingStrings.two_player_trade_str
if self.room is None:
self.room = self.get_default_room()
GSCTradingStrings.change_room_print(self.room)
self.room = self.get_int(self.room)
return True
def start_pool_trading(self):
self.trade_type = GSCTradingStrings.pool_trade_str
return True
def start_gen1_trading(self):
self.gen = 1
return True
def start_gen2_trading(self):
self.gen = 2
return True
def start_gen3_trading(self):
self.gen = 3
return True
def start_multiboot_gen3(self):
self.gen = 3
self.multiboot = True
return True
def handle_options(self):
ret_val = False
while not ret_val:
GSCTradingStrings.options_menu_print(self)
GSCTradingStrings.choice_print()
ret_val = self.options_menu_handlers.get(input(), self.options_menu_handlers["0"])()
return False
def handle_exit_option(self):
return True
def handle_server_option(self):
GSCTradingStrings.change_server_print()
self.server[0] = input()
return False
def handle_port_option(self):
GSCTradingStrings.change_port_print()
self.server[1] = self.get_int(self.server[1])
return False
def handle_emulator_host_option(self):
GSCTradingStrings.change_emu_server_print()
self.emulator[0] = input()
return False
def handle_emulator_port_option(self):
GSCTradingStrings.change_emu_port_print()
self.emulator[1] = self.get_int(self.emulator[1])
return False
def handle_buffered_option(self):
self.buffered = not self.buffered
return False
def handle_max_level_option(self):
GSCTradingStrings.change_max_level_print(self.max_level)
self.max_level = self.get_int(self.max_level)
if self.max_level < 2:
self.max_level = 2
if self.max_level > 100:
self.max_level = 100
return False
def handle_eggs_option(self):
self.egg = not self.egg
return False
def handle_japanese_option(self):
self.japanese = not self.japanese
return False
def handle_sanity_option(self):
self.do_sanity_checks = not self.do_sanity_checks
return False
def handle_kill_on_byte_drop_option(self):
self.kill_on_byte_drops = not self.kill_on_byte_drops
return False
def handle_verbose_option(self):
self.verbose = not self.verbose
return False
def handle_args(self, is_emulator):
# Parse program's arguments
parser = ArgumentParser()
parser.add_argument("-g", "--generation", dest="gen_number", default = None,
help="generation (1 = RBY/Timecapsule, 2 = GSC, 3 = RSE Special)", type=int)
parser.add_argument("-t", "--trade_type", dest="trade_type", default = None,
help="trade type (" + GSCTradingStrings.two_player_trade_str + " = 2-Player Trade, " + GSCTradingStrings.pool_trade_str + " = Pool Trade)")
parser.add_argument("-r", "--room", dest="room", default = None,
help="2-Player Trade's room", type=int)
parser.add_argument("-b", "--buffered",
action="store_true", dest="buffered", default=False,
help="default to buffered trading instead of synchronous")
parser.add_argument("-j", "--japanese",
action="store_true", dest="japanese", default=False,
help="use it if your game is Japanese")
parser.add_argument("-dsc", "--disable_sanity_checks",
action="store_false", dest="do_sanity_checks", default=True,
help="don't perform sanity checks for data sent to the device")
parser.add_argument("-dkb", "--disable_kill_drops",
action="store_false", dest="kill_on_byte_drops", default=True,
help="don't kill the process for dropped bytes")
parser.add_argument("-mlp", "--max_level_pool", dest="max_level", default = self.default_max_level,
help="Pool's max level", type=int)
parser.add_argument("-egp", "--eggify_pool",
action="store_true", dest="egg", default=False,
help="turns Pool Pokémon into ready-to-hatch eggs")
parser.add_argument("-q", "--quiet",
action="store_false", dest="verbose", default=True,
help="don't print status messages to stdout")
parser.add_argument("-sh", "--server_host", dest="server_host", default = self.default_server[0],
help="server's host")
parser.add_argument("-sp", "--server_port", dest="server_port", default = self.default_server[1],
help="server's port", type=int)
if is_emulator:
parser.add_argument("-eh", "--emulator_host", dest="emulator_host", default = self.default_emulator[0],
help="emulator's local host")
parser.add_argument("-ep", "--emulator_port", dest="emulator_port", default = self.default_emulator[1],
help="emulator's local port", type=int)
return parser.parse_args()
class GSCBufferedNegotiator(threading.Thread):
"""
Class used to handle the negotiation when the two clients'
buffered variable doesn't match up
"""
def __init__(self, menu, comms, buffered, sleep_func):
threading.Thread.__init__(self)
self.daemon=True
self.comms = comms
self.menu = menu
self.final_buffered = None
self.buffered = buffered
self.sleep_func = sleep_func
def force_receive(self, fun):
received = None
while received is None:
self.sleep_func()
received = fun()
return received
def choose_if_buffered(self):
buffered = self.buffered
self.comms.send_buffered_data(buffered)
other_buffered = self.force_receive(self.comms.get_buffered_data)
if buffered == other_buffered:
return buffered
change_buffered = None
while change_buffered is None:
own_val = self.comms.send_negotiation_data()
other_val = self.force_receive(self.comms.get_negotiation_data)
if other_val > own_val:
change_buffered = True
elif other_val < own_val:
change_buffered = False
while buffered != other_buffered:
if not change_buffered:
GSCTradingStrings.buffered_other_negotiation_print(buffered)
other_buffered = self.force_receive(self.comms.get_buffered_data)
else:
buffered = self.menu.handle_buffered_change_offer(buffered)
self.comms.send_buffered_data(buffered)
change_buffered = not change_buffered
return buffered
def get_chosen_buffered(self):
return self.final_buffered
def run(self):
self.final_buffered = self.choose_if_buffered()
if self.menu.verbose:
GSCTradingStrings.chosen_buffered_print(self.final_buffered)