Skip to content

Commit

Permalink
fix: majsoul url not saved
Browse files Browse the repository at this point in the history
feat: drag to dahai
feat: upstream proxy
  • Loading branch information
latorc committed Apr 12, 2024
1 parent 7bf165b commit ef5be0a
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 62 deletions.
37 changes: 23 additions & 14 deletions bot_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def __init__(self, setting:Settings) -> None:

self.liqi_parser:liqi.LiqiProto = None
self.mitm_port = self.st.mitm_port
self.mitm_server:mitm.MitmController = mitm.MitmController(self.mitm_port) # no domain restrictions for now
self.mitm_server:mitm.MitmController = mitm.MitmController() # no domain restrictions for now
self.browser = GameBrowser(self.st.browser_width, self.st.browser_height)
self.automation = Automation(self.browser, self.st)
self.bot:Bot = None
Expand All @@ -62,6 +62,7 @@ def __init__(self, setting:Settings) -> None:
# self._overlay_reaction:dict = None # update overlay guidance if new reaction is different
# self._overlay_guide_last_update:float = 0 # last update time

self.bot_need_update:bool = True # set this True to update bot in main thread
self.main_thread_exception:Exception = None
""" Exception that had stopped the main thread"""
self.game_exception:Exception = None # game run time error (but does not break main thread)
Expand Down Expand Up @@ -121,6 +122,12 @@ def start_browser(self):
proxy = r'http://localhost:' + str(self.mitm_port)
self.browser.start(ms_url, proxy, self.st.browser_width, self.st.browser_height)

def restart_mitm(self):
""" restart mitm proxy server"""
LOGGER.info("Restarting mitm proxy server, port=%d, upstream_proxy=%s", self.st.mitm_port, self.st.upstream_proxy)
self.mitm_server.stop()
self.mitm_server.start(self.st.mitm_port, self.st.upstream_proxy)

def get_pending_reaction(self) -> dict:
""" returns the pending mjai output reaction (which hasn't been acted on)"""
if self.game_state:
Expand Down Expand Up @@ -175,7 +182,7 @@ def disable_autojoin(self):
if name in (JOIN_GAME, END_GAME):
self.automation.stop_previous()

def create_bot(self):
def _create_bot(self):
""" create Bot object based on settings"""
try:
self.bot = get_bot(self.st)
Expand All @@ -200,22 +207,14 @@ def is_bot_calculating(self):
def _run(self):
""" Keep running the main loop (blocking)"""
try:
LOGGER.info("Starting MITM proxy server")
self.mitm_server.start()
LOGGER.info("Starting mitm proxy server, port=%d, upstream_proxy=%s", self.st.mitm_port, self.st.upstream_proxy)
self.mitm_server.start(self.st.mitm_port,self.st.upstream_proxy)
LOGGER.info("Installing MITM certificate")
if self.mitm_server.install_mitm_cert():
LOGGER.info("MITM certificate installed")
else:
LOGGER.warning("MITM certificate installation failed (No Admin rights?)")

# Attempt to create bot. wait for the bot (gui may re-create)
self.create_bot()
while True:
if self.bot is not None:
break
else:
time.sleep(0.5)


self.liqi_parser = liqi.LiqiProto()
if self.st.auto_launch_browser:
self.start_browser()
Expand All @@ -224,6 +223,7 @@ def _run(self):
while self._stop_event.is_set() is False:
# keep processing majsoul game messages forwarded from mitm server
self.fps_counter.frame()
self._udpate_bot()
try:
msg = self.mitm_server.get_message()
self._process_msg(msg)
Expand All @@ -250,13 +250,22 @@ def _run(self):
except Exception as e:
self.main_thread_exception = e
LOGGER.error("Bot Manager Thread Exception: %s", e, exc_info=True)

def _udpate_bot(self):
""" Wait for bot to be created"""
if self.bot_need_update and self.is_in_game() is False:
self._create_bot()
self.bot_need_update = False

def _every_loop_post_proc_msg(self):
# things to do in every loop

# check mitm
if self.mitm_server.is_running() is False:
raise utils.MITMException("MITM server stopped")
self.game_exception = utils.MITMException("MITM server stopped")
else: # clear exception
if isinstance(self.game_exception, utils.MITMException):
self.game_exception = None

