1
0
mirror of https://gitee.com/sui-feng-cb/AzurLaneAutoScript1 synced 2026-03-30 06:13:51 +08:00
This commit is contained in:
GH Action - Upstream Sync
2026-03-28 14:39:56 +00:00
17 changed files with 109 additions and 53 deletions

View File

@@ -1415,7 +1415,8 @@
}, },
"AddNewStudent": { "AddNewStudent": {
"Enable": false, "Enable": false,
"Favorite": true "Favorite": true,
"MinLevel": 50
}, },
"Storage": { "Storage": {
"Storage": {} "Storage": {}

View File

@@ -142,10 +142,13 @@ class EmulatorManager(AlasManager):
for adb in replace: for adb in replace:
logger.info(f'Replacing {adb}') logger.info(f'Replacing {adb}')
bak = self.adb_path_to_backup(adb, new_backup=True) bak = self.adb_path_to_backup(adb, new_backup=True)
logger.info(f'{adb} -----> {bak}') try:
shutil.move(adb, bak) logger.info(f'{adb} -----> {bak}')
logger.info(f'{self.adb} -----> {adb}') shutil.move(adb, bak)
shutil.copy(self.adb, adb) logger.info(f'{self.adb} -----> {adb}')
shutil.copy(self.adb, adb)
except OSError as e:
logger.warning(f'Failed to replace {adb}, {e}')
def adb_recover(self): def adb_recover(self):
""" """

View File

@@ -50,10 +50,11 @@ class VirtualBoxEmulator:
return root return root
try: try:
reg = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, f'{self.UNINSTALL_REG}\\{self.name}', 0) with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, f'{self.UNINSTALL_REG}\\{self.name}', 0) as reg:
res = winreg.QueryValueEx(reg, 'UninstallString')[0]
except FileNotFoundError: except FileNotFoundError:
reg = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, f'{self.UNINSTALL_REG_2}\\{self.name}', 0) with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, f'{self.UNINSTALL_REG_2}\\{self.name}', 0) as reg:
res = winreg.QueryValueEx(reg, 'UninstallString')[0] res = winreg.QueryValueEx(reg, 'UninstallString')[0]
file = re.search('"(.*?)"', res) file = re.search('"(.*?)"', res)
file = file.group(1) if file else res file = file.group(1) if file else res
@@ -70,17 +71,17 @@ class VirtualBoxEmulator:
str: Installation dir or None str: Installation dir or None
""" """
try: try:
reg = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path, 0) with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path, 0) as reg:
root = winreg.QueryValueEx(reg, key)[0] root = winreg.QueryValueEx(reg, key)[0]
if os.path.exists(root): if os.path.exists(root):
return root return root
except FileNotFoundError: except FileNotFoundError:
pass pass
try: try:
reg = winreg.OpenKey(winreg.HKEY_CURRENT_USER, path, 0) with winreg.OpenKey(winreg.HKEY_CURRENT_USER, path, 0) as reg:
root = winreg.QueryValueEx(reg, key)[0] root = winreg.QueryValueEx(reg, key)[0]
if os.path.exists(root): if os.path.exists(root):
return root return root
except FileNotFoundError: except FileNotFoundError:
pass pass
@@ -137,16 +138,19 @@ class VirtualBoxEmulator:
""" """
for ori, bak in zip(self.adb_binary, self.adb_backup): for ori, bak in zip(self.adb_binary, self.adb_backup):
logger.info(f'Replacing {ori}') logger.info(f'Replacing {ori}')
if os.path.exists(ori): try:
if filecmp.cmp(adb, ori, shallow=True): if os.path.exists(ori):
logger.info(f'{adb} is same as {ori}, skip') if filecmp.cmp(adb, ori, shallow=True):
logger.info(f'{adb} is same as {ori}, skip')
else:
logger.info(f'{ori} -----> {bak}')
shutil.move(ori, bak)
logger.info(f'{adb} -----> {ori}')
shutil.copy(adb, ori)
else: else:
logger.info(f'{ori} -----> {bak}') logger.info(f'{ori} not exists, skip')
shutil.move(ori, bak) except OSError as e:
logger.info(f'{adb} -----> {ori}') logger.warning(f'Failed to replace {ori}, {e}')
shutil.copy(adb, ori)
else:
logger.info(f'{ori} not exists, skip')
def adb_recover(self): def adb_recover(self):
""" Revert adb replacement """ """ Revert adb replacement """

