Add: AlasMaaBridge init

This commit is contained in:
SarContDeli 2022-09-13 16:35:13 +08:00
parent 782eebbb8c
commit 79dad6a6b0
18 changed files with 3009 additions and 0 deletions

3
.gitignore vendored
View File

@ -8,6 +8,9 @@ config/*.yaml
config/*.json
config/tmp*
!config/template.json
submodule/AlasMaaBridge/config/*.json
submodule/AlasMaaBridge/config/tmp*
!submodule/AlasMaaBridge/config/template.json
*.pyw
dev_tools/debug_tools
.idea

View File

@ -0,0 +1,174 @@
{
"Maa": {
"Emulator": {
"Serial": "127.0.0.1:5555",
"PackageName": "Official",
"Server": "CN",
"MaaPath": "D:/Program Files/MAA",
"ServerName": "disabled"
},
"Record": {
"ReportToPenguin": false,
"PenguinID": null
}
},
"MaaStartup": {
"Scheduler": {
"Enable": true,
"NextRun": "2020-01-01 00:00:00",
"Command": "MaaStartup",
"SuccessInterval": 0,
"FailureInterval": 0,
"ServerUpdate": "04:00"
}
},
"MaaAnnihilation": {
"Scheduler": {
"Enable": false,
"NextRun": "2020-01-01 00:00:00",
"Command": "MaaAnnihilation",
"SuccessInterval": 480,
"FailureInterval": 120,
"ServerUpdate": "04:00"
},
"Fight": {
"Stage": "Annihilation",
"Medicine": 0,
"Stone": 0,
"Times": 5,
"Drops": null,
"DrGrandet": false
}
},
"MaaMaterial": {
"Scheduler": {
"Enable": false,
"NextRun": "2020-01-01 00:00:00",
"Command": "MaaMaterial",
"SuccessInterval": 60,
"FailureInterval": 120,
"ServerUpdate": "04:00"
},
"Fight": {
"Stage": "1-7",
"Medicine": 0,
"Stone": 0,
"Times": 0,
"Drops": null,
"DrGrandet": false
}
},
"MaaFight": {
"Scheduler": {
"Enable": false,
"NextRun": "2020-01-01 00:00:00",
"Command": "MaaFight",
"SuccessInterval": 480,
"FailureInterval": 120,
"ServerUpdate": "04:00"
},
"Fight": {
"Stage": "1-7",
"Medicine": 0,
"Stone": 0,
"Times": 0,
"Drops": null,
"DrGrandet": false
}
},
"MaaRecruit": {
"Scheduler": {
"Enable": false,
"NextRun": "2020-01-01 00:00:00",
"Command": "MaaRecruit",
"SuccessInterval": 540,
"FailureInterval": 120,
"ServerUpdate": "04:00"
},
"Recruit": {
"Refresh": true,
"SkipRobot": true,
"Select3": true,
"Select4": true,
"Select5": true,
"Times": 4,
"Expedite": false
}
},
"MaaInfrast": {
"Scheduler": {
"Enable": false,
"NextRun": "2020-01-01 00:00:00",
"Command": "MaaInfrast",
"SuccessInterval": 1200,
"FailureInterval": 120,
"ServerUpdate": "04:00"
},
"Infrast": {
"Facility": "Mfg > Trade > Power > Control > Reception > Office > Dorm",
"Drones": "Money",
"Threshold": 0.3,
"Replenish": false
}
},
"MaaVisit": {
"Scheduler": {
"Enable": false,
"NextRun": "2020-01-01 00:00:00",
"Command": "MaaVisit",
"SuccessInterval": 60,
"FailureInterval": 120,
"ServerUpdate": "04:00"
}
},
"MaaMall": {
"Scheduler": {
"Enable": false,
"NextRun": "2020-01-01 00:00:00",
"Command": "MaaMall",
"SuccessInterval": 60,
"FailureInterval": 120,
"ServerUpdate": "04:00"
},
"Mall": {
"Shopping": true,
"BuyFirst": "招聘许可 > 龙门币",
"BlackList": "碳 > 家具"
}
},
"MaaAward": {
"Scheduler": {
"Enable": false,
"NextRun": "2020-01-01 00:00:00",
"Command": "MaaAward",
"SuccessInterval": 60,
"FailureInterval": 120,
"ServerUpdate": "04:00"
}
},
"MaaRoguelike": {
"Scheduler": {
"Enable": false,
"NextRun": "2020-01-01 00:00:00",
"Command": "MaaRoguelike",
"SuccessInterval": 60,
"FailureInterval": 120,
"ServerUpdate": "04:00"
},
"Roguelike": {
"Mode": 0,
"StartsCount": 9999999,
"InvestmentsCount": 9999999,
"StopWhenInvestmentFull": false,
"Squad": "指挥分队",
"Roles": "取长补短",
"CoreChar": null
}
},
"MaaCopilot": {
"Copilot": {
"FileName": null,
"Formation": false
}
}
}

View File

@ -0,0 +1,103 @@
import os
import json
from cached_property import cached_property
from alas import AutoScriptScheduler
from deploy.config import DeployConfig
from module.exception import RequestHumanTakeover
from module.logger import logger
from submodule.AlasMaaBridge.module.config.config import ArknightsConfig
from submodule.AlasMaaBridge.module.handler.handler import AssistantHandler
class ArknightsAutoScript(AutoScriptScheduler):
@cached_property
def device(self):
return None
@cached_property
def config(self):
try:
config = ArknightsConfig(config_name=self.config_name)
return config
except RequestHumanTakeover:
logger.critical('Request human takeover')
exit(1)
except Exception as e:
logger.exception(e)
exit(1)
@cached_property
def asst(self):
if self.config.task.command not in ['MaaStartup', 'Maa']:
self.config.task_call('MaaStartup', True)
self.config.task_stop()
AssistantHandler.load(self.config.Emulator_MaaPath)
@AssistantHandler.Asst.CallBackType
def callback(msg, details, arg):
"""
Args:
msg (int):
details (bytes):
arg (c_void_p):
"""
m = AssistantHandler.Message(msg)
d = details.decode('utf-8', 'ignore')
logger.info(f'{m} {d}')
handler = AssistantHandler.ASST_HANDLER
if handler:
handler.callback_timer.reset()
for func in handler.callback_list:
func(m, json.loads(d))
self.callback = callback
asst = AssistantHandler.Asst(callback)
if not asst.connect(os.path.abspath(DeployConfig().AdbExecutable), self.config.Emulator_Serial):
logger.critical('Adb connect failed')
raise RequestHumanTakeover
return asst
def maa_startup(self):
AssistantHandler(config=self.config, asst=self.asst).startup()
def maa_annihilation(self):
AssistantHandler(config=self.config, asst=self.asst).fight()
def maa_material(self):
AssistantHandler(config=self.config, asst=self.asst).fight()
def maa_fight(self):
AssistantHandler(config=self.config, asst=self.asst).fight()
def maa_recruit(self):
AssistantHandler(config=self.config, asst=self.asst).recruit()
def maa_infrast(self):
AssistantHandler(config=self.config, asst=self.asst).infrast()
def maa_visit(self):
AssistantHandler(config=self.config, asst=self.asst).visit()
def maa_mall(self):
AssistantHandler(config=self.config, asst=self.asst).mall()
def maa_award(self):
AssistantHandler(config=self.config, asst=self.asst).award()
def maa_roguelike(self):
AssistantHandler(config=self.config, asst=self.asst).roguelike()
def loop(config_name):
ArknightsAutoScript(config_name).loop()
def maa_copilot(config_name):
script = ArknightsAutoScript(config_name)
script.config.bind('MaaCopilot')
AssistantHandler(config=script.config, asst=script.asst).copilot()

View File

@ -0,0 +1,605 @@
{
"Maa": {
"Emulator": {
"Serial": {
"type": "input",
"value": "127.0.0.1:5555",
"valuetype": "str"
},
"PackageName": {
"type": "select",
"value": "Official",
"option": [
"Official",
"Bilibili"
]
},
"Server": {
"type": "select",
"value": "CN",
"option": [
"CN",
"US",
"JP",
"KR"
]
},
"MaaPath": {
"type": "textarea",
"value": "D:/Program Files/MAA"
},
"ServerName": {
"type": "input",
"value": "disabled",
"display": "hide"
}
},
"Record": {
"ReportToPenguin": {
"type": "checkbox",
"value": false
},
"PenguinID": {
"type": "input",
"value": null
}
}
},
"MaaStartup": {
"Scheduler": {
"Enable": {
"type": "checkbox",
"value": true,
"display": "disabled"
},
"NextRun": {
"type": "datetime",
"value": "2020-01-01 00:00:00",
"validate": "datetime"
},
"Command": {
"type": "input",
"value": "MaaStartup",
"display": "hide"
},
"SuccessInterval": {
"type": "input",
"value": 0,
"display": "hide"
},
"FailureInterval": {
"type": "input",
"value": 0,
"display": "hide"
},
"ServerUpdate": {
"type": "input",
"value": "04:00",
"display": "hide"
}
}
},
"MaaAnnihilation": {
"Scheduler": {
"Enable": {
"type": "checkbox",
"value": false
},
"NextRun": {
"type": "datetime",
"value": "2020-01-01 00:00:00",
"validate": "datetime"
},
"Command": {
"type": "input",
"value": "MaaAnnihilation",
"display": "hide"
},
"SuccessInterval": {
"type": "input",
"value": 480,
"display": "hide"
},
"FailureInterval": {
"type": "input",
"value": 120,
"display": "hide"
},
"ServerUpdate": {
"type": "input",
"value": "04:00",
"display": "hide"
}
},
"Fight": {
"Stage": {
"type": "input",
"value": "Annihilation",
"valuetype": "str",
"display": "hide"
},
"Medicine": {
"type": "input",
"value": 0,
"display": "hide"
},
"Stone": {
"type": "input",
"value": 0,
"display": "hide"
},
"Times": {
"type": "input",
"value": 5,
"display": "hide"
},
"Drops": {
"type": "textarea",
"value": null,
"display": "hide"
},
"DrGrandet": {
"type": "checkbox",
"value": false,
"display": "hide"
}
}
},
"MaaMaterial": {
"Scheduler": {
"Enable": {
"type": "checkbox",
"value": false
},
"NextRun": {
"type": "datetime",
"value": "2020-01-01 00:00:00",
"validate": "datetime"
},
"Command": {
"type": "input",
"value": "MaaMaterial",
"display": "hide"
},
"SuccessInterval": {
"type": "input",
"value": 60,
"display": "hide"
},
"FailureInterval": {
"type": "input",
"value": 120,
"display": "hide"
},
"ServerUpdate": {
"type": "input",
"value": "04:00",
"display": "hide"
}
},
"Fight": {
"Stage": {
"type": "input",
"value": "1-7",
"valuetype": "str"
},
"Medicine": {
"type": "input",
"value": 0
},
"Stone": {
"type": "input",
"value": 0
},
"Times": {
"type": "input",
"value": 0
},
"Drops": {
"type": "textarea",
"value": null
},
"DrGrandet": {
"type": "checkbox",
"value": false
}
}
},
"MaaFight": {
"Scheduler": {
"Enable": {
"type": "checkbox",
"value": false
},
"NextRun": {
"type": "datetime",
"value": "2020-01-01 00:00:00",
"validate": "datetime"
},
"Command": {
"type": "input",
"value": "MaaFight",
"display": "hide"
},
"SuccessInterval": {
"type": "input",
"value": 480,
"display": "hide"
},
"FailureInterval": {
"type": "input",
"value": 120,
"display": "hide"
},
"ServerUpdate": {
"type": "input",
"value": "04:00",
"display": "hide"
}
},
"Fight": {
"Stage": {
"type": "input",
"value": "1-7",
"valuetype": "str"
},
"Medicine": {
"type": "input",
"value": 0,
"display": "hide"
},
"Stone": {
"type": "input",
"value": 0,
"display": "hide"
},
"Times": {
"type": "input",
"value": 0,
"display": "hide"
},
"Drops": {
"type": "textarea",
"value": null,
"display": "hide"
},
"DrGrandet": {
"type": "checkbox",
"value": false
}
}
},
"MaaRecruit": {
"Scheduler": {
"Enable": {
"type": "checkbox",
"value": false
},
"NextRun": {
"type": "datetime",
"value": "2020-01-01 00:00:00",
"validate": "datetime"
},
"Command": {
"type": "input",
"value": "MaaRecruit",
"display": "hide"
},
"SuccessInterval": {
"type": "input",
"value": 540,
"display": "hide"
},
"FailureInterval": {
"type": "input",
"value": 120,
"display": "hide"
},
"ServerUpdate": {
"type": "input",
"value": "04:00",
"display": "hide"
}
},
"Recruit": {
"Refresh": {
"type": "checkbox",
"value": true
},
"SkipRobot": {
"type": "checkbox",
"value": true
},
"Select3": {
"type": "checkbox",
"value": true
},
"Select4": {
"type": "checkbox",
"value": true
},
"Select5": {
"type": "checkbox",
"value": true
},
"Times": {
"type": "input",
"value": 4
},
"Expedite": {
"type": "checkbox",
"value": false
}
}
},
"MaaInfrast": {
"Scheduler": {
"Enable": {
"type": "checkbox",
"value": false
},
"NextRun": {
"type": "datetime",
"value": "2020-01-01 00:00:00",
"validate": "datetime"
},
"Command": {
"type": "input",
"value": "MaaInfrast",
"display": "hide"
},
"SuccessInterval": {
"type": "input",
"value": 1200,
"display": "hide"
},
"FailureInterval": {
"type": "input",
"value": 120,
"display": "hide"
},
"ServerUpdate": {
"type": "input",
"value": "04:00",
"display": "hide"
}
},
"Infrast": {
"Facility": {
"type": "textarea",
"value": "Mfg > Trade > Power > Control > Reception > Office > Dorm"
},
"Drones": {
"type": "select",
"value": "Money",
"option": [
"_NotUse",
"Money",
"SyntheticJade",
"CombatRecord",
"PureGold",
"OriginStone",
"Chip"
]
},
"Threshold": {
"type": "input",
"value": 0.3
},
"Replenish": {
"type": "checkbox",
"value": false
}
}
},
"MaaVisit": {
"Scheduler": {
"Enable": {
"type": "checkbox",
"value": false
},
"NextRun": {
"type": "datetime",
"value": "2020-01-01 00:00:00",
"validate": "datetime"
},
"Command": {
"type": "input",
"value": "MaaVisit",
"display": "hide"
},
"SuccessInterval": {
"type": "input",
"value": 60,
"display": "hide"
},
"FailureInterval": {
"type": "input",
"value": 120,
"display": "hide"
},
"ServerUpdate": {
"type": "input",
"value": "04:00",
"display": "hide"
}
}
},
"MaaMall": {
"Scheduler": {
"Enable": {
"type": "checkbox",
"value": false
},
"NextRun": {
"type": "datetime",
"value": "2020-01-01 00:00:00",
"validate": "datetime"
},
"Command": {
"type": "input",
"value": "MaaMall",
"display": "hide"
},
"SuccessInterval": {
"type": "input",
"value": 60,
"display": "hide"
},
"FailureInterval": {
"type": "input",
"value": 120,
"display": "hide"
},
"ServerUpdate": {
"type": "input",
"value": "04:00",
"display": "hide"
}
},
"Mall": {
"Shopping": {
"type": "checkbox",
"value": true
},
"BuyFirst": {
"type": "textarea",
"value": "招聘许可 > 龙门币"
},
"BlackList": {
"type": "textarea",
"value": "碳 > 家具"
}
}
},
"MaaAward": {
"Scheduler": {
"Enable": {
"type": "checkbox",
"value": false
},
"NextRun": {
"type": "datetime",
"value": "2020-01-01 00:00:00",
"validate": "datetime"
},
"Command": {
"type": "input",
"value": "MaaAward",
"display": "hide"
},
"SuccessInterval": {
"type": "input",
"value": 60,
"display": "hide"
},
"FailureInterval": {
"type": "input",
"value": 120,
"display": "hide"
},
"ServerUpdate": {
"type": "input",
"value": "04:00",
"display": "hide"
}
}
},
"MaaRoguelike": {
"Scheduler": {
"Enable": {
"type": "checkbox",
"value": false
},
"NextRun": {
"type": "datetime",
"value": "2020-01-01 00:00:00",
"validate": "datetime"
},
"Command": {
"type": "input",
"value": "MaaRoguelike",
"display": "hide"
},
"SuccessInterval": {
"type": "input",
"value": 60,
"display": "hide"
},
"FailureInterval": {
"type": "input",
"value": 120,
"display": "hide"
},
"ServerUpdate": {
"type": "input",
"value": "04:00",
"display": "hide"
}
},
"Roguelike": {
"Mode": {
"type": "select",
"value": 0,
"option": [
0,
1
]
},
"StartsCount": {
"type": "input",
"value": 9999999
},
"InvestmentsCount": {
"type": "input",
"value": 9999999
},
"StopWhenInvestmentFull": {
"type": "checkbox",
"value": false
},
"Squad": {
"type": "select",
"value": "指挥分队",
"option": [
"指挥分队",
"集群分队",
"后勤分队",
"矛头分队",
"突击战术分队",
"堡垒战术分队",
"远程战术分队",
"破坏战术分队",
"研究分队",
"高规格分队"
]
},
"Roles": {
"type": "select",
"value": "取长补短",
"option": [
"先手必胜",
"稳扎稳打",
"取长补短",
"随心所欲"
]
},
"CoreChar": {
"type": "input",
"value": null
}
}
},
"MaaCopilot": {
"Copilot": {
"FileName": {
"type": "textarea",
"value": null
},
"Formation": {
"type": "checkbox",
"value": false
}
}
}
}

View File

@ -0,0 +1,117 @@
# --------------------
# Define arguments.
# --------------------
# ==================== Maa ====================
Scheduler:
Enable: false
NextRun: 2020-01-01 00:00:00
Command: Maa
SuccessInterval:
value: 60
display: hide
FailureInterval:
value: 120
display: hide
ServerUpdate:
value: 04:00
display: hide
Emulator:
Serial:
value: 127.0.0.1:5555
valuetype: str
PackageName:
value: Official
option: [Official, Bilibili]
Server:
value: CN
option: [CN, US, JP, KR]
MaaPath:
value: D:/Program Files/MAA
type: textarea
ServerName:
value: disabled
display: hide
Record:
ReportToPenguin: false
PenguinID: null
Error:
SaveError:
value: false
display: hide
OnePushConfig:
mode: yaml
value: 'provider: null'
display: hide
Optimization:
WhenTaskQueueEmpty:
value: stay_there
display: hide
Fight:
Stage:
value: 1-7
valuetype: str
Medicine: 0
Stone: 0
Times: 0
Drops:
value: null
type: textarea
DrGrandet: false
Recruit:
Refresh: true
SkipRobot: true
Select3: true
Select4: true
Select5: true
Times: 4
Expedite: false
Infrast:
Facility:
value: Mfg > Trade > Power > Control > Reception > Office > Dorm
type: textarea
Drones:
value: Money
option: [_NotUse, Money, SyntheticJade, CombatRecord, PureGold, OriginStone, Chip]
Threshold: 0.3
Replenish: false
Mall:
Shopping: true
BuyFirst:
value: 招聘许可 > 龙门币
type: textarea
BlackList:
value: 碳 > 家具
type: textarea
Roguelike:
Mode:
value: 0
option: [0, 1]
StartsCount: 9999999
InvestmentsCount: 9999999
StopWhenInvestmentFull: false
Squad:
value: 指挥分队
option: [指挥分队, 集群分队, 后勤分队, 矛头分队, 突击战术分队, 堡垒战术分队, 远程战术分队, 破坏战术分队, 研究分队, 高规格分队]
Roles:
value: 取长补短
option: [先手必胜, 稳扎稳打, 取长补短, 随心所欲]
CoreChar: null
# ==================== Tool ====================
Copilot:
FileName:
value: null
type: textarea
Formation: false

View File

@ -0,0 +1,8 @@
# --------------------
# Define default values
# --------------------
# ==================== Maa ====================
MaaStartup:
Scheduler:
Enable: true

View File

@ -0,0 +1,20 @@
{
"Task": {
"Maa": [
"Maa",
"MaaStartup",
"MaaAnnihilation",
"MaaMaterial",
"MaaFight",
"MaaRecruit",
"MaaInfrast",
"MaaVisit",
"MaaMall",
"MaaAward",
"MaaRoguelike"
],
"Tool": [
"MaaCopilot"
]
}
}

View File

@ -0,0 +1,43 @@
# --------------------
# Define non-modifiable values
# --------------------
# ==================== Maa ====================
MaaStartup:
Scheduler:
Enable:
value: true
display: disabled
SuccessInterval: 0
FailureInterval: 0
ServerUpdate: 04:00
MaaAnnihilation:
Scheduler:
SuccessInterval: 480
Fight:
Stage: Annihilation
Medicine: 0
Stone: 0
Times: 5
Drops: null
DrGrandet: false
MaaFight:
Scheduler:
SuccessInterval: 480
Fight:
Medicine: 0
Stone: 0
Times: 0
Drops: null
MaaRecruit:
Scheduler:
SuccessInterval: 540
MaaInfrast:
Scheduler:
SuccessInterval: 1200

View File

@ -0,0 +1,51 @@
# --------------------
# Define argument group of tasks.
# --------------------
# ==================== Maa ====================
Maa:
- Emulator
- Record
MaaStartup:
- Scheduler
MaaAnnihilation:
- Scheduler
- Fight
MaaMaterial:
- Scheduler
- Fight
MaaFight:
- Scheduler
- Fight
MaaRecruit:
- Scheduler
- Recruit
MaaInfrast:
- Scheduler
- Infrast
MaaVisit:
- Scheduler
MaaMall:
- Scheduler
- Mall
MaaAward:
- Scheduler
MaaRoguelike:
- Scheduler
- Roguelike
# ==================== Tool ====================
MaaCopilot:
- Copilot

View File

@ -0,0 +1,62 @@
import os
from datetime import datetime
from module.config.config import GeneralConfig, Function, name_to_function
from module.config.utils import path_to_arg, filepath_config
from module.logger import logger
from submodule.AlasMaaBridge.module.config.config_generated import GeneratedConfig
from submodule.AlasMaaBridge.module.config.config_manual import ManualConfig
from submodule.AlasMaaBridge.module.config.config_updater import ConfigUpdater
class ArknightsConfig(GeneralConfig, ConfigUpdater, ManualConfig, GeneratedConfig):
def __init__(self, config_name, task=None):
super().__init__(config_name, task)
if task is None:
task = name_to_function("Maa")
self.bind(task)
self.task = task
self.save()
def bind(self, func):
"""
Args:
func (str, Function): Function to run
"""
if isinstance(func, Function):
func = func.command
func_set = {func, "Maa"}
logger.info(f"Bind task {func_set}")
# Bind arguments
visited = set()
self.bound.clear()
for func in func_set:
func_data = self.data.get(func, {})
for group, group_data in func_data.items():
for arg, value in group_data.items():
path = f"{group}.{arg}"
if path in visited:
continue
arg = path_to_arg(path)
super().__setattr__(arg, value)
self.bound[arg] = f"{func}.{path}"
visited.add(path)
# Override arguments
for arg, value in self.overridden.items():
super().__setattr__(arg, value)
def save(self, mod_name='maa'):
super().save(mod_name)
def get_mtime(self) -> datetime:
timestamp = os.stat(filepath_config(self.config_name, mod_name='maa')).st_mtime
mtime = datetime.fromtimestamp(timestamp).replace(microsecond=0)
return mtime
def load_config(config_name, task):
return ArknightsConfig(config_name, task)

View File

@ -0,0 +1,77 @@
import datetime
# This file was automatically generated by module/config/config_updater.py.
# Don't modify it manually.
class GeneratedConfig:
"""
Auto generated configuration
"""
# Group `Scheduler`
Scheduler_Enable = False
Scheduler_NextRun = datetime.datetime(2020, 1, 1, 0, 0)
Scheduler_Command = 'Maa'
Scheduler_SuccessInterval = 60
Scheduler_FailureInterval = 120
Scheduler_ServerUpdate = '04:00'
# Group `Emulator`
Emulator_Serial = '127.0.0.1:5555'
Emulator_PackageName = 'Official' # Official, Bilibili
Emulator_Server = 'CN' # CN, US, JP, KR
Emulator_MaaPath = 'D:/Program Files/MAA'
Emulator_ServerName = 'disabled'
# Group `Record`
Record_ReportToPenguin = False
Record_PenguinID = None
# Group `Error`
Error_SaveError = False
Error_OnePushConfig = 'provider: null'
# Group `Optimization`
Optimization_WhenTaskQueueEmpty = 'stay_there'
# Group `Fight`
Fight_Stage = '1-7'
Fight_Medicine = 0
Fight_Stone = 0
Fight_Times = 0
Fight_Drops = None
Fight_DrGrandet = False
# Group `Recruit`
Recruit_Refresh = True
Recruit_SkipRobot = True
Recruit_Select3 = True
Recruit_Select4 = True
Recruit_Select5 = True
Recruit_Times = 4
Recruit_Expedite = False
# Group `Infrast`
Infrast_Facility = 'Mfg > Trade > Power > Control > Reception > Office > Dorm'
Infrast_Drones = 'Money' # _NotUse, Money, SyntheticJade, CombatRecord, PureGold, OriginStone, Chip
Infrast_Threshold = 0.3
Infrast_Replenish = False
# Group `Mall`
Mall_Shopping = True
Mall_BuyFirst = '招聘许可 > 龙门币'
Mall_BlackList = '碳 > 家具'
# Group `Roguelike`
Roguelike_Mode = 0 # 0, 1
Roguelike_StartsCount = 9999999
Roguelike_InvestmentsCount = 9999999
Roguelike_StopWhenInvestmentFull = False
Roguelike_Squad = '指挥分队' # 指挥分队, 集群分队, 后勤分队, 矛头分队, 突击战术分队, 堡垒战术分队, 远程战术分队, 破坏战术分队, 研究分队, 高规格分队
Roguelike_Roles = '取长补短' # 先手必胜, 稳扎稳打, 取长补短, 随心所欲
Roguelike_CoreChar = None
# Group `Copilot`
Copilot_FileName = None
Copilot_Formation = False

View File

@ -0,0 +1,33 @@
from pywebio.io_ctrl import Output
import module.config.server as server
class ManualConfig:
@property
def SERVER(self):
return server.server
SCHEDULER_PRIORITY = """
MaaStartup
> MaaRecruit > MaaInfrast
> MaaVisit > MaaMall > MaaAward
> MaaAnnihilation > MaaMaterial
> MaaFight > MaaRoguelike
"""
"""
module.device
"""
DEVICE_OVER_HTTP = False
FORWARD_PORT_RANGE = (20000, 21000)
REVERSE_SERVER_PORT = 7903
ASCREENCAP_FILEPATH_LOCAL = './bin/ascreencap'
ASCREENCAP_FILEPATH_REMOTE = '/data/local/tmp/ascreencap'
MINITOUCH_FILEPATH_REMOTE = '/data/local/tmp/minitouch'
HERMIT_FILEPATH_LOCAL = './bin/hermit/hermit.apk'
class OutputConfig(Output, ManualConfig):
def __init__(self, spec, on_embed=None):
super().__init__(spec, on_embed)

View File

@ -0,0 +1,123 @@
from cached_property import cached_property
from module.base.timer import timer
from module.config import config_updater
from module.config.utils import *
class ConfigGenerator(config_updater.ConfigGenerator):
@timer
def generate(self):
_ = self.args
_ = self.menu
write_file(filepath_args(), self.args)
write_file(filepath_args('menu'), self.menu)
self.generate_code()
for lang in LANGUAGES:
self.generate_i18n(lang)
@timer
def generate_i18n(self, lang):
"""
Load old translations and generate new translation file.
args.json ---+-----> i18n/<lang>.json
(old) i18n/<lang>.json ---+
"""
new = {}
old = read_file(filepath_i18n(lang))
def deep_load(keys, default=True, words=('name', 'help')):
for word in words:
k = keys + [str(word)]
d = ".".join(k) if default else str(word)
v = deep_get(old, keys=k, default=d)
deep_set(new, keys=k, value=v)
# Menu
for path, data in deep_iter(self.menu, depth=2):
func, group = path
deep_load(['Menu', func])
deep_load(['Menu', group])
for task in data:
deep_load([func, task])
# Arguments
visited_group = set()
for path, data in deep_iter(self.argument, depth=2):
if path[0] not in visited_group:
deep_load([path[0], '_info'])
visited_group.add(path[0])
deep_load(path)
if 'option' in data:
deep_load(path, words=data['option'], default=False)
# GUI i18n
for path, _ in deep_iter(self.gui, depth=2):
group, key = path
deep_load(keys=['Gui', group], words=(key,))
write_file(filepath_i18n(lang), new)
class ConfigUpdater(config_updater.ConfigUpdater):
redirection = []
@cached_property
def args(self):
return read_file(filepath_args(mod_name='maa'))
def read_file(self, config_name, is_template=False):
old = read_file(filepath_config(config_name, 'maa'))
return self.config_update(old, is_template=is_template)
@staticmethod
def write_file(config_name, data, mod_name='maa'):
write_file(filepath_config(config_name, mod_name), data)
def config_update(self, old, is_template=False):
"""
Args:
old (dict):
is_template (bool):
Returns:
dict:
"""
new = {}
def deep_load(keys):
data = deep_get(self.args, keys=keys, default={})
value = deep_get(old, keys=keys, default=data['value'])
if value is None or value == '' or data['type'] in ['lock'] or is_template:
value = data['value']
value = parse_value(value, data=data)
deep_set(new, keys=keys, value=value)
for path, _ in deep_iter(self.args, depth=3):
deep_load(path)
if not is_template:
new = self.config_redirect(old, new)
return new
if __name__ == '__main__':
"""
Process the whole config generation.
task.yaml -+----------------> menu.json
argument.yaml -+-> args.json ---> config_generated.py
override.yaml -+ |
gui.yaml --------\|
||
(old) i18n/<lang>.json --------\\========> i18n/<lang>.json
(old) template.json ---------\========> template.json
"""
# Ensure running in mod root folder
import os
os.chdir('../../')
ConfigGenerator().generate()
os.chdir('../../')
ConfigUpdater().update_file('template', is_template=True)

View File

@ -0,0 +1,341 @@
{
"Menu": {
"Task": {
"name": "",
"help": ""
},
"Maa": {
"name": "Menu.Maa.name",
"help": "Menu.Maa.help"
},
"Tool": {
"name": "Menu.Tool.name",
"help": "Menu.Tool.help"
}
},
"Task": {
"Maa": {
"name": "Task.Maa.name",
"help": "Task.Maa.help"
},
"MaaStartup": {
"name": "Task.MaaStartup.name",
"help": "Task.MaaStartup.help"
},
"MaaAnnihilation": {
"name": "Task.MaaAnnihilation.name",
"help": "Task.MaaAnnihilation.help"
},
"MaaMaterial": {
"name": "Task.MaaMaterial.name",
"help": "Task.MaaMaterial.help"
},
"MaaFight": {
"name": "Task.MaaFight.name",
"help": "Task.MaaFight.help"
},
"MaaRecruit": {
"name": "Task.MaaRecruit.name",
"help": "Task.MaaRecruit.help"
},
"MaaInfrast": {
"name": "Task.MaaInfrast.name",
"help": "Task.MaaInfrast.help"
},
"MaaVisit": {
"name": "Task.MaaVisit.name",
"help": "Task.MaaVisit.help"
},
"MaaMall": {
"name": "Task.MaaMall.name",
"help": "Task.MaaMall.help"
},
"MaaAward": {
"name": "Task.MaaAward.name",
"help": "Task.MaaAward.help"
},
"MaaRoguelike": {
"name": "Task.MaaRoguelike.name",
"help": "Task.MaaRoguelike.help"
},
"MaaCopilot": {
"name": "Task.MaaCopilot.name",
"help": "Task.MaaCopilot.help"
}
},
"Scheduler": {
"_info": {
"name": "Scheduler",
"help": ""
},
"Enable": {
"name": "Enable Task",
"help": "Join this task to scheduler.\nTask commission, research, reward are force to enable."
},
"NextRun": {
"name": "Next Run",
"help": "Updated automatically after completing the task to set next scheduled run, typically not manually modified\nHowever you can force immediate scheduling if you clear this text field"
},
"Command": {
"name": "Command",
"help": ""
},
"SuccessInterval": {
"name": "Success Interval",
"help": "After successful, postpone next run for X minutes"
},
"FailureInterval": {
"name": "Failure Interval",
"help": "After failure, postpone next run for X minutes"
},
"ServerUpdate": {
"name": "Server Update",
"help": "Series of server refresh time(s) as to when this task will next run, this is automatically converted to respective time zone, generally do not need to modify"
}
},
"Emulator": {
"_info": {
"name": "Emulator Settings",
"help": ""
},
"Serial": {
"name": "Serial",
"help": "Use \"auto\" to auto-detect emulators, but serial must be filled if multiple emulators are running\nDefault serial for select emulators:\n- BlueStacks 127.0.0.1:5555\n- BlueStacks4 Hyper-V use \"bluestacks4-hyperv\", \"bluestacks4-hyperv-2\" for multi instance, and so on\n- BlueStacks5 Hyper-V use \"bluestacks5-hyperv\", \"bluestacks5-hyperv-1\" for multi instance, and so on\n- NoxPlayer 127.0.0.1:62001\n- NoxPlayer64bit 127.0.0.1:59865\n- MuMuPlayer 127.0.0.1:7555\n- MemuPlayer 127.0.0.1:21503\n- LDPlayer emulator-5554 or 127.0.0.1:5555\n- WSA use \"wsa-0\" to make the game run in the background, which needs to be controlled or closed by third-party software\nIf there are multiple emulator instances running, the default is reserved for one of them and the others will use different serials to avoid conflicts\nOpen console.bat and run `adb devices` to find what they are"
},
"PackageName": {
"name": "Game Server",
"help": "Manual select is required if multiple game clients are installed on emulator",
"Official": "Official",
"Bilibili": "Bilibili"
},
"Server": {
"name": "Emulator.Server.name",
"help": "Emulator.Server.help",
"CN": "CN",
"US": "US",
"JP": "JP",
"KR": "KR"
},
"MaaPath": {
"name": "Emulator.MaaPath.name",
"help": "Emulator.MaaPath.help"
},
"ServerName": {
"name": "Emulator.ServerName.name",
"help": "Emulator.ServerName.help"
}
},
"Record": {
"_info": {
"name": "Record._info.name",
"help": "Record._info.help"
},
"ReportToPenguin": {
"name": "Record.ReportToPenguin.name",
"help": "Record.ReportToPenguin.help"
},
"PenguinID": {
"name": "Record.PenguinID.name",
"help": "Record.PenguinID.help"
}
},
"Error": {
"_info": {
"name": "Error._info.name",
"help": "Error._info.help"
},
"SaveError": {
"name": "Error.SaveError.name",
"help": "Error.SaveError.help"
},
"OnePushConfig": {
"name": "Error.OnePushConfig.name",
"help": "Error.OnePushConfig.help"
}
},
"Optimization": {
"_info": {
"name": "Optimization Settings",
"help": ""
},
"WhenTaskQueueEmpty": {
"name": "When Task Queue is Empty",
"help": "Close AL when there are no pending tasks, can help reduce CPU"
}
},
"Fight": {
"_info": {
"name": "Fight._info.name",
"help": "Fight._info.help"
},
"Stage": {
"name": "Fight.Stage.name",
"help": "Fight.Stage.help"
},
"Medicine": {
"name": "Fight.Medicine.name",
"help": "Fight.Medicine.help"
},
"Stone": {
"name": "Fight.Stone.name",
"help": "Fight.Stone.help"
},
"Times": {
"name": "Fight.Times.name",
"help": "Fight.Times.help"
},
"Drops": {
"name": "Fight.Drops.name",
"help": "Fight.Drops.help"
},
"DrGrandet": {
"name": "Fight.DrGrandet.name",
"help": "Fight.DrGrandet.help"
}
},
"Recruit": {
"_info": {
"name": "Recruit._info.name",
"help": "Recruit._info.help"
},
"Refresh": {
"name": "Recruit.Refresh.name",
"help": "Recruit.Refresh.help"
},
"SkipRobot": {
"name": "Recruit.SkipRobot.name",
"help": "Recruit.SkipRobot.help"
},
"Select3": {
"name": "Recruit.Select3.name",
"help": "Recruit.Select3.help"
},
"Select4": {
"name": "Recruit.Select4.name",
"help": "Recruit.Select4.help"
},
"Select5": {
"name": "Recruit.Select5.name",
"help": "Recruit.Select5.help"
},
"Times": {
"name": "Recruit.Times.name",
"help": "Recruit.Times.help"
},
"Expedite": {
"name": "Recruit.Expedite.name",
"help": "Recruit.Expedite.help"
}
},
"Infrast": {
"_info": {
"name": "Infrast._info.name",
"help": "Infrast._info.help"
},
"Facility": {
"name": "Infrast.Facility.name",
"help": "Infrast.Facility.help"
},
"Drones": {
"name": "Infrast.Drones.name",
"help": "Infrast.Drones.help",
"_NotUse": "_NotUse",
"Money": "Money",
"SyntheticJade": "SyntheticJade",
"CombatRecord": "CombatRecord",
"PureGold": "PureGold",
"OriginStone": "OriginStone",
"Chip": "Chip"
},
"Threshold": {
"name": "Infrast.Threshold.name",
"help": "Infrast.Threshold.help"
},
"Replenish": {
"name": "Infrast.Replenish.name",
"help": "Infrast.Replenish.help"
}
},
"Mall": {
"_info": {
"name": "Mall._info.name",
"help": "Mall._info.help"
},
"Shopping": {
"name": "Mall.Shopping.name",
"help": "Mall.Shopping.help"
},
"BuyFirst": {
"name": "Mall.BuyFirst.name",
"help": "Mall.BuyFirst.help"
},
"BlackList": {
"name": "Mall.BlackList.name",
"help": "Mall.BlackList.help"
}
},
"Roguelike": {
"_info": {
"name": "Roguelike._info.name",
"help": "Roguelike._info.help"
},
"Mode": {
"name": "Roguelike.Mode.name",
"help": "Roguelike.Mode.help",
"0": "0",
"1": "1"
},
"StartsCount": {
"name": "Roguelike.StartsCount.name",
"help": "Roguelike.StartsCount.help"
},
"InvestmentsCount": {
"name": "Roguelike.InvestmentsCount.name",
"help": "Roguelike.InvestmentsCount.help"
},
"StopWhenInvestmentFull": {
"name": "Roguelike.StopWhenInvestmentFull.name",
"help": "Roguelike.StopWhenInvestmentFull.help"
},
"Squad": {
"name": "Roguelike.Squad.name",
"help": "Roguelike.Squad.help",
"指挥分队": "指挥分队",
"集群分队": "集群分队",
"后勤分队": "后勤分队",
"矛头分队": "矛头分队",
"突击战术分队": "突击战术分队",
"堡垒战术分队": "堡垒战术分队",
"远程战术分队": "远程战术分队",
"破坏战术分队": "破坏战术分队",
"研究分队": "研究分队",
"高规格分队": "高规格分队"
},
"Roles": {
"name": "Roguelike.Roles.name",
"help": "Roguelike.Roles.help",
"先手必胜": "先手必胜",
"稳扎稳打": "稳扎稳打",
"取长补短": "取长补短",
"随心所欲": "随心所欲"
},
"CoreChar": {
"name": "Roguelike.CoreChar.name",
"help": "Roguelike.CoreChar.help"
}
},
"Copilot": {
"_info": {
"name": "Copilot._info.name",
"help": "Copilot._info.help"
},
"FileName": {
"name": "Copilot.FileName.name",
"help": "Copilot.FileName.help"
},
"Formation": {
"name": "Copilot.Formation.name",
"help": "Copilot.Formation.help"
}
}
}

View File

@ -0,0 +1,341 @@
{
"Menu": {
"Task": {
"name": "Menu.Task.name",
"help": "Menu.Task.help"
},
"Maa": {
"name": "Menu.Maa.name",
"help": "Menu.Maa.help"
},
"Tool": {
"name": "Menu.Tool.name",
"help": "Menu.Tool.help"
}
},
"Task": {
"Maa": {
"name": "Task.Maa.name",
"help": "Task.Maa.help"
},
"MaaStartup": {
"name": "Task.MaaStartup.name",
"help": "Task.MaaStartup.help"
},
"MaaAnnihilation": {
"name": "Task.MaaAnnihilation.name",
"help": "Task.MaaAnnihilation.help"
},
"MaaMaterial": {
"name": "Task.MaaMaterial.name",
"help": "Task.MaaMaterial.help"
},
"MaaFight": {
"name": "Task.MaaFight.name",
"help": "Task.MaaFight.help"
},
"MaaRecruit": {
"name": "Task.MaaRecruit.name",
"help": "Task.MaaRecruit.help"
},
"MaaInfrast": {
"name": "Task.MaaInfrast.name",
"help": "Task.MaaInfrast.help"
},
"MaaVisit": {
"name": "Task.MaaVisit.name",
"help": "Task.MaaVisit.help"
},
"MaaMall": {
"name": "Task.MaaMall.name",
"help": "Task.MaaMall.help"
},
"MaaAward": {
"name": "Task.MaaAward.name",
"help": "Task.MaaAward.help"
},
"MaaRoguelike": {
"name": "Task.MaaRoguelike.name",
"help": "Task.MaaRoguelike.help"
},
"MaaCopilot": {
"name": "Task.MaaCopilot.name",
"help": "Task.MaaCopilot.help"
}
},
"Scheduler": {
"_info": {
"name": "Scheduler._info.name",
"help": "Scheduler._info.help"
},
"Enable": {
"name": "Scheduler.Enable.name",
"help": "Scheduler.Enable.help"
},
"NextRun": {
"name": "Scheduler.NextRun.name",
"help": "Scheduler.NextRun.help"
},
"Command": {
"name": "Scheduler.Command.name",
"help": "Scheduler.Command.help"
},
"SuccessInterval": {
"name": "Scheduler.SuccessInterval.name",
"help": "Scheduler.SuccessInterval.help"
},
"FailureInterval": {
"name": "Scheduler.FailureInterval.name",
"help": "Scheduler.FailureInterval.help"
},
"ServerUpdate": {
"name": "Scheduler.ServerUpdate.name",
"help": "Scheduler.ServerUpdate.help"
}
},
"Emulator": {
"_info": {
"name": "Emulator._info.name",
"help": "Emulator._info.help"
},
"Serial": {
"name": "Emulator.Serial.name",
"help": "Emulator.Serial.help"
},
"PackageName": {
"name": "Emulator.PackageName.name",
"help": "Emulator.PackageName.help",
"Official": "Official",
"Bilibili": "Bilibili"
},
"Server": {
"name": "Emulator.Server.name",
"help": "Emulator.Server.help",
"CN": "CN",
"US": "US",
"JP": "JP",
"KR": "KR"
},
"MaaPath": {
"name": "Emulator.MaaPath.name",
"help": "Emulator.MaaPath.help"
},
"ServerName": {
"name": "Emulator.ServerName.name",
"help": "Emulator.ServerName.help"
}
},
"Record": {
"_info": {
"name": "Record._info.name",
"help": "Record._info.help"
},
"ReportToPenguin": {
"name": "Record.ReportToPenguin.name",
"help": "Record.ReportToPenguin.help"
},
"PenguinID": {
"name": "Record.PenguinID.name",
"help": "Record.PenguinID.help"
}
},
"Error": {
"_info": {
"name": "Error._info.name",
"help": "Error._info.help"
},
"SaveError": {
"name": "Error.SaveError.name",
"help": "Error.SaveError.help"
},
"OnePushConfig": {
"name": "Error.OnePushConfig.name",
"help": "Error.OnePushConfig.help"
}
},
"Optimization": {
"_info": {
"name": "Optimization._info.name",
"help": "Optimization._info.help"
},
"WhenTaskQueueEmpty": {
"name": "Optimization.WhenTaskQueueEmpty.name",
"help": "Optimization.WhenTaskQueueEmpty.help"
}
},
"Fight": {
"_info": {
"name": "Fight._info.name",
"help": "Fight._info.help"
},
"Stage": {
"name": "Fight.Stage.name",
"help": "Fight.Stage.help"
},
"Medicine": {
"name": "Fight.Medicine.name",
"help": "Fight.Medicine.help"
},
"Stone": {
"name": "Fight.Stone.name",
"help": "Fight.Stone.help"
},
"Times": {
"name": "Fight.Times.name",
"help": "Fight.Times.help"
},
"Drops": {
"name": "Fight.Drops.name",
"help": "Fight.Drops.help"
},
"DrGrandet": {
"name": "Fight.DrGrandet.name",
"help": "Fight.DrGrandet.help"
}
},
"Recruit": {
"_info": {
"name": "Recruit._info.name",
"help": "Recruit._info.help"
},
"Refresh": {
"name": "Recruit.Refresh.name",
"help": "Recruit.Refresh.help"
},
"SkipRobot": {
"name": "Recruit.SkipRobot.name",
"help": "Recruit.SkipRobot.help"
},
"Select3": {
"name": "Recruit.Select3.name",
"help": "Recruit.Select3.help"
},
"Select4": {
"name": "Recruit.Select4.name",
"help": "Recruit.Select4.help"
},
"Select5": {
"name": "Recruit.Select5.name",
"help": "Recruit.Select5.help"
},
"Times": {
"name": "Recruit.Times.name",
"help": "Recruit.Times.help"
},
"Expedite": {
"name": "Recruit.Expedite.name",
"help": "Recruit.Expedite.help"
}
},
"Infrast": {
"_info": {
"name": "Infrast._info.name",
"help": "Infrast._info.help"
},
"Facility": {
"name": "Infrast.Facility.name",
"help": "Infrast.Facility.help"
},
"Drones": {
"name": "Infrast.Drones.name",
"help": "Infrast.Drones.help",
"_NotUse": "_NotUse",
"Money": "Money",
"SyntheticJade": "SyntheticJade",
"CombatRecord": "CombatRecord",
"PureGold": "PureGold",
"OriginStone": "OriginStone",
"Chip": "Chip"
},
"Threshold": {
"name": "Infrast.Threshold.name",
"help": "Infrast.Threshold.help"
},
"Replenish": {
"name": "Infrast.Replenish.name",
"help": "Infrast.Replenish.help"
}
},
"Mall": {
"_info": {
"name": "Mall._info.name",
"help": "Mall._info.help"
},
"Shopping": {
"name": "Mall.Shopping.name",
"help": "Mall.Shopping.help"
},
"BuyFirst": {
"name": "Mall.BuyFirst.name",
"help": "Mall.BuyFirst.help"
},
"BlackList": {
"name": "Mall.BlackList.name",
"help": "Mall.BlackList.help"
}
},
"Roguelike": {
"_info": {
"name": "Roguelike._info.name",
"help": "Roguelike._info.help"
},
"Mode": {
"name": "Roguelike.Mode.name",
"help": "Roguelike.Mode.help",
"0": "0",
"1": "1"
},
"StartsCount": {
"name": "Roguelike.StartsCount.name",
"help": "Roguelike.StartsCount.help"
},
"InvestmentsCount": {
"name": "Roguelike.InvestmentsCount.name",
"help": "Roguelike.InvestmentsCount.help"
},
"StopWhenInvestmentFull": {
"name": "Roguelike.StopWhenInvestmentFull.name",
"help": "Roguelike.StopWhenInvestmentFull.help"
},
"Squad": {
"name": "Roguelike.Squad.name",
"help": "Roguelike.Squad.help",
"指挥分队": "指挥分队",
"集群分队": "集群分队",
"后勤分队": "后勤分队",
"矛头分队": "矛头分队",
"突击战术分队": "突击战术分队",
"堡垒战术分队": "堡垒战术分队",
"远程战术分队": "远程战术分队",
"破坏战术分队": "破坏战术分队",
"研究分队": "研究分队",
"高规格分队": "高规格分队"
},
"Roles": {
"name": "Roguelike.Roles.name",
"help": "Roguelike.Roles.help",
"先手必胜": "先手必胜",
"稳扎稳打": "稳扎稳打",
"取长补短": "取长补短",
"随心所欲": "随心所欲"
},
"CoreChar": {
"name": "Roguelike.CoreChar.name",
"help": "Roguelike.CoreChar.help"
}
},
"Copilot": {
"_info": {
"name": "Copilot._info.name",
"help": "Copilot._info.help"
},
"FileName": {
"name": "Copilot.FileName.name",
"help": "Copilot.FileName.help"
},
"Formation": {
"name": "Copilot.Formation.name",
"help": "Copilot.Formation.help"
}
}
}

View File

@ -0,0 +1,341 @@
{
"Menu": {
"Task": {
"name": "",
"help": ""
},
"Maa": {
"name": "Maa",
"help": ""
},
"Tool": {
"name": "Menu.Tool.name",
"help": "Menu.Tool.help"
}
},
"Task": {
"Maa": {
"name": "Maa设置",
"help": ""
},
"MaaStartup": {
"name": "开始唤醒",
"help": ""
},
"MaaAnnihilation": {
"name": "剿灭作战",
"help": ""
},
"MaaMaterial": {
"name": "刷材料",
"help": ""
},
"MaaFight": {
"name": "刷理智",
"help": ""
},
"MaaRecruit": {
"name": "自动公招",
"help": ""
},
"MaaInfrast": {
"name": "基建换班",
"help": ""
},
"MaaVisit": {
"name": "访问好友",
"help": ""
},
"MaaMall": {
"name": "收取信用及购物",
"help": ""
},
"MaaAward": {
"name": "领取日常奖励",
"help": ""
},
"MaaRoguelike": {
"name": "自动肉鸽",
"help": ""
},
"MaaCopilot": {
"name": "自动战斗",
"help": ""
}
},
"Scheduler": {
"_info": {
"name": "任务设置",
"help": ""
},
"Enable": {
"name": "启用该功能",
"help": "将这个任务加入调度器\n委托、科研、收获任务是强制打开的"
},
"NextRun": {
"name": "下一次运行时间",
"help": "自动计算的数值,不需要手动修改。清空后将立即运行"
},
"Command": {
"name": "内部任务名称",
"help": ""
},
"SuccessInterval": {
"name": "运行成功后,推迟下一次运行 X 分钟",
"help": ""
},
"FailureInterval": {
"name": "运行失败后,推迟下一次运行 X 分钟",
"help": ""
},
"ServerUpdate": {
"name": "服务器刷新时间",
"help": "一些任务运行成功后,将推迟下一次运行至服务器刷新时间\n自动换算时区一般不需要修改"
}
},
"Emulator": {
"_info": {
"name": "模拟器设置",
"help": ""
},
"Serial": {
"name": "模拟器 Serial",
"help": "模拟器默认 Serial\n- 蓝叠模拟器 127.0.0.1:5555\n- 蓝叠模拟器4 Hyper-v版填\"bluestacks4-hyperv\"自动连接,多开填\"bluestacks4-hyperv-2\"以此类推\n- 蓝叠模拟器5 Hyper-v版填\"bluestacks5-hyperv\"自动连接,多开填\"bluestacks5-hyperv-1\"以此类推\n- 夜神模拟器 127.0.0.1:62001\n- 夜神模拟器64位 127.0.0.1:59865\n- MuMu模拟器 127.0.0.1:7555\n- 逍遥模拟器 127.0.0.1:21503\n- 雷电模拟器 emulator-5554 或 127.0.0.1:5555\n- WSA填\"wsa-0\"使游戏在后台运行需要使用第三方软件操控或关闭建议使用scrcpy操控\n如果你有多个模拟器它们的 Serial 将不是默认的,可以在 console.bat 中执行 `adb devices` 查询"
},
"PackageName": {
"name": "游戏服务器",
"help": "模拟器上装有多个游戏客户端时,需要手动选择服务器",
"Official": "官服",
"Bilibili": "Bilibili服"
},
"Server": {
"name": "服务器",
"help": "会影响掉落和上传",
"CN": "CN",
"US": "US",
"JP": "JP",
"KR": "KR"
},
"MaaPath": {
"name": "MAA安装路径",
"help": ""
},
"ServerName": {
"name": "游戏内服务器(碧蓝航线)",
"help": "不显示在界面仅用于和ALAS接轨"
}
},
"Record": {
"_info": {
"name": "掉落记录",
"help": ""
},
"ReportToPenguin": {
"name": "上传到企鹅物流",
"help": ""
},
"PenguinID": {
"name": "企鹅物流ID",
"help": "留空即可,第一次上传后会自动生成"
}
},
"Error": {
"_info": {
"name": "调试设置",
"help": ""
},
"SaveError": {
"name": "出错时保存 Log",
"help": ""
},
"OnePushConfig": {
"name": "Error.OnePushConfig.name",
"help": "不显示在界面仅用于和ALAS接轨"
}
},
"Optimization": {
"_info": {
"name": "优化设置",
"help": ""
},
"WhenTaskQueueEmpty": {
"name": "当任务队列清空后",
"help": "无任务时关闭游戏,能在收菜期间降低 CPU 占用"
}
},
"Fight": {
"_info": {
"name": "战斗设置",
"help": ""
},
"Stage": {
"name": "关卡选择",
"help": ""
},
"Medicine": {
"name": "吃理智药",
"help": ""
},
"Stone": {
"name": "吃源石",
"help": ""
},
"Times": {
"name": "指定次数",
"help": ""
},
"Drops": {
"name": "指定掉落",
"help": "以\"掉落物:数量 > 掉落物:数量\"的形式支持中文名称和物品ID"
},
"DrGrandet": {
"name": "节省理智碎石模式",
"help": "在碎石确认界面等待,直到当前的 1 点理智恢复完成后再立刻碎石"
}
},
"Recruit": {
"_info": {
"name": "公招设置",
"help": ""
},
"Refresh": {
"name": "自动刷新3星 Tag",
"help": ""
},
"SkipRobot": {
"name": "手动确认1星",
"help": ""
},
"Select3": {
"name": "自动确认3星",
"help": ""
},
"Select4": {
"name": "自动确认4星",
"help": ""
},
"Select5": {
"name": "自动确认5星",
"help": ""
},
"Times": {
"name": "最大招募次数",
"help": ""
},
"Expedite": {
"name": "自动使用加急许可",
"help": ""
}
},
"Infrast": {
"_info": {
"name": "基建设置",
"help": ""
},
"Facility": {
"name": "换班设施顺序",
"help": "会影响多功能干员的工作位置"
},
"Drones": {
"name": "无人机用途",
"help": "",
"_NotUse": "不使用无人机",
"Money": "贸易站-龙门币",
"SyntheticJade": "贸易站-合成玉",
"CombatRecord": "制造站-经验书",
"PureGold": "制造站-赤金",
"OriginStone": "制造站-源石碎片",
"Chip": "制造站-芯片组"
},
"Threshold": {
"name": "基建工作心情阈值",
"help": "取值范围0 - 1.0"
},
"Replenish": {
"name": "源石碎片自动补货",
"help": ""
}
},
"Mall": {
"_info": {
"name": "信用商店",
"help": ""
},
"Shopping": {
"name": "信用购物",
"help": ""
},
"BuyFirst": {
"name": "优先购买",
"help": ""
},
"BlackList": {
"name": "黑名单",
"help": ""
}
},
"Roguelike": {
"_info": {
"name": "肉鸽设置",
"help": ""
},
"Mode": {
"name": "策略",
"help": "",
"0": "刷蜡烛",
"1": "刷源石锭"
},
"StartsCount": {
"name": "开始探索X次后停止任务",
"help": ""
},
"InvestmentsCount": {
"name": "投资X个源石锭后停止任务",
"help": ""
},
"StopWhenInvestmentFull": {
"name": "储备源石锭达到上限时停止",
"help": ""
},
"Squad": {
"name": "开局分队",
"help": "",
"指挥分队": "指挥分队",
"集群分队": "集群分队",
"后勤分队": "后勤分队",
"矛头分队": "矛头分队",
"突击战术分队": "突击战术分队",
"堡垒战术分队": "堡垒战术分队",
"远程战术分队": "远程战术分队",
"破坏战术分队": "破坏战术分队",
"研究分队": "研究分队",
"高规格分队": "高规格分队"
},
"Roles": {
"name": "开局职业组",
"help": "",
"先手必胜": "先手必胜",
"稳扎稳打": "稳扎稳打",
"取长补短": "取长补短",
"随心所欲": "随心所欲"
},
"CoreChar": {
"name": "开局干员",
"help": "仅支持单个干员中文名,不填写则默认选择"
}
},
"Copilot": {
"_info": {
"name": "作业设置",
"help": "请在有“开始行动”界面的按钮使用本功能\n更多作业下载见https://prts.plus/"
},
"FileName": {
"name": "作业路径",
"help": ""
},
"Formation": {
"name": "自动编队",
"help": ""
}
}
}

View File

@ -0,0 +1,341 @@
{
"Menu": {
"Task": {
"name": "",
"help": ""
},
"Maa": {
"name": "Menu.Maa.name",
"help": "Menu.Maa.help"
},
"Tool": {
"name": "Menu.Tool.name",
"help": "Menu.Tool.help"
}
},
"Task": {
"Maa": {
"name": "Task.Maa.name",
"help": "Task.Maa.help"
},
"MaaStartup": {
"name": "Task.MaaStartup.name",
"help": "Task.MaaStartup.help"
},
"MaaAnnihilation": {
"name": "Task.MaaAnnihilation.name",
"help": "Task.MaaAnnihilation.help"
},
"MaaMaterial": {
"name": "Task.MaaMaterial.name",
"help": "Task.MaaMaterial.help"
},
"MaaFight": {
"name": "Task.MaaFight.name",
"help": "Task.MaaFight.help"
},
"MaaRecruit": {
"name": "Task.MaaRecruit.name",
"help": "Task.MaaRecruit.help"
},
"MaaInfrast": {
"name": "Task.MaaInfrast.name",
"help": "Task.MaaInfrast.help"
},
"MaaVisit": {
"name": "Task.MaaVisit.name",
"help": "Task.MaaVisit.help"
},
"MaaMall": {
"name": "Task.MaaMall.name",
"help": "Task.MaaMall.help"
},
"MaaAward": {
"name": "Task.MaaAward.name",
"help": "Task.MaaAward.help"
},
"MaaRoguelike": {
"name": "Task.MaaRoguelike.name",
"help": "Task.MaaRoguelike.help"
},
"MaaCopilot": {
"name": "Task.MaaCopilot.name",
"help": "Task.MaaCopilot.help"
}
},
"Scheduler": {
"_info": {
"name": "任務設定",
"help": ""
},
"Enable": {
"name": "啟用該功能",
"help": "將這個任務加入調度器\n委託、科研、收穫任務是強制打開的"
},
"NextRun": {
"name": "下一次執行時間",
"help": "自動計算的數值,不需要手動修改。清空後將立刻執行"
},
"Command": {
"name": "內部任務名稱",
"help": ""
},
"SuccessInterval": {
"name": "執行成功後,推遲下一次執行 X 分鐘",
"help": ""
},
"FailureInterval": {
"name": "執行失敗後,推遲下一次執行 X 分鐘",
"help": ""
},
"ServerUpdate": {
"name": "伺服器更新時間",
"help": "一些任務執行成功後,將推遲下一次執行伺服器更新的時間\n自動換算時區一般不需要修改"
}
},
"Emulator": {
"_info": {
"name": "模擬器設定",
"help": ""
},
"Serial": {
"name": "模擬器 Serial",
"help": "填 \"auto\" 自動檢測模擬器,有多個模擬器正在運行時必須手動填寫 Serial\n模擬器預設 Serial\n- 藍疊模擬器 127.0.0.1:5555\n- 藍疊模擬器4 Hyper-v版填\"bluestacks4-hyperv\"自動連接,多開填\"bluestacks4-hyperv-2\"以此類推\n- 藍疊模擬器5 Hyper-v版填\"bluestacks5-hyperv\"自動連接,多開填\"bluestacks5-hyperv-1\"以此類推\n- 夜神模擬器 127.0.0.1:62001\n- 夜神模擬器64位元 127.0.0.1:59865\n- MuMu模擬器 127.0.0.1:7555\n- 逍遙模擬器 127.0.0.1:21503\n- 雷電模擬器 emulator-5554 或 127.0.0.1:5555\n- WSA填\"wsa-0\"使遊戲在後臺運行,需要使用第三方軟件操控或關閉\n如果你有多個模擬器他們的 Serial 將不是預設的,可以在 console.bat 中執行 `adb devices` 查詢"
},
"PackageName": {
"name": "遊戲伺服器",
"help": "模擬器上裝有多個遊戲客戶端時,需要手動選擇伺服器",
"Official": "Official",
"Bilibili": "Bilibili"
},
"Server": {
"name": "Emulator.Server.name",
"help": "Emulator.Server.help",
"CN": "CN",
"US": "US",
"JP": "JP",
"KR": "KR"
},
"MaaPath": {
"name": "Emulator.MaaPath.name",
"help": "Emulator.MaaPath.help"
},
"ServerName": {
"name": "Emulator.ServerName.name",
"help": "Emulator.ServerName.help"
}
},
"Record": {
"_info": {
"name": "Record._info.name",
"help": "Record._info.help"
},
"ReportToPenguin": {
"name": "Record.ReportToPenguin.name",
"help": "Record.ReportToPenguin.help"
},
"PenguinID": {
"name": "Record.PenguinID.name",
"help": "Record.PenguinID.help"
}
},
"Error": {
"_info": {
"name": "Error._info.name",
"help": "Error._info.help"
},
"SaveError": {
"name": "Error.SaveError.name",
"help": "Error.SaveError.help"
},
"OnePushConfig": {
"name": "Error.OnePushConfig.name",
"help": "Error.OnePushConfig.help"
}
},
"Optimization": {
"_info": {
"name": "優化設定",
"help": ""
},
"WhenTaskQueueEmpty": {
"name": "當任務隊列清空後",
"help": "無任務時關閉遊戲,能在收菜期間降低 CPU 佔用"
}
},
"Fight": {
"_info": {
"name": "Fight._info.name",
"help": "Fight._info.help"
},
"Stage": {
"name": "Fight.Stage.name",
"help": "Fight.Stage.help"
},
"Medicine": {
"name": "Fight.Medicine.name",
"help": "Fight.Medicine.help"
},
"Stone": {
"name": "Fight.Stone.name",
"help": "Fight.Stone.help"
},
"Times": {
"name": "Fight.Times.name",
"help": "Fight.Times.help"
},
"Drops": {
"name": "Fight.Drops.name",
"help": "Fight.Drops.help"
},
"DrGrandet": {
"name": "Fight.DrGrandet.name",
"help": "Fight.DrGrandet.help"
}
},
"Recruit": {
"_info": {
"name": "Recruit._info.name",
"help": "Recruit._info.help"
},
"Refresh": {
"name": "Recruit.Refresh.name",
"help": "Recruit.Refresh.help"
},
"SkipRobot": {
"name": "Recruit.SkipRobot.name",
"help": "Recruit.SkipRobot.help"
},
"Select3": {
"name": "Recruit.Select3.name",
"help": "Recruit.Select3.help"
},
"Select4": {
"name": "Recruit.Select4.name",
"help": "Recruit.Select4.help"
},
"Select5": {
"name": "Recruit.Select5.name",
"help": "Recruit.Select5.help"
},
"Times": {
"name": "Recruit.Times.name",
"help": "Recruit.Times.help"
},
"Expedite": {
"name": "Recruit.Expedite.name",
"help": "Recruit.Expedite.help"
}
},
"Infrast": {
"_info": {
"name": "Infrast._info.name",
"help": "Infrast._info.help"
},
"Facility": {
"name": "Infrast.Facility.name",
"help": "Infrast.Facility.help"
},
"Drones": {
"name": "Infrast.Drones.name",
"help": "Infrast.Drones.help",
"_NotUse": "_NotUse",
"Money": "Money",
"SyntheticJade": "SyntheticJade",
"CombatRecord": "CombatRecord",
"PureGold": "PureGold",
"OriginStone": "OriginStone",
"Chip": "Chip"
},
"Threshold": {
"name": "Infrast.Threshold.name",
"help": "Infrast.Threshold.help"
},
"Replenish": {
"name": "Infrast.Replenish.name",
"help": "Infrast.Replenish.help"
}
},
"Mall": {
"_info": {
"name": "Mall._info.name",
"help": "Mall._info.help"
},
"Shopping": {
"name": "Mall.Shopping.name",
"help": "Mall.Shopping.help"
},
"BuyFirst": {
"name": "Mall.BuyFirst.name",
"help": "Mall.BuyFirst.help"
},
"BlackList": {
"name": "Mall.BlackList.name",
"help": "Mall.BlackList.help"
}
},
"Roguelike": {
"_info": {
"name": "Roguelike._info.name",
"help": "Roguelike._info.help"
},
"Mode": {
"name": "Roguelike.Mode.name",
"help": "Roguelike.Mode.help",
"0": "0",
"1": "1"
},
"StartsCount": {
"name": "Roguelike.StartsCount.name",
"help": "Roguelike.StartsCount.help"
},
"InvestmentsCount": {
"name": "Roguelike.InvestmentsCount.name",
"help": "Roguelike.InvestmentsCount.help"
},
"StopWhenInvestmentFull": {
"name": "Roguelike.StopWhenInvestmentFull.name",
"help": "Roguelike.StopWhenInvestmentFull.help"
},
"Squad": {
"name": "Roguelike.Squad.name",
"help": "Roguelike.Squad.help",
"指挥分队": "指挥分队",
"集群分队": "集群分队",
"后勤分队": "后勤分队",
"矛头分队": "矛头分队",
"突击战术分队": "突击战术分队",
"堡垒战术分队": "堡垒战术分队",
"远程战术分队": "远程战术分队",
"破坏战术分队": "破坏战术分队",
"研究分队": "研究分队",
"高规格分队": "高规格分队"
},
"Roles": {
"name": "Roguelike.Roles.name",
"help": "Roguelike.Roles.help",
"先手必胜": "先手必胜",
"稳扎稳打": "稳扎稳打",
"取长补短": "取长补短",
"随心所欲": "随心所欲"
},
"CoreChar": {
"name": "Roguelike.CoreChar.name",
"help": "Roguelike.CoreChar.help"
}
},
"Copilot": {
"_info": {
"name": "Copilot._info.name",
"help": "Copilot._info.help"
},
"FileName": {
"name": "Copilot.FileName.name",
"help": "Copilot.FileName.help"
},
"Formation": {
"name": "Copilot.Formation.name",
"help": "Copilot.Formation.help"
}
}
}

View File

@ -0,0 +1,226 @@
import os
import sys
import time
from importlib import import_module
from typing import Any
from module.base.timer import Timer
from module.config.utils import read_file
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)]
def maa_start(self, task_name, params):
self.task_id = self.asst.append_task(task_name, params)
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
if self.signal == self.Message.AllTasksCompleted:
self.signal = None
self.task_id = None
self.callback_list.clear()
self.asst.stop()
return
time.sleep(0.5)
def generic_callback(self, m, d):
if m == self.Message.AllTasksCompleted:
self.signal = self.Message.AllTasksCompleted
def penguin_id_callback(self, m, d):
if not self.config.Record_PenguinID \
and m == self.Message.SubTaskExtraInfo \
and d.get('what') == 'PenguinId':
self.config.Record_PenguinID = d["details"]["id"]
self.params["penguin_id"] = self.config.Record_PenguinID
self.asst.set_task_params(self.task_id, self.params)
self.callback_list.remove(self.penguin_id_callback)
def annihilation_callback(self, m, d):
if m == self.Message.SubTaskError:
self.signal = self.Message.AllTasksCompleted
def startup(self):
self.maa_start('StartUp', {
"client_type": self.config.Emulator_PackageName,
"start_game_enabled": True
})
self.config.task_delay(server_update=True)
def fight(self):
args = {
"stage": self.config.Fight_Stage,
"report_to_penguin": self.config.Record_ReportToPenguin,
"server": self.config.Emulator_Server,
"client_type": self.config.Emulator_PackageName,
"DrGrandet": self.config.Fight_DrGrandet,
}
if self.config.Fight_Medicine != 0:
args["medicine"] = self.config.Fight_Medicine
if self.config.Fight_Stone != 0:
args["stone"] = self.config.Fight_Stone
if self.config.Fight_Times != 0:
args["times"] = self.config.Fight_Times
if self.config.Fight_Drops:
old = read_file(os.path.join(self.config.Emulator_MaaPath, './resource/item_index.json'))
new = {}
for key, value in old.items():
new[value['name']] = key
drops = {}
drops_filter = self.split_filter(self.config.Fight_Drops)
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
if self.config.Record_ReportToPenguin and self.config.Record_PenguinID:
args["penguin_id"] = self.config.Record_PenguinID
elif self.config.Record_ReportToPenguin and not self.config.Record_PenguinID:
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 = []
if self.config.Recruit_Select3:
select.append(3)
if self.config.Recruit_Select4:
select.append(4)
if self.config.Recruit_Select5:
select.append(5)
args = {
"refresh": self.config.Recruit_Refresh,
"select": select,
"confirm": select,
"times": self.config.Recruit_Times,
"expedite": self.config.Recruit_Expedite,
"skip_robot": self.config.Recruit_SkipRobot
}
if self.config.Record_ReportToPenguin and self.config.Record_PenguinID:
args["penguin_id"] = self.config.Record_PenguinID
elif self.config.Record_ReportToPenguin and not self.config.Record_PenguinID:
self.callback_list.append(self.penguin_id_callback)
self.maa_start('Recruit', args)
self.config.task_delay(success=True)
def infrast(self):
facility = self.split_filter(self.config.Infrast_Facility)
self.maa_start('Infrast', {
"facility": facility,
"drones": self.config.Infrast_Drones,
"threshold": self.config.Infrast_Threshold
})
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):
buy_first = self.split_filter(self.config.Mall_BuyFirst)
blacklist = self.split_filter(self.config.Mall_BlackList)
self.maa_start('Mall', {
"shopping": self.config.Mall_Shopping,
"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 = {
"mode": self.config.Roguelike_Mode,
"starts_count": self.config.Roguelike_StartsCount,
"investments_count": self.config.Roguelike_InvestmentsCount,
"stop_when_investment_full": self.config.Roguelike_StopWhenInvestmentFull,
"squad": self.config.Roguelike_Squad,
"roles": self.config.Roguelike_Roles
}
if self.config.Roguelike_CoreChar:
args["core_char"] = self.config.Roguelike_CoreChar
self.maa_start('Roguelike', args)
self.config.task_delay(success=True)
def copilot(self):
path = self.config.Copilot_FileName
homework = read_file(path)
self.maa_start('Copilot', {
"stage_name": homework['stage_name'],
"filename": path,
"formation": self.config.Copilot_Formation
})