# check overlay
if self.browser and self.browser.is_page_normal():
Expand Down
4 changes: 4 additions & 0 deletions common/lan_str.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class LanStr:
SETTINGS_TIPS = "A restart is needed to apply some settings"
AUTO_LAUNCH_BROWSER = "Auto Launch Browser"
MITM_PORT = "MITM Server Port"
UPSTREAM_PROXY = "Upstream Proxy"
BROWSER_WIDTH = "Web Client Width"
BROWSER_HEIGHT = "Web Client Height"
CLIENT_SIZE = "Web Client Size"
Expand All @@ -71,6 +72,7 @@ class LanStr:
AUTO_PLAY_SETTINGS = "Autoplay Settings"
AUTO_IDLE_MOVE = "Idle Mouse Move"
RANDOM_CHOICE = "Randomize AI Choice"
DRAG_DAHAI = "Mouse drag dahai"
RANDOM_DELAY_RANGE = "Base Delay Range (sec)"
AUTO_JOIN_GAME = "Auto Join"
GAME_LEVELS = ["Bronze", "Silver", "Gold", "Jade", "Throne"]
Expand Down Expand Up @@ -190,6 +192,7 @@ class LanStrZHS(LanStr):
CANCEL = "取消"
SETTINGS_TIPS = "部分设置项重启后生效"
MITM_PORT = "MITM 服务端口"
UPSTREAM_PROXY = "上游代理"
BROWSER_WIDTH = "网页客户端宽度"
BROWSER_HEIGHT = "网页客户端高度"
CLIENT_SIZE = "网页客户端大小"
Expand All @@ -209,6 +212,7 @@ class LanStrZHS(LanStr):
AUTO_PLAY_SETTINGS = "自动打牌设置"
AUTO_IDLE_MOVE = "鼠标空闲移动"
RANDOM_CHOICE = "AI 选项随机化(去重)"
DRAG_DAHAI = "鼠标拖拽出牌"
AUTO_JOIN_GAME = "自动加入"
RANDOM_DELAY_RANGE = "基础延迟随机范围(秒)"
GAME_LEVELS = ["铜之间", "银之间", "金之间", "玉之间", "王座之间"]
Expand Down
6 changes: 4 additions & 2 deletions common/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@ def __init__(self, json_file:str=DEFAULT_SETTING_FILE) -> None:
self._settings_dict:dict = self.load_json()
# read settings or set default values
# variable names must match keys in json, for saving later
("update_url", "https://update.mjcopilot.com", self.valid_url)

# UI settings
self.update_url:str = self._get_value("update_url", "https://update.mjcopilot.com", self.valid_url) # not shown
self.auto_launch_browser:bool = self._get_value("auto_launch_browser", False, self.valid_bool)
self.browser_width:int = self._get_value("browser_width", 1280)
self.browser_height:int = self._get_value("browser_height", 720)
self.ms_url:str = self._get_value("ms_url", "https://game.maj-soul.com/1/")
self.mitm_port:int = self._get_value("mitm_port", 10999)
self.language:str = self._get_value("language", list(LAN_OPTIONS.keys())[-1], self.valid_language)
self.upstream_proxy:str = self._get_value("upstream_proxy","") # mitm upstream proxy server e.g. http://ip:port
self.language:str = self._get_value("language", list(LAN_OPTIONS.keys())[-1], self.valid_language) # language code
self.enable_overlay:bool = self._get_value("enable_overlay", True, self.valid_bool) # not shown

