2022-09-13 16:35:13 +08:00
|
|
|
|
import os
|
|
|
|
|
|
import sys
|
|
|
|
|
|
import time
|
|
|
|
|
|
from importlib import import_module
|
|
|
|
|
|
from typing import Any
|
|
|
|
|
|
|
|
|
|
|
|
from module.base.timer import Timer
|
2022-09-13 21:01:00 +08:00
|
|
|
|
from module.config.utils import read_file, deep_get
|
2022-09-13 16:35:13 +08:00
|
|
|
|
from module.exception import RequestHumanTakeover
|
|
|
|
|
|
from module.logger import logger
|
|
|
|
|
|
|
|
|
|
|
|
from submodule.AlasMaaBridge.module.config.config import ArknightsConfig
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class AssistantHandler:
|
|
|
|
|
|
config: ArknightsConfig
|
|
|
|
|
|
Asst: Any
|
|
|
|
|
|
Message: Any
|
|
|
|
|
|
ASST_HANDLER: Any
|
|
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
|
def load(path):
|
|
|
|
|
|
sys.path.append(path)
|
|
|
|
|
|
asst_module = import_module('.asst', 'Python')
|
|
|
|
|
|
AssistantHandler.Asst = asst_module.Asst
|
|
|
|
|
|
AssistantHandler.Message = asst_module.Message
|
|
|
|
|
|
AssistantHandler.Asst.load(path)
|
|
|
|
|
|
AssistantHandler.ASST_HANDLER = None
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, config, asst, task=None):
|
|
|
|
|
|
"""
|
|
|
|
|
|
Args:
|
|
|
|
|
|
config (ArknightsConfig, str): Name of the user config under ./config
|
|
|
|
|
|
asst (Asst):
|
|
|
|
|
|
task (str): Bind a task only for dev purpose. Usually to be None for auto task scheduling.
|
|
|
|
|
|
"""
|
|
|
|
|
|
if isinstance(config, str):
|
|
|
|
|
|
self.config = ArknightsConfig(config, task=task)
|
|
|
|
|
|
else:
|
|
|
|
|
|
self.config = config
|
|
|
|
|
|
self.interval_timer = {}
|
|
|
|
|
|
AssistantHandler.ASST_HANDLER = self
|
|
|
|
|
|
self.asst = asst
|
|
|
|
|
|
self.callback_timer = Timer(3600)
|
|
|
|
|
|
self.signal = None
|
|
|
|
|
|
self.params = None
|
|
|
|
|
|
self.task_id = None
|
|
|
|
|
|
self.callback_list = []
|
|
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
|
def split_filter(string, sep='>'):
|
|
|
|
|
|
return [f.strip(' \t\r\n') for f in string.split(sep)]
|
|
|
|
|
|
|
2022-09-17 21:37:57 +08:00
|
|
|
|
def maa_stop(self):
|
|
|
|
|
|
self.asst.stop()
|
|
|
|
|
|
while 1:
|
|
|
|
|
|
if self.signal in [
|
|
|
|
|
|
self.Message.AllTasksCompleted,
|
|
|
|
|
|
self.Message.TaskChainCompleted,
|
|
|
|
|
|
self.Message.TaskChainError
|
|
|
|
|
|
]:
|
|
|
|
|
|
return
|
|
|
|
|
|
|
2022-09-13 16:35:13 +08:00
|
|
|
|
def maa_start(self, task_name, params):
|
|
|
|
|
|
self.task_id = self.asst.append_task(task_name, params)
|
2022-09-17 16:04:36 +08:00
|
|
|
|
self.signal = None
|
2022-09-13 16:35:13 +08:00
|
|
|
|
self.params = params
|
|
|
|
|
|
self.callback_list.append(self.generic_callback)
|
|
|
|
|
|
self.callback_timer.reset()
|
|
|
|
|
|
self.asst.start()
|
|
|
|
|
|
while 1:
|
|
|
|
|
|
if self.callback_timer.reached():
|
|
|
|
|
|
logger.critical('MAA no respond, probably stuck')
|
|
|
|
|
|
raise RequestHumanTakeover
|
|
|
|
|
|
|
2022-09-17 21:37:57 +08:00
|
|
|
|
if self.signal is not None:
|
|
|
|
|
|
self.maa_stop()
|
2022-09-13 16:35:13 +08:00
|
|
|
|
self.callback_list.clear()
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
time.sleep(0.5)
|
|
|
|
|
|
|
|
|
|
|
|
def generic_callback(self, m, d):
|
2022-09-13 21:01:00 +08:00
|
|
|
|
"""
|
|
|
|
|
|
从MAA的回调中处理任务结束的信息。
|
|
|
|
|
|
|
|
|
|
|
|
所有其他回调处理函数应遵循同样格式,
|
|
|
|
|
|
在需要使用的时候加入callback_list,
|
|
|
|
|
|
可以被随时移除,或在任务结束时自动清空。
|
|
|
|
|
|
参数的详细说明见https://github.com/MaaAssistantArknights/MaaAssistantArknights/blob/master/docs/3.2-回调信息协议.md
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
m (Message): 消息类型
|
|
|
|
|
|
d (dict): 消息详情
|
|
|
|
|
|
"""
|
2022-09-17 21:37:57 +08:00
|
|
|
|
if m in [
|
|
|
|
|
|
self.Message.AllTasksCompleted,
|
|
|
|
|
|
self.Message.TaskChainCompleted,
|
|
|
|
|
|
self.Message.TaskChainError
|
|
|
|
|
|
]:
|
|
|
|
|
|
self.signal = m
|
2022-09-13 16:35:13 +08:00
|
|
|
|
|
|
|
|
|
|
def penguin_id_callback(self, m, d):
|
2022-09-13 21:01:00 +08:00
|
|
|
|
if not self.config.MaaRecord_PenguinID \
|
2022-09-13 16:35:13 +08:00
|
|
|
|
and m == self.Message.SubTaskExtraInfo \
|
2022-09-13 21:01:00 +08:00
|
|
|
|
and deep_get(d, keys='what') == 'PenguinId':
|
|
|
|
|
|
self.config.MaaRecord_PenguinID = deep_get(d, keys='details.id')
|
2022-09-13 16:35:13 +08:00
|
|
|
|
self.callback_list.remove(self.penguin_id_callback)
|
|
|
|
|
|
|
|
|
|
|
|
def annihilation_callback(self, m, d):
|
|
|
|
|
|
if m == self.Message.SubTaskError:
|
2022-09-17 21:37:57 +08:00
|
|
|
|
self.signal = m
|
|
|
|
|
|
|
|
|
|
|
|
def roguelike_callback(self, m, d):
|
|
|
|
|
|
if self.task_switch_timer.reached():
|
|
|
|
|
|
if self.config.task_switched():
|
|
|
|
|
|
self.task_switch_timer = None
|
|
|
|
|
|
self.params['starts_count'] = 0
|
|
|
|
|
|
self.asst.set_task_params(self.task_id, self.params)
|
|
|
|
|
|
self.callback_list.remove(self.roguelike_callback)
|
|
|
|
|
|
else:
|
|
|
|
|
|
self.task_switch_timer.reset()
|
2022-09-13 16:35:13 +08:00
|
|
|
|
|
|
|
|
|
|
def startup(self):
|
|
|
|
|
|
self.maa_start('StartUp', {
|
2022-09-13 21:01:00 +08:00
|
|
|
|
"client_type": self.config.MaaEmulator_PackageName,
|
2022-09-13 16:35:13 +08:00
|
|
|
|
"start_game_enabled": True
|
|
|
|
|
|
})
|
|
|
|
|
|
self.config.task_delay(server_update=True)
|
|
|
|
|
|
|
|
|
|
|
|
def fight(self):
|
|
|
|
|
|
args = {
|
2022-09-13 21:01:00 +08:00
|
|
|
|
"stage": self.config.MaaFight_Stage,
|
|
|
|
|
|
"report_to_penguin": self.config.MaaRecord_ReportToPenguin,
|
|
|
|
|
|
"server": self.config.MaaEmulator_Server,
|
|
|
|
|
|
"client_type": self.config.MaaEmulator_PackageName,
|
|
|
|
|
|
"DrGrandet": self.config.MaaFight_DrGrandet,
|
2022-09-13 16:35:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-09-13 21:01:00 +08:00
|
|
|
|
if self.config.MaaFight_Medicine != 0:
|
|
|
|
|
|
args["medicine"] = self.config.MaaFight_Medicine
|
|
|
|
|
|
if self.config.MaaFight_Stone != 0:
|
|
|
|
|
|
args["stone"] = self.config.MaaFight_Stone
|
|
|
|
|
|
if self.config.MaaFight_Times != 0:
|
|
|
|
|
|
args["times"] = self.config.MaaFight_Times
|
2022-09-13 16:35:13 +08:00
|
|
|
|
|
2022-09-13 21:01:00 +08:00
|
|
|
|
if self.config.MaaFight_Drops:
|
|
|
|
|
|
old = read_file(os.path.join(self.config.MaaEmulator_MaaPath, './resource/item_index.json'))
|
2022-09-13 16:35:13 +08:00
|
|
|
|
new = {}
|
|
|
|
|
|
for key, value in old.items():
|
|
|
|
|
|
new[value['name']] = key
|
|
|
|
|
|
drops = {}
|
2022-09-13 21:01:00 +08:00
|
|
|
|
drops_filter = self.split_filter(self.config.MaaFight_Drops)
|
2022-09-13 16:35:13 +08:00
|
|
|
|
for drop in drops_filter:
|
|
|
|
|
|
drop = self.split_filter(drop, sep=':')
|
|
|
|
|
|
try:
|
|
|
|
|
|
drops[new[drop[0]]] = int(drop[1])
|
|
|
|
|
|
except KeyError:
|
|
|
|
|
|
drops[drop[0]] = int(drop[1])
|
|
|
|
|
|
args['drops'] = drops
|
|
|
|
|
|
|
2022-09-13 21:01:00 +08:00
|
|
|
|
if self.config.MaaRecord_ReportToPenguin and self.config.MaaRecord_PenguinID:
|
|
|
|
|
|
args["penguin_id"] = self.config.MaaRecord_PenguinID
|
|
|
|
|
|
elif self.config.MaaRecord_ReportToPenguin and not self.config.MaaRecord_PenguinID:
|
2022-09-13 16:35:13 +08:00
|
|
|
|
self.callback_list.append(self.penguin_id_callback)
|
|
|
|
|
|
|
|
|
|
|
|
if self.config.task.command == 'MaaAnnihilation':
|
|
|
|
|
|
self.callback_list.append(self.annihilation_callback)
|
|
|
|
|
|
|
|
|
|
|
|
self.maa_start('Fight', args)
|
|
|
|
|
|
|
|
|
|
|
|
if self.config.task.command == 'MaaAnnihilation':
|
|
|
|
|
|
self.config.task_delay(server_update=True)
|
|
|
|
|
|
elif self.config.task.command == 'MaaMaterial':
|
|
|
|
|
|
self.config.Scheduler_Enable = False
|
|
|
|
|
|
else:
|
|
|
|
|
|
self.config.task_delay(success=True)
|
|
|
|
|
|
|
|
|
|
|
|
def recruit(self):
|
|
|
|
|
|
select = []
|
2022-09-13 21:01:00 +08:00
|
|
|
|
if self.config.MaaRecruit_Select3:
|
2022-09-13 16:35:13 +08:00
|
|
|
|
select.append(3)
|
2022-09-13 21:01:00 +08:00
|
|
|
|
if self.config.MaaRecruit_Select4:
|
2022-09-13 16:35:13 +08:00
|
|
|
|
select.append(4)
|
2022-09-13 21:01:00 +08:00
|
|
|
|
if self.config.MaaRecruit_Select5:
|
2022-09-13 16:35:13 +08:00
|
|
|
|
select.append(5)
|
|
|
|
|
|
|
|
|
|
|
|
args = {
|
2022-09-13 21:01:00 +08:00
|
|
|
|
"refresh": self.config.MaaRecruit_Refresh,
|
2022-09-13 16:35:13 +08:00
|
|
|
|
"select": select,
|
|
|
|
|
|
"confirm": select,
|
2022-09-13 21:01:00 +08:00
|
|
|
|
"times": self.config.MaaRecruit_Times,
|
|
|
|
|
|
"expedite": self.config.MaaRecruit_Expedite,
|
|
|
|
|
|
"skip_robot": self.config.MaaRecruit_SkipRobot
|
2022-09-13 16:35:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-09-13 21:01:00 +08:00
|
|
|
|
if self.config.MaaRecord_ReportToPenguin and self.config.MaaRecord_PenguinID:
|
|
|
|
|
|
args["penguin_id"] = self.config.MaaRecord_PenguinID
|
|
|
|
|
|
elif self.config.MaaRecord_ReportToPenguin and not self.config.MaaRecord_PenguinID:
|
2022-09-13 16:35:13 +08:00
|
|
|
|
self.callback_list.append(self.penguin_id_callback)
|
|
|
|
|
|
|
|
|
|
|
|
self.maa_start('Recruit', args)
|
|
|
|
|
|
self.config.task_delay(success=True)
|
|
|
|
|
|
|
|
|
|
|
|
def infrast(self):
|
2022-09-13 21:01:00 +08:00
|
|
|
|
facility = self.split_filter(self.config.MaaInfrast_Facility)
|
2022-09-13 16:35:13 +08:00
|
|
|
|
self.maa_start('Infrast', {
|
|
|
|
|
|
"facility": facility,
|
2022-09-13 21:01:00 +08:00
|
|
|
|
"drones": self.config.MaaInfrast_Drones,
|
|
|
|
|
|
"threshold": self.config.MaaInfrast_Threshold
|
2022-09-13 16:35:13 +08:00
|
|
|
|
})
|
|
|
|
|
|
self.config.task_delay(success=True)
|
|
|
|
|
|
|
|
|
|
|
|
def visit(self):
|
|
|
|
|
|
self.maa_start('Visit', {
|
|
|
|
|
|
"enable": True
|
|
|
|
|
|
})
|
|
|
|
|
|
self.config.task_delay(server_update=True)
|
|
|
|
|
|
|
|
|
|
|
|
def mall(self):
|
2022-09-13 21:01:00 +08:00
|
|
|
|
buy_first = self.split_filter(self.config.MaaMall_BuyFirst)
|
|
|
|
|
|
blacklist = self.split_filter(self.config.MaaMall_BlackList)
|
2022-09-13 16:35:13 +08:00
|
|
|
|
self.maa_start('Mall', {
|
2022-09-13 21:01:00 +08:00
|
|
|
|
"shopping": self.config.MaaMall_Shopping,
|
2022-09-13 16:35:13 +08:00
|
|
|
|
"buy_first": buy_first,
|
|
|
|
|
|
"blacklist": blacklist
|
|
|
|
|
|
})
|
|
|
|
|
|
self.config.task_delay(server_update=True)
|
|
|
|
|
|
|
|
|
|
|
|
def award(self):
|
|
|
|
|
|
self.maa_start('Award', {
|
|
|
|
|
|
"enable": True
|
|
|
|
|
|
})
|
|
|
|
|
|
self.config.task_delay(server_update=True)
|
|
|
|
|
|
|
|
|
|
|
|
def roguelike(self):
|
|
|
|
|
|
args = {
|
2022-09-13 21:01:00 +08:00
|
|
|
|
"mode": self.config.MaaRoguelike_Mode,
|
|
|
|
|
|
"starts_count": self.config.MaaRoguelike_StartsCount,
|
|
|
|
|
|
"investments_count": self.config.MaaRoguelike_InvestmentsCount,
|
|
|
|
|
|
"stop_when_investment_full": self.config.MaaRoguelike_StopWhenInvestmentFull,
|
|
|
|
|
|
"squad": self.config.MaaRoguelike_Squad,
|
|
|
|
|
|
"roles": self.config.MaaRoguelike_Roles
|
2022-09-13 16:35:13 +08:00
|
|
|
|
}
|
2022-09-13 21:01:00 +08:00
|
|
|
|
if self.config.MaaRoguelike_CoreChar:
|
|
|
|
|
|
args["core_char"] = self.config.MaaRoguelike_CoreChar
|
2022-09-13 16:35:13 +08:00
|
|
|
|
|
2022-09-17 21:37:57 +08:00
|
|
|
|
self.task_switch_timer = Timer(30).start()
|
|
|
|
|
|
self.callback_list.append(self.roguelike_callback)
|
2022-09-13 16:35:13 +08:00
|
|
|
|
self.maa_start('Roguelike', args)
|
2022-09-17 21:37:57 +08:00
|
|
|
|
|
|
|
|
|
|
if self.task_switch_timer is not None:
|
|
|
|
|
|
self.config.Scheduler_Enable = False
|
2022-09-13 16:35:13 +08:00
|
|
|
|
|
|
|
|
|
|
def copilot(self):
|
2022-09-13 21:01:00 +08:00
|
|
|
|
path = self.config.MaaCopilot_FileName
|
2022-09-13 16:35:13 +08:00
|
|
|
|
homework = read_file(path)
|
2022-09-13 21:01:00 +08:00
|
|
|
|
stage = deep_get(homework, keys='stage_name')
|
|
|
|
|
|
if not stage:
|
|
|
|
|
|
logger.critical('作业文件不存在或已经损坏')
|
|
|
|
|
|
raise RequestHumanTakeover
|
2022-09-13 16:35:13 +08:00
|
|
|
|
|
|
|
|
|
|
self.maa_start('Copilot', {
|
2022-09-13 21:01:00 +08:00
|
|
|
|
"stage_name": stage,
|
2022-09-13 16:35:13 +08:00
|
|
|
|
"filename": path,
|
2022-09-13 21:01:00 +08:00
|
|
|
|
"formation": self.config.MaaCopilot_Formation
|
2022-09-13 16:35:13 +08:00
|
|
|
|
})
|