Merge branch 'master' of https://github.com/LmeSzinc/AzurLaneAutoScript
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 7.2 KiB |
@@ -238,4 +238,4 @@ To add a new event, add a new row in here, and run `python -m module.config.conf
|
|||||||
| 20250320 | event 20230223 cn | Revelations of Dust | 复刻湮烬尘墟 | Revelations of Dust Rerun | 黙示の遺構(復刻) | - |
|
| 20250320 | event 20230223 cn | Revelations of Dust | 复刻湮烬尘墟 | Revelations of Dust Rerun | 黙示の遺構(復刻) | - |
|
||||||
| 20250320 | event 20240521 cn | Light of the Martyrium | - | - | - | 綻放於輝光之城 |
|
| 20250320 | event 20240521 cn | Light of the Martyrium | - | - | - | 綻放於輝光之城 |
|
||||||
| 20250410 | event 20241024 cn | Tempesta and the Sleeping Sea | - | - | - | 颶風與沉眠之海 |
|
| 20250410 | event 20241024 cn | Tempesta and the Sleeping Sea | - | - | - | 颶風與沉眠之海 |
|
||||||
| 20250417 | coalition 20230323 | Frostfall Rerun | 复刻极地风暴 | Frostfall Rerun | 星霜海嵐(復刻) | - |
|
| 20250417 | coalition 20230323 | Frostfall | 极地风暴 | Frostfall | 星霜海嵐 | - |
|
||||||
|
|||||||
@@ -765,7 +765,7 @@
|
|||||||
"AmbushEvade": true
|
"AmbushEvade": true
|
||||||
},
|
},
|
||||||
"Coalition": {
|
"Coalition": {
|
||||||
"Mode": "TC1",
|
"Mode": "tc1",
|
||||||
"Fleet": "single"
|
"Fleet": "single"
|
||||||
},
|
},
|
||||||
"StopCondition": {
|
"StopCondition": {
|
||||||
@@ -1352,7 +1352,7 @@
|
|||||||
"AmbushEvade": true
|
"AmbushEvade": true
|
||||||
},
|
},
|
||||||
"Coalition": {
|
"Coalition": {
|
||||||
"Mode": "TC1",
|
"Mode": "sp",
|
||||||
"Fleet": "single"
|
"Fleet": "single"
|
||||||
},
|
},
|
||||||
"StopCondition": {
|
"StopCondition": {
|
||||||
|
|||||||
@@ -68,12 +68,13 @@ def windows_attempt_delay(attempt: int) -> float:
|
|||||||
return 2 ** attempt * WINDOWS_RETRY_DELAY
|
return 2 ** attempt * WINDOWS_RETRY_DELAY
|
||||||
|
|
||||||
|
|
||||||
def replace_tmp(temp: str, file: str):
|
def replace_tmp(tmp: str, file: str):
|
||||||
"""
|
"""
|
||||||
Replace temp file to file
|
Replace temp file to file
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
PermissionError: (Windows only) If another process is still reading the file and all retries failed
|
PermissionError: (Windows only) If another process is still reading the file and all retries failed
|
||||||
|
FileNotFoundError: If tmp file gets deleted unexpectedly
|
||||||
"""
|
"""
|
||||||
if IS_WINDOWS:
|
if IS_WINDOWS:
|
||||||
# PermissionError on Windows if another process is reading
|
# PermissionError on Windows if another process is reading
|
||||||
@@ -81,7 +82,7 @@ def replace_tmp(temp: str, file: str):
|
|||||||
for attempt in range(WINDOWS_MAX_ATTEMPT):
|
for attempt in range(WINDOWS_MAX_ATTEMPT):
|
||||||
try:
|
try:
|
||||||
# Atomic operation
|
# Atomic operation
|
||||||
os.replace(temp, file)
|
os.replace(tmp, file)
|
||||||
# success
|
# success
|
||||||
return
|
return
|
||||||
except PermissionError as e:
|
except PermissionError as e:
|
||||||
@@ -89,6 +90,9 @@ def replace_tmp(temp: str, file: str):
|
|||||||
delay = windows_attempt_delay(attempt)
|
delay = windows_attempt_delay(attempt)
|
||||||
time.sleep(delay)
|
time.sleep(delay)
|
||||||
continue
|
continue
|
||||||
|
except FileNotFoundError:
|
||||||
|
# tmp file gets deleted unexpectedly
|
||||||
|
raise
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
last_error = e
|
last_error = e
|
||||||
break
|
break
|
||||||
@@ -96,15 +100,20 @@ def replace_tmp(temp: str, file: str):
|
|||||||
# Linux and Mac allow existing reading
|
# Linux and Mac allow existing reading
|
||||||
try:
|
try:
|
||||||
# Atomic operation
|
# Atomic operation
|
||||||
os.replace(temp, file)
|
os.replace(tmp, file)
|
||||||
# success
|
# success
|
||||||
return
|
return
|
||||||
|
except FileNotFoundError:
|
||||||
|
raise
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
last_error = e
|
last_error = e
|
||||||
|
|
||||||
# Clean up temp file on failure
|
# Clean up tmp file on failure
|
||||||
try:
|
try:
|
||||||
os.unlink(temp)
|
os.unlink(tmp)
|
||||||
|
except FileNotFoundError:
|
||||||
|
# tmp file already get deleted
|
||||||
|
pass
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
if last_error is not None:
|
if last_error is not None:
|
||||||
@@ -117,6 +126,7 @@ def atomic_replace(replace_from: str, replace_to: str):
|
|||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
PermissionError: (Windows only) If another process is still reading the file and all retries failed
|
PermissionError: (Windows only) If another process is still reading the file and all retries failed
|
||||||
|
FileNotFoundError:
|
||||||
"""
|
"""
|
||||||
if IS_WINDOWS:
|
if IS_WINDOWS:
|
||||||
# PermissionError on Windows if another process is reading
|
# PermissionError on Windows if another process is reading
|
||||||
@@ -132,6 +142,11 @@ def atomic_replace(replace_from: str, replace_to: str):
|
|||||||
delay = windows_attempt_delay(attempt)
|
delay = windows_attempt_delay(attempt)
|
||||||
time.sleep(delay)
|
time.sleep(delay)
|
||||||
continue
|
continue
|
||||||
|
except FileNotFoundError:
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
last_error = e
|
||||||
|
break
|
||||||
if last_error is not None:
|
if last_error is not None:
|
||||||
raise last_error from None
|
raise last_error from None
|
||||||
else:
|
else:
|
||||||
@@ -522,7 +537,7 @@ def folder_rmtree(folder, may_symlinks=True):
|
|||||||
# If it's a symlinks, unlink it
|
# If it's a symlinks, unlink it
|
||||||
if may_symlinks and os.path.islink(folder):
|
if may_symlinks and os.path.islink(folder):
|
||||||
file_remove(folder)
|
file_remove(folder)
|
||||||
return
|
return True
|
||||||
# Iter folder
|
# Iter folder
|
||||||
with os.scandir(folder) as entries:
|
with os.scandir(folder) as entries:
|
||||||
for entry in entries:
|
for entry in entries:
|
||||||
@@ -539,10 +554,10 @@ def folder_rmtree(folder, may_symlinks=True):
|
|||||||
|
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
# directory to clean up does not exist, no need to clean up
|
# directory to clean up does not exist, no need to clean up
|
||||||
return
|
return True
|
||||||
except NotADirectoryError:
|
except NotADirectoryError:
|
||||||
file_remove(folder)
|
file_remove(folder)
|
||||||
return
|
return True
|
||||||
|
|
||||||
# Remove empty folder
|
# Remove empty folder
|
||||||
# May raise OSError if it's still not empty
|
# May raise OSError if it's still not empty
|
||||||
@@ -550,10 +565,10 @@ def folder_rmtree(folder, may_symlinks=True):
|
|||||||
os.rmdir(folder)
|
os.rmdir(folder)
|
||||||
return True
|
return True
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
return
|
return True
|
||||||
except NotADirectoryError:
|
except NotADirectoryError:
|
||||||
file_remove(folder)
|
file_remove(folder)
|
||||||
return
|
return True
|
||||||
except OSError:
|
except OSError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -565,8 +580,12 @@ def atomic_rmtree(folder: str):
|
|||||||
folder can be removed by atomic_failure_cleanup at next startup if remove gets interrupted
|
folder can be removed by atomic_failure_cleanup at next startup if remove gets interrupted
|
||||||
"""
|
"""
|
||||||
temp = to_tmp_file(folder)
|
temp = to_tmp_file(folder)
|
||||||
atomic_replace(folder, temp)
|
try:
|
||||||
folder_rmtree(folder)
|
atomic_replace(folder, temp)
|
||||||
|
except FileNotFoundError:
|
||||||
|
# Folder not exist, no need to rmtree
|
||||||
|
return
|
||||||
|
folder_rmtree(temp)
|
||||||
|
|
||||||
|
|
||||||
def atomic_failure_cleanup(folder: str, recursive: bool = False):
|
def atomic_failure_cleanup(folder: str, recursive: bool = False):
|
||||||
@@ -607,4 +626,5 @@ def atomic_failure_cleanup(folder: str, recursive: bool = False):
|
|||||||
except NotADirectoryError:
|
except NotADirectoryError:
|
||||||
file_remove(folder)
|
file_remove(folder)
|
||||||
except:
|
except:
|
||||||
|
# Ignore all failures, it doesn't matter if tmp files still exist
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -23,13 +23,13 @@ COALITION_ACADEMY_MAIN_CHECK = Button(area={'cn': (132, 57, 163, 92), 'en': (164
|
|||||||
COALITION_REWARD_CONFIRM = Button(area={'cn': (814, 611, 877, 637), 'en': (788, 612, 902, 634), 'jp': (814, 611, 876, 637), 'tw': (814, 611, 877, 637)}, color={'cn': (155, 186, 227), 'en': (162, 189, 226), 'jp': (143, 176, 219), 'tw': (150, 181, 221)}, button={'cn': (814, 611, 877, 637), 'en': (788, 612, 902, 634), 'jp': (814, 611, 876, 637), 'tw': (814, 611, 877, 637)}, file={'cn': './assets/cn/coalition/COALITION_REWARD_CONFIRM.png', 'en': './assets/en/coalition/COALITION_REWARD_CONFIRM.png', 'jp': './assets/jp/coalition/COALITION_REWARD_CONFIRM.png', 'tw': './assets/tw/coalition/COALITION_REWARD_CONFIRM.png'})
|
COALITION_REWARD_CONFIRM = Button(area={'cn': (814, 611, 877, 637), 'en': (788, 612, 902, 634), 'jp': (814, 611, 876, 637), 'tw': (814, 611, 877, 637)}, color={'cn': (155, 186, 227), 'en': (162, 189, 226), 'jp': (143, 176, 219), 'tw': (150, 181, 221)}, button={'cn': (814, 611, 877, 637), 'en': (788, 612, 902, 634), 'jp': (814, 611, 876, 637), 'tw': (814, 611, 877, 637)}, file={'cn': './assets/cn/coalition/COALITION_REWARD_CONFIRM.png', 'en': './assets/en/coalition/COALITION_REWARD_CONFIRM.png', 'jp': './assets/jp/coalition/COALITION_REWARD_CONFIRM.png', 'tw': './assets/tw/coalition/COALITION_REWARD_CONFIRM.png'})
|
||||||
FLEET_NOT_PREPARED = Button(area={'cn': (1008, 310, 1110, 334), 'en': (1008, 310, 1110, 334), 'jp': (1008, 310, 1110, 334), 'tw': (1008, 310, 1110, 334)}, color={'cn': (106, 106, 112), 'en': (106, 106, 112), 'jp': (106, 106, 112), 'tw': (108, 107, 112)}, button={'cn': (1008, 310, 1110, 334), 'en': (1008, 310, 1110, 334), 'jp': (1008, 310, 1110, 334), 'tw': (1008, 310, 1110, 334)}, file={'cn': './assets/cn/coalition/FLEET_NOT_PREPARED.png', 'en': './assets/cn/coalition/FLEET_NOT_PREPARED.png', 'jp': './assets/cn/coalition/FLEET_NOT_PREPARED.png', 'tw': './assets/tw/coalition/FLEET_NOT_PREPARED.png'})
|
FLEET_NOT_PREPARED = Button(area={'cn': (1008, 310, 1110, 334), 'en': (1008, 310, 1110, 334), 'jp': (1008, 310, 1110, 334), 'tw': (1008, 310, 1110, 334)}, color={'cn': (106, 106, 112), 'en': (106, 106, 112), 'jp': (106, 106, 112), 'tw': (108, 107, 112)}, button={'cn': (1008, 310, 1110, 334), 'en': (1008, 310, 1110, 334), 'jp': (1008, 310, 1110, 334), 'tw': (1008, 310, 1110, 334)}, file={'cn': './assets/cn/coalition/FLEET_NOT_PREPARED.png', 'en': './assets/cn/coalition/FLEET_NOT_PREPARED.png', 'jp': './assets/cn/coalition/FLEET_NOT_PREPARED.png', 'tw': './assets/tw/coalition/FLEET_NOT_PREPARED.png'})
|
||||||
FROSTFALL_EX = Button(area={'cn': (622, 372, 649, 384), 'en': (622, 372, 649, 384), 'jp': (622, 372, 649, 384), 'tw': (622, 372, 649, 384)}, color={'cn': (198, 152, 252), 'en': (198, 152, 252), 'jp': (198, 152, 252), 'tw': (182, 127, 252)}, button={'cn': (622, 372, 649, 384), 'en': (622, 372, 649, 384), 'jp': (622, 372, 649, 384), 'tw': (622, 372, 649, 384)}, file={'cn': './assets/cn/coalition/FROSTFALL_EX.png', 'en': './assets/en/coalition/FROSTFALL_EX.png', 'jp': './assets/jp/coalition/FROSTFALL_EX.png', 'tw': './assets/tw/coalition/FROSTFALL_EX.png'})
|
FROSTFALL_EX = Button(area={'cn': (622, 372, 649, 384), 'en': (622, 372, 649, 384), 'jp': (622, 372, 649, 384), 'tw': (622, 372, 649, 384)}, color={'cn': (198, 152, 252), 'en': (198, 152, 252), 'jp': (198, 152, 252), 'tw': (182, 127, 252)}, button={'cn': (622, 372, 649, 384), 'en': (622, 372, 649, 384), 'jp': (622, 372, 649, 384), 'tw': (622, 372, 649, 384)}, file={'cn': './assets/cn/coalition/FROSTFALL_EX.png', 'en': './assets/en/coalition/FROSTFALL_EX.png', 'jp': './assets/jp/coalition/FROSTFALL_EX.png', 'tw': './assets/tw/coalition/FROSTFALL_EX.png'})
|
||||||
FROSTFALL_FLEET_PREPARATION = Button(area={'cn': (1057, 527, 1155, 548), 'en': (1057, 527, 1155, 548), 'jp': (1057, 527, 1155, 548), 'tw': (1057, 527, 1155, 548)}, color={'cn': (122, 146, 222), 'en': (122, 146, 222), 'jp': (122, 146, 222), 'tw': (110, 136, 224)}, button={'cn': (1057, 527, 1155, 548), 'en': (1057, 527, 1155, 548), 'jp': (1057, 527, 1155, 548), 'tw': (968, 511, 1245, 563)}, file={'cn': './assets/cn/coalition/FROSTFALL_FLEET_PREPARATION.png', 'en': './assets/cn/coalition/FROSTFALL_FLEET_PREPARATION.png', 'jp': './assets/cn/coalition/FROSTFALL_FLEET_PREPARATION.png', 'tw': './assets/tw/coalition/FROSTFALL_FLEET_PREPARATION.png'})
|
FROSTFALL_FLEET_PREPARATION = Button(area={'cn': (1057, 527, 1155, 548), 'en': (1114, 527, 1200, 545), 'jp': (1056, 525, 1157, 550), 'tw': (1057, 527, 1155, 548)}, color={'cn': (122, 146, 222), 'en': (106, 135, 228), 'jp': (115, 141, 222), 'tw': (110, 136, 224)}, button={'cn': (1057, 527, 1155, 548), 'en': (968, 511, 1245, 563), 'jp': (968, 511, 1245, 563), 'tw': (968, 511, 1245, 563)}, file={'cn': './assets/cn/coalition/FROSTFALL_FLEET_PREPARATION.png', 'en': './assets/en/coalition/FROSTFALL_FLEET_PREPARATION.png', 'jp': './assets/jp/coalition/FROSTFALL_FLEET_PREPARATION.png', 'tw': './assets/tw/coalition/FROSTFALL_FLEET_PREPARATION.png'})
|
||||||
FROSTFALL_MODE_BATTLE = Button(area={'cn': (71, 608, 137, 653), 'en': (71, 608, 137, 653), 'jp': (71, 608, 137, 653), 'tw': (71, 608, 137, 653)}, color={'cn': (63, 106, 122), 'en': (63, 106, 122), 'jp': (63, 106, 122), 'tw': (63, 106, 122)}, button={'cn': (71, 608, 137, 653), 'en': (71, 608, 137, 653), 'jp': (71, 608, 137, 653), 'tw': (71, 608, 137, 653)}, file={'cn': './assets/cn/coalition/FROSTFALL_MODE_BATTLE.png', 'en': './assets/cn/coalition/FROSTFALL_MODE_BATTLE.png', 'jp': './assets/cn/coalition/FROSTFALL_MODE_BATTLE.png', 'tw': './assets/tw/coalition/FROSTFALL_MODE_BATTLE.png'})
|
FROSTFALL_MODE_BATTLE = Button(area={'cn': (71, 608, 137, 653), 'en': (71, 608, 137, 653), 'jp': (71, 608, 137, 653), 'tw': (71, 608, 137, 653)}, color={'cn': (63, 106, 122), 'en': (63, 106, 122), 'jp': (63, 106, 122), 'tw': (63, 106, 122)}, button={'cn': (71, 608, 137, 653), 'en': (71, 608, 137, 653), 'jp': (71, 608, 137, 653), 'tw': (71, 608, 137, 653)}, file={'cn': './assets/cn/coalition/FROSTFALL_MODE_BATTLE.png', 'en': './assets/en/coalition/FROSTFALL_MODE_BATTLE.png', 'jp': './assets/jp/coalition/FROSTFALL_MODE_BATTLE.png', 'tw': './assets/tw/coalition/FROSTFALL_MODE_BATTLE.png'})
|
||||||
FROSTFALL_MODE_STORY = Button(area={'cn': (73, 610, 134, 652), 'en': (73, 610, 134, 652), 'jp': (73, 610, 134, 652), 'tw': (73, 610, 134, 652)}, color={'cn': (119, 44, 32), 'en': (119, 44, 32), 'jp': (119, 44, 32), 'tw': (119, 44, 32)}, button={'cn': (73, 610, 134, 652), 'en': (73, 610, 134, 652), 'jp': (73, 610, 134, 652), 'tw': (73, 610, 134, 652)}, file={'cn': './assets/cn/coalition/FROSTFALL_MODE_STORY.png', 'en': './assets/cn/coalition/FROSTFALL_MODE_STORY.png', 'jp': './assets/cn/coalition/FROSTFALL_MODE_STORY.png', 'tw': './assets/tw/coalition/FROSTFALL_MODE_STORY.png'})
|
FROSTFALL_MODE_STORY = Button(area={'cn': (73, 610, 134, 652), 'en': (73, 610, 134, 652), 'jp': (73, 610, 134, 652), 'tw': (73, 610, 134, 652)}, color={'cn': (119, 44, 32), 'en': (119, 44, 32), 'jp': (119, 44, 32), 'tw': (119, 44, 32)}, button={'cn': (73, 610, 134, 652), 'en': (73, 610, 134, 652), 'jp': (73, 610, 134, 652), 'tw': (73, 610, 134, 652)}, file={'cn': './assets/cn/coalition/FROSTFALL_MODE_STORY.png', 'en': './assets/en/coalition/FROSTFALL_MODE_STORY.png', 'jp': './assets/jp/coalition/FROSTFALL_MODE_STORY.png', 'tw': './assets/tw/coalition/FROSTFALL_MODE_STORY.png'})
|
||||||
FROSTFALL_OCR_PT = Button(area={'cn': (1181, 641, 1254, 663), 'en': (1181, 641, 1254, 663), 'jp': (1181, 641, 1254, 663), 'tw': (1181, 641, 1254, 663)}, color={'cn': (93, 100, 106), 'en': (93, 100, 106), 'jp': (93, 100, 106), 'tw': (93, 100, 106)}, button={'cn': (1181, 641, 1254, 663), 'en': (1181, 641, 1254, 663), 'jp': (1181, 641, 1254, 663), 'tw': (1181, 641, 1254, 663)}, file={'cn': './assets/cn/coalition/FROSTFALL_OCR_PT.png', 'en': './assets/en/coalition/FROSTFALL_OCR_PT.png', 'jp': './assets/jp/coalition/FROSTFALL_OCR_PT.png', 'tw': './assets/tw/coalition/FROSTFALL_OCR_PT.png'})
|
FROSTFALL_OCR_PT = Button(area={'cn': (1181, 641, 1254, 663), 'en': (1181, 641, 1254, 663), 'jp': (1181, 641, 1254, 663), 'tw': (1181, 641, 1254, 663)}, color={'cn': (93, 100, 106), 'en': (93, 100, 106), 'jp': (93, 100, 106), 'tw': (93, 100, 106)}, button={'cn': (1181, 641, 1254, 663), 'en': (1181, 641, 1254, 663), 'jp': (1181, 641, 1254, 663), 'tw': (1181, 641, 1254, 663)}, file={'cn': './assets/cn/coalition/FROSTFALL_OCR_PT.png', 'en': './assets/en/coalition/FROSTFALL_OCR_PT.png', 'jp': './assets/jp/coalition/FROSTFALL_OCR_PT.png', 'tw': './assets/tw/coalition/FROSTFALL_OCR_PT.png'})
|
||||||
FROSTFALL_SP = Button(area={'cn': (505, 290, 532, 302), 'en': (631, 160, 658, 173), 'jp': (631, 160, 658, 173), 'tw': (505, 290, 532, 302)}, color={'cn': (210, 172, 252), 'en': (194, 145, 252), 'jp': (194, 145, 252), 'tw': (183, 128, 253)}, button={'cn': (505, 290, 532, 302), 'en': (631, 160, 658, 173), 'jp': (631, 160, 658, 173), 'tw': (505, 290, 532, 302)}, file={'cn': './assets/cn/coalition/FROSTFALL_SP.png', 'en': './assets/en/coalition/FROSTFALL_SP.png', 'jp': './assets/jp/coalition/FROSTFALL_SP.png', 'tw': './assets/tw/coalition/FROSTFALL_SP.png'})
|
FROSTFALL_SP = Button(area={'cn': (505, 290, 532, 302), 'en': (505, 290, 532, 302), 'jp': (505, 290, 532, 302), 'tw': (505, 290, 532, 302)}, color={'cn': (183, 128, 253), 'en': (183, 128, 253), 'jp': (183, 128, 253), 'tw': (183, 128, 253)}, button={'cn': (505, 290, 532, 302), 'en': (505, 290, 532, 302), 'jp': (505, 290, 532, 302), 'tw': (505, 290, 532, 302)}, file={'cn': './assets/cn/coalition/FROSTFALL_SP.png', 'en': './assets/en/coalition/FROSTFALL_SP.png', 'jp': './assets/jp/coalition/FROSTFALL_SP.png', 'tw': './assets/tw/coalition/FROSTFALL_SP.png'})
|
||||||
FROSTFALL_SWITCH_MULTI = Button(area={'cn': (1106, 449, 1237, 478), 'en': (1106, 449, 1237, 478), 'jp': (1106, 449, 1237, 478), 'tw': (1106, 449, 1237, 478)}, color={'cn': (232, 175, 58), 'en': (232, 175, 58), 'jp': (232, 175, 58), 'tw': (225, 170, 59)}, button={'cn': (1106, 449, 1237, 478), 'en': (1106, 449, 1237, 478), 'jp': (1106, 449, 1237, 478), 'tw': (1106, 449, 1237, 478)}, file={'cn': './assets/cn/coalition/FROSTFALL_SWITCH_MULTI.png', 'en': './assets/cn/coalition/FROSTFALL_SWITCH_MULTI.png', 'jp': './assets/cn/coalition/FROSTFALL_SWITCH_MULTI.png', 'tw': './assets/tw/coalition/FROSTFALL_SWITCH_MULTI.png'})
|
FROSTFALL_SWITCH_MULTI = Button(area={'cn': (1106, 449, 1237, 478), 'en': (1106, 449, 1237, 478), 'jp': (1106, 449, 1237, 478), 'tw': (1106, 449, 1237, 478)}, color={'cn': (232, 175, 58), 'en': (197, 147, 49), 'jp': (220, 165, 55), 'tw': (225, 170, 59)}, button={'cn': (1106, 449, 1237, 478), 'en': (1106, 449, 1237, 478), 'jp': (1106, 449, 1237, 478), 'tw': (1106, 449, 1237, 478)}, file={'cn': './assets/cn/coalition/FROSTFALL_SWITCH_MULTI.png', 'en': './assets/en/coalition/FROSTFALL_SWITCH_MULTI.png', 'jp': './assets/jp/coalition/FROSTFALL_SWITCH_MULTI.png', 'tw': './assets/tw/coalition/FROSTFALL_SWITCH_MULTI.png'})
|
||||||
FROSTFALL_SWITCH_SINGLE = Button(area={'cn': (968, 449, 1098, 478), 'en': (968, 449, 1098, 478), 'jp': (968, 449, 1098, 478), 'tw': (968, 449, 1098, 478)}, color={'cn': (230, 173, 57), 'en': (230, 173, 57), 'jp': (230, 173, 57), 'tw': (220, 166, 58)}, button={'cn': (968, 449, 1098, 478), 'en': (968, 449, 1098, 478), 'jp': (968, 449, 1098, 478), 'tw': (968, 449, 1098, 478)}, file={'cn': './assets/cn/coalition/FROSTFALL_SWITCH_SINGLE.png', 'en': './assets/cn/coalition/FROSTFALL_SWITCH_SINGLE.png', 'jp': './assets/cn/coalition/FROSTFALL_SWITCH_SINGLE.png', 'tw': './assets/tw/coalition/FROSTFALL_SWITCH_SINGLE.png'})
|
FROSTFALL_SWITCH_SINGLE = Button(area={'cn': (968, 449, 1098, 478), 'en': (968, 449, 1098, 478), 'jp': (968, 449, 1098, 478), 'tw': (968, 449, 1098, 478)}, color={'cn': (230, 173, 57), 'en': (199, 148, 49), 'jp': (221, 166, 55), 'tw': (220, 166, 58)}, button={'cn': (968, 449, 1098, 478), 'en': (968, 449, 1098, 478), 'jp': (968, 449, 1098, 478), 'tw': (968, 449, 1098, 478)}, file={'cn': './assets/cn/coalition/FROSTFALL_SWITCH_SINGLE.png', 'en': './assets/en/coalition/FROSTFALL_SWITCH_SINGLE.png', 'jp': './assets/jp/coalition/FROSTFALL_SWITCH_SINGLE.png', 'tw': './assets/tw/coalition/FROSTFALL_SWITCH_SINGLE.png'})
|
||||||
FROSTFALL_TC1 = Button(area={'cn': (304, 320, 330, 332), 'en': (304, 320, 330, 332), 'jp': (304, 320, 330, 332), 'tw': (304, 320, 330, 332)}, color={'cn': (204, 162, 254), 'en': (204, 162, 254), 'jp': (204, 162, 254), 'tw': (188, 137, 254)}, button={'cn': (304, 320, 330, 332), 'en': (304, 320, 330, 332), 'jp': (304, 320, 330, 332), 'tw': (304, 320, 330, 332)}, file={'cn': './assets/cn/coalition/FROSTFALL_TC1.png', 'en': './assets/en/coalition/FROSTFALL_TC1.png', 'jp': './assets/jp/coalition/FROSTFALL_TC1.png', 'tw': './assets/tw/coalition/FROSTFALL_TC1.png'})
|
FROSTFALL_TC1 = Button(area={'cn': (304, 320, 330, 332), 'en': (304, 320, 330, 332), 'jp': (304, 320, 330, 332), 'tw': (304, 320, 330, 332)}, color={'cn': (204, 162, 254), 'en': (204, 162, 254), 'jp': (204, 162, 254), 'tw': (188, 137, 254)}, button={'cn': (304, 320, 330, 332), 'en': (304, 320, 330, 332), 'jp': (304, 320, 330, 332), 'tw': (304, 320, 330, 332)}, file={'cn': './assets/cn/coalition/FROSTFALL_TC1.png', 'en': './assets/en/coalition/FROSTFALL_TC1.png', 'jp': './assets/jp/coalition/FROSTFALL_TC1.png', 'tw': './assets/tw/coalition/FROSTFALL_TC1.png'})
|
||||||
FROSTFALL_TC2 = Button(area={'cn': (631, 160, 658, 173), 'en': (810, 362, 835, 373), 'jp': (810, 362, 835, 373), 'tw': (631, 160, 658, 173)}, color={'cn': (194, 145, 252), 'en': (214, 178, 254), 'jp': (214, 178, 254), 'tw': (186, 136, 252)}, button={'cn': (631, 160, 658, 173), 'en': (810, 362, 835, 373), 'jp': (810, 362, 835, 373), 'tw': (631, 160, 658, 173)}, file={'cn': './assets/cn/coalition/FROSTFALL_TC2.png', 'en': './assets/en/coalition/FROSTFALL_TC2.png', 'jp': './assets/jp/coalition/FROSTFALL_TC2.png', 'tw': './assets/tw/coalition/FROSTFALL_TC2.png'})
|
FROSTFALL_TC2 = Button(area={'cn': (631, 160, 658, 173), 'en': (631, 160, 658, 173), 'jp': (631, 160, 658, 173), 'tw': (631, 160, 658, 173)}, color={'cn': (186, 136, 252), 'en': (186, 136, 252), 'jp': (186, 136, 252), 'tw': (186, 136, 252)}, button={'cn': (631, 160, 658, 173), 'en': (631, 160, 658, 173), 'jp': (631, 160, 658, 173), 'tw': (631, 160, 658, 173)}, file={'cn': './assets/cn/coalition/FROSTFALL_TC2.png', 'en': './assets/en/coalition/FROSTFALL_TC2.png', 'jp': './assets/jp/coalition/FROSTFALL_TC2.png', 'tw': './assets/tw/coalition/FROSTFALL_TC2.png'})
|
||||||
FROSTFALL_TC3 = Button(area={'cn': (810, 362, 835, 373), 'en': (505, 290, 532, 302), 'jp': (505, 290, 532, 302), 'tw': (810, 362, 835, 373)}, color={'cn': (214, 178, 254), 'en': (210, 172, 252), 'jp': (210, 172, 252), 'tw': (197, 153, 255)}, button={'cn': (810, 362, 835, 373), 'en': (505, 290, 532, 302), 'jp': (505, 290, 532, 302), 'tw': (810, 362, 835, 373)}, file={'cn': './assets/cn/coalition/FROSTFALL_TC3.png', 'en': './assets/en/coalition/FROSTFALL_TC3.png', 'jp': './assets/jp/coalition/FROSTFALL_TC3.png', 'tw': './assets/tw/coalition/FROSTFALL_TC3.png'})
|
FROSTFALL_TC3 = Button(area={'cn': (810, 362, 835, 373), 'en': (810, 362, 835, 373), 'jp': (810, 362, 835, 373), 'tw': (810, 362, 835, 373)}, color={'cn': (197, 153, 255), 'en': (197, 153, 255), 'jp': (197, 153, 255), 'tw': (197, 153, 255)}, button={'cn': (810, 362, 835, 373), 'en': (810, 362, 835, 373), 'jp': (810, 362, 835, 373), 'tw': (810, 362, 835, 373)}, file={'cn': './assets/cn/coalition/FROSTFALL_TC3.png', 'en': './assets/en/coalition/FROSTFALL_TC3.png', 'jp': './assets/jp/coalition/FROSTFALL_TC3.png', 'tw': './assets/tw/coalition/FROSTFALL_TC3.png'})
|
||||||
|
|||||||
@@ -3995,12 +3995,12 @@
|
|||||||
"Coalition": {
|
"Coalition": {
|
||||||
"Mode": {
|
"Mode": {
|
||||||
"type": "select",
|
"type": "select",
|
||||||
"value": "TC1",
|
"value": "tc1",
|
||||||
"option": [
|
"option": [
|
||||||
"TC1",
|
"tc1",
|
||||||
"TC2",
|
"tc2",
|
||||||
"TC3",
|
"tc3",
|
||||||
"EX"
|
"ex"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"Fleet": {
|
"Fleet": {
|
||||||
@@ -7373,13 +7373,15 @@
|
|||||||
"Coalition": {
|
"Coalition": {
|
||||||
"Mode": {
|
"Mode": {
|
||||||
"type": "select",
|
"type": "select",
|
||||||
"value": "TC1",
|
"value": "sp",
|
||||||
"option": [
|
"option": [
|
||||||
"TC1",
|
"tc1",
|
||||||
"TC2",
|
"tc2",
|
||||||
"TC3",
|
"tc3",
|
||||||
"EX"
|
"sp",
|
||||||
]
|
"ex"
|
||||||
|
],
|
||||||
|
"display": "hide"
|
||||||
},
|
},
|
||||||
"Fleet": {
|
"Fleet": {
|
||||||
"type": "select",
|
"type": "select",
|
||||||
|
|||||||
@@ -334,8 +334,8 @@ MaritimeEscort:
|
|||||||
Enable: true
|
Enable: true
|
||||||
Coalition:
|
Coalition:
|
||||||
Mode:
|
Mode:
|
||||||
value: TC1
|
value: tc1
|
||||||
option: [ TC1, TC2, TC3, EX ]
|
option: [ tc1, tc2, tc3, sp, ex ]
|
||||||
Fleet:
|
Fleet:
|
||||||
value: single
|
value: single
|
||||||
option: [ single, multi ]
|
option: [ single, multi ]
|
||||||
|
|||||||
@@ -259,6 +259,9 @@ Coalition:
|
|||||||
UseAutoSearch: false
|
UseAutoSearch: false
|
||||||
Use2xBook: false
|
Use2xBook: false
|
||||||
AmbushEvade: true
|
AmbushEvade: true
|
||||||
|
Coalition:
|
||||||
|
Mode:
|
||||||
|
option: [ tc1, tc2, tc3, ex ]
|
||||||
StopCondition:
|
StopCondition:
|
||||||
MapAchievement: non_stop
|
MapAchievement: non_stop
|
||||||
StageIncrease: false
|
StageIncrease: false
|
||||||
@@ -288,7 +291,7 @@ CoalitionSp:
|
|||||||
AmbushEvade: true
|
AmbushEvade: true
|
||||||
Coalition:
|
Coalition:
|
||||||
# CoalitionSp hard-codes Mode='sp'
|
# CoalitionSp hard-codes Mode='sp'
|
||||||
Mode: hard
|
Mode: sp
|
||||||
StopCondition:
|
StopCondition:
|
||||||
MapAchievement: non_stop
|
MapAchievement: non_stop
|
||||||
StageIncrease: false
|
StageIncrease: false
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ class GeneratedConfig:
|
|||||||
MaritimeEscort_Enable = True
|
MaritimeEscort_Enable = True
|
||||||
|
|
||||||
# Group `Coalition`
|
# Group `Coalition`
|
||||||
Coalition_Mode = 'TC1' # TC1, TC2, TC3, EX
|
Coalition_Mode = 'tc1' # tc1, tc2, tc3, sp, ex
|
||||||
Coalition_Fleet = 'single' # single, multi
|
Coalition_Fleet = 'single' # single, multi
|
||||||
|
|
||||||
# Group `Commission`
|
# Group `Commission`
|
||||||
|
|||||||
@@ -616,6 +616,8 @@ class ConfigUpdater:
|
|||||||
# 'GemsFarming.GemsFarming.ChangeVanguard',
|
# 'GemsFarming.GemsFarming.ChangeVanguard',
|
||||||
# change_ship_redirect),
|
# change_ship_redirect),
|
||||||
# ('Alas.DropRecord.API', 'Alas.DropRecord.API', api_redirect2)
|
# ('Alas.DropRecord.API', 'Alas.DropRecord.API', api_redirect2)
|
||||||
|
# 2025.04.17
|
||||||
|
('Coalition.Coalition.Mode', 'Coalition.Coalition.Mode', coalition_to_frostfall)
|
||||||
]
|
]
|
||||||
# redirection += [
|
# redirection += [
|
||||||
# (
|
# (
|
||||||
|
|||||||
@@ -1367,10 +1367,11 @@
|
|||||||
"Mode": {
|
"Mode": {
|
||||||
"name": "Mode",
|
"name": "Mode",
|
||||||
"help": "SP needs to use event daily SP to run",
|
"help": "SP needs to use event daily SP to run",
|
||||||
"TC1": "TC1",
|
"tc1": "tc1",
|
||||||
"TC2": "TC2",
|
"tc2": "tc2",
|
||||||
"TC3": "TC3",
|
"tc3": "tc3",
|
||||||
"EX": "EX"
|
"sp": "sp",
|
||||||
|
"ex": "EX"
|
||||||
},
|
},
|
||||||
"Fleet": {
|
"Fleet": {
|
||||||
"name": "Fleet",
|
"name": "Fleet",
|
||||||
|
|||||||
@@ -87,7 +87,7 @@
|
|||||||
"help": ""
|
"help": ""
|
||||||
},
|
},
|
||||||
"Coalition": {
|
"Coalition": {
|
||||||
"name": "リトル学園",
|
"name": "星霜海嵐",
|
||||||
"help": ""
|
"help": ""
|
||||||
},
|
},
|
||||||
"MaritimeEscort": {
|
"MaritimeEscort": {
|
||||||
@@ -123,8 +123,8 @@
|
|||||||
"help": ""
|
"help": ""
|
||||||
},
|
},
|
||||||
"CoalitionSp": {
|
"CoalitionSp": {
|
||||||
"name": "Task.CoalitionSp.name",
|
"name": "星霜海嵐SP",
|
||||||
"help": "Task.CoalitionSp.help"
|
"help": ""
|
||||||
},
|
},
|
||||||
"Commission": {
|
"Commission": {
|
||||||
"name": "委託",
|
"name": "委託",
|
||||||
@@ -156,7 +156,7 @@
|
|||||||
},
|
},
|
||||||
"Awaken": {
|
"Awaken": {
|
||||||
"name": "Task.Awaken.name",
|
"name": "Task.Awaken.name",
|
||||||
"help": "Task.Awaken.help"
|
"help": ""
|
||||||
},
|
},
|
||||||
"Daily": {
|
"Daily": {
|
||||||
"name": "デイリー",
|
"name": "デイリー",
|
||||||
@@ -192,7 +192,7 @@
|
|||||||
},
|
},
|
||||||
"Minigame": {
|
"Minigame": {
|
||||||
"name": "Task.Minigame.name",
|
"name": "Task.Minigame.name",
|
||||||
"help": "Task.Minigame.help"
|
"help": ""
|
||||||
},
|
},
|
||||||
"OpsiGeneral": {
|
"OpsiGeneral": {
|
||||||
"name": "一般設定",
|
"name": "一般設定",
|
||||||
@@ -1367,10 +1367,11 @@
|
|||||||
"Mode": {
|
"Mode": {
|
||||||
"name": "Coalition.Mode.name",
|
"name": "Coalition.Mode.name",
|
||||||
"help": "Coalition.Mode.help",
|
"help": "Coalition.Mode.help",
|
||||||
"TC1": "TC1",
|
"tc1": "tc1",
|
||||||
"TC2": "TC2",
|
"tc2": "tc2",
|
||||||
"TC3": "TC3",
|
"tc3": "tc3",
|
||||||
"EX": "EX"
|
"sp": "sp",
|
||||||
|
"ex": "ex"
|
||||||
},
|
},
|
||||||
"Fleet": {
|
"Fleet": {
|
||||||
"name": "Coalition.Fleet.name",
|
"name": "Coalition.Fleet.name",
|
||||||
|
|||||||
@@ -1367,10 +1367,11 @@
|
|||||||
"Mode": {
|
"Mode": {
|
||||||
"name": "难度",
|
"name": "难度",
|
||||||
"help": "SP图需要使用活动每日SP运行",
|
"help": "SP图需要使用活动每日SP运行",
|
||||||
"TC1": "TC1",
|
"tc1": "tc1",
|
||||||
"TC2": "TC2",
|
"tc2": "tc2",
|
||||||
"TC3": "TC3",
|
"tc3": "tc3",
|
||||||
"EX": "EX"
|
"sp": "sp",
|
||||||
|
"ex": "EX"
|
||||||
},
|
},
|
||||||
"Fleet": {
|
"Fleet": {
|
||||||
"name": "出击队伍",
|
"name": "出击队伍",
|
||||||
|
|||||||
@@ -1367,10 +1367,11 @@
|
|||||||
"Mode": {
|
"Mode": {
|
||||||
"name": "難度",
|
"name": "難度",
|
||||||
"help": "SP圖需要使用活動每日SP運行",
|
"help": "SP圖需要使用活動每日SP運行",
|
||||||
"TC1": "TC1",
|
"tc1": "tc1",
|
||||||
"TC2": "TC2",
|
"tc2": "tc2",
|
||||||
"TC3": "TC3",
|
"tc3": "tc3",
|
||||||
"EX": "EX"
|
"sp": "sp",
|
||||||
|
"ex": "EX"
|
||||||
},
|
},
|
||||||
"Fleet": {
|
"Fleet": {
|
||||||
"name": "出擊隊伍",
|
"name": "出擊隊伍",
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ def emotion_mode_redirect(value):
|
|||||||
|
|
||||||
def change_ship_redirect(value):
|
def change_ship_redirect(value):
|
||||||
"""
|
"""
|
||||||
FlagshipChange + FlagshipEquipChange -> ChangeFlagship
|
FlagshipChange + FlagshipEquipChange -> ChangeFlagship
|
||||||
"""
|
"""
|
||||||
ship, equip = value
|
ship, equip = value
|
||||||
if not ship:
|
if not ship:
|
||||||
@@ -93,6 +93,7 @@ def change_ship_redirect(value):
|
|||||||
else:
|
else:
|
||||||
return 'ship'
|
return 'ship'
|
||||||
|
|
||||||
|
|
||||||
def api_redirect2(value):
|
def api_redirect2(value):
|
||||||
"""
|
"""
|
||||||
remove shanghai proxy, use guangzhou
|
remove shanghai proxy, use guangzhou
|
||||||
@@ -100,4 +101,32 @@ def api_redirect2(value):
|
|||||||
if value == 'cn_sh_reverse_proxy':
|
if value == 'cn_sh_reverse_proxy':
|
||||||
return 'cn_gz_reverse_proxy'
|
return 'cn_gz_reverse_proxy'
|
||||||
else:
|
else:
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def coalition_to_frostfall(value):
|
||||||
|
"""
|
||||||
|
Redirect Little Academy stage names to Frostfall
|
||||||
|
"""
|
||||||
|
if value == 'easy':
|
||||||
|
return 'tc1'
|
||||||
|
elif value == 'normal':
|
||||||
|
return 'tc2'
|
||||||
|
elif value == 'hard':
|
||||||
|
return 'tc3'
|
||||||
|
else:
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def coalition_to_little_academy(value):
|
||||||
|
"""
|
||||||
|
Redirect Little Academy stage names to Frostfall
|
||||||
|
"""
|
||||||
|
if value == 'tc1':
|
||||||
|
return 'easy'
|
||||||
|
elif value == 'tc2':
|
||||||
|
return 'normal'
|
||||||
|
elif value == 'tc3':
|
||||||
|
return 'hard'
|
||||||
|
else:
|
||||||
|
return value
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ from uiautomator2.xpath import XPath, XPathSelector
|
|||||||
import module.config.server as server
|
import module.config.server as server
|
||||||
from module.base.timer import Timer
|
from module.base.timer import Timer
|
||||||
from module.base.utils import color_similarity_2d, crop, random_rectangle_point
|
from module.base.utils import color_similarity_2d, crop, random_rectangle_point
|
||||||
from module.exception import (GameStuckError, GameTooManyClickError,
|
|
||||||
RequestHumanTakeover)
|
|
||||||
from module.handler.assets import *
|
from module.handler.assets import *
|
||||||
from module.logger import logger
|
from module.logger import logger
|
||||||
from module.map.assets import *
|
from module.map.assets import *
|
||||||
@@ -25,12 +23,19 @@ class LoginHandler(UI):
|
|||||||
Pages:
|
Pages:
|
||||||
in: Any page
|
in: Any page
|
||||||
out: page_main
|
out: page_main
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
GameStuckError:
|
||||||
|
GameTooManyClickError:
|
||||||
|
GameNotRunningError:
|
||||||
"""
|
"""
|
||||||
logger.hr('App login')
|
logger.hr('App login')
|
||||||
|
|
||||||
confirm_timer = Timer(1.5, count=4).start()
|
confirm_timer = Timer(1.5, count=4).start()
|
||||||
orientation_timer = Timer(5)
|
orientation_timer = Timer(5)
|
||||||
login_success = False
|
login_success = False
|
||||||
|
self.device.stuck_record_clear()
|
||||||
|
self.device.click_record_clear()
|
||||||
|
|
||||||
while 1:
|
while 1:
|
||||||
# Watch device rotation
|
# Watch device rotation
|
||||||
@@ -124,23 +129,16 @@ class LoginHandler(UI):
|
|||||||
bool: If login success
|
bool: If login success
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RequestHumanTakeover: If login failed more than 3
|
GameStuckError:
|
||||||
|
GameTooManyClickError:
|
||||||
|
GameNotRunningError:
|
||||||
"""
|
"""
|
||||||
for _ in range(3):
|
logger.info('handle_app_login')
|
||||||
self.device.stuck_record_clear()
|
self.device.screenshot_interval_set(1.0)
|
||||||
self.device.click_record_clear()
|
try:
|
||||||
try:
|
self._handle_app_login()
|
||||||
self._handle_app_login()
|
finally:
|
||||||
return True
|
self.device.screenshot_interval_set()
|
||||||
except (GameTooManyClickError, GameStuckError) as e:
|
|
||||||
logger.warning(e)
|
|
||||||
self.device.app_stop()
|
|
||||||
self.device.app_start()
|
|
||||||
continue
|
|
||||||
|
|
||||||
logger.critical('Login failed more than 3')
|
|
||||||
logger.critical('Azur Lane server may be under maintenance, or you may lost network connection')
|
|
||||||
raise RequestHumanTakeover
|
|
||||||
|
|
||||||
def app_stop(self):
|
def app_stop(self):
|
||||||
logger.hr('App stop')
|
logger.hr('App stop')
|
||||||
|
|||||||