# AI Model settings
Expand All @@ -43,6 +44,7 @@ def __init__(self, json_file:str=DEFAULT_SETTING_FILE) -> None:
self.enable_automation:bool = self._get_value("enable_automation", False, self.valid_bool)
self.auto_idle_move:bool = self._get_value("auto_idle_move", False, self.valid_bool)
self.auto_random_move:bool = self._get_value("auto_random_move", False, self.valid_bool)
self.auto_dahai_drag:bool = self._get_value("auto_dahai_drag", True, self.valid_bool)
self.ai_randomize_choice:int = self._get_value("ai_randomize_choice", 1, lambda x: 0 <= x <= 5)
self.delay_random_lower:float = self._get_value("delay_random_lower", 1, lambda x: 0 <= x )
self.delay_random_upper:float = self._get_value(
Expand Down
18 changes: 9 additions & 9 deletions game/automation.py
Original file line number Diff line number Diff line change
Expand Up @@ -518,8 +518,8 @@ def steps_action_dahai(self, mjai_action:dict, gi:GameInfo) -> list[ActionStep]:
idx = gi.my_tehai.index(dahai)
steps = self.steps_randomized_move(Positions.TEHAI_X[idx], Positions.TEHAI_Y)

# click / drag 50/50
if self.st.auto_random_move and random.random()< 0.5:
# drag or click to dahai
if self.st.auto_dahai_drag:
steps += self.steps_mouse_drag_to_center()
else:
steps += self.steps_mouse_click()
Expand Down Expand Up @@ -649,11 +649,11 @@ def steps_randomized_move(self, x:float, y:float) -> list[ActionStep]:
rx = max(0, min(16, rx))
ry = y + 9*random.uniform(-0.5, 0.5)
ry = max(0, min(9, ry))
steps.append(ActionStepMove(rx*self.scaler, ry*self.scaler, random.randint(3,6)))
steps.append(ActionStepMove(rx*self.scaler, ry*self.scaler, random.randint(2, 5)))
steps.append(ActionStepDelay(random.uniform(0.05, 0.11)))
# then move to target
tx, ty = x*self.scaler, y*self.scaler
steps.append(ActionStepMove(tx, ty, random.randint(3,6)))
steps.append(ActionStepMove(tx, ty, random.randint(2, 5)))
return steps

def steps_randomized_move_click(self, x:float, y:float) -> list[ActionStep]:
Expand All @@ -669,17 +669,17 @@ def steps_randomized_move_click(self, x:float, y:float) -> list[ActionStep]:
def steps_mouse_click(self) -> list[ActionStep]:
""" generate list of steps for a simple mouse click"""
steps = []
steps.append(ActionStepDelay(random.uniform(0.3, 0.5)))
steps.append(ActionStepDelay(random.uniform(0.2, 0.4)))
steps.append(ActionStepClick(random.randint(60, 100)))
return steps

def steps_mouse_drag_to_center(self) -> list[ActionStep]:
""" steps for dragging to center (e.g. for dahai)"""
steps = []
steps.append(ActionStepDelay(random.uniform(0.2, 0.4)))
steps.append(ActionStepDelay(random.uniform(0.1, 0.3)))
steps.append(ActionStepMouseDown())
steps += self.steps_move_to_center(False)
steps.append(ActionStepDelay(random.uniform(0.2, 0.4)))
steps.append(ActionStepDelay(random.uniform(0.1, 0.3)))
steps.append(ActionStepMouseUp())
return steps

Expand All @@ -692,7 +692,7 @@ def steps_move_to_center(self, ignore_step_change:bool=False) -> list[ActionStep
steps.append(delay_step)

xmid, ymid = 16 * random.uniform(0.25, 0.75), 9 * random.uniform(0.25, 0.75)
move_step = ActionStepMove(xmid*self.scaler, ymid*self.scaler, random.randint(3,6))
move_step = ActionStepMove(xmid*self.scaler, ymid*self.scaler, random.randint(2, 5))
move_step.ignore_step_change = ignore_step_change
steps.append(move_step)
return steps
Expand All @@ -703,7 +703,7 @@ def steps_random_wheels(self, total_dx:float, total_dy:float) -> list[ActionStep
total_dx, total_dy: total distance to wheel move"""
# break the wheel action into several steps
steps = []
times = random.randint(3,6)
times = random.randint(2, 5)
for _i in range(times):
dx = total_dx / times
dy = total_dy / times
Expand Down
15 changes: 9 additions & 6 deletions gui/main_gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,15 @@ def _on_btn_settings_clicked(self):

if settings_window.gui_need_reload: # reload UI if needed
self.reload_gui()
if settings_window.model_updated: # re-create bot if needed
if not self.bot_manager.is_in_game():
self.bot_manager.create_bot()
else:
if not self.bot_manager.is_bot_created():
self.bot_manager.create_bot()
self.bot_manager.bot_need_update = True # tell bot manager to update bot when possible
if settings_window.mitm_updated:
self.bot_manager.restart_mitm()
# if settings_window.model_updated: # re-create bot if needed
# if not self.bot_manager.is_in_game():

# else:
# if not self.bot_manager.is_bot_created():
# self.bot_manager.create_bot()

def _on_btn_help_clicked(self):
# open help dialog
Expand Down
Loading

0 comments on commit ef5be0a

Please sign in to comment.