mirror of
https://github.com/LmeSzinc/StarRailCopilot.git
synced 2024-11-16 06:25:24 +00:00
commit
41bc376943
@ -258,6 +258,7 @@ class AzurLaneAutoScript:
|
|||||||
task = self.get_next_task()
|
task = self.get_next_task()
|
||||||
# Init device and change server
|
# Init device and change server
|
||||||
_ = self.device
|
_ = self.device
|
||||||
|
self.device.config = self.config
|
||||||
# Skip first restart
|
# Skip first restart
|
||||||
if self.is_first_task and task == 'Restart':
|
if self.is_first_task and task == 'Restart':
|
||||||
logger.info('Skip task `Restart` at scheduler start')
|
logger.info('Skip task `Restart` at scheduler start')
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
|
||||||
|
from module.base.timer import Timer
|
||||||
from module.device.method.adb import Adb
|
from module.device.method.adb import Adb
|
||||||
from module.device.method.uiautomator_2 import Uiautomator2
|
from module.device.method.uiautomator_2 import Uiautomator2
|
||||||
from module.device.method.utils import HierarchyButton
|
from module.device.method.utils import HierarchyButton
|
||||||
from module.device.method.wsa import WSA
|
from module.device.method.wsa import WSA
|
||||||
|
from module.exception import ScriptError
|
||||||
from module.logger import logger
|
from module.logger import logger
|
||||||
|
|
||||||
|
|
||||||
@ -12,6 +14,7 @@ class AppControl(Adb, WSA, Uiautomator2):
|
|||||||
# Use ADB for all
|
# Use ADB for all
|
||||||
# See https://github.com/openatx/uiautomator2/issues/565
|
# See https://github.com/openatx/uiautomator2/issues/565
|
||||||
_app_u2_family = []
|
_app_u2_family = []
|
||||||
|
_hierarchy_interval = Timer(0.1)
|
||||||
|
|
||||||
def app_is_running(self) -> bool:
|
def app_is_running(self) -> bool:
|
||||||
method = self.config.Emulator_ControlMethod
|
method = self.config.Emulator_ControlMethod
|
||||||
@ -44,11 +47,28 @@ class AppControl(Adb, WSA, Uiautomator2):
|
|||||||
else:
|
else:
|
||||||
self.app_stop_adb()
|
self.app_stop_adb()
|
||||||
|
|
||||||
|
def hierarchy_timer_set(self, interval=None):
|
||||||
|
if interval is None:
|
||||||
|
interval = 0.1
|
||||||
|
elif isinstance(interval, (int, float)):
|
||||||
|
# No limitation for manual set in code
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
logger.warning(f'Unknown hierarchy interval: {interval}')
|
||||||
|
raise ScriptError(f'Unknown hierarchy interval: {interval}')
|
||||||
|
|
||||||
|
if interval != self._hierarchy_interval.limit:
|
||||||
|
logger.info(f'Hierarchy interval set to {interval}s')
|
||||||
|
self._hierarchy_interval.limit = interval
|
||||||
|
|
||||||
def dump_hierarchy(self) -> etree._Element:
|
def dump_hierarchy(self) -> etree._Element:
|
||||||
"""
|
"""
|
||||||
Returns:
|
Returns:
|
||||||
etree._Element: Select elements with `self.hierarchy.xpath('//*[@text="Hermit"]')` for example.
|
etree._Element: Select elements with `self.hierarchy.xpath('//*[@text="Hermit"]')` for example.
|
||||||
"""
|
"""
|
||||||
|
self._hierarchy_interval.wait()
|
||||||
|
self._hierarchy_interval.reset()
|
||||||
|
|
||||||
# method = self.config.Emulator_ControlMethod
|
# method = self.config.Emulator_ControlMethod
|
||||||
# if method in AppControl._app_u2_family:
|
# if method in AppControl._app_u2_family:
|
||||||
# self.hierarchy = self.dump_hierarchy_uiautomator2()
|
# self.hierarchy = self.dump_hierarchy_uiautomator2()
|
||||||
|
@ -1023,7 +1023,14 @@ class Connection(ConnectionAttr):
|
|||||||
self.package = packages[0]
|
self.package = packages[0]
|
||||||
# Set config
|
# Set config
|
||||||
if set_config:
|
if set_config:
|
||||||
self.config.Emulator_PackageName = server_.to_server(self.package)
|
with self.config.multi_set():
|
||||||
|
self.config.Emulator_PackageName = server_.to_server(self.package)
|
||||||
|
if self.package in server_.VALID_CLOUD_PACKAGE:
|
||||||
|
if self.config.Emulator_GameClient != 'cloud_android':
|
||||||
|
self.config.Emulator_GameClient = 'cloud_android'
|
||||||
|
else:
|
||||||
|
if self.config.Emulator_GameClient != 'android':
|
||||||
|
self.config.Emulator_GameClient = 'android'
|
||||||
# Set server
|
# Set server
|
||||||
# logger.info('Server changed, release resources')
|
# logger.info('Server changed, release resources')
|
||||||
# set_server(self.package)
|
# set_server(self.package)
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import collections
|
import collections
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
|
from lxml import etree
|
||||||
|
|
||||||
# Patch pkg_resources before importing adbutils and uiautomator2
|
# Patch pkg_resources before importing adbutils and uiautomator2
|
||||||
from module.device.pkg_resources import get_distribution
|
from module.device.pkg_resources import get_distribution
|
||||||
|
|
||||||
@ -157,6 +159,10 @@ class Device(Screenshot, Control, AppControl):
|
|||||||
|
|
||||||
return self.image
|
return self.image
|
||||||
|
|
||||||
|
def dump_hierarchy(self) -> etree._Element:
|
||||||
|
self.stuck_record_check()
|
||||||
|
return super().dump_hierarchy()
|
||||||
|
|
||||||
def release_during_wait(self):
|
def release_during_wait(self):
|
||||||
# Scrcpy server is still sending video stream,
|
# Scrcpy server is still sending video stream,
|
||||||
# stop it during wait
|
# stop it during wait
|
||||||
|
@ -98,8 +98,8 @@ class PlatformWindows(PlatformBase, EmulatorManager):
|
|||||||
# Nox.exe -clone:Nox_1
|
# Nox.exe -clone:Nox_1
|
||||||
self.execute(f'"{exe}" -clone:{instance.name}')
|
self.execute(f'"{exe}" -clone:{instance.name}')
|
||||||
elif instance == Emulator.BlueStacks5:
|
elif instance == Emulator.BlueStacks5:
|
||||||
# HD-Player.exe -instance Pie64
|
# HD-Player.exe --instance Pie64
|
||||||
self.execute(f'"{exe}" -instance {instance.name}')
|
self.execute(f'"{exe}" --instance {instance.name}')
|
||||||
elif instance == Emulator.BlueStacks4:
|
elif instance == Emulator.BlueStacks4:
|
||||||
# BlueStacks\Client\Bluestacks.exe -vmname Android_1
|
# BlueStacks\Client\Bluestacks.exe -vmname Android_1
|
||||||
self.execute(f'"{exe}" -vmname {instance.name}')
|
self.execute(f'"{exe}" -vmname {instance.name}')
|
||||||
|
@ -61,7 +61,9 @@ class UI(MainPage):
|
|||||||
def cloud_login():
|
def cloud_login():
|
||||||
if self.config.is_cloud_game:
|
if self.config.is_cloud_game:
|
||||||
from tasks.login.login import Login
|
from tasks.login.login import Login
|
||||||
Login(config=self.config, device=self.device).cloud_login()
|
login = Login(config=self.config, device=self.device)
|
||||||
|
self.device.dump_hierarchy()
|
||||||
|
login.cloud_try_enter_game()
|
||||||
|
|
||||||
timeout = Timer(10, count=20).start()
|
timeout = Timer(10, count=20).start()
|
||||||
while 1:
|
while 1:
|
||||||
|
@ -133,6 +133,9 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, CombatSuppo
|
|||||||
return False
|
return False
|
||||||
if not self.handle_combat_prepare():
|
if not self.handle_combat_prepare():
|
||||||
return False
|
return False
|
||||||
|
if self.is_doing_planner and self.combat_wave_cost == 0:
|
||||||
|
logger.info('Free combat gets nothing cannot meet planner needs')
|
||||||
|
return False
|
||||||
self.device.click(COMBAT_PREPARE)
|
self.device.click(COMBAT_PREPARE)
|
||||||
self.interval_reset(COMBAT_PREPARE)
|
self.interval_reset(COMBAT_PREPARE)
|
||||||
trial += 1
|
trial += 1
|
||||||
|
@ -72,7 +72,7 @@ class XPath:
|
|||||||
悬浮窗及侧边栏元素
|
悬浮窗及侧边栏元素
|
||||||
"""
|
"""
|
||||||
# 悬浮窗
|
# 悬浮窗
|
||||||
FLOAT_WINDOW = '//*[@class="android.widget.ImageView"]'
|
FLOAT_WINDOW = '//*[@package="com.miHoYo.cloudgames.hkrpg" and @class="android.widget.ImageView"]'
|
||||||
# 退出按钮,返回登录页面
|
# 退出按钮,返回登录页面
|
||||||
FLOAT_EXIT = '//*[@resource-id="com.miHoYo.cloudgames.hkrpg:id/iv_exit"]'
|
FLOAT_EXIT = '//*[@resource-id="com.miHoYo.cloudgames.hkrpg:id/iv_exit"]'
|
||||||
# 弹出侧边栏的 节点信息
|
# 弹出侧边栏的 节点信息
|
||||||
@ -342,13 +342,16 @@ class LoginAndroidCloud(ModuleBase):
|
|||||||
logger.attr('Net state', None)
|
logger.attr('Net state', None)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def cloud_ensure_ingame(self):
|
def cloud_enter_game(self):
|
||||||
"""
|
"""
|
||||||
|
Note that cloud game needs to be started before calling,
|
||||||
|
hierarchy needs to be updated before calling
|
||||||
|
|
||||||
Pages:
|
Pages:
|
||||||
in: Any
|
in: Any page in cloud game
|
||||||
out: page_main
|
out: page_main
|
||||||
"""
|
"""
|
||||||
logger.hr('Cloud ensure ingame', level=1)
|
logger.hr('Cloud enter game', level=1)
|
||||||
|
|
||||||
with self.config.multi_set():
|
with self.config.multi_set():
|
||||||
if self.config.Emulator_GameClient != 'cloud_android':
|
if self.config.Emulator_GameClient != 'cloud_android':
|
||||||
@ -358,48 +361,27 @@ class LoginAndroidCloud(ModuleBase):
|
|||||||
if self.config.Optimization_WhenTaskQueueEmpty != 'close_game':
|
if self.config.Optimization_WhenTaskQueueEmpty != 'close_game':
|
||||||
self.config.Optimization_WhenTaskQueueEmpty = 'close_game'
|
self.config.Optimization_WhenTaskQueueEmpty = 'close_game'
|
||||||
|
|
||||||
for _ in range(3):
|
if self.appear(XPath.START_GAME):
|
||||||
if self.device.app_is_running():
|
logger.info('Cloud game is in main page')
|
||||||
logger.info('Cloud game is already running')
|
self._cloud_get_remain()
|
||||||
self.device.dump_hierarchy()
|
self._cloud_enter()
|
||||||
|
return True
|
||||||
if self.appear(XPath.START_GAME):
|
elif self.appear(XPath.FLOAT_WINDOW):
|
||||||
logger.info('Cloud game is in main page')
|
logger.info('Cloud game is in game')
|
||||||
self._cloud_get_remain()
|
return True
|
||||||
self._cloud_enter()
|
elif self.appear(XPath.FLOAT_DELAY):
|
||||||
return True
|
logger.info('Cloud game is in game with float window expanded')
|
||||||
elif self.appear(XPath.FLOAT_WINDOW):
|
self._cloud_setting_exit()
|
||||||
logger.info('Cloud game is in game')
|
return True
|
||||||
return True
|
elif self.appear(XPath.POPUP_CONFIRM):
|
||||||
elif self.appear(XPath.FLOAT_DELAY):
|
logger.info('Cloud game have a popup')
|
||||||
logger.info('Cloud game is in game with float window expanded')
|
self._cloud_enter()
|
||||||
self._cloud_setting_exit()
|
return True
|
||||||
return True
|
else:
|
||||||
elif self.appear(XPath.POPUP_CONFIRM):
|
self._cloud_start()
|
||||||
logger.info('Cloud game have a popup')
|
self._cloud_get_remain()
|
||||||
self._cloud_enter()
|
self._cloud_enter()
|
||||||
return True
|
return True
|
||||||
else:
|
|
||||||
try:
|
|
||||||
self._cloud_start()
|
|
||||||
except GameNotRunningError:
|
|
||||||
continue
|
|
||||||
self._cloud_get_remain()
|
|
||||||
self._cloud_enter()
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
logger.info('Cloud game is not running')
|
|
||||||
self.device.app_start()
|
|
||||||
try:
|
|
||||||
self._cloud_start()
|
|
||||||
except GameNotRunningError:
|
|
||||||
continue
|
|
||||||
self._cloud_get_remain()
|
|
||||||
self._cloud_enter()
|
|
||||||
return True
|
|
||||||
|
|
||||||
logger.error('Failed to enter cloud game after 3 trials')
|
|
||||||
return False
|
|
||||||
|
|
||||||
def is_in_cloud_page(self):
|
def is_in_cloud_page(self):
|
||||||
if self.appear(XPath.START_GAME):
|
if self.appear(XPath.START_GAME):
|
||||||
@ -418,15 +400,16 @@ class LoginAndroidCloud(ModuleBase):
|
|||||||
logger.info('Not in cloud page')
|
logger.info('Not in cloud page')
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def cloud_login(self):
|
def cloud_try_enter_game(self):
|
||||||
"""
|
"""
|
||||||
|
Note that hierarchy needs to be updated before calling
|
||||||
|
|
||||||
Pages:
|
Pages:
|
||||||
in: Any page in cloud game
|
in: Any page in cloud game
|
||||||
out: page_main
|
out: page_main
|
||||||
"""
|
"""
|
||||||
self.device.dump_hierarchy()
|
|
||||||
if self.is_in_cloud_page():
|
if self.is_in_cloud_page():
|
||||||
self.cloud_ensure_ingame()
|
self.cloud_enter_game()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
@ -522,5 +505,7 @@ class LoginAndroidCloud(ModuleBase):
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
self = LoginAndroidCloud('src')
|
self = LoginAndroidCloud('src')
|
||||||
self.cloud_login()
|
self.device.app_start()
|
||||||
|
self.device.dump_hierarchy()
|
||||||
|
self.cloud_enter_game()
|
||||||
self.cloud_keep_alive()
|
self.cloud_keep_alive()
|
||||||
|
@ -90,18 +90,23 @@ class Login(UI, LoginAndroidCloud):
|
|||||||
|
|
||||||
def app_start(self):
|
def app_start(self):
|
||||||
logger.hr('App start')
|
logger.hr('App start')
|
||||||
|
self.device.app_start()
|
||||||
|
|
||||||
if self.config.is_cloud_game:
|
if self.config.is_cloud_game:
|
||||||
self.cloud_ensure_ingame()
|
self.device.dump_hierarchy()
|
||||||
|
self.cloud_enter_game()
|
||||||
else:
|
else:
|
||||||
self.device.app_start()
|
|
||||||
self.handle_app_login()
|
self.handle_app_login()
|
||||||
|
|
||||||
def app_restart(self):
|
def app_restart(self):
|
||||||
logger.hr('App restart')
|
logger.hr('App restart')
|
||||||
self.device.app_stop()
|
self.device.app_stop()
|
||||||
|
self.device.app_start()
|
||||||
|
|
||||||
if self.config.is_cloud_game:
|
if self.config.is_cloud_game:
|
||||||
self.cloud_ensure_ingame()
|
self.device.dump_hierarchy()
|
||||||
|
self.cloud_enter_game()
|
||||||
else:
|
else:
|
||||||
self.device.app_start()
|
|
||||||
self.handle_app_login()
|
self.handle_app_login()
|
||||||
|
|
||||||
self.config.task_delay(server_update=True)
|
self.config.task_delay(server_update=True)
|
||||||
|
@ -375,13 +375,7 @@ class RogueEntry(RouteBase, RogueRewardHandler, RoguePathHandler, DungeonRogueUI
|
|||||||
# Expired, do rogue
|
# Expired, do rogue
|
||||||
pass
|
pass
|
||||||
elif self.config.stored.SimulatedUniverse.is_full():
|
elif self.config.stored.SimulatedUniverse.is_full():
|
||||||
if self.config.RogueWorld_UseImmersifier and self.config.stored.Immersifier.value > 0:
|
if self.config.RogueWorld_WeeklyFarming and not self.config.stored.SimulatedUniverseFarm.is_full():
|
||||||
logger.info(
|
|
||||||
'Reached weekly point limit but still have immersifiers left, continue to use them')
|
|
||||||
if ornament:
|
|
||||||
logger.info('Ornament enabled, skip farming rogue')
|
|
||||||
raise RogueReachedWeeklyPointLimit
|
|
||||||
elif self.config.RogueWorld_WeeklyFarming and not self.config.stored.SimulatedUniverseFarm.is_full():
|
|
||||||
logger.info(
|
logger.info(
|
||||||
'Reached weekly point limit but still continue to farm materials')
|
'Reached weekly point limit but still continue to farm materials')
|
||||||
logger.attr(
|
logger.attr(
|
||||||
@ -389,6 +383,12 @@ class RogueEntry(RouteBase, RogueRewardHandler, RoguePathHandler, DungeonRogueUI
|
|||||||
if self.config.is_cloud_game and not self.config.stored.CloudRemainSeasonPass.value:
|
if self.config.is_cloud_game and not self.config.stored.CloudRemainSeasonPass.value:
|
||||||
logger.warning('Running WeeklyFarming on cloud game without season pass may cause fee, skip')
|
logger.warning('Running WeeklyFarming on cloud game without season pass may cause fee, skip')
|
||||||
raise RogueReachedWeeklyPointLimit
|
raise RogueReachedWeeklyPointLimit
|
||||||
|
elif self.config.RogueWorld_UseImmersifier and self.config.stored.Immersifier.value > 0:
|
||||||
|
logger.info(
|
||||||
|
'Reached weekly point limit but still have immersifiers left, continue to use them')
|
||||||
|
if ornament:
|
||||||
|
logger.info('Ornament enabled, skip farming rogue')
|
||||||
|
raise RogueReachedWeeklyPointLimit
|
||||||
else:
|
else:
|
||||||
raise RogueReachedWeeklyPointLimit
|
raise RogueReachedWeeklyPointLimit
|
||||||
else:
|
else:
|
||||||
|
Loading…
Reference in New Issue
Block a user