fix(baal_xp): restore the 09-08 join hardening lost in the 09-09 branch switch
The stash taken before switching to main (stash@{1}) carried a re-verified
_try_join - row click retried up to 3x with a re-OCR of the row when the list
scrolled, JOIN GAME press retried up to 3x when the lobby swallowed it, and a
join_game() default of 900s - but the switch was stashed, never re-applied, and
the branch tip kept the single-click version from 09-02. A single missed click
(or a list that scrolled between scan and click) then failed the whole join,
which is exactly the 'no matching game found' the cycle kept hitting.
Also add the finally: start_detecting_window() the 09-08 version had dropped:
join_game() stops the window-detection thread at the top, and every return
path (success, failure, exception) has to re-arm it or screen tracking stays
dead for the rest of the cycle.
This commit is contained in:
+51
-16
@@ -408,35 +408,67 @@ def _try_join(cand: dict) -> bool | None:
|
||||
True = joined
|
||||
False = that game was full or gone, try the next candidate
|
||||
None = we are no longer in a lobby state where retrying makes sense
|
||||
"""
|
||||
|
||||
Every click is re-verified against the screen: a single click missed by a
|
||||
frame (window focus, a covered button, a list that scrolled) used to end
|
||||
the whole join attempt, and the caller then reported "no matching game"
|
||||
after a few seconds of a perfectly good lobby. Re-click the row when the
|
||||
JOIN GAME button does not appear, re-OCR the row when the name no longer
|
||||
matches (the list scrolled), and retry the JOIN press when the first one
|
||||
is swallowed. Only give up on a candidate after the retries are spent."""
|
||||
Logger.info(f"game_browser: joining '{cand['name']}' "
|
||||
f"({cand['players'] if cand['players'] is not None else '?'} players, row {cand['row']})")
|
||||
_click((LIST_X + LIST_W // 2, cand["y_center"]), "game row")
|
||||
wait(0.3, 0.5)
|
||||
if not is_visible(ScreenObjects.LobbyJoinBtn):
|
||||
# Usually a leftover error dialog sitting on top of the lobby. Clear it
|
||||
# and let the caller try the next candidate rather than aborting.
|
||||
for click_attempt in range(3):
|
||||
_click((LIST_X + LIST_W // 2, cand["y_center"]), "game row")
|
||||
wait(0.3, 0.5)
|
||||
if is_visible(ScreenObjects.LobbyJoinBtn):
|
||||
break
|
||||
if is_visible(ScreenObjects.ServerError):
|
||||
# Usually a leftover error dialog sitting on top of the lobby. Clear
|
||||
# it and let the caller try the next candidate rather than aborting.
|
||||
Logger.warning("game_browser: error dialog over the lobby - dismissing")
|
||||
error_screens.handle_error()
|
||||
return False
|
||||
if not _in_lobby():
|
||||
Logger.error("game_browser: left the lobby while selecting a row")
|
||||
return None
|
||||
# The list may have scrolled between the scan and now: re-read the row
|
||||
# we are actually pointing at before burning another click on it.
|
||||
img = grab()
|
||||
actual = _ocr_roi(img, [LIST_X, cand["y_center"] - 9, LIST_W, ROW_H])
|
||||
if actual and actual != cand["name"]:
|
||||
Logger.debug(f"game_browser: row now reads '{actual}' (was '{cand['name']}') - list moved, re-scanning")
|
||||
return False
|
||||
Logger.debug(f"game_browser: JOIN GAME button not up after row click {click_attempt + 1}/3 - re-clicking")
|
||||
wait(0.5, 0.8)
|
||||
|
||||
if not is_visible(ScreenObjects.LobbyJoinBtn):
|
||||
if _in_lobby():
|
||||
Logger.warning("game_browser: JOIN GAME button not visible but still in the lobby - trying the next")
|
||||
return False
|
||||
Logger.error("game_browser: JOIN GAME button not visible after selecting a row")
|
||||
return None
|
||||
_click(JOIN_BTN, "JOIN GAME")
|
||||
if _wait_for_join():
|
||||
return True
|
||||
if is_visible(ScreenObjects.LobbyJoinBtn):
|
||||
Logger.info(f"game_browser: '{cand['name']}' was full or gone - trying the next candidate")
|
||||
# The lobby swallows input for a moment after a bounced join.
|
||||
wait(1.0, 1.5)
|
||||
return False
|
||||
return None
|
||||
|
||||
# The first JOIN press is the one that gets swallowed (lobby input lag right
|
||||
# after a row click). Retry it before calling the candidate a failure.
|
||||
for press in range(3):
|
||||
_click(JOIN_BTN, "JOIN GAME")
|
||||
if _wait_for_join():
|
||||
return True
|
||||
if is_visible(ScreenObjects.LobbyJoinBtn):
|
||||
Logger.info(f"game_browser: '{cand['name']}' was full or gone - trying the next candidate")
|
||||
# The lobby swallows input for a moment after a bounced join.
|
||||
wait(1.0, 1.5)
|
||||
return False
|
||||
if not _in_lobby():
|
||||
Logger.error("game_browser: no longer in the lobby after a JOIN GAME press")
|
||||
return None
|
||||
Logger.debug("game_browser: JOIN GAME press produced no state change - retrying")
|
||||
wait(0.5, 0.8)
|
||||
return False
|
||||
|
||||
|
||||
def join_game(name_filter: str = "", max_wait_s: float = 60.0,
|
||||
def join_game(name_filter: str = "", max_wait_s: float = 900.0,
|
||||
difficulty: str = "normal", min_players: int = 3,
|
||||
max_players: int = 7) -> bool:
|
||||
"""
|
||||
@@ -524,6 +556,9 @@ def join_game(name_filter: str = "", max_wait_s: float = 60.0,
|
||||
Logger.error(f"game_browser: no matching game found within {max_wait_s}s")
|
||||
return False
|
||||
finally:
|
||||
# Re-arm the window-detection thread on every exit path (success,
|
||||
# failure, or an exception mid-join) - leaving it stopped strands the
|
||||
# bot's screen tracking for the rest of the cycle.
|
||||
start_detecting_window()
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user