Compare commits
27 Commits
c27bd74050
...
v0.2.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
15bf77da3d
|
|||
|
4ce8073096
|
|||
|
aa872c890d
|
|||
|
25e0559171
|
|||
|
df6da1f77a
|
|||
|
fc49adc859
|
|||
|
4582406ef2
|
|||
|
256dc96598
|
|||
|
04744d6f8c
|
|||
|
8fe578615d
|
|||
|
5e9615542c
|
|||
|
36c5f60eb3
|
|||
|
91650cc584
|
|||
|
67881568dd
|
|||
|
f8404edd9e
|
|||
|
ff3ec041d2
|
|||
|
99074a1575
|
|||
|
7862fa6cb8
|
|||
|
baac90ecf0
|
|||
|
53ec298fed
|
|||
|
b4f18f78ff
|
|||
|
eb9af42f38
|
|||
|
c29d972c6c
|
|||
|
92b34d4760
|
|||
|
04853b6c31
|
|||
|
9604e8962a
|
|||
|
03380b2d71
|
@@ -22,7 +22,12 @@ The script is still under active development. The following features have been i
|
||||
Supported servers:
|
||||
|
||||
- [x] JP
|
||||
- [x] OVERSEA - Global
|
||||
- [x] OVERSEA
|
||||
|
||||
Supported in-game languages:
|
||||
|
||||
- [x] Japanese
|
||||
- [x] English
|
||||
|
||||
## Relative projects
|
||||
|
||||
|
||||
@@ -22,12 +22,18 @@
|
||||
目前支持的服务器:
|
||||
|
||||
- [x] 日服
|
||||
- [x] 国际服 - 全球
|
||||
- [x] 国际服
|
||||
|
||||
目前支持的游戏内语言:
|
||||
|
||||
- [x] 日语
|
||||
- [x] 英语
|
||||
|
||||
## 已知问题
|
||||
|
||||
若愿意提供其他服务器支持,请开 PR 或 Issue。
|
||||
若愿意提供其他语言或国服支持,请开 PR 或 Issue。
|
||||
|
||||
- **国际服登录的全屏通知**:未实现自动关闭,正在研究中
|
||||
- **大小月卡**:未实现自动领取,~~因为没买过~~,可能不影响使用。愿意提供图片的请开 Issue
|
||||
- **月卡的额外悬赏券和学院交流券**:不太清楚月卡领取额外券的机制,~~因为没买过~~,可能影响相关任务使用券和体力的计算。愿意提供相关信息的请开
|
||||
Issue
|
||||
|
||||
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 6.0 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 8.3 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 129 KiB |
|
After Width: | Height: | Size: 6.8 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 905 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 905 KiB After Width: | Height: | Size: 905 KiB |
|
After Width: | Height: | Size: 1016 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
@@ -128,8 +128,8 @@ Deploy:
|
||||
WebuiHost: 0.0.0.0
|
||||
# --port. Port to listen
|
||||
# You will be able to access webui via `http://{host}:{port}`
|
||||
# [In most cases] Default to 22367
|
||||
WebuiPort: 22367
|
||||
# [In most cases] Default to 23467
|
||||
WebuiPort: 23467
|
||||
# Language to use on web ui
|
||||
# 'zh-CN' for Chinese simplified
|
||||
# 'en-US' for English
|
||||
|
||||
@@ -128,8 +128,8 @@ Deploy:
|
||||
WebuiHost: 0.0.0.0
|
||||
# --port. Port to listen
|
||||
# You will be able to access webui via `http://{host}:{port}`
|
||||
# [In most cases] Default to 22367
|
||||
WebuiPort: 22367
|
||||
# [In most cases] Default to 23467
|
||||
WebuiPort: 23467
|
||||
# Language to use on web ui
|
||||
# 'zh-CN' for Chinese simplified
|
||||
# 'en-US' for English
|
||||
|
||||
@@ -55,7 +55,7 @@ class ConfigModel:
|
||||
|
||||
# Webui
|
||||
WebuiHost: str = "0.0.0.0"
|
||||
WebuiPort: int = 22367
|
||||
WebuiPort: int = 23467
|
||||
Language: str = "en-US"
|
||||
Theme: str = "default"
|
||||
DpiScaling: bool = True
|
||||
@@ -77,6 +77,12 @@ class DeployConfig(ConfigModel):
|
||||
self.config_template = {}
|
||||
self.read()
|
||||
|
||||
self.set_repo()
|
||||
|
||||
self.write()
|
||||
self.show_config()
|
||||
|
||||
def set_repo(self):
|
||||
# Bypass webui.config.DeployConfig.__setattr__()
|
||||
# Don't write these into deploy.yaml
|
||||
if self.Repository == 'cn':
|
||||
@@ -84,9 +90,6 @@ class DeployConfig(ConfigModel):
|
||||
if self.Repository == 'global':
|
||||
super().__setattr__('Repository', 'https://github.com/TheFunny/ArisuAutoSweeper')
|
||||
|
||||
self.write()
|
||||
self.show_config()
|
||||
|
||||
def show_config(self):
|
||||
logger.hr("Show deploy config", 1)
|
||||
for k, v in self.config.items():
|
||||
|
||||
@@ -128,8 +128,8 @@ Deploy:
|
||||
WebuiHost: 0.0.0.0
|
||||
# --port. Port to listen
|
||||
# You will be able to access webui via `http://{host}:{port}`
|
||||
# [In most cases] Default to 22367
|
||||
WebuiPort: 22367
|
||||
# [In most cases] Default to 23467
|
||||
WebuiPort: 23467
|
||||
# Language to use on web ui
|
||||
# 'zh-CN' for Chinese simplified
|
||||
# 'en-US' for English
|
||||
|
||||
@@ -179,20 +179,29 @@ def iter_assets():
|
||||
if image.attr != '':
|
||||
row = deep_get(data, keys=[image.module, image.assets, image.server, image.frame])
|
||||
row.load_image(image)
|
||||
# Apply `search` of the first frame to all
|
||||
# Set `search`
|
||||
for path, frames in deep_iter(data, depth=3):
|
||||
print(path, frames)
|
||||
# If `search` attribute is set in the first frame, apply to all
|
||||
first = frames[1]
|
||||
search = first.search if first.search else DataAssets.area_to_search(first.area)
|
||||
for frame in frames.values():
|
||||
frame.search = search
|
||||
if first.search:
|
||||
for frame in frames.values():
|
||||
frame.search = first.search
|
||||
else:
|
||||
for frame in frames.values():
|
||||
if frame.search:
|
||||
# Follow frame specific `search`
|
||||
pass
|
||||
else:
|
||||
# Generate `search` from `area`
|
||||
frame.search = DataAssets.area_to_search(frame.area)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def generate_code():
|
||||
all = iter_assets()
|
||||
for module, module_data in all.items():
|
||||
all_assets = iter_assets()
|
||||
for module, module_data in all_assets.items():
|
||||
path = os.path.join(AzurLaneConfig.ASSETS_MODULE, module.split('/', maxsplit=1)[0])
|
||||
output = os.path.join(path, 'assets.py')
|
||||
if os.path.exists(output):
|
||||
@@ -204,7 +213,7 @@ def generate_code():
|
||||
continue
|
||||
os.remove(prev)
|
||||
|
||||
for module, module_data in all.items():
|
||||
for module, module_data in all_assets.items():
|
||||
path = os.path.join(AzurLaneConfig.ASSETS_MODULE, module.split('/', maxsplit=1)[0])
|
||||
output = os.path.join(path, 'assets')
|
||||
gen = CodeGenerator()
|
||||
|
||||
@@ -49,7 +49,7 @@ def func(ev: threading.Event):
|
||||
args, _ = parser.parse_known_args()
|
||||
|
||||
host = args.host or State.deploy_config.WebuiHost or "0.0.0.0"
|
||||
port = args.port or int(State.deploy_config.WebuiPort) or 22367
|
||||
port = args.port or int(State.deploy_config.WebuiPort) or 23467
|
||||
State.electron = args.electron
|
||||
|
||||
logger.hr("Launcher config")
|
||||
|
||||
@@ -74,7 +74,7 @@ class Button(Resource):
|
||||
threshold=threshold
|
||||
)
|
||||
|
||||
def match_template(self, image, similarity=0.85) -> bool:
|
||||
def match_template(self, image, similarity=0.85, direct_match=False) -> bool:
|
||||
"""
|
||||
Detects assets by template matching.
|
||||
|
||||
@@ -83,18 +83,45 @@ class Button(Resource):
|
||||
Args:
|
||||
image: Screenshot.
|
||||
similarity (float): 0-1.
|
||||
direct_match: True to ignore `self.search`
|
||||
|
||||
Returns:
|
||||
bool.
|
||||
"""
|
||||
image = crop(image, self.search, copy=False)
|
||||
if not direct_match:
|
||||
image = crop(image, self.search, copy=False)
|
||||
res = cv2.matchTemplate(self.image, image, cv2.TM_CCOEFF_NORMED)
|
||||
_, sim, _, point = cv2.minMaxLoc(res)
|
||||
|
||||
self._button_offset = np.array(point) + self.search[:2] - self.area[:2]
|
||||
return sim > similarity
|
||||
|
||||
def match_template_color(self, image, similarity=0.85, threshold=30) -> bool:
|
||||
def match_multi_template(self, image, similarity=0.85, direct_match=False):
|
||||
"""
|
||||
Detects assets by template matching, return multiple reults
|
||||
|
||||
Args:
|
||||
image: Screenshot.
|
||||
similarity (float): 0-1.
|
||||
direct_match: True to ignore `self.search`
|
||||
|
||||
Returns:
|
||||
list:
|
||||
"""
|
||||
if not direct_match:
|
||||
image = crop(image, self.search, copy=False)
|
||||
res = cv2.matchTemplate(self.image, image, cv2.TM_CCOEFF_NORMED)
|
||||
res = cv2.inRange(res, similarity, 1.)
|
||||
try:
|
||||
points = np.array(cv2.findNonZero(res))[:, 0, :]
|
||||
points += self.search[:2]
|
||||
return points.tolist()
|
||||
except IndexError:
|
||||
# Empty result
|
||||
# IndexError: too many indices for array: array is 0-dimensional, but 3 were indexed
|
||||
return []
|
||||
|
||||
def match_template_color(self, image, similarity=0.85, threshold=30, direct_match=False) -> bool:
|
||||
"""
|
||||
Template match first, color match then
|
||||
|
||||
@@ -102,11 +129,12 @@ class Button(Resource):
|
||||
image: Screenshot.
|
||||
similarity (float): 0-1.
|
||||
threshold (int): Default to 10.
|
||||
direct_match: True to ignore `self.search`
|
||||
|
||||
Returns:
|
||||
|
||||
bool.
|
||||
"""
|
||||
matched = self.match_template(image, similarity=similarity)
|
||||
matched = self.match_template(image, similarity=similarity, direct_match=direct_match)
|
||||
if not matched:
|
||||
return False
|
||||
|
||||
@@ -124,10 +152,10 @@ class ButtonWrapper(Resource):
|
||||
self.name = name
|
||||
self.data_buttons = kwargs
|
||||
self._matched_button: t.Optional[Button] = None
|
||||
self.resource_add(self.name)
|
||||
self.resource_add(f'{name}:{next(self.iter_buttons(), None)}')
|
||||
|
||||
def resource_release(self):
|
||||
del_cached_property(self, 'assets')
|
||||
del_cached_property(self, 'buttons')
|
||||
self._matched_button = None
|
||||
|
||||
def __str__(self):
|
||||
@@ -144,16 +172,25 @@ class ButtonWrapper(Resource):
|
||||
def __bool__(self):
|
||||
return True
|
||||
|
||||
def iter_buttons(self) -> t.Iterator[Button]:
|
||||
for _, assets in self.data_buttons.items():
|
||||
if isinstance(assets, Button):
|
||||
yield assets
|
||||
elif isinstance(assets, list):
|
||||
for asset in assets:
|
||||
yield asset
|
||||
|
||||
@cached_property
|
||||
def buttons(self) -> t.List[Button]:
|
||||
# for trial in [server.lang, 'share', 'cn']:
|
||||
for trial in [server.lang, 'share', 'jp']:
|
||||
assets = self.data_buttons.get(trial, None)
|
||||
if assets is not None:
|
||||
for trial in [server.lang, 'share', 'cn']:
|
||||
try:
|
||||
assets = self.data_buttons[trial]
|
||||
if isinstance(assets, Button):
|
||||
return [assets]
|
||||
elif isinstance(assets, list):
|
||||
return assets
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
raise ScriptError(f'ButtonWrapper({self}) on server {server.lang} has no fallback button')
|
||||
|
||||
@@ -164,16 +201,45 @@ class ButtonWrapper(Resource):
|
||||
return True
|
||||
return False
|
||||
|
||||
def match_template(self, image, similarity=0.85) -> bool:
|
||||
def match_template(self, image, similarity=0.85, direct_match=False) -> bool:
|
||||
for assets in self.buttons:
|
||||
if assets.match_template(image, similarity=similarity):
|
||||
if assets.match_template(image, similarity=similarity, direct_match=direct_match):
|
||||
self._matched_button = assets
|
||||
return True
|
||||
return False
|
||||
|
||||
def match_template_color(self, image, similarity=0.85, threshold=30) -> bool:
|
||||
def match_multi_template(self, image, similarity=0.85, threshold=5, direct_match=False):
|
||||
"""
|
||||
Detects assets by template matching, return multiple results
|
||||
|
||||
Args:
|
||||
image: Screenshot.
|
||||
similarity (float): 0-1.
|
||||
threshold:
|
||||
direct_match: True to ignore `self.search`
|
||||
|
||||
Returns:
|
||||
list[ClickButton]:
|
||||
"""
|
||||
ps = []
|
||||
for assets in self.buttons:
|
||||
if assets.match_template_color(image, similarity=similarity, threshold=threshold):
|
||||
ps += assets.match_multi_template(image, similarity=similarity, direct_match=direct_match)
|
||||
if not ps:
|
||||
return []
|
||||
|
||||
from module.base.utils.points import Points
|
||||
ps = Points(ps).group(threshold=threshold)
|
||||
area_list = [area_offset(self.area, p - self.area[:2]) for p in ps]
|
||||
button_list = [area_offset(self.button, p - self.area[:2]) for p in ps]
|
||||
return [
|
||||
ClickButton(area=info[0], button=info[1], name=f'{self.name}_result{i}')
|
||||
for i, info in enumerate(zip(area_list, button_list))
|
||||
]
|
||||
|
||||
def match_template_color(self, image, similarity=0.85, threshold=30, direct_match=False) -> bool:
|
||||
for assets in self.buttons:
|
||||
if assets.match_template_color(
|
||||
image, similarity=similarity, threshold=threshold, direct_match=direct_match):
|
||||
self._matched_button = assets
|
||||
return True
|
||||
return False
|
||||
@@ -222,18 +288,32 @@ class ButtonWrapper(Resource):
|
||||
"""
|
||||
if isinstance(button, ButtonWrapper):
|
||||
button = button.matched_button
|
||||
for b in self.buttons:
|
||||
for b in self.iter_buttons():
|
||||
b.load_offset(button)
|
||||
|
||||
def clear_offset(self):
|
||||
for b in self.buttons:
|
||||
for b in self.iter_buttons():
|
||||
b.clear_offset()
|
||||
|
||||
def load_search(self, area):
|
||||
"""
|
||||
Set `search` attribute.
|
||||
Note that this method is irreversible.
|
||||
|
||||
Args:
|
||||
area:
|
||||
"""
|
||||
for b in self.iter_buttons():
|
||||
b.search = area
|
||||
|
||||
|
||||
class ClickButton:
|
||||
def __init__(self, button, name='CLICK_BUTTON'):
|
||||
self.area = button
|
||||
self.button = button
|
||||
def __init__(self, area, button=None, name='CLICK_BUTTON'):
|
||||
self.area = area
|
||||
if button is None:
|
||||
self.button = area
|
||||
else:
|
||||
self.button = button
|
||||
self.name = name
|
||||
|
||||
def __str__(self):
|
||||
@@ -265,4 +345,4 @@ def match_template(image, template, similarity=0.85):
|
||||
"""
|
||||
res = cv2.matchTemplate(image, template, cv2.TM_CCOEFF_NORMED)
|
||||
_, sim, _, point = cv2.minMaxLoc(res)
|
||||
return sim > similarity
|
||||
return sim > similarity
|
||||
@@ -1,11 +1,11 @@
|
||||
import re
|
||||
|
||||
import module.config.server as server
|
||||
from module.base.decorator import cached_property, del_cached_property
|
||||
from module.base.decorator import cached_property
|
||||
|
||||
|
||||
def get_assets_from_file(file, regex):
|
||||
def get_assets_from_file(file):
|
||||
assets = set()
|
||||
regex = re.compile(r"file='(.*?)'")
|
||||
with open(file, 'r', encoding='utf-8') as f:
|
||||
for row in f.readlines():
|
||||
result = regex.search(row)
|
||||
@@ -20,11 +20,9 @@ class PreservedAssets:
|
||||
assets = set()
|
||||
assets |= get_assets_from_file(
|
||||
file='./tasks/base/assets/assets_base_page.py',
|
||||
regex=re.compile(r'^([A-Za-z][A-Za-z0-9_]+) = ')
|
||||
)
|
||||
assets |= get_assets_from_file(
|
||||
file='./tasks/base/assets/assets_base_popup.py',
|
||||
regex=re.compile(r'^([A-Za-z][A-Za-z0-9_]+) = ')
|
||||
)
|
||||
return assets
|
||||
|
||||
@@ -44,11 +42,13 @@ class Resource:
|
||||
|
||||
@classmethod
|
||||
def is_loaded(cls, obj):
|
||||
if hasattr(obj, '_image') and obj._image is None:
|
||||
return False
|
||||
elif hasattr(obj, 'image') and obj.image is None:
|
||||
return False
|
||||
return True
|
||||
if hasattr(obj, '_image') and obj._image is not None:
|
||||
return True
|
||||
if hasattr(obj, 'image') and obj.image is not None:
|
||||
return True
|
||||
if hasattr(obj, 'buttons') and obj.buttons is not None:
|
||||
return True
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def resource_show(cls):
|
||||
@@ -56,11 +56,16 @@ class Resource:
|
||||
logger.hr('Show resource')
|
||||
for key, obj in cls.instances.items():
|
||||
if cls.is_loaded(obj):
|
||||
continue
|
||||
logger.info(f'{obj}: {key}')
|
||||
logger.info(f'{obj}: {key}')
|
||||
|
||||
|
||||
def release_resources(next_task=''):
|
||||
# Release all OCR models
|
||||
# det models take 400MB
|
||||
if not next_task:
|
||||
from module.ocr.models import OCR_MODEL
|
||||
OCR_MODEL.resource_release()
|
||||
|
||||
# Release assets cache
|
||||
# module.ui has about 80 assets and takes about 3MB
|
||||
# Alas has about 800 assets, but they are not all loaded.
|
||||
@@ -74,4 +79,4 @@ def release_resources(next_task=''):
|
||||
obj.resource_release()
|
||||
|
||||
# Useless in most cases, but just call it
|
||||
# gc.collect()
|
||||
# gc.collect()
|
||||
@@ -12,6 +12,10 @@
|
||||
"option": [
|
||||
"auto",
|
||||
"JP-Official",
|
||||
"OVERSEA-TWHKMO",
|
||||
"OVERSEA-Korea",
|
||||
"OVERSEA-Asia",
|
||||
"OVERSEA-America",
|
||||
"OVERSEA-Global"
|
||||
]
|
||||
},
|
||||
|
||||
@@ -17,7 +17,7 @@ class GeneratedConfig:
|
||||
|
||||
# Group `Emulator`
|
||||
Emulator_Serial = 'auto'
|
||||
Emulator_PackageName = 'auto' # auto, JP-Official, OVERSEA-Global
|
||||
Emulator_PackageName = 'auto' # auto, JP-Official, OVERSEA-TWHKMO, OVERSEA-Korea, OVERSEA-Asia, OVERSEA-America, OVERSEA-Global
|
||||
Emulator_GameLanguage = 'auto' # auto, jp, en
|
||||
Emulator_ScreenshotMethod = 'auto' # auto, ADB, ADB_nc, uiautomator2, aScreenCap, aScreenCap_nc, DroidCast, DroidCast_raw, scrcpy
|
||||
Emulator_ControlMethod = 'MaaTouch' # minitouch, MaaTouch
|
||||
|
||||
@@ -458,7 +458,8 @@ class ConfigUpdater:
|
||||
value = deep_get(old, keys=keys, default=data['value'])
|
||||
typ = data['type']
|
||||
display = data.get('display')
|
||||
if is_template or value is None or value == '' or typ == 'lock' or (display == 'hide' and typ != 'stored'):
|
||||
if (is_template or value is None or value == ''
|
||||
or typ in ['lock', 'state'] or (display == 'hide' and typ != 'stored')):
|
||||
value = data['value']
|
||||
value = parse_value(value, data=data)
|
||||
deep_set(new, keys=keys, value=value)
|
||||
|
||||
@@ -85,11 +85,15 @@
|
||||
"help": "Can't distinguish different regions of oversea servers, please select the server manually.",
|
||||
"auto": "Auto-detect",
|
||||
"JP-Official": "[JP]-Official",
|
||||
"OVERSEA-TWHKMO": "[OVERSEA]-TW/HK/MO",
|
||||
"OVERSEA-Korea": "[OVERSEA]-Korea",
|
||||
"OVERSEA-Asia": "[OVERSEA]-Asia",
|
||||
"OVERSEA-America": "[OVERSEA]-North America",
|
||||
"OVERSEA-Global": "[OVERSEA]-Global"
|
||||
},
|
||||
"GameLanguage": {
|
||||
"name": "In-game Text Language",
|
||||
"help": "",
|
||||
"help": "Can't detect language automatically, please select the language manually.",
|
||||
"auto": "Auto-detect",
|
||||
"jp": "Japanese",
|
||||
"en": "English"
|
||||
|
||||
@@ -85,11 +85,15 @@
|
||||
"help": "无法区分国际服的不同地区,请手动选择服务器",
|
||||
"auto": "自动检测",
|
||||
"JP-Official": "[日服]-官服",
|
||||
"OVERSEA-TWHKMO": "[国际服]-港澳台",
|
||||
"OVERSEA-Korea": "[国际服]-韩国",
|
||||
"OVERSEA-Asia": "[国际服]-亚洲",
|
||||
"OVERSEA-America": "[国际服]-北美",
|
||||
"OVERSEA-Global": "[国际服]-全球"
|
||||
},
|
||||
"GameLanguage": {
|
||||
"name": "游戏内文本语言",
|
||||
"help": "",
|
||||
"help": "无法自动检测语言,请手动选择语言",
|
||||
"auto": "自动检测",
|
||||
"jp": "日语",
|
||||
"en": "英语"
|
||||
|
||||
@@ -8,6 +8,10 @@ server = 'JP-Official'
|
||||
VALID_LANG = ['jp', 'en']
|
||||
VALID_SERVER = {
|
||||
'JP-Official': 'com.YostarJP.BlueArchive',
|
||||
'OVERSEA-TWHKMO': 'com.nexon.bluearchive',
|
||||
'OVERSEA-Korea': 'com.nexon.bluearchive',
|
||||
'OVERSEA-Asia': 'com.nexon.bluearchive',
|
||||
'OVERSEA-America': 'com.nexon.bluearchive',
|
||||
'OVERSEA-Global': 'com.nexon.bluearchive',
|
||||
}
|
||||
VALID_PACKAGE = set(list(VALID_SERVER.values()))
|
||||
|
||||
@@ -13,7 +13,11 @@ from module.config.atomicwrites import atomic_write
|
||||
LANGUAGES = ['zh-CN', 'en-US']
|
||||
SERVER_TO_TIMEZONE = {
|
||||
'JP-Official': timedelta(hours=9),
|
||||
'OVERSEA-Global': timedelta(hours=0),
|
||||
'OVERSEA-TWHKMO': timedelta(hours=9),
|
||||
'OVERSEA-Korea': timedelta(hours=9),
|
||||
'OVERSEA-Asia': timedelta(hours=9),
|
||||
'OVERSEA-America': timedelta(hours=9),
|
||||
'OVERSEA-Global': timedelta(hours=9),
|
||||
}
|
||||
DEFAULT_TIME = datetime(2020, 1, 1, 0, 0)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from pponnxcr import TextSystem as TextSystem_
|
||||
|
||||
from module.base.decorator import cached_property
|
||||
from module.base.decorator import cached_property, del_cached_property
|
||||
from module.exception import ScriptError
|
||||
|
||||
DIC_LANG_TO_MODEL = {
|
||||
@@ -56,6 +56,12 @@ class OcrModel:
|
||||
except AttributeError:
|
||||
raise ScriptError(f'OCR model under lang "{lang}" does not exists')
|
||||
|
||||
def resource_release(self):
|
||||
del_cached_property(self, 'zhs')
|
||||
del_cached_property(self, 'en')
|
||||
del_cached_property(self, 'ja')
|
||||
del_cached_property(self, 'zht')
|
||||
|
||||
@cached_property
|
||||
def zhs(self):
|
||||
return TextSystem('zhs')
|
||||
|
||||
@@ -89,12 +89,15 @@ def readable_time(before: str) -> str:
|
||||
elif diff < 60:
|
||||
# < 1 min
|
||||
return t("Gui.Dashboard.JustNow")
|
||||
elif diff < 3600:
|
||||
elif diff < 5400:
|
||||
# < 90 min
|
||||
return t("Gui.Dashboard.MinutesAgo", time=int(diff // 60))
|
||||
elif diff < 86400:
|
||||
elif diff < 129600:
|
||||
# < 36 hours
|
||||
return t("Gui.Dashboard.HoursAgo", time=int(diff // 3600))
|
||||
elif diff < 1296000:
|
||||
# < 15 days
|
||||
return t("Gui.Dashboard.DaysAgo", time=int(diff // 86400))
|
||||
else:
|
||||
# > 15 days
|
||||
# >= 15 days
|
||||
return t("Gui.Dashboard.LongTimeAgo")
|
||||
|
||||
@@ -16,8 +16,8 @@ import time
|
||||
from subprocess import PIPE, Popen
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from module.logger import logger
|
||||
from module.config.utils import random_id
|
||||
from module.logger import logger
|
||||
from module.webui.setting import State
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -41,7 +41,7 @@ def am_i_the_only_thread() -> bool:
|
||||
|
||||
def remote_access_service(
|
||||
local_host="127.0.0.1",
|
||||
local_port=22367,
|
||||
local_port=23467,
|
||||
server="app.pywebio.online",
|
||||
server_port=1022,
|
||||
remote_port="/",
|
||||
|
||||
@@ -5,6 +5,7 @@ import time
|
||||
from typing import Generator, List, Tuple
|
||||
|
||||
import requests
|
||||
|
||||
from deploy.Windows.config import ExecutionError
|
||||
from deploy.Windows.git import GitManager
|
||||
from deploy.Windows.pip import PipManager
|
||||
@@ -20,6 +21,7 @@ from module.webui.utils import TaskHandler, get_next_time
|
||||
class Updater(DeployConfig, GitManager, PipManager):
|
||||
def __init__(self, file=DEPLOY_CONFIG):
|
||||
super().__init__(file=file)
|
||||
self.set_repo()
|
||||
self.state = 0
|
||||
self.event: threading.Event = None
|
||||
|
||||
@@ -194,6 +196,7 @@ class Updater(DeployConfig, GitManager, PipManager):
|
||||
|
||||
def update(self):
|
||||
logger.hr("Run update")
|
||||
self.set_repo()
|
||||
try:
|
||||
self.git_install()
|
||||
self.pip_install()
|
||||
|
||||
@@ -9,17 +9,17 @@ from queue import Queue
|
||||
from typing import Callable, Generator, List
|
||||
|
||||
import pywebio
|
||||
from module.config.utils import deep_iter
|
||||
from module.logger import logger
|
||||
from module.webui.setting import State
|
||||
from pywebio.input import PASSWORD, input
|
||||
from pywebio.output import PopupSize, popup, put_html, toast
|
||||
from pywebio.session import eval_js
|
||||
from pywebio.session import info as session_info
|
||||
from pywebio.session import register_thread, run_js
|
||||
from rich.console import Console, ConsoleOptions
|
||||
from rich.console import Console
|
||||
from rich.terminal_theme import TerminalTheme
|
||||
|
||||
from module.config.utils import deep_iter
|
||||
from module.logger import logger
|
||||
from module.webui.setting import State
|
||||
|
||||
RE_DATETIME = (
|
||||
r"\d{4}\-(0\d|1[0-2])\-([0-2]\d|[3][0-1]) "
|
||||
@@ -455,7 +455,11 @@ def get_localstorage(key):
|
||||
|
||||
def re_fullmatch(pattern, string):
|
||||
if pattern == "datetime":
|
||||
pattern = RE_DATETIME
|
||||
try:
|
||||
datetime.datetime.fromisoformat(string)
|
||||
return True
|
||||
except ValueError:
|
||||
return False
|
||||
# elif:
|
||||
return re.fullmatch(pattern=pattern, string=string)
|
||||
|
||||
|
||||
@@ -22,15 +22,8 @@ ACCOUNT_INFO_CHECK = ButtonWrapper(
|
||||
)
|
||||
BACK = ButtonWrapper(
|
||||
name='BACK',
|
||||
jp=Button(
|
||||
file='./assets/jp/base/page/BACK.png',
|
||||
area=(34, 19, 81, 56),
|
||||
search=(14, 0, 101, 76),
|
||||
color=(93, 118, 164),
|
||||
button=(34, 19, 81, 56),
|
||||
),
|
||||
en=Button(
|
||||
file='./assets/en/base/page/BACK.png',
|
||||
share=Button(
|
||||
file='./assets/share/base/page/BACK.png',
|
||||
area=(34, 19, 81, 56),
|
||||
search=(14, 0, 101, 76),
|
||||
color=(93, 118, 164),
|
||||
@@ -141,15 +134,8 @@ GACHA_CHECK = ButtonWrapper(
|
||||
)
|
||||
HOME = ButtonWrapper(
|
||||
name='HOME',
|
||||
jp=Button(
|
||||
file='./assets/jp/base/page/HOME.png',
|
||||
area=(1218, 8, 1253, 41),
|
||||
search=(1198, 0, 1273, 61),
|
||||
color=(168, 182, 205),
|
||||
button=(1218, 8, 1253, 41),
|
||||
),
|
||||
en=Button(
|
||||
file='./assets/en/base/page/HOME.png',
|
||||
share=Button(
|
||||
file='./assets/share/base/page/HOME.png',
|
||||
area=(1218, 8, 1253, 41),
|
||||
search=(1198, 0, 1273, 61),
|
||||
color=(168, 182, 205),
|
||||
@@ -158,15 +144,8 @@ HOME = ButtonWrapper(
|
||||
)
|
||||
LOADING_CHECK = ButtonWrapper(
|
||||
name='LOADING_CHECK',
|
||||
jp=Button(
|
||||
file='./assets/jp/base/page/LOADING_CHECK.png',
|
||||
area=(1084, 659, 1120, 674),
|
||||
search=(1064, 639, 1140, 694),
|
||||
color=(173, 196, 219),
|
||||
button=(1084, 659, 1120, 674),
|
||||
),
|
||||
en=Button(
|
||||
file='./assets/en/base/page/LOADING_CHECK.png',
|
||||
share=Button(
|
||||
file='./assets/share/base/page/LOADING_CHECK.png',
|
||||
area=(1084, 659, 1120, 674),
|
||||
search=(1064, 639, 1140, 694),
|
||||
color=(173, 196, 219),
|
||||
@@ -192,15 +171,8 @@ MAIL_CHECK = ButtonWrapper(
|
||||
)
|
||||
MAIN_GO_TO_CAFE = ButtonWrapper(
|
||||
name='MAIN_GO_TO_CAFE',
|
||||
jp=Button(
|
||||
file='./assets/jp/base/page/MAIN_GO_TO_CAFE.png',
|
||||
area=(81, 638, 102, 668),
|
||||
search=(61, 618, 122, 688),
|
||||
color=(156, 209, 233),
|
||||
button=(81, 638, 102, 668),
|
||||
),
|
||||
en=Button(
|
||||
file='./assets/en/base/page/MAIN_GO_TO_CAFE.png',
|
||||
share=Button(
|
||||
file='./assets/share/base/page/MAIN_GO_TO_CAFE.png',
|
||||
area=(81, 638, 102, 668),
|
||||
search=(61, 618, 122, 688),
|
||||
color=(156, 209, 233),
|
||||
@@ -209,15 +181,8 @@ MAIN_GO_TO_CAFE = ButtonWrapper(
|
||||
)
|
||||
MAIN_GO_TO_CIRCLE = ButtonWrapper(
|
||||
name='MAIN_GO_TO_CIRCLE',
|
||||
jp=Button(
|
||||
file='./assets/jp/base/page/MAIN_GO_TO_CIRCLE.png',
|
||||
area=(540, 631, 583, 660),
|
||||
search=(520, 611, 603, 680),
|
||||
color=(131, 204, 234),
|
||||
button=(540, 631, 583, 660),
|
||||
),
|
||||
en=Button(
|
||||
file='./assets/en/base/page/MAIN_GO_TO_CIRCLE.png',
|
||||
share=Button(
|
||||
file='./assets/share/base/page/MAIN_GO_TO_CIRCLE.png',
|
||||
area=(540, 631, 583, 660),
|
||||
search=(520, 611, 603, 680),
|
||||
color=(131, 204, 234),
|
||||
@@ -226,15 +191,8 @@ MAIN_GO_TO_CIRCLE = ButtonWrapper(
|
||||
)
|
||||
MAIN_GO_TO_CRAFTING = ButtonWrapper(
|
||||
name='MAIN_GO_TO_CRAFTING',
|
||||
jp=Button(
|
||||
file='./assets/jp/base/page/MAIN_GO_TO_CRAFTING.png',
|
||||
area=(665, 622, 693, 664),
|
||||
search=(645, 602, 713, 684),
|
||||
color=(192, 229, 241),
|
||||
button=(665, 622, 693, 664),
|
||||
),
|
||||
en=Button(
|
||||
file='./assets/en/base/page/MAIN_GO_TO_CRAFTING.png',
|
||||
share=Button(
|
||||
file='./assets/share/base/page/MAIN_GO_TO_CRAFTING.png',
|
||||
area=(665, 622, 693, 664),
|
||||
search=(645, 602, 713, 684),
|
||||
color=(192, 229, 241),
|
||||
@@ -243,15 +201,8 @@ MAIN_GO_TO_CRAFTING = ButtonWrapper(
|
||||
)
|
||||
MAIN_GO_TO_GACHA = ButtonWrapper(
|
||||
name='MAIN_GO_TO_GACHA',
|
||||
jp=Button(
|
||||
file='./assets/jp/base/page/MAIN_GO_TO_GACHA.png',
|
||||
area=(900, 623, 924, 670),
|
||||
search=(880, 603, 944, 690),
|
||||
color=(157, 219, 241),
|
||||
button=(900, 623, 924, 670),
|
||||
),
|
||||
en=Button(
|
||||
file='./assets/en/base/page/MAIN_GO_TO_GACHA.png',
|
||||
share=Button(
|
||||
file='./assets/share/base/page/MAIN_GO_TO_GACHA.png',
|
||||
area=(900, 623, 924, 670),
|
||||
search=(880, 603, 944, 690),
|
||||
color=(157, 219, 241),
|
||||
@@ -260,15 +211,8 @@ MAIN_GO_TO_GACHA = ButtonWrapper(
|
||||
)
|
||||
MAIN_GO_TO_MAIL = ButtonWrapper(
|
||||
name='MAIN_GO_TO_MAIL',
|
||||
jp=Button(
|
||||
file='./assets/jp/base/page/MAIN_GO_TO_MAIL.png',
|
||||
area=(1130, 29, 1156, 49),
|
||||
search=(1110, 9, 1176, 69),
|
||||
color=(94, 121, 166),
|
||||
button=(1130, 29, 1156, 49),
|
||||
),
|
||||
en=Button(
|
||||
file='./assets/en/base/page/MAIN_GO_TO_MAIL.png',
|
||||
share=Button(
|
||||
file='./assets/share/base/page/MAIN_GO_TO_MAIL.png',
|
||||
area=(1130, 29, 1156, 49),
|
||||
search=(1110, 9, 1176, 69),
|
||||
color=(94, 121, 166),
|
||||
@@ -277,15 +221,8 @@ MAIN_GO_TO_MAIL = ButtonWrapper(
|
||||
)
|
||||
MAIN_GO_TO_MOMOTALK = ButtonWrapper(
|
||||
name='MAIN_GO_TO_MOMOTALK',
|
||||
jp=Button(
|
||||
file='./assets/jp/base/page/MAIN_GO_TO_MOMOTALK.png',
|
||||
area=(154, 134, 177, 158),
|
||||
search=(134, 114, 197, 178),
|
||||
color=(255, 219, 227),
|
||||
button=(154, 134, 177, 158),
|
||||
),
|
||||
en=Button(
|
||||
file='./assets/en/base/page/MAIN_GO_TO_MOMOTALK.png',
|
||||
share=Button(
|
||||
file='./assets/share/base/page/MAIN_GO_TO_MOMOTALK.png',
|
||||
area=(154, 134, 177, 158),
|
||||
search=(134, 114, 197, 178),
|
||||
color=(255, 219, 227),
|
||||
@@ -294,15 +231,8 @@ MAIN_GO_TO_MOMOTALK = ButtonWrapper(
|
||||
)
|
||||
MAIN_GO_TO_PURCHASE = ButtonWrapper(
|
||||
name='MAIN_GO_TO_PURCHASE',
|
||||
jp=Button(
|
||||
file='./assets/jp/base/page/MAIN_GO_TO_PURCHASE.png',
|
||||
area=(148, 204, 183, 253),
|
||||
search=(128, 184, 203, 273),
|
||||
color=(172, 214, 239),
|
||||
button=(148, 204, 183, 253),
|
||||
),
|
||||
en=Button(
|
||||
file='./assets/en/base/page/MAIN_GO_TO_PURCHASE.png',
|
||||
share=Button(
|
||||
file='./assets/share/base/page/MAIN_GO_TO_PURCHASE.png',
|
||||
area=(148, 204, 183, 253),
|
||||
search=(128, 184, 203, 273),
|
||||
color=(172, 214, 239),
|
||||
@@ -311,15 +241,8 @@ MAIN_GO_TO_PURCHASE = ButtonWrapper(
|
||||
)
|
||||
MAIN_GO_TO_SCHEDULE = ButtonWrapper(
|
||||
name='MAIN_GO_TO_SCHEDULE',
|
||||
jp=Button(
|
||||
file='./assets/jp/base/page/MAIN_GO_TO_SCHEDULE.png',
|
||||
area=(194, 638, 216, 672),
|
||||
search=(174, 618, 236, 692),
|
||||
color=(149, 194, 222),
|
||||
button=(194, 638, 216, 672),
|
||||
),
|
||||
en=Button(
|
||||
file='./assets/en/base/page/MAIN_GO_TO_SCHEDULE.png',
|
||||
share=Button(
|
||||
file='./assets/share/base/page/MAIN_GO_TO_SCHEDULE.png',
|
||||
area=(194, 638, 216, 672),
|
||||
search=(174, 618, 236, 692),
|
||||
color=(149, 194, 222),
|
||||
@@ -328,15 +251,8 @@ MAIN_GO_TO_SCHEDULE = ButtonWrapper(
|
||||
)
|
||||
MAIN_GO_TO_SHOP = ButtonWrapper(
|
||||
name='MAIN_GO_TO_SHOP',
|
||||
jp=Button(
|
||||
file='./assets/jp/base/page/MAIN_GO_TO_SHOP.png',
|
||||
area=(773, 630, 816, 667),
|
||||
search=(753, 610, 836, 687),
|
||||
color=(146, 208, 235),
|
||||
button=(773, 630, 816, 667),
|
||||
),
|
||||
en=Button(
|
||||
file='./assets/en/base/page/MAIN_GO_TO_SHOP.png',
|
||||
share=Button(
|
||||
file='./assets/share/base/page/MAIN_GO_TO_SHOP.png',
|
||||
area=(773, 630, 816, 667),
|
||||
search=(753, 610, 836, 687),
|
||||
color=(146, 208, 235),
|
||||
@@ -345,15 +261,8 @@ MAIN_GO_TO_SHOP = ButtonWrapper(
|
||||
)
|
||||
MAIN_GO_TO_TASK = ButtonWrapper(
|
||||
name='MAIN_GO_TO_TASK',
|
||||
jp=Button(
|
||||
file='./assets/jp/base/page/MAIN_GO_TO_TASK.png',
|
||||
area=(52, 220, 78, 248),
|
||||
search=(32, 200, 98, 268),
|
||||
color=(226, 207, 203),
|
||||
button=(52, 220, 78, 248),
|
||||
),
|
||||
en=Button(
|
||||
file='./assets/en/base/page/MAIN_GO_TO_TASK.png',
|
||||
share=Button(
|
||||
file='./assets/share/base/page/MAIN_GO_TO_TASK.png',
|
||||
area=(52, 220, 78, 248),
|
||||
search=(32, 200, 98, 268),
|
||||
color=(226, 207, 203),
|
||||
@@ -396,15 +305,8 @@ MISSION_CHECK = ButtonWrapper(
|
||||
)
|
||||
MOMOTALK_CHECK = ButtonWrapper(
|
||||
name='MOMOTALK_CHECK',
|
||||
jp=Button(
|
||||
file='./assets/jp/base/page/MOMOTALK_CHECK.png',
|
||||
area=(144, 107, 169, 130),
|
||||
search=(124, 87, 189, 150),
|
||||
color=(253, 211, 219),
|
||||
button=(144, 107, 169, 130),
|
||||
),
|
||||
en=Button(
|
||||
file='./assets/en/base/page/MOMOTALK_CHECK.png',
|
||||
share=Button(
|
||||
file='./assets/share/base/page/MOMOTALK_CHECK.png',
|
||||
area=(144, 107, 169, 130),
|
||||
search=(124, 87, 189, 150),
|
||||
color=(253, 211, 219),
|
||||
@@ -413,15 +315,8 @@ MOMOTALK_CHECK = ButtonWrapper(
|
||||
)
|
||||
MOMOTALK_GO_TO_MAIN = ButtonWrapper(
|
||||
name='MOMOTALK_GO_TO_MAIN',
|
||||
jp=Button(
|
||||
file='./assets/jp/base/page/MOMOTALK_GO_TO_MAIN.png',
|
||||
area=(1108, 105, 1134, 131),
|
||||
search=(1088, 85, 1154, 151),
|
||||
color=(252, 182, 194),
|
||||
button=(1108, 105, 1134, 131),
|
||||
),
|
||||
en=Button(
|
||||
file='./assets/en/base/page/MOMOTALK_GO_TO_MAIN.png',
|
||||
share=Button(
|
||||
file='./assets/share/base/page/MOMOTALK_GO_TO_MAIN.png',
|
||||
area=(1108, 105, 1134, 131),
|
||||
search=(1088, 85, 1154, 151),
|
||||
color=(252, 182, 194),
|
||||
|
||||
@@ -39,15 +39,8 @@ AP_EXCEED = ButtonWrapper(
|
||||
)
|
||||
DAILY_NEWS = ButtonWrapper(
|
||||
name='DAILY_NEWS',
|
||||
jp=Button(
|
||||
file='./assets/jp/base/popup/DAILY_NEWS.png',
|
||||
area=(120, 89, 326, 113),
|
||||
search=(100, 69, 346, 133),
|
||||
color=(150, 204, 253),
|
||||
button=(1128, 89, 1156, 117),
|
||||
),
|
||||
en=Button(
|
||||
file='./assets/en/base/popup/DAILY_NEWS.png',
|
||||
share=Button(
|
||||
file='./assets/share/base/popup/DAILY_NEWS.png',
|
||||
area=(120, 89, 326, 113),
|
||||
search=(100, 69, 346, 133),
|
||||
color=(150, 204, 253),
|
||||
@@ -56,15 +49,8 @@ DAILY_NEWS = ButtonWrapper(
|
||||
)
|
||||
DAILY_REWARD = ButtonWrapper(
|
||||
name='DAILY_REWARD',
|
||||
jp=Button(
|
||||
file='./assets/jp/base/popup/DAILY_REWARD.png',
|
||||
area=(416, 165, 434, 216),
|
||||
search=(396, 145, 454, 236),
|
||||
color=(203, 227, 237),
|
||||
button=(920, 632, 1140, 712),
|
||||
),
|
||||
en=Button(
|
||||
file='./assets/en/base/popup/DAILY_REWARD.png',
|
||||
share=Button(
|
||||
file='./assets/share/base/popup/DAILY_REWARD.png',
|
||||
area=(416, 165, 434, 216),
|
||||
search=(396, 145, 454, 236),
|
||||
color=(203, 227, 237),
|
||||
@@ -73,15 +59,8 @@ DAILY_REWARD = ButtonWrapper(
|
||||
)
|
||||
GET_NEW_STUDENT = ButtonWrapper(
|
||||
name='GET_NEW_STUDENT',
|
||||
jp=Button(
|
||||
file='./assets/jp/base/popup/GET_NEW_STUDENT.png',
|
||||
area=(32, 93, 158, 114),
|
||||
search=(12, 73, 178, 134),
|
||||
color=(125, 132, 92),
|
||||
button=(934, 643, 1263, 714),
|
||||
),
|
||||
en=Button(
|
||||
file='./assets/en/base/popup/GET_NEW_STUDENT.png',
|
||||
share=Button(
|
||||
file='./assets/share/base/popup/GET_NEW_STUDENT.png',
|
||||
area=(32, 93, 158, 114),
|
||||
search=(12, 73, 178, 134),
|
||||
color=(125, 132, 92),
|
||||
|
||||
@@ -12,7 +12,13 @@ CHECK_BOUNTY = ButtonWrapper(
|
||||
color=(88, 113, 139),
|
||||
button=(654, 87, 889, 129),
|
||||
),
|
||||
en=None,
|
||||
en=Button(
|
||||
file='./assets/en/bounty/CHECK_BOUNTY.png',
|
||||
area=(654, 87, 891, 126),
|
||||
search=(634, 67, 911, 146),
|
||||
color=(92, 116, 141),
|
||||
button=(654, 87, 891, 126),
|
||||
),
|
||||
)
|
||||
CHECK_DESERT_RAILROAD = ButtonWrapper(
|
||||
name='CHECK_DESERT_RAILROAD',
|
||||
@@ -23,7 +29,13 @@ CHECK_DESERT_RAILROAD = ButtonWrapper(
|
||||
color=(172, 179, 183),
|
||||
button=(106, 147, 401, 179),
|
||||
),
|
||||
en=None,
|
||||
en=Button(
|
||||
file='./assets/en/bounty/CHECK_DESERT_RAILROAD.png',
|
||||
area=(105, 144, 490, 183),
|
||||
search=(85, 124, 510, 203),
|
||||
color=(200, 207, 211),
|
||||
button=(105, 144, 490, 183),
|
||||
),
|
||||
)
|
||||
CHECK_HIGHWAY = ButtonWrapper(
|
||||
name='CHECK_HIGHWAY',
|
||||
@@ -34,7 +46,13 @@ CHECK_HIGHWAY = ButtonWrapper(
|
||||
color=(191, 199, 203),
|
||||
button=(107, 147, 400, 179),
|
||||
),
|
||||
en=None,
|
||||
en=Button(
|
||||
file='./assets/en/bounty/CHECK_HIGHWAY.png',
|
||||
area=(104, 143, 391, 188),
|
||||
search=(84, 123, 411, 208),
|
||||
color=(206, 213, 217),
|
||||
button=(104, 143, 391, 188),
|
||||
),
|
||||
)
|
||||
CHECK_SCHOOLHOUSE = ButtonWrapper(
|
||||
name='CHECK_SCHOOLHOUSE',
|
||||
@@ -45,7 +63,13 @@ CHECK_SCHOOLHOUSE = ButtonWrapper(
|
||||
color=(176, 183, 187),
|
||||
button=(106, 147, 314, 179),
|
||||
),
|
||||
en=None,
|
||||
en=Button(
|
||||
file='./assets/en/bounty/CHECK_SCHOOLHOUSE.png',
|
||||
area=(102, 144, 408, 185),
|
||||
search=(82, 124, 428, 205),
|
||||
color=(203, 210, 214),
|
||||
button=(102, 144, 408, 185),
|
||||
),
|
||||
)
|
||||
OCR_TICKET = ButtonWrapper(
|
||||
name='OCR_TICKET',
|
||||
@@ -56,7 +80,13 @@ OCR_TICKET = ButtonWrapper(
|
||||
color=(197, 206, 213),
|
||||
button=(195, 85, 237, 113),
|
||||
),
|
||||
en=None,
|
||||
en=Button(
|
||||
file='./assets/en/bounty/OCR_TICKET.png',
|
||||
area=(225, 85, 267, 114),
|
||||
search=(205, 65, 287, 134),
|
||||
color=(197, 206, 213),
|
||||
button=(225, 85, 267, 114),
|
||||
),
|
||||
)
|
||||
SELECT_DESERT_RAILROAD = ButtonWrapper(
|
||||
name='SELECT_DESERT_RAILROAD',
|
||||
@@ -67,7 +97,13 @@ SELECT_DESERT_RAILROAD = ButtonWrapper(
|
||||
color=(178, 188, 199),
|
||||
button=(1066, 271, 1224, 311),
|
||||
),
|
||||
en=None,
|
||||
en=Button(
|
||||
file='./assets/en/bounty/SELECT_DESERT_RAILROAD.png',
|
||||
area=(989, 270, 1223, 308),
|
||||
search=(969, 250, 1243, 328),
|
||||
color=(196, 203, 212),
|
||||
button=(989, 270, 1223, 308),
|
||||
),
|
||||
)
|
||||
SELECT_HIGHWAY = ButtonWrapper(
|
||||
name='SELECT_HIGHWAY',
|
||||
@@ -78,7 +114,13 @@ SELECT_HIGHWAY = ButtonWrapper(
|
||||
color=(214, 221, 228),
|
||||
button=(1065, 165, 1223, 203),
|
||||
),
|
||||
en=None,
|
||||
en=Button(
|
||||
file='./assets/en/bounty/SELECT_HIGHWAY.png',
|
||||
area=(1073, 167, 1223, 202),
|
||||
search=(1053, 147, 1243, 222),
|
||||
color=(192, 201, 211),
|
||||
button=(1073, 167, 1223, 202),
|
||||
),
|
||||
)
|
||||
SELECT_SCHOOLHOUSE = ButtonWrapper(
|
||||
name='SELECT_SCHOOLHOUSE',
|
||||
@@ -89,5 +131,11 @@ SELECT_SCHOOLHOUSE = ButtonWrapper(
|
||||
color=(173, 185, 198),
|
||||
button=(1154, 381, 1223, 417),
|
||||
),
|
||||
en=None,
|
||||
en=Button(
|
||||
file='./assets/en/bounty/SELECT_SCHOOLHOUSE.png',
|
||||
area=(1055, 378, 1226, 415),
|
||||
search=(1035, 358, 1246, 435),
|
||||
color=(198, 206, 215),
|
||||
button=(1055, 378, 1226, 415),
|
||||
),
|
||||
)
|
||||
|
||||