View File

@@ -375,6 +375,7 @@
"LDPlayer3", "LDPlayer3",
"LDPlayer4", "LDPlayer4",
"LDPlayer9", "LDPlayer9",
"LDPlayer14",
"MuMuPlayer", "MuMuPlayer",
"MuMuPlayerX", "MuMuPlayerX",
"MuMuPlayer12", "MuMuPlayer12",
@@ -7363,6 +7364,10 @@
"Favorite": { "Favorite": {
"type": "checkbox", "type": "checkbox",
"value": true "value": true
},
"MinLevel": {
"type": "input",
"value": 50
} }
}, },
"Storage": { "Storage": {

View File

@@ -69,6 +69,7 @@ EmulatorInfo:
LDPlayer3, LDPlayer3,
LDPlayer4, LDPlayer4,
LDPlayer9, LDPlayer9,
LDPlayer14,
MuMuPlayer, MuMuPlayer,
MuMuPlayerX, MuMuPlayerX,
MuMuPlayer12, MuMuPlayer12,
@@ -401,6 +402,7 @@ ControlExpOverflow:
AddNewStudent: AddNewStudent:
Enable: false Enable: false
Favorite: true Favorite: true
MinLevel: 50
Research: Research:
UseCube: UseCube:
value: only_05_hour value: only_05_hour

View File

@@ -27,7 +27,7 @@ class GeneratedConfig:
Emulator_AdbRestart = False Emulator_AdbRestart = False
# Group `EmulatorInfo` # Group `EmulatorInfo`
EmulatorInfo_Emulator = 'auto' # auto, NoxPlayer, NoxPlayer64, BlueStacks4, BlueStacks5, BlueStacks4HyperV, BlueStacks5HyperV, LDPlayer3, LDPlayer4, LDPlayer9, MuMuPlayer, MuMuPlayerX, MuMuPlayer12, MEmuPlayer EmulatorInfo_Emulator = 'auto' # auto, NoxPlayer, NoxPlayer64, BlueStacks4, BlueStacks5, BlueStacks4HyperV, BlueStacks5HyperV, LDPlayer3, LDPlayer4, LDPlayer9, LDPlayer14, MuMuPlayer, MuMuPlayerX, MuMuPlayer12, MEmuPlayer
EmulatorInfo_name = None EmulatorInfo_name = None
EmulatorInfo_path = None EmulatorInfo_path = None
@@ -223,6 +223,7 @@ class GeneratedConfig:
# Group `AddNewStudent` # Group `AddNewStudent`
AddNewStudent_Enable = False AddNewStudent_Enable = False
AddNewStudent_Favorite = True AddNewStudent_Favorite = True
AddNewStudent_MinLevel = 50
# Group `Research` # Group `Research`
Research_UseCube = 'only_05_hour' # always_use, only_05_hour, only_no_project, do_not_use Research_UseCube = 'only_05_hour' # always_use, only_05_hour, only_no_project, do_not_use

View File

@@ -482,6 +482,7 @@
"LDPlayer3": "LD Player 3", "LDPlayer3": "LD Player 3",
"LDPlayer4": "LD Player 4", "LDPlayer4": "LD Player 4",
"LDPlayer9": "LD Player 9", "LDPlayer9": "LD Player 9",
"LDPlayer14": "LDPlayer 14",
"MuMuPlayer": "MuMu Player", "MuMuPlayer": "MuMu Player",
"MuMuPlayerX": "MuMu Player X", "MuMuPlayerX": "MuMu Player X",
"MuMuPlayer12": "MuMu Player 12", "MuMuPlayer12": "MuMu Player 12",
@@ -1531,6 +1532,10 @@
"Favorite": { "Favorite": {
"name": "Use Favorite Filter", "name": "Use Favorite Filter",
"help": "During student selection apply the favorite filter\nThereby, giving priority to certain ship girls\nApply the favorite status to a ship girl in-game" "help": "During student selection apply the favorite filter\nThereby, giving priority to certain ship girls\nApply the favorite status to a ship girl in-game"
},
"MinLevel": {
"name": "Add Students with Level >= X Only",
"help": ""
} }
}, },
"Research": { "Research": {

View File

@@ -482,6 +482,7 @@
"LDPlayer3": "LDPlayer3", "LDPlayer3": "LDPlayer3",
"LDPlayer4": "LDPlayer4", "LDPlayer4": "LDPlayer4",
"LDPlayer9": "LDPlayer9", "LDPlayer9": "LDPlayer9",
"LDPlayer14": "LDPlayer14",
"MuMuPlayer": "MuMuPlayer", "MuMuPlayer": "MuMuPlayer",
"MuMuPlayerX": "MuMuPlayerX", "MuMuPlayerX": "MuMuPlayerX",
"MuMuPlayer12": "MuMuPlayer12", "MuMuPlayer12": "MuMuPlayer12",
@@ -1531,6 +1532,10 @@
"Favorite": { "Favorite": {
"name": "好ましい選択", "name": "好ましい選択",
"help": "" "help": ""
},
"MinLevel": {
"name": "レベルがX以上のキャラクターのみを追加してください。",
"help": ""
} }
}, },
"Research": { "Research": {

View File

@@ -482,6 +482,7 @@
"LDPlayer3": "雷电模拟器3", "LDPlayer3": "雷电模拟器3",
"LDPlayer4": "雷电模拟器4", "LDPlayer4": "雷电模拟器4",
"LDPlayer9": "雷电模拟器9", "LDPlayer9": "雷电模拟器9",
"LDPlayer14": "雷电模拟器14",
"MuMuPlayer": "MuMu模拟器", "MuMuPlayer": "MuMu模拟器",
"MuMuPlayerX": "MuMu模拟器X", "MuMuPlayerX": "MuMu模拟器X",
"MuMuPlayer12": "MuMu模拟器12", "MuMuPlayer12": "MuMu模拟器12",
@@ -1531,6 +1532,10 @@
"Favorite": { "Favorite": {
"name": "优先选择常用", "name": "优先选择常用",
"help": "" "help": ""
},
"MinLevel": {
"name": "仅添加等级 >= X 的角色",
"help": ""
} }
}, },
"Research": { "Research": {

View File

@@ -482,6 +482,7 @@
"LDPlayer3": "雷電模擬器3", "LDPlayer3": "雷電模擬器3",
"LDPlayer4": "雷電模擬器4", "LDPlayer4": "雷電模擬器4",
"LDPlayer9": "雷電模擬器9", "LDPlayer9": "雷電模擬器9",
"LDPlayer14": "雷電模擬器14",
"MuMuPlayer": "MuMu模擬器", "MuMuPlayer": "MuMu模擬器",
"MuMuPlayerX": "MuMu模擬器X", "MuMuPlayerX": "MuMu模擬器X",
"MuMuPlayer12": "MuMu模擬器12", "MuMuPlayer12": "MuMu模擬器12",
@@ -1531,6 +1532,10 @@
"Favorite": { "Favorite": {
"name": "優先選擇常用", "name": "優先選擇常用",
"help": "" "help": ""
},
"MinLevel": {
"name": "僅新增等級 >= X 的角色",
"help": ""
} }
}, },
"Research": { "Research": {

View File

@@ -39,7 +39,7 @@ class Benchmark(DaemonBase, CampaignUI):
record = [] record = []
for n in range(1, self.TEST_TOTAL + 1): for n in range(1, self.TEST_TOTAL + 1):
start = time.time() start = time.perf_counter()
try: try:
func(*args, **kwargs) func(*args, **kwargs)
@@ -52,7 +52,7 @@ class Benchmark(DaemonBase, CampaignUI):
logger.warning(f'Benchmark tests failed on func: {func.__name__}') logger.warning(f'Benchmark tests failed on func: {func.__name__}')
return 'Failed' return 'Failed'
cost = time.time() - start cost = time.perf_counter() - start
logger.attr( logger.attr(
f'{str(n).rjust(2, "0")}/{self.TEST_TOTAL}', f'{str(n).rjust(2, "0")}/{self.TEST_TOTAL}',
f'{float2str(cost)}' f'{float2str(cost)}'
@@ -194,6 +194,10 @@ class Benchmark(DaemonBase, CampaignUI):
if device == 'android_phone_vmos': if device == 'android_phone_vmos':
screenshot = ['ADB', 'aScreenCap', 'DroidCast', 'DroidCast_raw'] screenshot = ['ADB', 'aScreenCap', 'DroidCast', 'DroidCast_raw']
click = ['ADB', 'Hermit', 'MaaTouch'] click = ['ADB', 'Hermit', 'MaaTouch']
# Droidcast on SDK 23 (Android 6.0) to SDK 32 (Android 12)
if not (23 <= sdk <= 32):
screenshot = remove('DroidCast', 'DroidCast_raw')
if self.device.nemu_ipc_available(): if self.device.nemu_ipc_available():
screenshot.append('nemu_ipc') screenshot.append('nemu_ipc')
if self.device.ldopengl_available(): if self.device.ldopengl_available():

View File

@@ -332,7 +332,7 @@ class LDOpenGL(Platform):
if not self.is_ldplayer_bluestacks_family: if not self.is_ldplayer_bluestacks_family:
return False return False
logger.attr('EmulatorInfo_Emulator', self.config.EmulatorInfo_Emulator) logger.attr('EmulatorInfo_Emulator', self.config.EmulatorInfo_Emulator)
if self.config.EmulatorInfo_Emulator not in ['LDPlayer9']: if self.config.EmulatorInfo_Emulator not in ['LDPlayer9', 'LDPlayer14']:
return False return False
try: try:

View File

@@ -155,7 +155,8 @@ class EmulatorBase:
LDPlayer3 = 'LDPlayer3' LDPlayer3 = 'LDPlayer3'
LDPlayer4 = 'LDPlayer4' LDPlayer4 = 'LDPlayer4'
LDPlayer9 = 'LDPlayer9' LDPlayer9 = 'LDPlayer9'
LDPlayerFamily = [LDPlayer3, LDPlayer4, LDPlayer9] LDPlayer14 = 'LDPlayer14'
LDPlayerFamily = [LDPlayer3, LDPlayer4, LDPlayer9, LDPlayer14]
MuMuPlayer = 'MuMuPlayer' MuMuPlayer = 'MuMuPlayer'
MuMuPlayerX = 'MuMuPlayerX' MuMuPlayerX = 'MuMuPlayerX'
MuMuPlayer12 = 'MuMuPlayer12' MuMuPlayer12 = 'MuMuPlayer12'

View File

@@ -110,6 +110,8 @@ class Emulator(EmulatorBase):
return cls.LDPlayer4 return cls.LDPlayer4
elif dir1 == 'ldplayer9': elif dir1 == 'ldplayer9':
return cls.LDPlayer9 return cls.LDPlayer9
elif dir1 == 'ldplayer14':
return cls.LDPlayer14
else: else:
return cls.LDPlayer3 return cls.LDPlayer3
if exe == 'nemuplayer.exe': if exe == 'nemuplayer.exe':
@@ -538,8 +540,11 @@ class EmulatorManager(EmulatorManagerBase):
exe.add(file) exe.add(file)
# LDPlayer install path # LDPlayer install path
for path in [r'SOFTWARE\leidian\ldplayer', for path in [
r'SOFTWARE\leidian\ldplayer9']: r'SOFTWARE\leidian\ldplayer',
r'SOFTWARE\leidian\ldplayer9',
r'SOFTWARE\leidian\ldplayer14',
]:
ld = self.get_install_dir_from_reg(path, 'InstallDir') ld = self.get_install_dir_from_reg(path, 'InstallDir')
if ld: if ld:
ld = abspath(os.path.join(ld, './dnplayer.exe')) ld = abspath(os.path.join(ld, './dnplayer.exe'))

View File

@@ -181,6 +181,20 @@ class PlatformBase(Connection, EmulatorManagerBase):
logger.info(f'Found emulator instance: {instance}') logger.info(f'Found emulator instance: {instance}')
return instance return instance
# search by emulator type first, which is the easiest setting for user to setup, so more trustworthy
# Multiple instances in given serial, name and path, search by emulator
if emulator:
search_args['type'] = emulator
select = instances.select(**search_args)
if select.count == 0:
logger.warning(f'No emulator instances with {search_args}, type invalid')
search_args.pop('type')
elif select.count == 1:
instance = select[0]
logger.hr('Emulator instance', level=2)
logger.info(f'Found emulator instance: {instance}')
return instance
# Multiple instances in given serial, search by name # Multiple instances in given serial, search by name
if name: if name:
search_args['name'] = name search_args['name'] = name
@@ -207,19 +221,6 @@ class PlatformBase(Connection, EmulatorManagerBase):
logger.info(f'Found emulator instance: {instance}') logger.info(f'Found emulator instance: {instance}')
return instance return instance
# Multiple instances in given serial, name and path, search by emulator
if emulator:
search_args['type'] = emulator
select = instances.select(**search_args)
if select.count == 0:
logger.warning(f'No emulator instances with {search_args}, type invalid')
search_args.pop('type')
elif select.count == 1:
instance = select[0]
logger.hr('Emulator instance', level=2)
logger.info(f'Found emulator instance: {instance}')
return instance
# Still too many instances, search from running emulators # Still too many instances, search from running emulators
running = remove_duplicated_path(list(self.iter_running_emulator())) running = remove_duplicated_path(list(self.iter_running_emulator()))
logger.info('Running emulators') logger.info('Running emulators')

View File

@@ -89,6 +89,8 @@ class Reward(UI):
click_interval.reset() click_interval.reset()
clicked = True clicked = True
continue continue
if self.appear(MISSION_UNFINISH, offset=(20, 20)):
return clicked
def _reward_mission_claim_receive(self): def _reward_mission_claim_receive(self):
""" """

View File

@@ -643,27 +643,34 @@ class RewardTacticalClass(Dock):
# Wait until they turn into # Wait until they turn into
# [120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120] # [120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120]
level_ocr = LevelOcr(CARD_LEVEL_GRIDS.buttons, name='DOCK_LEVEL_OCR', threshold=64) level_ocr = LevelOcr(CARD_LEVEL_GRIDS.buttons, name='DOCK_LEVEL_OCR', threshold=64)
timeout = Timer(1, count=1).start() list_level = []
while 1: for _ in self.loop(timeout=1):
list_level = level_ocr.ocr(self.device.image) list_level = level_ocr.ocr(self.device.image)
first_ship = next((i for i, x in enumerate(list_level) if x > 0), len(list_level)) first_ship = next((i for i, x in enumerate(list_level) if x > 0), len(list_level))
first_empty = next((i for i, x in enumerate(list_level) if x == 0), len(list_level)) first_empty = next((i for i, x in enumerate(list_level) if x == 0), len(list_level))
if timeout.reached():
logger.warning('Wait ship cards timeout')
break
if first_empty >= first_ship: if first_empty >= first_ship:
break break
self.device.screenshot() else:
logger.warning('Wait ship cards timeout')
try:
min_level = int(self.config.AddNewStudent_MinLevel)
if min_level < 1:
min_level = 1
except (ValueError, TypeError) as e:
logger.warning(f'Invalid AddNewStudent_MinLevel: {self.config.AddNewStudent_MinLevel}, {e}')
min_level = 1
logger.attr('AddNewStudent_MinLevel', min_level)
should_select_button = None should_select_button = None
for button, level in list(zip(CARD_GRIDS.buttons, list_level))[self.dock_select_index:]: for button, level in list(zip(CARD_GRIDS.buttons, list_level))[self.dock_select_index:]:
# Select ship LV > 1 only # Select ship LV > 1 only
if level > 1: if level >= min_level:
should_select_button = button should_select_button = button
break break
if should_select_button is None: if should_select_button is None:
logger.info('No ships with level > 1 in dock') logger.info(f'No ships with level >= {min_level} in dock')
return False return False
# select a ship # select a ship