feat(core): 启动模拟器支持指定命令行参数

Close #20
This commit is contained in:
XcantloadX 2025-04-27 16:43:52 +08:00
parent 1ecf8c4756
commit a1f34e5f5f
4 changed files with 28 additions and 10 deletions

View File

@ -191,7 +191,8 @@ class KotoneBot:
adb_ip=config.backend.adb_ip,
adb_port=config.backend.adb_port,
adb_emulator_name=config.backend.adb_emulator_name,
exe_path=exe
exe_path=exe,
emulator_args=config.backend.emulator_args
)
if not self.backend_instance.running():
logger.info('Starting custom backend...')
@ -265,7 +266,7 @@ class KotoneBot:
run_status.callstack = []
self.events.finished -= _on_finished
self.events.task_status_changed -= _on_task_status_changed
def _on_task_status_changed(task: Task, status: Literal['pending', 'running', 'finished', 'error', 'cancelled']):
def _find(task: Task) -> TaskStatus:
for task_status in run_status.tasks:

View File

@ -13,9 +13,10 @@ P = ParamSpec('P')
T = TypeVar('T')
class CustomInstance(Instance):
def __init__(self, exe_path: str, *args, **kwargs):
def __init__(self, exe_path: str, emulator_args: str = "", *args, **kwargs):
super().__init__(*args, **kwargs)
self.exe_path: str = exe_path
self.exe_args: str = emulator_args
self.process: subprocess.Popen | None = None
@override
@ -23,8 +24,14 @@ class CustomInstance(Instance):
if self.process:
logger.warning('Process is already running.')
return
logger.info('Starting process "%s"...', self.exe_path)
self.process = subprocess.Popen(self.exe_path)
if self.exe_args:
logger.info('Starting process "%s" with args "%s"...', self.exe_path, self.exe_args)
cmd = f'"{self.exe_path}" {self.exe_args}'
self.process = subprocess.Popen(cmd, shell=True)
else:
logger.info('Starting process "%s"...', self.exe_path)
self.process = subprocess.Popen(self.exe_path)
@override
def stop(self):
@ -47,7 +54,7 @@ class CustomInstance(Instance):
return True
else:
return False
def __repr__(self) -> str:
return f'CustomInstance(#{self.id}# at "{self.exe_path}" with {self.adb_ip}:{self.adb_port})'
@ -56,8 +63,8 @@ def _type_check(ins: Instance) -> CustomInstance:
raise ValueError(f'Instance {ins} is not a CustomInstance')
return ins
def create(exe_path: str, adb_ip: str, adb_port: int, adb_emulator_name: str) -> CustomInstance:
return CustomInstance(exe_path, id='custom', name='Custom', adb_ip=adb_ip, adb_port=adb_port, adb_emulator_name=adb_emulator_name)
def create(exe_path: str, adb_ip: str, adb_port: int, adb_emulator_name: str, emulator_args: str = "") -> CustomInstance:
return CustomInstance(exe_path, emulator_args=emulator_args, id='custom', name='Custom', adb_ip=adb_ip, adb_port=adb_port, adb_emulator_name=adb_emulator_name)
if __name__ == '__main__':

View File

@ -37,6 +37,8 @@ class BackendConfig(ConfigBaseModel):
"""
emulator_path: str | None = None
"""模拟器 exe 文件路径"""
emulator_args: str = ""
"""模拟器启动时的命令行参数"""
class PushConfig(ConfigBaseModel):
"""推送配置。"""

View File

@ -239,6 +239,7 @@ class KotoneBotUI:
check_emulator: bool,
emulator_path: str,
adb_emulator_name: str,
emulator_args: str,
trace_recommend_card_detection: bool,
purchase_enabled: bool,
money_enabled: bool,
@ -313,6 +314,7 @@ class KotoneBotUI:
self.current_config.keep_screenshots = keep_screenshots
self.current_config.backend.check_emulator = check_emulator
self.current_config.backend.emulator_path = emulator_path
self.current_config.backend.emulator_args = emulator_args
options = BaseConfig(
purchase=PurchaseConfig(
@ -515,7 +517,7 @@ class KotoneBotUI:
outputs=[task_result]
)
def _create_emulator_settings(self) -> Tuple[gr.Textbox, gr.Number, gr.Dropdown, gr.Checkbox, gr.Checkbox, gr.Textbox, gr.Textbox]:
def _create_emulator_settings(self) -> Tuple[gr.Textbox, gr.Number, gr.Dropdown, gr.Checkbox, gr.Checkbox, gr.Textbox, gr.Textbox, gr.Textbox]:
with gr.Column():
gr.Markdown("### 模拟器设置")
adb_ip = gr.Textbox(
@ -565,12 +567,18 @@ class KotoneBotUI:
info=BackendConfig.model_fields['adb_emulator_name'].description,
interactive=True
)
emulator_args = gr.Textbox(
value=self.current_config.backend.emulator_args,
label="模拟器启动参数",
info=BackendConfig.model_fields['emulator_args'].description,
interactive=True
)
check_emulator.change(
fn=lambda x: gr.Group(visible=x),
inputs=[check_emulator],
outputs=[check_emulator_group]
)
return adb_ip, adb_port, screenshot_impl, keep_screenshots, check_emulator, emulator_path, adb_emulator_name
return adb_ip, adb_port, screenshot_impl, keep_screenshots, check_emulator, emulator_path, adb_emulator_name, emulator_args
def _create_purchase_settings(self) -> Tuple[gr.Checkbox, gr.Checkbox, gr.Checkbox, gr.Dropdown, gr.Dropdown]:
with gr.Column():