Compare commits

..

1 Commits

Author SHA1 Message Date
zzyyyl
02961e60e9 feat: 增加从 GitHub 直接获取资源文件的方式,并优先尝试从 GitHub 获取
github raw 没有 dynamic_list.txt
2024-07-14 17:34:23 +08:00
7190 changed files with 174478 additions and 883987 deletions

View File

@@ -1,9 +1,12 @@
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
# for clang-format 20.0.0
# for clang-format 17.0.1
Language: Json
IndentWidth: 4
---
Language: Cpp
BasedOnStyle: "WebKit"
BasedOnStyle: 'WebKit'
# AccessModifierOffset: 2
AlignAfterOpenBracket: "AlwaysBreak"
AlignAfterOpenBracket: 'AlwaysBreak'
AlignArrayOfStructures: None
AlignConsecutiveAssignments: None
AlignConsecutiveBitFields: None
@@ -26,9 +29,9 @@ AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: Inline
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
BreakAfterReturnType: Automatic
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
BreakTemplateDeclarations: Yes
AlwaysBreakTemplateDeclarations: Yes
# AttributeMacros:
# - __pragma
# - _Pragma
@@ -60,15 +63,15 @@ BraceWrapping:
BreakAfterAttributes: Never
BreakAfterJavaFieldAnnotations: true
BreakArrays: true
BreakBeforeBinaryOperators: None
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Custom
BreakBeforeConceptDeclarations: Always
BreakBeforeInlineASMColon: OnlyMultiline
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: AfterColon
BreakInheritanceList: AfterColon
BreakConstructorInitializers: BeforeComma
BreakInheritanceList: BeforeComma
BreakStringLiterals: true
ColumnLimit: 120
ColumnLimit: 100
# CommentPragmas: '^ MEO pragma:'
CompactNamespaces: false
ConstructorInitializerIndentWidth: 4
@@ -84,12 +87,12 @@ FixNamespaceComments: true
# - foreach
# - Q_FOREACH
# - BOOST_FOREACH
# IfMacros:
# IfMacros:
# - 'KJ_IF_MAYBE'
IncludeBlocks: Preserve
# IncludeCategories:
# IncludeIsMainRegex:
# IncludeIsMainSourceRegex:
# IncludeIsMainRegex:
# IncludeIsMainSourceRegex:
IndentAccessModifiers: false
IndentCaseBlocks: false
IndentCaseLabels: false
@@ -127,7 +130,7 @@ NamespaceIndentation: None
# ObjCSpaceAfterProperty:
# ObjCSpaceBeforeProtocolList:
PackConstructorInitializers: Never
# PenaltyBreakAssignment:
# PenaltyBreakAssignment:
# PenaltyBreakBeforeFirstCallParameter:
# PenaltyBreakComment:
# PenaltyBreakFirstLessLess:
@@ -145,7 +148,7 @@ PointerAlignment: Left
# - constexpr
# - type
ReferenceAlignment: Left
ReflowComments: Always
ReflowComments: true
RemoveBracesLLVM: false
RemoveParentheses: Leave
RemoveSemicolon: false
@@ -180,7 +183,7 @@ SpacesInLineCommentPrefix:
SpacesInParens: Never
SpacesInSquareBrackets: false
Standard: c++20
# StatementAttributeLikeMacros:
# StatementAttributeLikeMacros:
# StatementMacros:
TabWidth: 4
# TypeNames:
@@ -188,4 +191,3 @@ TabWidth: 4
UseTab: Never
# VerilogBreakBetweenInstancePorts:
# WhitespaceSensitiveMacros:
RemoveEmptyLinesInUnwrappedLines: true

View File

@@ -1,29 +0,0 @@
FROM mcr.microsoft.com/devcontainers/base:ubuntu
USER vscode
ENV CONDA_DIR=/home/vscode/miniconda
ENV PATH="$CONDA_DIR/bin:$PATH"
ARG PYTHON_VERSION=3.12
ARG NODEJS_VERSION=24
# Install Miniconda
RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda.sh \
&& bash ~/miniconda.sh -b -p $CONDA_DIR \
&& rm ~/miniconda.sh \
&& conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/main \
&& conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/r
# Configure conda environment
RUN eval "$(conda shell.bash hook)" \
&& conda create -n maa python=$PYTHON_VERSION -y \
&& conda activate maa \
&& conda install -y conda-forge::nodejs=$NODEJS_VERSION \
&& pip install pre-commit black \
&& npm install -g pnpm
# Finalize conda setup
RUN conda init \
&& conda config --set auto_activate false \
&& echo "conda activate maa" >> ~/.bashrc

View File

@@ -1,50 +1,16 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/javascript-node
{
"name": "MAA",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
// "image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"build": {
"dockerfile": "Dockerfile"
"image": "mcr.microsoft.com/devcontainers/cpp:ubuntu-22.04",
"features": {
"ghcr.io/devcontainers/features/python:1": {},
"ghcr.io/devcontainers/features/sshd:1": {}
},
// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [3001],
// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": "bash .devcontainer/post-create.sh",
// Configure tool-specific properties.
"postCreateCommand": "sudo sh -ce 'apt update && apt install g++-12 -y && echo export CC=gcc-12 CXX=g++-12 >> /etc/profile.d/set-compiler.sh'",
"customizations": {
"vscode": {
"extensions": [
"mkxml.vscode-filesize",
"nekosu.maa-support",
"DavidAnson.vscode-markdownlint",
"esbenp.prettier-vscode",
"vue.volar",
"ms-python.python",
"ms-python.black-formatter"
],
"settings": {
// format
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[markdown]": {
"editor.defaultFormatter": "DavidAnson.vscode-markdownlint"
},
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter"
},
// python
"python.terminal.launchArgs": ["-u"],
"python.defaultInterpreterPath": "/home/vscode/miniconda/envs/maa/bin/python",
"python.terminal.activateEnvironment": false
}
"llvm-vs-code-extensions.vscode-clangd",
"DavidAnson.vscode-markdownlint"
]
}
}
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}

View File

@@ -1,21 +0,0 @@
#!/bin/bash
WORKSPACE=$(pwd)
# conda activate maa
echo "===================="
echo "Setting up git safe.directory for $WORKSPACE and its submodules..."
cd "$WORKSPACE"
git config --global --add safe.directory "$WORKSPACE"
git submodule foreach --recursive 'git config --global --add safe.directory "$toplevel/$path"'
echo "===================="
cd "$WORKSPACE"
echo "Installing dependencies for python..."
# pip install -r tools/.../requirements.txt
# pip install -r tools/.../requirements-dev.txt
echo "===================="
echo "Installing dependencies for nodejs..."
cd "$WORKSPACE"/docs
pnpm install --frozen-lockfile

View File

@@ -13,7 +13,6 @@
290cc30f153a0206bd870a0a58cb6338aa16ea34
db9afdc77e85d5fc462d923fca5318be021656cd
a5daac889a55baf8895918d4964f20dad1938470
9ed30c5658c88edf1ef839771a53c7d599183b8b
# incorrect format of 3rdparty/resource/Arknights-Tile-Pos/levels.json
65d654e54b9d04d1902c9ee9f9fb2679520adafd
@@ -23,7 +22,6 @@ a5daac889a55baf8895918d4964f20dad1938470
206df466fd5e3d8ef80387049b0c5011fb58cada
c9b5aa638a97397ab8666031ea646904527afc09
559c913fca0dd0966896396e251be13f76ea3e52
# Re-structure again.
4b3b84df8f487be0ac86506c28dbebc4635f1282
91abbb7f175b93a58368a136acf3799666f770d2
@@ -31,24 +29,3 @@ c9b5aa638a97397ab8666031ea646904527afc09
bae271c09bb79e5cc2a7f8491ce882d276ac97b4
3d83b80dd67d996a5f4f1732fe1eb36cacc7605e
21617270bcef2456cb7f89e54560ca6788450711
# resource/*.json prettier mass styling
d84da5d01a872540d520bc87408d4524e07cfa39
546bfc399cdd140a9812f44b5e6bc89fccfda5fa
f0bdccdf0da7fac29f475951f0f43d3ab56a7ffe
7a758bce844bc2778f04a789195efbd17681dac7
5f3730b76785b1168125eb3b5edbed399722f8f9
bc3ad67a02cb3b8e154c06955cf17091c4265000
# oxipng template optimization
e3d63894b28b2ef5e2405e144a32a6981de5e1b2
# refactor: divide tasks.json into multiple jsons
dce6e317c8e56836662b64ac4b3d1a69b4ff4dd8
# usage: add "[blame ignore]" to the commit message
# This file is managed by an automated workflow
# Do not add, remove or modify lines below this comment
# as they are automatically appended
# --------------------------------------------------- #
f7772bc814c52f9a5e65af02404cf54b70fe0a32

1
.gitattributes vendored
View File

@@ -8,5 +8,4 @@
*.json text eol=lf
*.md text eol=lf
*.yml text eol=lf
*.yaml text eol=lf

View File

@@ -1 +0,0 @@
272d71fa2938f945832f86232532b86a9e5406b8

View File

@@ -1,22 +1,20 @@
name: Bug 反馈(使用中文)
description: 识别错误、操作异常、连接错误等
labels: ["bug"]
labels: ['bug']
body:
- type: checkboxes
id: checks
attributes:
label: 请确认自己完成了下列必选项之后再进行勾选,若未完成必选项或勾选了"我未仔细阅读"选项将视为自愿接受被直接关闭 Issue
label: 在提问之前...
options:
- label: 我理解 Issue 是用于反馈和解决问题的,而非吐槽评论区,将尽可能提供更多信息帮助问题解决
required: false
- label: 未仔细阅读这些内容,只是一键已读[所有内容](/MaaAssistantArknights/MaaAssistantArknights/issues),并相信这不会影响问题的处理
required: false
- label: 填写了简短且清晰明确的标题,以便开发者在翻阅 Issue 列表时能快速确定大致问题。而不是“一个建议”、“卡住了”等
required: false
- label: 使用的是当前更新版本的最新版, 并已查看版本发布至今的 [更新内容](https://github.com/MaaAssistantArknights/MaaAssistantArknights/commits/dev/), [Pull Requests](https://github.com/MaaAssistantArknights/MaaAssistantArknights/pulls) 中尚未发布的更新内容并未提及该 Bug 已被修复的情况
required: false
- label: 我已检查了 [常见问题](https://docs.maa.plus/zh-cn/manual/faq.html), [公告](https://github.com/MaaAssistantArknights/MaaAssistantArknights/issues/7732), [活跃议题](https://github.com/MaaAssistantArknights/MaaAssistantArknights/issues), [已关闭议题](https://github.com/MaaAssistantArknights/MaaAssistantArknights/issues?q=is%3Aissue%20state%3Aclosed) 确认我的问题未被提及
required: false
- label: 我理解 Issue 是用于反馈和解决问题的,而非吐槽评论区,将尽可能提供更多信息帮助问题解决
required: true
- label: 填写了简短且清晰明确的标题,以便开发者在翻阅 Issue 列表时能快速确定大致问题。而不是“一个建议”、“卡住了”等
required: true
- label: 已查看最新测试版本的更新内容,并未提及该 Bug 已被修复的情况
required: true
- label: 已检查了置顶议题pinned issue确认我的问题未被提及
required: true
- type: textarea
id: describe
attributes:
@@ -28,49 +26,32 @@ body:
id: version
attributes:
label: Version
description: |
请提供 MAA 版本。可在 MAA -> 设置 -> 软件更新中找到点击图标可复制
请分别点击 `资源版本` 和 `MAA 版本` 并粘贴,最终应有 5 行版本信息。
description: >-
请提供 MAA 版本。可在 MAA -> 设置 -> 软件更新中找到点击图标可复制)。
placeholder: |
Resource Version:
MAA Version:
UI Version:
Core Version:
validations:
required: true
- type: textarea
id: logs
attributes:
label: 日志和配置文件
label: 日志文件
description: |
**请在 MAA -> 设置 -> 问题反馈中找到生成日志压缩包按钮,点击并上传压缩包**
**请在关闭MAA后,上传 `debug` 文件夹中的 `asst.log` 和 `gui.log` 日志文件,并说明问题出现的大致时间点**
**请直接将完整的文件拖拽进来,而非自己裁切或复制的片段;若文件体积过大可压缩后再上传**
如果你在使用 MacBook请点击屏幕左上角的“文件”点击“打开日志文件夹”
placeholder: |
请确认上传文件前已关闭 MAA
validations:
required: true
- type: textarea
id: configuration
attributes:
label: 配置信息
description: |
请说明操作系统及版本、模拟器品牌、模拟器分辨率、DPI、帧率
若正在使用 MuMu 或雷电 9请说明截图增强是否开启
最后请说明 GPU 加速推理是否开启,若开启请提供 GPU 型号。
validations:
required: true
- type: textarea
id: screenshots
attributes:
label: 截图或录屏
label: 截图
description: |
`debug` 目录下按功能分类的文件夹内,有一些自动截图的错误图片,若有相关的,请一并打包上传
可上传屏幕截图或录制以帮助解释你的问题,包括但不限于 MAA 软件截图、游戏画面截图
如果有,添加屏幕截图以帮助解释你的问题,包括但不限于 MAA 软件截图、游戏画面截图
若是**识别相关问题**,请尽可能提供模拟器自带的截图工具截取的无遮挡的**原图**(或通过 adb 截取原图)
用其他的工具如QQ/微信)截取的图片包含窗口边框且长宽比、分辨率不固定不利于我们排除bug
若文件体积过大可压缩后再上传
用其他的工具如QQ截取的图片包含窗口边框不利于我们排除bug
`debug` 文件夹下有一些自动截图的错误图片,若有相关的,请一并打包上传
validations:
required: false
- type: textarea
@@ -78,6 +59,7 @@ body:
attributes:
label: 还有别的吗?
description: |
使用的模拟器?操作系统?相关的配置?链接?参考资料?
任何能让我们对你所遇到的问题有更多了解的东西
validations:
required: false

View File

@@ -1,22 +1,16 @@
name: 需求建议(使用中文)
description: 新功能、建议等
labels: ["enhancement"]
labels: ['enhancement']
body:
- type: checkboxes
id: checks
attributes:
label: 请确认自己完成了下列必选项之后再进行勾选,若未完成必选项或勾选了"我未仔细阅读"选项将视为自愿接受被直接关闭 Issue
label: 在提问之前...
options:
- label: 基本确定这是一个新功能/建议,而不是遇到了 Bug不确定的话请附上日志
required: false
- label: 未仔细阅读这些内容,只是一键已读[所有内容](/MaaAssistantArknights/MaaAssistantArknights/issues),并相信这不会影响问题的处理
required: false
- label: 我填写了简短且清晰明确的标题,以便开发者在翻阅 Issue 列表时能快速确定大致问题。而不是“一个建议”、“卡住了”等
required: false
- label: 我使用的是当前更新版本的最新版, 并已查看版本发布至今的 [更新内容](https://github.com/MaaAssistantArknights/MaaAssistantArknights/commits/dev/), [Pull Requests](https://github.com/MaaAssistantArknights/MaaAssistantArknights/pulls) 中尚未发布的更新内容,确认我的建议未被提及
required: false
- label: 我已检查了 [常见问题](https://docs.maa.plus/zh-cn/manual/faq.html), [公告](https://github.com/MaaAssistantArknights/MaaAssistantArknights/issues/7732), [活跃议题](https://github.com/MaaAssistantArknights/MaaAssistantArknights/issues), [已关闭议题](https://github.com/MaaAssistantArknights/MaaAssistantArknights/issues?q=is%3Aissue%20state%3Aclosed) 确认我的建议未被提及
required: false
- label: 填写了简短且清晰明确的标题,以便开发者在翻阅 Issue 列表时能快速确定大致问题。而不是“一个建议”、“卡住了”等
required: true
- label: 基本确定这是一个新功能/建议,而不是遇到了 Bug不确定的话请附上日志
required: true
- type: textarea
id: describe
attributes:

View File

@@ -1,85 +0,0 @@
name: 雷电截图增强反馈(使用中文)
description: 有关雷电 9 截图增强功能的集中反馈
labels: ["LD9 API"]
body:
- type: checkboxes
id: checks
attributes:
label: 在提问之前...
options:
- label: 我理解 Issue 是用于反馈和解决问题的,而非吐槽评论区,将尽可能提供更多信息帮助问题解决
required: false
- label: 我填写了简短且清晰明确的标题,以便开发者在翻阅 Issue 列表时能快速确定大致问题。而不是“一个建议”、“卡住了”等
required: false
- label: 我已检查了[公告](/MaaAssistantArknights/MaaAssistantArknights/issues/7732)、[活跃议题](https://github.com/MaaAssistantArknights/MaaAssistantArknights/issues)、[已关闭议题](https://github.com/MaaAssistantArknights/MaaAssistantArknights/issues?q=is%3Aissue%20state%3Aclosed),确认我的问题未被提及
required: false
- label: 我未仔细阅读这些内容,只是一键已读[所有内容](/MaaAssistantArknights/MaaAssistantArknights/issues),并相信这不会影响问题的处理
required: false
- label: 我正在使用最新的 MAA 公测版本和最新的官版雷电 9 模拟器
required: false
- label: 我已参考文档确定安装路径、实例编号填写正确,并确认在关闭截图增强模式后问题消失
required: false
- label: 我未开启高帧率,且模拟器帧数设置为 60
required: false
- type: textarea
id: describe
attributes:
label: 问题描述
description: 描述问题时请尽可能详细
validations:
required: true
- type: textarea
id: version
attributes:
label: Version
description: |
请提供 MAA 版本和雷电 9 版本。MAA 版本可在 MAA -> 设置 -> 软件更新中找到(点击图标可复制)。
雷电 9 版本可在右上角菜单按钮 -> 关于雷电 中找到。
placeholder: |
Resource Version:
MAA Version:
雷电 9 版本号:
validations:
required: true
- type: textarea
id: logs
attributes:
label: MAA 日志和配置文件
description: |
**请在 MAA -> 设置 -> 问题反馈中找到生成日志压缩包按钮,点击并上传压缩包**
**请直接将完整的文件拖拽进来,而非自己裁切或复制的片段;若文件体积过大可压缩后再上传**
placeholder: |
请确认上传文件前已关闭 MAA
validations:
required: true
- type: textarea
id: ldlogs
attributes:
label: 雷电 9 诊断信息
description: |
**在雷电 9 右上角菜单按钮 -> 诊断信息 中点击 复制信息,并将全部内容粘贴进来。**
validations:
required: true
- type: textarea
id: screenshots
attributes:
label: 截图
description: |
`debug` 目录下按功能分类的文件夹内,有一些自动截图的错误图片,若有相关的,请一并打包上传
可上传屏幕截图或录制以帮助解释你的问题,包括但不限于 MAA 软件截图、游戏画面截图
若是**识别相关问题**,请尽可能提供模拟器自带的截图工具截取的无遮挡的**原图**(或通过 adb 截取原图)
用其他的工具如QQ/微信截取的图片包含窗口边框且长宽比、分辨率不固定不利于我们排除bug
若文件体积过大可压缩后再上传
validations:
required: false
- type: textarea
id: others
attributes:
label: 其他
description: |
GPU 加速推理是否开启,若开启请提供 GPU 型号。
亦或者任何能让我们对你所遇到的问题有更多了解的东西
validations:
required: false

View File

@@ -1,26 +1,26 @@
name: MuMu 截图增强反馈(使用中文)
description: 有关 MuMu 截图增强功能的集中反馈
labels: ["MuMu API"]
labels: ['mumu api']
body:
- type: checkboxes
id: checks
attributes:
label: 在提问之前...
options:
- label: 我理解 Issue 是用于反馈和解决问题的,而非吐槽评论区,将尽可能提供更多信息帮助问题解决
required: false
- label: 我填写了简短且清晰明确的标题,以便开发者在翻阅 Issue 列表时能快速确定大致问题。而不是“一个建议”、“卡住了”等
required: false
- label: 我已检查了[公告](/MaaAssistantArknights/MaaAssistantArknights/issues/7732)、[活跃议题](https://github.com/MaaAssistantArknights/MaaAssistantArknights/issues)、[已关闭议题](https://github.com/MaaAssistantArknights/MaaAssistantArknights/issues?q=is%3Aissue%20state%3Aclosed),确认我的问题未被提及
required: false
- label: 未仔细阅读这些内容,只是一键已读[所有内容](/MaaAssistantArknights/MaaAssistantArknights/issues),并相信这不会影响问题的处理
required: false
- label: 正在使用最新的 MAA 公测版本和最新的官版或方舟专版 MuMu 模拟器
required: false
- label: 已参考文档确定安装路径、实例编号、屏幕编号填写正确,并确认在关闭截图增强模式后问题消失
required: false
- label: 未开启动态帧率及后台保活,模拟器帧数为 60显存使用策略为“画面表现更好”
required: false
- label: 我理解 Issue 是用于反馈和解决问题的,而非吐槽评论区,将尽可能提供更多信息帮助问题解决
required: true
- label: 我填写了简短且清晰明确的标题,以便开发者在翻阅 Issue 列表时能快速确定大致问题。而不是“一个建议”、“卡住了”等
required: true
- label: 我已检查了置顶议题Pinned Issue,确认我的问题未被提及
required: true
- label: 正在使用最新的 MAA 内测版本和最新的**官版** MuMu 模拟器
required: true
- label: 已参考文档确定安装路径、实例编号、屏幕编号填写正确,并确认在关闭截图增强模式后问题消失
required: true
- label: 未开启高帧率模式,且显存使用策略为“画面表现更好”
required: false
- label: 正在使用后台保活功能,并确定该问题仅在开启后台保活时出现
required: false
- type: textarea
id: describe
attributes:
@@ -32,25 +32,22 @@ body:
id: version
attributes:
label: Version
description: |
请提供 MAA 版本和 MuMu 版本。MAA 版本可在 MAA -> 设置 -> 软件更新中找到(点击图标可复制)。
MuMu 版本可在右上角菜单按钮 -> 关于 MuMu 中找到。
description: >-
请提供 MAA 版本和 MuMu 版本。MAA 版本可在 MAA -> 设置 -> 软件更新中找到(点击图标可复制)。MuMu 版本可在右上角菜单按钮 -> 关于 MuMu 中找到。
placeholder: |
Resource Version:
MAA Version:
MuMu 版本号:
Resource Version:
UI Version:
Core Version:
MuMu 版本号:
validations:
required: true
- type: textarea
id: logs
attributes:
label: MAA 日志和配置文件
label: MAA 日志文件
description: |
**请在 MAA -> 设置 -> 问题反馈中找到生成日志压缩包按钮,点击并上传压缩包**
**上传 `debug` 文件夹中的 `asst.log` 和 `gui.log` 日志文件,并说明问题出现的大致时间点**
**请直接将完整的文件拖拽进来,而非自己裁切或复制的片段;若文件体积过大可压缩后再上传**
placeholder: |
请确认上传文件前已关闭 MAA
validations:
required: true
- type: textarea
@@ -67,20 +64,18 @@ body:
attributes:
label: 截图
description: |
`debug` 目录下按功能分类的文件夹内,有一些自动截图的错误图片,若有相关的,请一并打包上传
可上传屏幕截图或录制以帮助解释你的问题,包括但不限于 MAA 软件截图、游戏画面截图
如果有,添加屏幕截图以帮助解释你的问题,包括但不限于 MAA 软件截图、游戏画面截图
若是**识别相关问题**,请尽可能提供模拟器自带的截图工具截取的无遮挡的**原图**(或通过 adb 截取原图)
用其他的工具如QQ/微信)截取的图片包含窗口边框且长宽比、分辨率不固定不利于我们排除bug
若文件体积过大可压缩后再上传
用其他的工具如QQ截取的图片包含窗口边框不利于我们排除bug
`debug` 文件夹下有一些自动截图的错误图片,若有相关的,请一并打包上传
validations:
required: false
- type: textarea
id: others
attributes:
label: 其他
label: 还有别的吗?
description: |
GPU 加速推理是否开启,若开启请提供 GPU 型号。
亦或者任何能让我们对你所遇到的问题有更多了解的东西
操作系统?相关的配置?链接?参考资料?
任何能让我们对你所遇到的问题有更多了解的东西
validations:
required: false

View File

@@ -1,6 +1,6 @@
name: 其他议题(使用中文)
description: 提出问题,而不是 Bug 反馈或需求建议
labels: ["question"]
labels: ['question']
body:
- type: textarea
id: describe

View File

@@ -1,24 +1,33 @@
name: Bug Report (in English)
description: Recognition errors, operation abnormalities, connection errors, etc.
labels: ["bug"]
description: >-
Recognition errors, operation abnormalities,
connection errors, etc.
labels: ['bug']
body:
- type: checkboxes
id: checks
attributes:
label: |
Please ensure that you have completed the required items before checking the boxes.
Issues with incomplete required items or with the 'I did not read carefully' option checked will be considered voluntary acceptance of direct closure.
label: Before raising the issue...
options:
- label: I understand that Issues are for feedback and problem solving, not trolling the comments section, and will provide as much information as possible to help solve the problem.
required: true
- label: I filled in a short, clear title so that developers could quickly identify the general problem when going through the issue list. Instead of "Some suggestions", "Stuck", etc.
required: true
- label: I am using the latest version of the current update version, and have reviewed the [update content](https://github.com/MaaAssistantArknights/MaaAssistantArknights/commits/dev/) released to date, [Pull Requests](https://github.com/MaaAssistantArknights/MaaAssistantArknights/pulls) unreleased update content and there is no mention of the bug being fixed.
required: true
- label: I have checked all the options without carefully reading the content and believe this will not affect issue resolution.
required: false
- label: I have reviewed the [FAQs](https://docs.maa.plus/en-us/manual/faq.html), [Announcement](/MaaAssistantArknights/MaaAssistantArknights/issues/7732), [Open Issues](https://github.com/MaaAssistantArknights/MaaAssistantArknights/issues), [Closed Issues](https://github.com/MaaAssistantArknights/MaaAssistantArknights/issues?q=is%3Aissue%20state%3Aclosed) to ensure that my issue has not been mentioned.
required: true
- label: >-
I understand that Issues are for feedback and problem solving,
not trolling the comments section, and will provide as
much information as possible to help solve the problem.
required: true
- label: >-
I filled in a short, clear title
so that developers could quickly identify the general problem
when going through the issue list.
Instead of "Some suggestions", "Stuck", etc.
required: true
- label: >-
I have checked the latest beta update and there is no mention
of the bug being fixed.
required: true
- label: >-
I have reviewed the pinned issues and confirmed that my issue
is not mentioned.
required: true
- type: textarea
id: describe
attributes:
@@ -30,48 +39,32 @@ body:
id: version
attributes:
label: Version
description: |
Please provide the MAA version. Can be found in MAA -> Settings -> Update. Click to copy.
Click on `Resource Version` and `MAA Version` and paste them respectively. There should be 5 lines of version information in total.
description: >-
Please provide the MAA version. Can be found in MAA -> Settings -> Update. (Click to copy)
placeholder: |
Resource Version:
MAA Version:
UI Version:
Core Version:
validations:
required: true
- type: textarea
id: logs
attributes:
label: Log and config files
description: |
**Please locate the Generate Support Payload button under MAA Settings -> Issue Report, click the button, and upload the generated zip file**
label: Log files
description: >-
**After closing the MAA, upload the `asst.log` and `gui.log` log file in the `debug` folder and**
**indicate the approximate point in time when the problem occurred.**
**Please drag and drop the full file in, not your own cuttings or copies; compress it before uploading if too large.**
If you are using MacBook, please click the "File" option in the top-left corner of the screen, then click "Open Log Folder".
placeholder: |
Please confirm that MAA is not running before uploading files.
validations:
required: true
- type: textarea
id: configuration
attributes:
label: Configuration information
description: |
Please specify the operating system and version, emulator brand, emulator resolution, DPI, and frame rate;
If you are using MuMu or LDPlayer 9, please specify whether Screenshot Enhancement is enabled;
Finally, please specify whether GPU accelerated inference is enabled, and if so, provide the GPU model.
**Please drag and drop the full file in, not your own cuttings or copies;**
**compress it before uploading if too large.**
validations:
required: true
- type: textarea
id: screenshots
attributes:
label: Screenshots or recordings
description: |
In the `debug` directory, within the functionally categorized folders,
there are some error images captured automatically.
If related to this issue, please upload them together.
If available, upload screenshots and recordings to help explain your problem,
label: Screenshots
description: >-
If available, add screenshots to help explain your problem,
including but not limited to screenshots of MAA software,
screenshots of game screens.
@@ -79,18 +72,23 @@ body:
the **original image** taken by the emulator's own screenshot tool
(or via adb).
Screenshots taken with other tools may contain the frames of the window/emulator
and their aspect ratio and resolution are inconsistent,
which makes it harder for us to debug.
Screenshots taken with other tools may contain the frames of the window/emulator, which makes it harder for us to debug.
The `debug` folder has some automatic screenshots of the error images,
if you have any,
please upload them together.
If the file size is too large, you may compress it before uploading.
validations:
required: false
- type: textarea
id: others
attributes:
label: Anything else?
description: |
Anything that will give us more insight into the problem you are having.
label: Anthing else?
description: >-
Emulator used, operating system, related configuration, links,
reference material, etc.
Anything that will give us more insight into the problem
you are having.
validations:
required: false

View File

@@ -1,24 +1,16 @@
name: Feature Request (in English)
description: New features, suggestions, etc.
labels: ["enhancement"]
labels: ['enhancement']
body:
- type: checkboxes
id: checks
attributes:
label: |
Please ensure that you have completed the required items before checking the boxes.
Issues with incomplete required items or with the 'I did not read carefully' option checked will be considered voluntary acceptance of direct closure.
label: Before raising the issue...
options:
- label: I'm probably sure this is a new feature/suggestion and not a bug encountered (please attach logs if you're not sure).
required: true
- label: I filled in a short, clear title so that developers could quickly identify the general problem when going through the issue list. Instead of "Some suggestions", "Stuck", etc.
required: true
- label: I am using the latest version of the current update version, and have reviewed the [update content](https://github.com/MaaAssistantArknights/MaaAssistantArknights/commits/dev/) released to date, [Pull Requests](https://github.com/MaaAssistantArknights/MaaAssistantArknights/pulls) unreleased update content and there is no mention of this feature/suggestion being added.
required: true
- label: I have checked all the options without carefully reading the content and believe this will not affect issue resolution.
required: false
- label: I have reviewed the [FAQs](https://docs.maa.plus/en-us/manual/faq.html), [Announcement](/MaaAssistantArknights/MaaAssistantArknights/issues/7732), [Open Issues](https://github.com/MaaAssistantArknights/MaaAssistantArknights/issues), [Closed Issues](https://github.com/MaaAssistantArknights/MaaAssistantArknights/issues?q=is%3Aissue%20state%3Aclosed) to ensure that my feature/suggestion has not been mentioned.
required: true
- label: I filled in a short, clear title so that developers could quickly identify the general problem when going through the issue list. Instead of "Some suggestions", "Stuck", etc.
required: true
- label: I'm probably sure this is a new feature/suggestion and not a bug encountered (please attach logs if you're not sure)
required: true
- type: textarea
id: describe
attributes:

View File

@@ -1,6 +1,6 @@
name: Others (in English)
description: Ask a question rather than a bug report or feature request.
labels: ["question"]
labels: ['question']
body:
- type: textarea
id: describe

View File

@@ -1,18 +0,0 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /.github/workflows
schedule:
interval: weekly
commit-message:
prefix: ci
assignees:
- AnnAngela
- Constrat
groups:
github-actions:
patterns:
- "*"
ignore:
- dependency-name: "Nerixyz/actionsx-prettier"
versions: ["3.0.0"]

File diff suppressed because it is too large Load Diff

View File

@@ -1,38 +0,0 @@
$totalClearedSize = 0
$cacheList = gh cache list --json id,ref,sizeInBytes | ConvertFrom-Json
$prCaches = $cacheList | Where-Object { $_.ref -like "*merge*" }
if (-not $prCaches) {
Write-Output "No PR caches found."
exit
}
foreach ($cache in $prCaches) {
$cacheId = $cache.id
$cacheRef = $cache.ref
$cacheSizeInBytes = $cache.sizeInBytes
if ($cacheRef -match "refs/pull/(\d+)/merge") {
$prNumber = $matches[1]
Write-Host "PR #${prNumber}: " -NoNewline
$prStatus = gh pr view $prNumber --json state | ConvertFrom-Json
Write-Host $prStatus.state -NoNewline
if ($prStatus.state -eq "MERGED" -or $prStatus.state -eq "CLOSED") {
Write-Host " -> DELETING"
gh cache delete $cacheId
$totalClearedSize += $cacheSizeInBytes
}
else {
Write-Host ""
}
}
}
$formattedSize = "{0:N2}" -f ($totalClearedSize / 1MB)
Write-Output "Cleared size: $formattedSize MB"

View File

@@ -11,6 +11,7 @@ reviewers:
# A list of assignees to be added to pull requests (GitHub user name)
assignees:
- AnnAngela
# A list of keywords to be skipped the process that add reviewers if pull requests include it
# skipKeywords:
# - wip

View File

@@ -1,75 +0,0 @@
$totalClearedSize = 0
$cacheList = gh cache list --json id,key,ref,sizeInBytes,createdAt | ConvertFrom-Json
# List of keys to process
$keyPatterns = @(
"Windows-x64-nuget",
"Windows-x64-maadeps",
"Windows-arm64-nuget",
"Windows-arm64-maadeps",
"macOS-x64-maadeps",
"macOS-arm64-maadeps",
"Linux-x64-maadeps",
"Linux-arm64-maadeps",
"Smoke-testing"
)
# Filter caches matching any of our key patterns
$matchingCaches = $cacheList | Where-Object {
$cache = $_
($keyPatterns | Where-Object { $cache.key -like "*$_*" }).Count -gt 0
}
# Get unique branch references from the matching caches
$branches = $matchingCaches | Select-Object -Property ref -Unique | ForEach-Object { $_.ref }
Write-Output "Found caches across $($branches.Count) branches"
foreach ($branch in $branches) {
# Extract branch name from ref for display
$branchName = $branch -replace "refs/heads/", ""
if ($branch -match "refs/pull/(\d+)/merge") {
$branchName = "PR #$($matches[1])"
}
Write-Output "Processing caches for branch: $branchName"
# Filter for current branch caches
$branchCaches = $matchingCaches | Where-Object { $_.ref -eq $branch }
foreach ($pattern in $keyPatterns) {
Write-Output " Processing $branchName branch caches for pattern: $pattern"
# Filter for caches matching the current key pattern within branch
$patternCaches = $branchCaches | Where-Object { $_.key -like "*$pattern*" }
if (-not $patternCaches) {
Write-Output " No $branchName branch caches found for pattern: $pattern"
continue
}
# Sort by creation time (newest first)
$sortedCaches = $patternCaches | Sort-Object -Property createdAt -Descending
# Keep the first one (latest) and delete the rest
$latestCache = $sortedCaches[0]
Write-Output " Keeping latest cache for $branchName/${pattern}: '$($latestCache.key)' (ID: $($latestCache.id))"
# Delete all except the latest one
for ($i = 1; $i -lt $sortedCaches.Count; $i++) {
$cache = $sortedCaches[$i]
$cacheId = $cache.id
$cacheKey = $cache.key
Write-Output " Deleting cache for $branchName/${pattern}: '$cacheKey' (ID: $cacheId)"
gh cache delete $cacheId
$totalClearedSize += $cache.sizeInBytes
}
}
Write-Output ""
}
$formattedSize = "{0:N2}" -f ($totalClearedSize / 1MB)
Write-Output "Total cleared size: $formattedSize MB"

View File

@@ -1,59 +0,0 @@
$totalClearedSize = 0
$cacheList = gh cache list --json id,key,ref,sizeInBytes,createdAt | ConvertFrom-Json
# Filter for dev branch caches only
$devCaches = $cacheList | Where-Object { $_.ref -eq "refs/heads/dev" }
if (-not $devCaches) {
Write-Output "No caches found for dev branch."
exit
}
# List of keys to process
$keyPatterns = @(
"Windows-x64-nuget",
"Windows-x64-maadeps",
"Windows-arm64-nuget",
"Windows-arm64-maadeps",
"macOS-x64-maadeps",
"macOS-arm64-maadeps",
"Linux-x64-maadeps",
"Linux-arm64-maadeps",
"Smoke-testing"
)
foreach ($pattern in $keyPatterns) {
Write-Output "Processing dev branch caches for pattern: $pattern"
# Filter for caches matching the current key pattern within dev branch
$matchingCaches = $devCaches | Where-Object { $_.key -like "*$pattern*" }
if (-not $matchingCaches) {
Write-Output " No dev branch caches found for pattern: $pattern"
continue
}
# Sort by creation time (newest first)
$sortedCaches = $matchingCaches | Sort-Object -Property createdAt -Descending
# Keep the first one (latest) and delete the rest
$latestCache = $sortedCaches[0]
Write-Output " Keeping latest dev branch cache: '$($latestCache.key)' (ID: $($latestCache.id))"
# Delete all except the latest one
for ($i = 1; $i -lt $sortedCaches.Count; $i++) {
$cache = $sortedCaches[$i]
$cacheId = $cache.id
$cacheKey = $cache.key
Write-Output " Deleting dev branch cache: '$cacheKey' (ID: $cacheId)"
gh cache delete $cacheId
$totalClearedSize += $cache.sizeInBytes
}
Write-Output ""
}
$formattedSize = "{0:N2}" -f ($totalClearedSize / 1MB)
Write-Output "Total cleared size: $formattedSize MB"

View File

@@ -1,49 +0,0 @@
name: Git Blame Ignore
on:
schedule:
- cron: "45 21 * * *" # Runs daily at 22:00 UTC
workflow_dispatch:
jobs:
blame-ignore:
if: github.repository_owner == 'MaaAssistantArknights'
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v5
with:
fetch-depth: 0
persist-credentials: false # Needed to bypass protection rules in Push changes
- name: Check blame
id: check_changes
run: |
LAST_CHECKED_COMMIT=$(cat .github/.last-blame-ignore-commit 2>/dev/null || git rev-list --max-parents=0 HEAD)
git log $LAST_CHECKED_COMMIT..HEAD --pretty=format:"%H %s" --grep="\[blame ignore\]" | awk '{print $1}' >> .git-blame-ignore-revs
git diff --quiet .git-blame-ignore-revs
- name: Commit and Push changes
if: ${{ steps.check_changes.outcome == 'failure' }}
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git rev-parse HEAD > .github/.last-blame-ignore-commit
git add .github/.last-blame-ignore-commit .git-blame-ignore-revs
git commit -m "chore: auto blame ignore" -m "[skip changelog]"
- name: Push changes
if: ${{ steps.check_changes.outcome == 'failure' }}
uses: ad-m/github-push-action@master
with:
branch: ${{ github.ref }}
github_token: ${{ secrets.MAA_RESOURCE_SYNC }}
- name: Stop if no changes
if: ${{ steps.check_changes.outcome == 'success' }}
uses: andymckay/cancel-action@0.5

View File

@@ -1,39 +0,0 @@
name: Delete Cache
on:
pull_request:
types: [closed]
workflow_dispatch:
inputs:
pr_number:
description: "PR Number"
required: true
jobs:
cache-delete:
# Run only on organization branches with PRs
if: github.event_name == 'workflow_dispatch' ||
github.event.pull_request.head.repo.full_name ==
github.event.pull_request.base.repo.full_name
runs-on: ubuntu-latest
steps:
- name: Delete cache on PR merged
run: |
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
PR_NUMBER=${{ github.event.inputs.pr_number }}
else
PR_NUMBER=${{ github.event.pull_request.number }}
fi
echo "PR Number: $PR_NUMBER"
curl -s -L https://api.github.com/repos/Maaassistantarknights/Maaassistantarknights/actions/caches |
jq -r --arg PR_NUMBER "refs/pull/$PR_NUMBER/merge" '.actions_caches[] | select(.ref == $PR_NUMBER) | .id' |
while read -r id; do
echo "Deleting cache with ID: $id"
curl -L -X DELETE \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"https://api.github.com/repos/MaaAssistantArknights/MaaAssistantArknights/actions/caches/$id"
done

View File

@@ -12,9 +12,9 @@ on:
- "src/**"
- "cmake/**"
- "CMakeLists.txt"
- "MAA.sln"
- ".github/workflows/ci.yml"
- "!**/*.md"
- "tools/maadeps-download.py"
pull_request:
branches:
- "dev"
@@ -24,28 +24,19 @@ on:
- "src/**"
- "cmake/**"
- "CMakeLists.txt"
- "MAA.sln"
- "!**/*.md"
- "tools/maadeps-download.py"
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
meta:
# Prevent duplicate runs on organization branches with PRs
if: github.event_name != 'pull_request' ||
github.event.pull_request.head.repo.full_name !=
github.event.pull_request.base.repo.full_name
runs-on: ubuntu-latest
outputs:
tag: ${{ steps.set_tag.outputs.tag }}
prerelease: ${{ steps.set_pre.outputs.prerelease }}
steps:
- name: Checkout code
uses: actions/checkout@v5
uses: actions/checkout@v4
with:
path: temp
show-progress: false
@@ -89,8 +80,6 @@ jobs:
fi
echo >> CHANGELOG.md
echo "**Full Changelog**: [$last_tag -> $this_tag](https://github.com/MaaAssistantArknights/MaaAssistantArknights/compare/${last_tag}...${this_tag})" >> CHANGELOG.md
echo >> CHANGELOG.md
echo "[已有 Mirror酱 CDK前往 Mirror酱 高速下载](https://mirrorchyan.com/zh/projects?rid=MAA&source=maagh-release)" >> CHANGELOG.md
- name: Upload changelog to Github
uses: actions/upload-artifact@v4
@@ -100,56 +89,24 @@ jobs:
path: CHANGELOG.md
windows:
# Prevent duplicate runs on organization branches with PRs
if: github.event_name != 'pull_request' ||
github.event.pull_request.head.repo.full_name !=
github.event.pull_request.base.repo.full_name
needs: meta
strategy:
matrix:
arch: [arm64, x64]
fail-fast: false
include:
- msbuild_target: x64
lowercase_target: x64
- msbuild_target: ARM64
lowercase_target: arm64
env:
MAABUILDER_TARGET_PLATFORM: ${{ matrix.msbuild_target }}
runs-on: windows-latest
steps:
- name: Checkout code
uses: actions/checkout@v5
uses: actions/checkout@v4
with:
show-progress: false
- name: Fetch submodules
run: |
git submodule update --init --depth 1 3rdparty/EmulatorExtras
- name: Cache MaaDeps
id: cache-maadeps
uses: actions/cache@v4
with:
path: |
./MaaDeps
key: ${{ runner.os }}-${{ matrix.arch }}-maadeps-${{ hashFiles('tools/maadeps-download.py') }}
- name: Bootstrap MaaDeps
if: steps.cache-maadeps.outputs.cache-hit != 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
python3 tools/maadeps-download.py ${{ matrix.arch }}-windows
- name: Config cmake
run: |
mkdir -p build
cmake -B build ${{ matrix.arch == 'arm64' && '-A ARM64' }} -DCMAKE_BUILD_TYPE=Release -DMAADEPS_TRIPLET='maa-${{ matrix.arch }}-windows' -DINSTALL_RESOURCE=ON -DINSTALL_PYTHON=ON -DMAA_HASH_VERSION='${{ needs.meta.outputs.tag }}' -DBUILD_WPF_GUI=OFF
- name: Build
run: |
cmake --build build --config Release --parallel $env:NUMBER_OF_PROCESSORS
- name: Install
run: |
mkdir -p install
cmake --install build --prefix install --config Release
submodules: recursive
- name: Cache .nuke/temp, ~/.nuget/packages
id: cache-nuget
@@ -158,13 +115,29 @@ jobs:
path: |
.nuke/temp
~/.nuget/packages
key: ${{ runner.os }}-${{ matrix.arch }}-nuget-${{ hashFiles('**/*.csproj') }}
key: ${{ runner.os }}-${{ matrix.msbuild_target }}-${{ hashFiles('**/global.json', '**/*.csproj') }}
- name: Restore dependencies
if: steps.cache-nuget.outputs.cache-hit != 'true'
run: dotnet restore src/MaaWpfGui/MaaWpfGui.csproj
run: dotnet restore
- name: Taggify Version for csproj
- name: Bootstrap MaaDeps
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
python3 maadeps-download.py ${{ matrix.lowercase_target }}-windows
- name: Create fake event file
shell: bash
run: cp -v "$GITHUB_EVENT_PATH" ./event.json
- name: Merge Event Data with Inputs
if: startsWith(github.ref, 'refs/tags/v')
shell: bash
run: |
cat "$GITHUB_EVENT_PATH" | jq '. + { "inputs": {"ReleaseSimulation": "${{ needs.meta.outputs.tag }}"} }' | tee ./event.json
- name: Taggify Version
run: |
$csprojPath = "src/MaaWpfGui/MaaWpfGui.csproj"
$csprojPath = Resolve-Path -Path $csprojPath
@@ -181,90 +154,76 @@ jobs:
$node.FileVersion = $match
$node.AssemblyVersion = $match
$csproj.Save($csprojPath)
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Publish WPF GUI
continue-on-error: true
- name: Build
run: |
dotnet publish src/MaaWpfGui/MaaWpfGui.csproj -c Release -o install
$env:GITHUB_WORKFLOW = 'dev-build-win' # pretend this is a dev-build-win workflow
$env:GITHUB_EVENT_PATH = "$pwd\\event.json"
$env:GITHUB_REF = "refs/heads/not_master"
$env:MAA_BUILDER_MAA_VERSION = '${{ needs.meta.outputs.tag }}'
./build.cmd DevBuild
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Organize Install Files
- name: Cleanup checksum file
run: |
rm -vf ./artifacts/checksum.json
shell: bash
run: |
rm -rf install/*.pdb
rm -rf install/msvc-debug
rm -rf install/*.h
cp tools/DependencySetup_依赖库安装.bat install
- name: Zip files
run: |
cd install
Compress-Archive -Destination MAA-${{ needs.meta.outputs.tag }}-win-${{ matrix.arch }}.zip -Path ./*
- name: Upload MAA to Github
uses: actions/upload-artifact@v4
with:
name: MAA-win-${{ matrix.arch }}
path: install/*.zip
name: MAA-win-${{ matrix.lowercase_target }}
path: artifacts
ubuntu:
# Prevent duplicate runs on organization branches with PRs
if: github.event_name != 'pull_request' ||
github.event.pull_request.head.repo.full_name !=
github.event.pull_request.base.repo.full_name
needs: meta
runs-on: ubuntu-latest
strategy:
matrix:
arch: [aarch64, x86_64]
fail-fast: false
steps:
- name: Checkout code
uses: actions/checkout@v5
uses: actions/checkout@v4
with:
show-progress: false
submodules: recursive
- name: Fetch submodules
- name: Install cross compile toolchains
if: ${{ matrix.arch != 'x86_64' }}
run: |
git submodule update --init --depth 1 3rdparty/EmulatorExtras
git submodule update --init --depth 1 src/maa-cli
sudo apt-get update
sudo apt-get install g++-12-aarch64-linux-gnu g++-12-aarch64-linux-gnu
- name: Cache MaaDeps
id: cache-maadeps
uses: actions/cache@v4
- name: Setup ccache
uses: Chocobo1/setup-ccache-action@v1
with:
path: ./MaaDeps
key: ${{ runner.os }}-${{ matrix.arch == 'x86_64' && 'x64' || 'arm64' }}-maadeps-${{ hashFiles('tools/maadeps-download.py') }}
remove_stale_cache: false
- name: Bootstrap MaaDeps
if: steps.cache-maadeps.outputs.cache-hit != 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
python3 tools/maadeps-download.py ${{ matrix.arch == 'x86_64' && 'x64' || 'arm64' }}-linux
python3 maadeps-download.py ${{ matrix.arch == 'x86_64' && 'x64' || 'arm64' }}-linux
- name: Config cmake
- name: Build MAA
run: |
mkdir -p build
cmake -B build \
-DCMAKE_BUILD_TYPE=Release \
-DMAADEPS_TRIPLET='maa-${{ matrix.arch == 'x86_64' && 'x64' || 'arm64' }}-linux' \
-DINSTALL_THIRD_LIBS=ON \
-DINSTALL_RESOURCE=ON \
-DINSTALL_PYTHON=ON \
-DMAA_HASH_VERSION='${{ needs.meta.outputs.tag }}' \
-DCMAKE_TOOLCHAIN_FILE=MaaDeps/cmake/maa-${{ matrix.arch == 'x86_64' && 'x64' || 'arm64' }}-linux-toolchain.cmake
-DMAA_VERSION='${{ needs.meta.outputs.tag }}'
cmake --build build --parallel $(nproc --all)
- name: Build
run: |
cmake --build build --config Release --parallel $(nproc)
env:
CLICOLOR_FORCE: 1
- name: Install
run: |
mkdir -p install
cmake --install build --prefix install --config Release
cmake --install build --prefix install
env:
CC: ${{ matrix.arch == 'x86_64' && 'ccache gcc-12' || 'ccache aarch64-linux-gnu-gcc-12' }}
CXX: ${{ matrix.arch == 'x86_64' && 'ccache g++-12' || 'ccache aarch64-linux-gnu-g++-12' }}
- name: Setup Cross Compile Toolchains for CLI
uses: ./src/maa-cli/.github/actions/setup
@@ -309,11 +268,11 @@ jobs:
ln -sv usr/share/maa/maa Maa.AppDir/AppRun
mkdir -pv Maa.AppDir/usr/share/metainfo/
cp -v tools/AppImage/io.github.maaassistantarknights.maaassistantarknights.metainfo.xml Maa.AppDir/usr/share/metainfo/
wget "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
wget "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage"
# appimagetool with embedded runtime does not support cross build, till AppImage/appimagetool 7a10b8
wget "https://github.com/AppImage/type2-runtime/releases/download/old/runtime-fuse3-${{ matrix.arch }}"
wget "https://github.com/AppImage/type2-runtime/releases/download/continuous/runtime-${{ matrix.arch }}"
chmod a+x appimagetool-x86_64.AppImage
ARCH=${{ matrix.arch }} ./appimagetool-x86_64.AppImage --runtime-file runtime-fuse3-${{ matrix.arch }} Maa.AppDir
ARCH=${{ matrix.arch }} ./appimagetool-x86_64.AppImage --runtime-file runtime-${{ matrix.arch }} Maa.AppDir
chmod a+x MaaAssistantArknights-${{ matrix.arch }}.AppImage
mv -v MaaAssistantArknights-${{ matrix.arch }}.AppImage $GITHUB_WORKSPACE/release/MAA-${{ needs.meta.outputs.tag }}-linux-${{ matrix.arch }}.AppImage
@@ -332,56 +291,36 @@ jobs:
release/*.tar.gz
macOS-Core:
# Prevent duplicate runs on organization branches with PRs
if: github.event_name != 'pull_request' ||
github.event.pull_request.head.repo.full_name !=
github.event.pull_request.base.repo.full_name
needs: meta
runs-on: macos-latest
runs-on: macos-14
strategy:
matrix:
arch: [arm64, x86_64]
fail-fast: false
steps:
- name: Checkout code
uses: actions/checkout@v5
uses: actions/checkout@v4
with:
show-progress: false
# ninja 1.13.1 is already installed and up-to-date.
# - name: Install Dependencies
# run: |
# brew install ninja
- name: Cache MaaDeps
id: cache-maadeps
uses: actions/cache@v4
with:
path: ./MaaDeps
key: ${{ runner.os }}-${{ matrix.arch == 'x86_64' && 'x64' || 'arm64' }}-maadeps-${{ hashFiles('tools/maadeps-download.py') }}
- name: Install Dependencies
run: |
brew install ninja
- name: Bootstrap MaaDeps
run: |
[[ ${{ matrix.arch }} = "arm64" ]] && triplet="arm64-osx" || triplet="x64-osx"
python3 tools/maadeps-download.py ${triplet}
python3 maadeps-download.py ${triplet}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Config cmake
- name: Configure MaaCore
run: |
cmake -B build -GNinja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_OSX_ARCHITECTURES='${{ matrix.arch }}' \
-DMAA_HASH_VERSION='${{ needs.meta.outputs.tag }}'
cmake -B build -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES='${{ matrix.arch }}' -DMAA_VERSION='${{ needs.meta.outputs.tag }}'
- name: Build
- name: Build MaaCore
run: |
cmake --build build --config Release --parallel $(sysctl -n hw.logicalcpu)
- name: Install
run: |
cmake --install build --prefix install --config Release
cmake --build build
cmake --install build --prefix install
- name: Upload MAA to Github
uses: actions/upload-artifact@v4
@@ -390,62 +329,34 @@ jobs:
path: "install/*.dylib"
macOS-GUI:
# Prevent duplicate runs on organization branches with PRs
if: github.event_name != 'pull_request' ||
github.event.pull_request.head.repo.full_name !=
github.event.pull_request.base.repo.full_name
needs: [meta, macOS-Core]
runs-on: macos-latest
runs-on: macos-14
steps:
- name: Checkout code
uses: actions/checkout@v5
uses: actions/checkout@v4
with:
show-progress: false
- name: Install Dependencies
if: startsWith(github.ref, 'refs/tags/v')
run: |
brew install graphicsmagick imagemagick
npm install -g create-dmg
- name: Fetch submodules
run: |
git submodule update --init --depth 1 src/MaaMacGui
submodules: recursive
- name: Download Arm64 MAA from Github
uses: actions/download-artifact@v5
uses: actions/download-artifact@v4
with:
name: MAACore-macos-arm64
path: install-arm64
- name: Download x64 MAA from Github
uses: actions/download-artifact@v5
uses: actions/download-artifact@v4
with:
name: MAACore-macos-x86_64
path: install-x86_64
- name: Install Developer ID Certificate
if: startsWith(github.ref, 'refs/tags/v')
uses: apple-actions/import-codesign-certs@v5
uses: ssrobins/import-codesign-certs@v2
with:
p12-file-base64: ${{ secrets.HGUANDL_SIGN_CERT_P12 }}
p12-password: ${{ secrets.HGUANDL_SIGN_CERT_PASSWD }}
- name: Download Provisioning Profiles
if: startsWith(github.ref, 'refs/tags/v')
uses: apple-actions/download-provisioning-profiles@v4
with:
bundle-id: "com.hguandl.MeoAsstMac"
issuer-id: ${{ secrets.HGUANDL_APPSTORE_ISSUER }}
api-key-id: ${{ secrets.HGUANDL_APPSTORE_KEYID }}
api-private-key: ${{ secrets.HGUANDL_APPSTORE_KEY }}
- name: Setup Xcode Toolchain
if: true
run: |
sudo xcode-select -s /Applications/Xcode_16.1.app/Contents/Developer
- name: Build Universal Binaries
run: |
mkdir build
@@ -453,24 +364,6 @@ jobs:
lipo -create install-arm64/$LIB_NAME install-x86_64/$LIB_NAME -output build/$LIB_NAME
done
- name: Archive Runtime Files
run: |
mkdir runtime && cd runtime
name='MAA-${{ needs.meta.outputs.tag }}-macos-runtime-universal'
mkdir "$name" && cd "$name"
cp -v ../../build/*.dylib .
ln -vs libonnxruntime*.dylib libonnxruntime.dylib
ln -vs libopencv_world4*.dylib libopencv_world4.dylib
cp -vr ../../resource .
cd .. || exit 1
zip -yrX9 "$name.zip" "$name"
- name: Upload MAA runtime to Github
uses: actions/upload-artifact@v4
with:
name: MAA-macos-runtime-universal
path: runtime/MAA-${{ needs.meta.outputs.tag }}-macos-runtime-universal.zip
- name: Build XCFramework
run: |
xcodebuild -create-xcframework -library libMaaCore.dylib -headers ../include -output MaaCore.xcframework
@@ -488,9 +381,9 @@ jobs:
- name: Build MAA
run: |
if ${{ startsWith(github.ref, 'refs/tags/v') }}; then
xcodebuild -scheme MAA archive -archivePath MAA.xcarchive
xcodebuild -project MeoAsstMac.xcodeproj -scheme MAA archive -archivePath MAA.xcarchive -configuration Release
else
xcodebuild CODE_SIGNING_ALLOWED=NO -scheme MAA archive -archivePath MAA.xcarchive
xcodebuild CODE_SIGN_IDENTITY="-" DEVELOPMENT_TEAM="-" ONLY_ACTIVE_ARCH=NO -project MeoAsstMac.xcodeproj -scheme MAA archive -archivePath MAA.xcarchive -configuration Debug
fi
working-directory: src/MaaMacGui
@@ -503,8 +396,10 @@ jobs:
- name: Create Disk Image
if: startsWith(github.ref, 'refs/tags/v')
run: |
create-dmg Export/MAA.app
mv MAA*.dmg MAA.dmg
mkdir Image
mv Export/MAA.app Image/
ln -s /Applications Image/
hdiutil create -volname MAA -srcfolder Image -ov -fs APFS -format ULMO MAA.dmg
working-directory: src/MaaMacGui
- name: Archive Debug Symbols
@@ -524,26 +419,17 @@ jobs:
mv src/MaaMacGui/MAA.xcarchive/dSYMs/MAA.app.dSYM.zip release/${APP_SYM}
- name: Notarize Image
if: startsWith(github.ref, 'refs/tags/v')
uses: nick-fields/retry@v3
with:
max_attempts: 3
timeout_minutes: 15
command: |
cd release
echo "$APPSTORE_KEY" > "AuthKey_${APPSTORE_KEYID}.p8"
dmg="MAA-${{ needs.meta.outputs.tag }}-macos-universal.dmg"
xcrun notarytool submit -k "AuthKey_${APPSTORE_KEYID}.p8" -d "$APPSTORE_KEYID" -i "$ISSUER_ID" --wait ${dmg}
env:
APPSTORE_KEYID: ${{ secrets.HGUANDL_APPSTORE_KEYID }}
APPSTORE_KEY: ${{ secrets.HGUANDL_APPSTORE_KEY }}
ISSUER_ID: ${{ secrets.HGUANDL_APPSTORE_ISSUER }}
- name: Attach Notarization Tickets
if: startsWith(github.ref, 'refs/tags/v')
run: |
dmg="MAA-${{ needs.meta.outputs.tag }}-macos-universal.dmg"
xcrun stapler staple ${dmg}
find . -name "*.dmg" | while read dmg; do
codesign -s "$NOTARY_TEAM" --timestamp ${dmg}
xcrun notarytool submit --apple-id "$NOTARY_USER" --password "$NOTARY_PASSWD" --team-id "$NOTARY_TEAM" --wait ${dmg}
xcrun stapler staple ${dmg}
done
env:
NOTARY_USER: ${{ secrets.HGUANDL_NOTARY_AAPL_ID }}
NOTARY_PASSWD: ${{ secrets.HGUANDL_NOTARY_PASSWD }}
NOTARY_TEAM: ${{ secrets.HGUANDL_SIGN_IDENTITY }}
working-directory: release
- name: Upload MAA to Github
@@ -553,16 +439,12 @@ jobs:
path: ${{ startsWith(github.ref, 'refs/tags/v') && 'release/MAA*' || 'src/MaaMacGui/MAA.xcarchive/**' }}
release:
# Prevent duplicate runs on organization branches with PRs
if: (github.event_name != 'pull_request' ||
github.event.pull_request.head.repo.full_name !=
github.event.pull_request.base.repo.full_name) && startsWith(github.ref, 'refs/tags/v')
needs: [meta, windows, ubuntu, macOS-Core, macOS-GUI]
if: startsWith(github.ref, 'refs/tags/v')
needs: [meta, windows, ubuntu, macOS-GUI]
runs-on: ubuntu-latest
steps:
- name: Download MAA from Github
uses: actions/download-artifact@v5
uses: actions/download-artifact@v4
with:
path: assets
@@ -575,31 +457,15 @@ jobs:
find . -type f | while read f; do mv -fvt . $f; done
- name: Release to Github
uses: softprops/action-gh-release@v2.3.3
uses: softprops/action-gh-release@v1
with:
body_path: CHANGELOG.md
files: |
assets/*
prerelease: ${{ needs.meta.outputs.prerelease != 'false' }}
- name: Trigger MirrorChyan
run: |
gh workflow run --repo $GITHUB_REPOSITORY mirrorchyan
gh workflow run --repo $GITHUB_REPOSITORY mirrorchyan_release_note
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Trigger secondary workflows # ref: https://docs.github.com/en/actions/using-workflows/triggering-a-workflow#triggering-a-workflow-from-a-workflow
run: |
gh workflow run --repo $GITHUB_REPOSITORY release-ota
env:
GH_TOKEN: ${{ secrets.MISTEOWORKFLOW }}
- name: Create issue if failed
if: failure()
uses: actions-cool/issues-helper@v3
with:
actions: "create-issue"
title: "Failed Release"
body: |
${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}

View File

@@ -1,57 +0,0 @@
name: "CodeQL MaaCore and MaaWpfGui Analysis"
on:
pull_request:
branches: ["dev"]
paths:
- "3rdparty/include/**"
- "include/**"
- "src/**"
- "cmake/**"
- "CMakeLists.txt"
- ".github/workflows/codeql-core.yml"
- "!**/*.md"
- "!**/*.xaml"
schedule:
- cron: "45 11 * * *" # Runs daily at 11:45 UTC
workflow_dispatch:
permissions:
actions: write
contents: read
packages: read
security-events: write
jobs:
analyze-manual:
name: Analyze MaaCore and MaaWpfGui
runs-on: windows-latest
steps:
- name: Checkout repository
uses: actions/checkout@v5
with:
show-progress: false
- name: Setup CodeQL
uses: github/codeql-action/init@v3
with:
languages: c-cpp,csharp
build-mode: manual
- name: Run CodeQL
uses: github/codeql-action/analyze@v3
with:
category: "/language:multi-manual"
- name: Delete old caches
shell: pwsh
run: |
$oldCaches = gh cache list --key codeql --order asc --json key | ConvertFrom-Json | Select-Object -SkipLast 1
foreach ($cache in $oldCaches) {
if ($cache.key) {
Write-Host "Deleting cache: $($cache.key)"
gh cache delete $cache.key
}
}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,36 +0,0 @@
name: "CodeQL Workflows Analysis"
on:
pull_request:
branches: ["dev"]
paths:
- ".github/**/*.yml"
schedule:
- cron: "00 12 * * *" # Runs daily at 12:00 UTC
workflow_dispatch:
permissions:
actions: write
contents: read
security-events: write
jobs:
analyze-workflows:
name: Analyze GitHub Workflows
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v5
with:
show-progress: false
- name: Setup CodeQL for GitHub Actions
uses: github/codeql-action/init@v3
with:
languages: actions
build-mode: none
- name: Run CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:multi-none"

View File

@@ -2,7 +2,7 @@ name: gen-changelog
on:
pull_request:
types:
types:
- opened
- reopened
- ready_for_review
@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v5
uses: actions/checkout@v4
with:
fetch-depth: 0
show-progress: false
@@ -48,7 +48,7 @@ jobs:
echo '======='
echo 'Target PR: ${{ github.event.pull_request.html_url }}' >> $PR_BODY
echo 'Target RP: ${{ github.event.pull_request.html_url }}' >> $PR_BODY
echo '' >> $PR_BODY
echo '<details><summary>Debug info</summary>' >> $PR_BODY
echo '' >> $PR_BODY
@@ -79,9 +79,8 @@ jobs:
git commit -m "$commit_msg"
- name: Create PR
uses: peter-evans/create-pull-request@v7
uses: peter-evans/create-pull-request@v5
with:
sign-commits: true
token: ${{ secrets.GITHUB_TOKEN }}
title: ${{ steps.extract_tag.outputs.pr_title }}
body-path: ${{ format('{0}/{1}', runner.temp, 'output' ) }}
@@ -94,6 +93,6 @@ jobs:
AnnAngela
- name: Add reviewers to release PR
uses: kentaro-m/auto-assign-action@v2.0.0
uses: kentaro-m/auto-assign-action@v1.2.5
with:
configuration-path: ".github/release_reviewers.yaml"

View File

@@ -1,152 +0,0 @@
name: Auto Close not reading issues or Fold checkboxes
on:
issues:
types: [opened]
jobs:
check-then-close-or-fold:
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- name: Check for duplicate issues in last hour
id: duplicate-check
uses: actions/github-script@v8
with:
script: |
const oneHourAgo = new Date(Date.now() - 60 * 60 * 1000);
const currentIssueCreatedAt = new Date(context.payload.issue.created_at);
const issueAuthor = context.payload.issue.user.login;
// 重新获取该用户最近的 issues
const { data: userIssues } = await github.rest.issues.listForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
creator: issueAuthor,
state: 'all',
since: oneHourAgo.toISOString(),
per_page: 30
});
// 过滤出1小时内创建的其他 issues排除当前 issue
const recentIssues = userIssues.filter(issue => {
const issueCreatedAt = new Date(issue.created_at);
return issue.number !== context.issue.number &&
issueCreatedAt >= oneHourAgo &&
issueCreatedAt < currentIssueCreatedAt;
});
if (recentIssues.length > 0) {
// 给当前 issue 添加标签
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
labels: ['rapid-submission']
});
// 给1小时内的其他 issues 也添加标签
for (const issue of recentIssues) {
try {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
labels: ['rapid-submission']
});
console.log(`Added rapid-submission label to issue #${issue.number}`);
} catch (error) {
console.log(`Failed to add label to issue #${issue.number}: ${error.message}`);
}
}
}
- name: Check checkbox status
id: unread-checkbox-check
uses: actions/github-script@v8
with:
script: |
// 找不到###就算了
if (!/###([^#]+)###/.test(context.payload.issue.body)) {
return false;
}
var checkList = /###([^#]+)###/.exec(context.payload.issue.body)[1];
const UnreadRegexCn = /- \[x\]\s*.*?我.*未仔细阅读/i;
const UnreadRegexCn_ = /- \[ \]\s*.*?我.*未仔细阅读/i;
if (/- \[(x| )\]\s*.*?[\u4e00-\u9fa5]+/i.test(checkList)) { // 中英区分
if (UnreadRegexCn.test(checkList)) {
return true;
}
checkList = checkList.replace(UnreadRegexCn_, "");
return /- \[ \]\s*.*?[\u4e00-\u9fa5]+/i.test(checkList);
}
const texts = [
'I have checked all the options without carefully reading the content and believe this will not affect issue resolution.'];
return texts.some(text => new RegExp(`- \\[x\\]\\s*${text}`).test(context.payload.issue.body));
- name: Close and lock issue
if: steps.unread-checkbox-check.outputs.result == 'true'
uses: actions/github-script@v8
with:
script: |
await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
state: 'closed',
state_reason: 'not_planned'
});
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
labels: ['low-quality-report']
});
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: '因为未阅读模板提示并正确提交,触发了自动关闭规则\n\nBecause the template prompt was not read and submitted correctly, the automatic closing rule was triggered'
});
- name: Fold checkboxes
if: steps.unread-checkbox-check.outputs.result == 'false'
uses: actions/github-script@v8
with:
script: |
const originalBody = context.payload.issue.body;
if (originalBody.includes('<details><summary>Checkboxes</summary>\n\n')) {
return;
}
const checkboxSectionRegex_cn_bug = /([\s\S]*?)(### 问题描述\n\n)/;
const checkboxSectionRegex_cn_feat = /([\s\S]*?)(### 说说你遇到的问题?\n\n)/;
const checkboxSectionRegex_en_bug = /([\s\S]*?)(### Description\n\n)/;
const checkboxSectionRegex_en_feat = /([\s\S]*?)(### The problems you have encountered?\n\n)/;
const foldedBody_cn_bug = originalBody.replace(
checkboxSectionRegex_cn_bug,
`<details><summary>Checkboxes</summary>\n\n$1\n\n</details>\n\n$2`
);
const foldedBody_cn_feat = foldedBody_cn_bug.replace(
checkboxSectionRegex_cn_feat,
`<details><summary>Checkboxes</summary>\n\n$1\n\n</details>\n\n$2`
);
const foldedBody_en_bug = foldedBody_cn_feat.replace(
checkboxSectionRegex_en_bug,
`<details><summary>Checkboxes</summary>\n\n$1\n\n</details>\n\n$2`
);
const foldedBody = foldedBody_en_bug.replace(
checkboxSectionRegex_en_feat,
`<details><summary>Checkboxes</summary>\n\n$1\n\n</details>\n\n$2`
);
await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: foldedBody
});

View File

@@ -1,5 +1,4 @@
name: "Issue Checker"
on:
issues:
types: [opened, edited]
@@ -17,7 +16,7 @@ jobs:
triage:
runs-on: ubuntu-latest
steps:
- uses: MaaAssistantArknights/issue-checker@v1.14
- uses: zzyyyl/issue-checker@v1.8
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
configuration-path: .github/issue-checker.yml

View File

@@ -1,63 +1,49 @@
name: Check Dead Links
name: Lint Markdown files
on:
schedule:
- cron: "0 0 * * 2" # Every Tuesday at 00:00 UTC
push:
branches:
- dev
paths:
- "**/*.md"
- "docs/**"
- ".github/workflows/markdown-checker.yml"
- ".github/workflows/lint-markdown.yml"
pull_request:
branches:
- dev
paths:
- "**/*.md"
- "docs/**"
- ".github/workflows/markdown-checker.yml"
- ".github/workflows/lint-markdown.yml"
schedule:
- cron: "44 7 * * 2"
workflow_dispatch:
jobs:
check-links:
if: github.repository_owner == 'MaaAssistantArknights' && github.event.head_commit.author.email != '41898282+github-actions[bot]@users.noreply.github.com'
name: Check Dead Links
lint:
name: Lint Markdown
runs-on: ubuntu-latest
permissions:
pull-requests: write
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Check out code
uses: actions/checkout@v5
uses: actions/checkout@v4
with:
show-progress: false
- name: Cache Primes
id: cache-primes
uses: actions/cache@v4
- name: Lint Markdown
uses: DavidAnson/markdownlint-cli2-action@v16
with:
path: .lycheecache
key: lychee-cache
config: docs/.markdownlint.yaml
globs: |
README.md
docs/**/*.md
- name: Check dead links
uses: lycheeverse/lychee-action@v2
with:
# 仅检查内部链接,排除所有外部链接
args: >
--verbose --no-progress
--cache --max-cache-age 1d --cache-exclude-status '429, 500..599'
--exclude 'https?://.*'
--exclude-path 'docs/zh-tw/manual/introduction/introduction_old.md'
--exclude-path 'docs/ja-jp/manual/introduction/introduction_old.md'
-- './docs/**/*.md' './README.md'
- name: Comment (only for PR)
if: failure() && github.event_name == 'pull_request'
uses: marocchino/sticky-pull-request-comment@v2
with:
message: |
Dead links found in the documentation. Please fix them.
Details: https://github.com/MaaAssistantArknights/MaaAssistantArknights/actions/runs/${{ github.run_id }}
# check-links:
# name: Check Dead Links
# runs-on: ubuntu-latest
# steps:
# - name: Check out code
# uses: actions/checkout@v4
# with:
# show-progress: false
#
# - name: Check Dead Link
# uses: umbrelladocs/action-linkspector@v1
# with:
# # Use github-pr-review when triggered by a pull request; otherwise, use github-check
# reporter: ${{ github.event_name == 'pull_request' && 'github-pr-review' || 'github-check' }}
# filter_mode: nofilter
# fail_on_error: true

View File

@@ -1,71 +0,0 @@
name: mirrorchyan
on:
workflow_dispatch:
jobs:
mirrorchyan:
runs-on: macos-latest
steps:
- name: Upload MAA win x64
uses: MirrorChyan/uploading-action@v1
if: always()
with:
filetype: latest-release
filename: "*MAA-*-win-x64.zip"
mirrorchyan_rid: MAA
github_token: ${{ secrets.GITHUB_TOKEN }}
owner: ${{ github.repository_owner }}
repo: ${{ github.event.repository.name }}
upload_token: ${{ secrets.MirrorChyanUploadToken }}
os: win
arch: x64
- name: Upload MAA win arm64
uses: MirrorChyan/uploading-action@v1
if: always()
with:
filetype: latest-release
filename: "*MAA-*-win-arm64.zip"
mirrorchyan_rid: MAA
github_token: ${{ secrets.GITHUB_TOKEN }}
owner: ${{ github.repository_owner }}
repo: ${{ github.event.repository.name }}
upload_token: ${{ secrets.MirrorChyanUploadToken }}
os: win
arch: arm64
- name: Upload MAA macos arm64
uses: MirrorChyan/uploading-action@v1
if: always()
with:
filetype: latest-release
filename: "MAA-*-macos-universal.dmg"
extra_zip: true
mirrorchyan_rid: MAA
github_token: ${{ secrets.GITHUB_TOKEN }}
owner: ${{ github.repository_owner }}
repo: ${{ github.event.repository.name }}
upload_token: ${{ secrets.MirrorChyanUploadToken }}
os: macos
arch: arm64
- name: Upload MAA macos x64
uses: MirrorChyan/uploading-action@v1
if: always()
with:
filetype: latest-release
filename: "MAA-*-macos-universal.dmg"
extra_zip: true
mirrorchyan_rid: MAA
github_token: ${{ secrets.GITHUB_TOKEN }}
owner: ${{ github.repository_owner }}
repo: ${{ github.event.repository.name }}
upload_token: ${{ secrets.MirrorChyanUploadToken }}
os: macos
arch: x64

View File

@@ -1,19 +0,0 @@
name: mirrorchyan_release_note
on:
workflow_dispatch:
release:
types: [edited]
jobs:
mirrorchyan:
runs-on: macos-latest
steps:
- name: Release Note for MAA
uses: MirrorChyan/release-note-action@v1
with:
mirrorchyan_rid: MAA
upload_token: ${{ secrets.MirrorChyanUploadToken }}
github_token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,109 +0,0 @@
name: Optimize PNG Templates
on:
push:
branches:
- "dev"
paths:
- "resource/**/*.png"
- "docs/.vuepress/public/images/**"
- "website/apps/web/public/**"
- "website/apps/web/src/assets/links/**"
workflow_dispatch:
inputs:
commit_message:
description: "Commit Message"
type: string
required: false
jobs:
optimize-png:
# Skip workflow to prevent double consecutive runs
# Skip workflow on PR merges
if: github.repository_owner == 'MaaAssistantArknights' && ${{ github.event.head_commit.author.email != '41898282+github-actions[bot]@users.noreply.github.com' }}
runs-on: ubuntu-latest
steps:
- name: Check for direct push
id: check_push
run: |
if [[ "${{ github.event_name }}" != "workflow_dispatch" ]]; then
pr_merge_status=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
"https://api.github.com/repos/${{ github.repository }}/commits/${{ github.event.after }}/pulls" | xargs)
if [[ "$pr_merge_status" == "[ ]" ]]; then
echo "Direct push detected. Proceeding..."
echo "is_pr=False" >> $GITHUB_OUTPUT
else
echo "PR merge detected. Exiting."
echo "is_pr=True" >> $GITHUB_OUTPUT
fi
else
echo "Manual trigger detected. Proceeding..."
echo "is_pr=False" >> $GITHUB_OUTPUT
fi
- name: Checkout repository
if: steps.check_push.outputs.is_pr != 'True'
uses: actions/checkout@v5
with:
show-progress: false
persist-credentials: false
- name: Setup python
if: steps.check_push.outputs.is_pr != 'True'
uses: actions/setup-python@v6
with:
python-version: "3.11"
# - name: Cache Python packages
# id: cache_python
# if: steps.check_push.outputs.is_pr != 'True' && always()
# uses: actions/cache@v4
# with:
# path: ${{ env.pythonLocation }}/lib/python3.11/site-packages
# key: ${{ runner.os }}-pip-optimize-templates-${{ hashFiles('./tools/OptimizeTemplates/requirements.txt') }}
- name: Install dependencies
# if: steps.check_push.outputs.is_pr != 'True' && steps.cache_python.outputs.cache-hit != 'true'
if: steps.check_push.outputs.is_pr != 'True'
run: |
pip install -r tools/OptimizeTemplates/requirements.txt
- name: Setup oxipng
if: steps.check_push.outputs.is_pr != 'True'
uses: baptiste0928/cargo-install@v3
with:
crate: oxipng
- name: Run optimize_templates
if: steps.check_push.outputs.is_pr != 'True'
run: |
python3 tools/OptimizeTemplates/optimize_templates.py
- name: Commit changes
id: commit_changes
if: steps.check_push.outputs.is_pr != 'True'
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add .
if git diff-index --quiet HEAD --; then
echo "No changes to commit"
else
commit_msg="${{ github.event.inputs.commit_message }}"
if [ -z "$commit_msg" ]; then
commit_msg="chore: Auto Templates Optimization"
fi
git commit -m "$commit_msg" -m "Triggered by ${{github.sha}}" -m "[skip changelog]"
git pull origin $(git rev-parse --abbrev-ref HEAD) --unshallow --rebase
echo "have_commits=True" >> $GITHUB_OUTPUT
fi
- name: Push changes
if: steps.check_push.outputs.is_pr != 'True' && steps.commit_changes.outputs.have_commits == 'True' && github.repository_owner == 'MaaAssistantArknights'
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.MAA_RESOURCE_SYNC }}
branch: ${{ github.ref }}

View File

@@ -9,7 +9,6 @@ on:
workflow_dispatch:
inputs:
tag:
description: "Name of the tag to create for the release"
type: string
required: true
@@ -20,7 +19,7 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v5
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.MAARELEASE_RELEASE }}

View File

@@ -4,13 +4,14 @@ on:
pull_request_target:
types: [opened, edited, ready_for_review, reopened, synchronize]
jobs:
check_commit_name_in_pr:
if: ${{ !github.event.pull_request.merged && github.base_ref != 'master' }}
runs-on: ubuntu-latest
steps:
- name: Cleanup Previous Comment
uses: actions/github-script@v8
uses: actions/github-script@v7
with:
script: |
const { data: comments } = await github.rest.issues.listComments({
@@ -28,7 +29,7 @@ jobs:
});
}
- name: Check Commits
uses: actions/github-script@v8
uses: actions/github-script@v7
with:
script: |
const { data: commits } = await github.rest.pulls.listCommits({
@@ -38,7 +39,7 @@ jobs:
per_page: 100
});
const regex = /^((build|chore|ci|docs?|feat!?|fix|perf|refactor|rft|style|test|i18n|typo|debug)[\:\.\(\,]|[Rr]evert|[Rr]elease|[Rr]eapply)/;
const regex = /^((build|chore|ci|docs?|feat!?|fix|perf|refactor|rft|style|test|i18n|typo)[\:\.\(\,]|[Rr]evert|[Rr]elease)/;
const invalidCommits = commits.filter(commit => !regex.test(commit.commit.message) || commit.parents.length > 1);
console.log(`Checked ${commits.length} commit(s)`);
@@ -51,8 +52,8 @@ jobs:
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
body: `## ⚠️ Found ${invalidCommits.length} invalid commit(s):\n\n${invalidCommitInfoList}\n\n---\nPlease follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) format, and **DO NOT** use merge commits.\n请遵循 [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) 格式,以及**不要**使用Merge Commit修改 Commit Message 无法绕过检测)。`
body: `## ⚠️ Found ${invalidCommits.length} invalid commit(s):\n\n${invalidCommitInfoList}\n\n---\nPlease follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) format.`
});
core.setFailed(`Found ${invalidCommits.length} invalid commit(s):\n${invalidCommitNames.join("\n-------------------\n")}`);
}
}

View File

@@ -1,8 +1,6 @@
name: release-nightly-ota
on:
schedule:
- cron: "0 22 * * *" # Runs daily at 22:00 UTC
workflow_dispatch:
inputs:
release_body:
@@ -13,238 +11,77 @@ on:
description: "Commit to build (git checkout)"
type: string
required: false
limit_maa:
limit:
description: "Number of releases to fetch from MaaAssistantArknights"
required: true
default: 10
default: 30
type: number
limit_maarelease:
limit_2:
description: "Number of releases to fetch from MaaRelease"
required: true
default: 10
default: 30
type: number
jobs:
build-win-nightly:
if: github.repository_owner == 'MaaAssistantArknights'
runs-on: windows-latest
strategy:
matrix:
arch: [x64]
include:
- msbuild_target: x64
lowercase_target: x64
fail-fast: false
env:
MAABUILDER_TARGET_PLATFORM: ${{ matrix.msbuild_target }}
outputs:
tag: ${{ steps.set_tag.outputs.tag }}
pre_version: ${{ steps.set_tag.outputs.pre_version }}
main_tag_name: ${{ steps.push_main_tag.outputs.main_tag_name }}
changelog: ${{ steps.read_changelog.outputs.content }}
changelog: ${{ steps.generate_changelog.outputs.changelog }}
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
with:
# repository: 'MaaAssistantArknights/MaaAssistantArknights'
submodules: recursive
#ref: ${{ inputs.ref }}
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 250
- name: Fetch tags
- name: Checkout ref
run: |
git fetch --depth=250 --tags
if ("${{ inputs.ref }}" -ne "") {
git checkout --progress --recurse-submodules ${{ inputs.ref || 'dev' }}
}
- name: Fetch submodules
- name: Install semver
run: |
git submodule update --init --depth 1 3rdparty/EmulatorExtras
npm install --global --progress semver
- name: Checkout ref (if provided)
if: inputs.ref != ''
run: |
git checkout --progress --recurse-submodules ${{ inputs.ref }}
- name: Check for Changes and Set tag
- name: Set tag
id: set_tag
run: |
# Fetch the latest tag from the repository
$latest_tag = git describe --tags --abbrev=0
Write-Output "Previous Tag: $latest_tag"
Write-Output "latest_tag=$latest_tag" >> $env:GITHUB_OUTPUT
# Check for changes between the latest tag and HEAD
$recent_changes = git log "$latest_tag..HEAD" --oneline
if (-not $recent_changes) {
Write-Output "No commits. Cancelling workflow..."
Write-Output "cancel_run=true" >> $env:GITHUB_ENV
exit 0
} else {
Write-Output "Recent commits: $recent_changes"
Write-Output "Commits found. Continuing build..."
Write-Output "cancel_run=false" >> $env:GITHUB_ENV
}
# Get the full description of the current commit
$described = git describe --tags --long --match 'v*'
Write-Output "New Described: $described"
$ids = $described -split "-"
if ($ids.Length -eq 3) {
# Extract and parse the current version
$current_version = $ids[0].Substring(1)
$parts = $current_version -split '\.'
if ($parts.Length -ne 3) {
Write-Error "Invalid version format: $current_version. Expected 'major.minor.patch'."
exit 1
}
# Increment the patch version
$parts[2] = [int]$parts[2] + 1
$new_version = "$($parts[0]).$($parts[1]).$($parts[2])"
# Construct the new tag and pre_version
$ver = "v$new_version"
$pre_version = $ids[0]
$dist = "{0:D3}" -f [int]$ids[1]
Write-Output "pre_version=$pre_version" >> $env:GITHUB_OUTPUT
Write-Output "New Tag: $ver-alpha.1.d$dist.$($ids[2])"
Write-Output "tag=$ver-alpha.1.d$dist.$($ids[2])" >> $env:GITHUB_OUTPUT
# pre_version是上一个公版这里需要拉上一个tag避免堆积过多commit
$latest_tag=$(git describe --tags --abbrev=0)
echo "latest_tag=$latest_tag" >> $env:GITHUB_OUTPUT
$described = $(git describe --tags --long --match 'v*')
$ids = $($described -split "-")
if ($ids.length -eq 3) {
$ver = "v$(semver --increment $ids[0].Substring(1))"
$pre_version = "$($ids[0])"
$dist = `printf "%03d"` $ids[1]
echo "tag=$ver-alpha.1.d$($dist).$($ids[2])" >> $env:GITHUB_OUTPUT
echo "pre_version=$pre_version" >> $env:GITHUB_OUTPUT
exit 0
}
if ($ids.Length -eq 4) {
$dist = "{0:D3}" -f [int]$ids[2]
$pre_version = "$($ids[0])-$($ids[1])"
Write-Output "Pre Version: $pre_version"
Write-Output "pre_version=$pre_version" >> $env:GITHUB_OUTPUT
Write-Output "tag: $pre_version.d$dist.$($ids[3])"
Write-Output "tag=$pre_version.d$dist.$($ids[3])" >> $env:GITHUB_OUTPUT
if ($ids.length -eq 4) {
$dist = `printf "%03d"` $ids[2]
$pre_version = "$($ids[0])""-""$($ids[1])"
echo "tag=$($ids[0])-$($ids[1]).d$($dist).$($ids[3])" >> $env:GITHUB_OUTPUT
echo "pre_version=$pre_version" >> $env:GITHUB_OUTPUT
exit 0
}
exit 1
- name: Stop if no changes
if: env.cancel_run == 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
curl -s -L -X POST `
-H "Accept: application/vnd.github+json" `
-H "Authorization: Bearer ${{ secrets.MAA_ACTION_READ_WRITE }}" `
-H "X-GitHub-Api-Version: 2022-11-28" `
"https://api.github.com/repos/MaaAssistantArknights/MaaAssistantArknights/actions/runs/${{ github.run_id }}/cancel" > $null
gh run watch ${{ github.run_id }}
- name: Generate Changelog
id: generate_changelog
run: |
python3 tools/ChangelogGenerator/changelog_generator.py --latest "${{ steps.set_tag.outputs.latest_tag }}" --tag "${{ steps.set_tag.outputs.tag }}"
Get-Content .\changelog.md | Select-Object -Skip 2 | Out-File -FilePath changelog_notag.md -Encoding utf8
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PYTHONIOENCODING: "utf-8"
- name: Stop if no changes
if: steps.generate_changelog.outputs.cancel_run == 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
curl -s -L -X POST `
-H "Accept: application/vnd.github+json" `
-H "Authorization: Bearer ${{ secrets.MAA_ACTION_READ_WRITE }}" `
-H "X-GitHub-Api-Version: 2022-11-28" `
"https://api.github.com/repos/MaaAssistantArknights/MaaAssistantArknights/actions/runs/${{ github.run_id }}/cancel" > $null
gh run watch ${{ github.run_id }}
- name: Read Changelog to variable
id: read_changelog
uses: juliangruber/read-file-action@v1
with:
path: ./changelog_notag.md
- name: Cache MaaDeps
id: cache-maadeps
uses: actions/cache@v4
with:
path: |
./MaaDeps
key: ${{ runner.os }}-${{ matrix.arch }}-maadeps-${{ hashFiles('tools/maadeps-download.py') }}
- name: Bootstrap MaaDeps
if: steps.cache-maadeps.outputs.cache-hit != 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
python3 tools/maadeps-download.py ${{ matrix.arch }}-windows
- name: Config cmake
run: |
mkdir -p build
cmake -B build ${{ matrix.arch == 'arm64' && '-A ARM64' }} -DCMAKE_BUILD_TYPE=Release -DMAADEPS_TRIPLET='maa-${{ matrix.arch }}-windows' -DINSTALL_RESOURCE=ON -DINSTALL_PYTHON=ON -DMAA_HASH_VERSION='${{ steps.set_tag.outputs.tag }}' -DBUILD_WPF_GUI=OFF
- name: Build
run: |
cmake --build build --config Release --parallel $env:NUMBER_OF_PROCESSORS
- name: Install
run: |
mkdir -p install
cmake --install build --prefix install --config Release
- name: Cache .nuke/temp, ~/.nuget/packages
id: cache-nuget
uses: actions/cache@v4
with:
path: |
.nuke/temp
~/.nuget/packages
key: ${{ runner.os }}-${{ matrix.arch }}-nuget-${{ hashFiles('**/*.csproj') }}
- name: Restore dependencies
if: steps.cache-nuget.outputs.cache-hit != 'true'
run: dotnet restore src/MaaWpfGui/MaaWpfGui.csproj
- name: Taggify Version for csproj
run: |
$csprojPath = "src/MaaWpfGui/MaaWpfGui.csproj"
$csprojPath = Resolve-Path -Path $csprojPath
$tag = '${{ steps.set_tag.outputs.tag }}' -replace '.*?/', ''
if ($tag -match '\d+(\.\d+){1,3}') {
$match = $Matches[0]
} else {
$match = "0.0.1"
}
[xml]$csproj = Get-Content -Path $csprojPath
$node = $csproj.Project.PropertyGroup | where {$_.ApplicationVersion -ne $null}
$node.InformationalVersion = $tag
$node.Version = $match
$node.FileVersion = $match
$node.AssemblyVersion = $match
$csproj.Save($csprojPath)
- name: Publish WPF GUI
run: |
dotnet publish src/MaaWpfGui/MaaWpfGui.csproj -c Release -o install
- name: Organize Install Files
shell: bash
run: |
rm -rf install/*.pdb
rm -rf install/msvc-debug
rm -rf install/*.h
cp tools/DependencySetup_依赖库安装.bat install
- name: Upload MAA to Github
uses: actions/upload-artifact@v4
with:
name: MAA-win-${{ matrix.arch }}
path: install
- name: Push tag to main repo
id: push_main_tag
run: |
@@ -256,13 +93,81 @@ jobs:
git push --tags origin HEAD:refs/tags/$main_tag_name -f
echo "main_tag_name=$main_tag_name" >> $env:GITHUB_OUTPUT
- name: Generate Changelog
id: generate_changelog
run: |
python3 tools/ChangelogGenerator/changelog_generator.py --latest "${{ steps.set_tag.outputs.latest_tag }}" --tag "${{ steps.set_tag.outputs.tag }}"
$content=$(((Get-Content .\changelog.md) | Select-Object -Skip 2) -join "\n\n")
echo "changelog=$content" >> $env:GITHUB_OUTPUT
echo $content
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PYTHONIOENCODING: "utf-8"
- name: Cache .nuke/temp, ~/.nuget/packages
id: cache-nuget
uses: actions/cache@v4
with:
path: |
.nuke/temp
~/.nuget/packages
key: ${{ runner.os }}-${{ hashFiles('**/global.json', '**/*.csproj') }}
- name: Restore dependencies
if: steps.cache-nuget.outputs.cache-hit != 'true'
run: dotnet restore
- name: Bootstrap MaaDeps
run: |
python3 maadeps-download.py ${{ matrix.lowercase_target }}-windows
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Taggify Version
run: |
$csprojPath = "src/MaaWpfGui/MaaWpfGui.csproj"
$csprojPath = Resolve-Path -Path $csprojPath
$tag = '${{ steps.set_tag.outputs.tag }}' -replace '.*?/', ''
if ($tag -match '\d+(\.\d+){1,3}') {
$match = $Matches[0]
} else {
$match = "0.0.1"
}
echo "Tag value: $tag"
echo "Version value: $match"
[xml]$csproj = Get-Content -Path $csprojPath
$node = $csproj.Project.PropertyGroup | where {$_.ApplicationVersion -ne $null}
$node.InformationalVersion = $tag
$node.Version = $match
$node.FileVersion = $match
$node.AssemblyVersion = $match
$csproj.Save($csprojPath)
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Run './build.cmd DevBuild'
run: |
$env:GITHUB_WORKFLOW = 'dev-build-win' # pretend this is a dev-build-win workflow
$env:MAA_BUILDER_MAA_VERSION = "${{ steps.set_tag.outputs.tag }}"
echo "tag: " $env:MAA_BUILDER_MAA_VERSION
./build.cmd DevBuild
env:
Reason: "Build nightly version"
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload MAA to Github
uses: actions/upload-artifact@v4
with:
name: MAA-win-${{ matrix.lowercase_target }}
path: artifacts
push-tag:
if: github.repository_owner == 'MaaAssistantArknights'
needs: build-win-nightly
runs-on: ubuntu-latest
steps:
- name: Fetch MaaRelease
uses: actions/checkout@v5
uses: actions/checkout@v4
with:
repository: ${{ format('{0}/{1}', github.repository_owner, 'MaaRelease') }}
fetch-depth: 0
@@ -280,7 +185,6 @@ jobs:
git push --tags origin HEAD:refs/tags/${{ needs.build-win-nightly.outputs.tag }}
make-ota:
if: github.repository_owner == 'MaaAssistantArknights'
needs: [build-win-nightly, push-tag]
strategy:
matrix:
@@ -292,14 +196,14 @@ jobs:
echo ${{ needs.build-win-nightly.outputs.tag }}
- name: Checkout code
uses: actions/checkout@v5
uses: actions/checkout@v4
with:
path: MaaAssistantArknights
token: ${{ secrets.MAARELEASE_RELEASE }}
show-progress: false
- name: Download MAA from Github
uses: actions/download-artifact@v5
uses: actions/download-artifact@v4
with:
name: MAA-win-${{ matrix.target }}
path: ${{ format('{0}/{1}', 'build-ota', needs.build-win-nightly.outputs.tag) }}
@@ -308,17 +212,8 @@ jobs:
run: |
mkdir -pv build-ota && cd build-ota
# Convert inputs to integers
limit_maa=${{ inputs.limit_maa || 10 }}
limit_maa=${limit_maa%.*}
echo "Parsed limit_maa: $limit_maa"
limit_maarelease=${{ inputs.limit_maarelease || 10 }}
limit_maarelease=${limit_maarelease%.*}
echo "Parsed limit_maarelease: $limit_maarelease"
gh release list --repo 'MaaAssistantArknights/MaaAssistantArknights' --limit $limit_maa | tee ./release_maa.txt
gh release list --repo "${{ github.repository_owner }}/MaaRelease" --limit $limit_maarelease | tee ./release_mr.txt
gh release list --repo 'MaaAssistantArknights/MaaAssistantArknights' --limit ${{ inputs.limit || 30 }} | tee ./release_maa.txt
gh release list --repo "${{ github.repository_owner }}/MaaRelease" --limit ${{ inputs.limit_2 || 30 }} | tee ./release_mr.txt
echo ${{ needs.build-win-nightly.outputs.tag }} > ./config
cat ./release_maa.txt | awk '{ print $1 }' > ./tags_maa.txt
@@ -338,7 +233,8 @@ jobs:
cd build-ota
pushd ${{ needs.build-win-nightly.outputs.tag }}
zip -r MAA-${{ env.release_tag }}-win-${{ matrix.target }}.zip ./*
zip -d *.zip '*.lib' '*.pdb' '*.exp' '*.config' '*.xml'
mv *.zip MAA-${{ env.release_tag }}-win-${{ matrix.target }}.zip
popd
$GITHUB_WORKSPACE/MaaAssistantArknights/tools/OTAPacker/build.sh 'MaaAssistantArknights/MaaAssistantArknights' ./config ${{ matrix.target }} "${{ github.repository_owner }}/MaaRelease"
@@ -346,6 +242,22 @@ jobs:
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Make release body
id: make_release_body
shell: bash
run: |
pre_version=${{ needs.build-win-nightly.outputs.pre_version }}
cur_version=${{ needs.build-win-nightly.outputs.main_tag_name }}
echo -e "${{ inputs.release_body || '' }}\n\n${{ needs.build-win-nightly.outputs.changelog }}\n\n**Full Changelog**: [$pre_version -> $cur_version](https://github.com/$GITHUB_REPOSITORY/compare/$pre_version...$cur_version)" > alpha_changelog.md
export r=$(cat alpha_changelog.md)
# https://github.com/svenstaro/upload-release-action
r="${r//'%'/'%25'}" # Multiline escape sequences for %
r="${r//$'\n'/'%0A'}" # Multiline escape sequences for '\n'
r="${r//$'\r'/'%0D'}" # Multiline escape sequences for '\r'
echo $r
echo "full_release_body=$r" >> $GITHUB_OUTPUT
- name: Upload to MaaRelease
uses: svenstaro/upload-release-action@v2
with:
@@ -356,17 +268,10 @@ jobs:
tag: ${{ env.release_tag }}
prerelease: true
overwrite: true
body: |
${{ inputs.release_body || '' }}
${{ needs.build-win-nightly.outputs.changelog }}
**Full Changelog**: [${{ needs.build-win-nightly.outputs.pre_version }} -> ${{ needs.build-win-nightly.outputs.main_tag_name }}](https://github.com/${{ github.repository }}/compare/${{ needs.build-win-nightly.outputs.pre_version }}...${{ needs.build-win-nightly.outputs.main_tag_name }})
body: ${{ steps.make_release_body.outputs.full_release_body }}
- name: Setup release mirror
run: |
gh workflow --repo MaaAssistantArknights/MaaRelease run release-mirrors.yml
gh workflow --repo MaaAssistantArknights/MaaRelease run mirrorchyan_alpha.yml
gh workflow --repo MaaAssistantArknights/MaaRelease run mirrorchyan_alpha_release_note.yml
env:
GH_TOKEN: ${{ secrets.MISTEOWORKFLOW }}

View File

@@ -9,12 +9,12 @@ on:
limit:
description: Number of releases to fetch from MaaAssistantArknights, 2 at least
required: false
default: 31
default: '31'
type: number
limit_2:
description: Number of releases to fetch from MaaRelease
required: false
default: 30
default: '30'
type: number
env:
@@ -25,7 +25,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Fetch MaaRelease
uses: actions/checkout@v5
uses: actions/checkout@v4
with:
show-progress: false
repository: ${{ format('{0}/{1}', github.repository_owner, 'MaaRelease') }}
@@ -37,18 +37,8 @@ jobs:
id: fetchReleaseInfo
run: |
mkdir -pv build-ota && cd build-ota
# Convert inputs to integers
limit=${{ inputs.limit || 31 }}
limit=${limit%.*}
echo "Parsed limit: $limit"
limit_2=${{ inputs.limit_2 || 30 }}
limit_2=${limit_2%.*}
echo "Parsed limit_2: $limit_2"
gh release list --repo 'MaaAssistantArknights/MaaAssistantArknights' --limit $limit | tee ./release_maa.txt
gh release list --repo "MaaAssistantArknights/MaaRelease" --limit $limit_2 | tee ./release_mr.txt
gh release list --repo 'MaaAssistantArknights/MaaAssistantArknights' --limit ${{ inputs.limit || 31 }} | tee ./release_maa.txt
gh release list --repo "MaaAssistantArknights/MaaRelease" --limit ${{ inputs.limit_2 || 30 }} | tee ./release_mr.txt
head -n 1 ./release_maa.txt | awk '{ print $1 }' > ./config
tail -n +1 ./release_maa.txt | awk '{ print $1 }' > ./tags_maa.txt
@@ -94,13 +84,10 @@ jobs:
- x64
steps:
- name: Download release config
uses: actions/download-artifact@v5
with:
name: MaaReleaseConfig
path: ./MaaReleaseConfig
uses: actions/download-artifact@v4
- name: Fetch MaaRelease
uses: actions/checkout@v5
uses: actions/checkout@v4
with:
show-progress: false
repository: ${{ format('{0}/{1}', github.repository_owner, 'MaaRelease') }}
@@ -109,7 +96,7 @@ jobs:
token: ${{ secrets.MAARELEASE_RELEASE }}
- name: Checkout code
uses: actions/checkout@v5
uses: actions/checkout@v4
with:
show-progress: false
path: MaaAssistantArknights
@@ -137,15 +124,6 @@ jobs:
prerelease: ${{ fromJSON(needs.create-tag.outputs.prerelease) }}
overwrite: true
- name: Create issue if failed
if: failure()
uses: actions-cool/issues-helper@v3
with:
actions: "create-issue"
title: "Failed make release OTA for Windows"
body: |
${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
make-ota-mac:
needs: create-tag
runs-on: macos-14
@@ -178,6 +156,31 @@ jobs:
run: |
find ./packages -type f ! \( -name 'MAA-${{ needs.create-tag.outputs.release_tag }}-macos-universal.dmg' -o -name '*.delta' -o -name '*.xml' \) -print -delete
- name: Unpack the .dmg files for .dylib
run: |
cd ${{ runner.temp }}
mkdir -p macos-runtime-temp
echo ::group::Attaching release package...
hdiutil attach ${{ github.workspace }}/packages/MAA-${{ needs.create-tag.outputs.release_tag }}-macos-universal.dmg
echo ::endgroup::
echo ::group::Copying files...
cp -v /Volumes/MAA/MAA.app/Contents/Frameworks/*.dylib macos-runtime-temp/
cp -vr /Volumes/MAA/MAA.app/Contents/Resources/resource macos-runtime-temp/resource
echo ::endgroup::
echo ::group::Linking files...
libonnxruntime_file=$(basename macos-runtime-temp/libonnxruntime*.dylib)
ln -vs $libonnxruntime_file macos-runtime-temp/libonnxruntime.dylib
libopencv_world_file=$(basename macos-runtime-temp/libopencv_world*.dylib)
ln -vs $libopencv_world_file macos-runtime-temp/libopencv_world4.dylib
echo ::endgroup::
cd macos-runtime-temp
echo ::group::Compressing files...
zip -yrX9 ${{ github.workspace }}/packages/MAA-${{ needs.create-tag.outputs.release_tag }}-macos-runtime-universal.zip *
echo ::endgroup::
echo ::group::Detaching release package...
hdiutil detach /Volumes/MAA
echo ::endgroup::
- name: Upload to MaaRelease
uses: svenstaro/upload-release-action@v2
with:
@@ -189,15 +192,6 @@ jobs:
prerelease: ${{ fromJSON(needs.create-tag.outputs.prerelease) }}
overwrite: true
- name: Create issue if failed
if: failure()
uses: actions-cool/issues-helper@v3
with:
actions: "create-issue"
title: "Failed make release OTA for macos"
body: |
${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
release:
needs:
- make-ota

View File

@@ -1,8 +1,8 @@
name: Resource Updater
name: res-update-game
on:
schedule:
- cron: "*/20 * * * *" # Runs every 20 minutes
- cron: "*/20 * * * *"
workflow_dispatch:
inputs:
commit_message:
@@ -11,18 +11,38 @@ on:
required: false
jobs:
clone-resources-official:
update-game-resources:
if: github.repository_owner == 'MaaAssistantArknights'
runs-on: ubuntu-latest
runs-on: windows-latest
env:
GH_TOKEN: ${{ secrets.MISTEOWORKFLOW }}
steps:
- name: Checkout MAA
uses: actions/checkout@v4
with:
show-progress: false
token: ${{ secrets.MISTEOWORKFLOW }}
- name: Bootstrap MaaDeps
run: |
python3 maadeps-download.py x64-windows
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1
- name: Build Resource Updater
run: |
MSBUILD tools/ResourceUpdater/ResourceUpdater.vcxproj /t:rebuild /p:Configuration="Release" /p:Platform="x64" /p:BuildProjectReferences=false /m
- name: Clone ArknightsGameResource for Official
uses: actions/checkout@v5
uses: actions/checkout@v4
with:
show-progress: false
repository: yuanyan3060/ArknightsGameResource
ref: main
path: ./Official
sparse-checkout-cone-mode: false
path: .\tools\ResourceUpdater\x64\Release\Official
sparse-checkout: |
/levels.json
/item
@@ -34,319 +54,136 @@ jobs:
/gamedata/excel/gacha_table.json
/gamedata/excel/roguelike_topic_table.json
/gamedata/excel/activity_table.json
sparse-checkout-cone-mode: false
- name: Upload Official
uses: actions/upload-artifact@v4
with:
name: official
path: ./Official
compression-level: 0
clone-resources-overseas:
if: github.repository_owner == 'MaaAssistantArknights'
runs-on: ubuntu-latest
steps:
- name: Clone ArknightsGameResource_Yostar for Overseas
uses: actions/checkout@v5
uses: actions/checkout@v4
with:
show-progress: false
repository: ArknightsAssets/ArknightsGamedata
ref: master
path: ./Overseas
sparse-checkout-cone-mode: false
repository: Kengxxiao/ArknightsGameData_Yostar
ref: main
path: .\tools\ResourceUpdater\x64\Release\Overseas
sparse-checkout: |
/en/gamedata/excel/item_table.json
/en/gamedata/excel/building_data.json
/en/gamedata/excel/range_table.json
/en/gamedata/excel/character_table.json
/en/gamedata/excel/gacha_table.json
/en/gamedata/excel/roguelike_topic_table.json
/en/gamedata/excel/activity_table.json
/jp/gamedata/excel/item_table.json
/jp/gamedata/excel/building_data.json
/jp/gamedata/excel/range_table.json
/jp/gamedata/excel/character_table.json
/jp/gamedata/excel/gacha_table.json
/jp/gamedata/excel/roguelike_topic_table.json
/jp/gamedata/excel/activity_table.json
/kr/gamedata/excel/item_table.json
/kr/gamedata/excel/building_data.json
/kr/gamedata/excel/range_table.json
/kr/gamedata/excel/character_table.json
/kr/gamedata/excel/gacha_table.json
/kr/gamedata/excel/roguelike_topic_table.json
/kr/gamedata/excel/activity_table.json
/en_US/gamedata/excel/item_table.json
/en_US/gamedata/excel/building_data.json
/en_US/gamedata/excel/range_table.json
/en_US/gamedata/excel/character_table.json
/en_US/gamedata/excel/gacha_table.json
/en_US/gamedata/excel/roguelike_topic_table.json
/en_US/gamedata/excel/activity_table.json
/ja_JP/gamedata/excel/item_table.json
/ja_JP/gamedata/excel/building_data.json
/ja_JP/gamedata/excel/range_table.json
/ja_JP/gamedata/excel/character_table.json
/ja_JP/gamedata/excel/gacha_table.json
/ja_JP/gamedata/excel/roguelike_topic_table.json
/ja_JP/gamedata/excel/activity_table.json
/ko_KR/gamedata/excel/item_table.json
/ko_KR/gamedata/excel/building_data.json
/ko_KR/gamedata/excel/range_table.json
/ko_KR/gamedata/excel/character_table.json
/ko_KR/gamedata/excel/gacha_table.json
/ko_KR/gamedata/excel/roguelike_topic_table.json
/ko_KR/gamedata/excel/activity_table.json
sparse-checkout-cone-mode: false
- name: Upload Official
uses: actions/upload-artifact@v4
with:
name: overseas
path: ./Overseas
compression-level: 0
clone-resources-txwy:
if: github.repository_owner == 'MaaAssistantArknights'
runs-on: ubuntu-latest
steps:
- name: Clone arknights-toolbox-update for Taiwan
uses: actions/checkout@v5
uses: actions/checkout@v4
with:
show-progress: false
repository: arkntools/arknights-toolbox-update
ref: data-tw
path: ./excel
path: .\tools\ResourceUpdater\x64\Release\Overseas\zh_TW\gamedata\excel
token: ${{ secrets.ARKNTOOLS_MAA_RESOURCE_UPDATER}}
- name: Download stages.json from Penguin Stats
run: |
cd "./excel"
baseUrl="https://penguin-stats.io/PenguinStats/api/v2/stages?server="
parameters=("CN" "US" "JP" "KR")
for param in "${parameters[@]}"; do
{
if curl -s -o "stages_${param}.json" "${baseUrl}${param}"; then
echo "Successfully fetched data for ${param}"
else
echo "Failed to fetch data for ${param}" >&2
exit 1
fi
} &
done
wait
- name: Upload Official
uses: actions/upload-artifact@v4
with:
name: txwy
path: ./excel
compression-level: 0
update-game-resources:
# In case of rate limitations on the runners/instances, add dependency, by removing the comment
# needs: [clone-resources-official, clone-resources-overseas, clone-resources-txwy]
if: github.repository_owner == 'MaaAssistantArknights'
runs-on: macos-latest
steps:
- name: Checkout MAA
uses: actions/checkout@v5
with:
# TL;DR https://github.com/MaaAssistantArknights/MaaAssistantArknights/issues/9872#issuecomment-2251378371
# actions/checkout uses ${{ secrets.GITHUB_TOKEN }} by default, meaning all steps will inherit it
persist-credentials: false # Needed to bypass protection rules in Push changes
show-progress: false
fetch-depth: 3
- name: Restore ResourceUpdater from cache
id: resupd-cache
uses: actions/cache/restore@v4
with:
key: ResourceUpdater-${{ runner.os }}-${{ hashFiles('tools/ResourceUpdater/main.cpp') }}
path: |
./tools/ResourceUpdater/libopencv_world4.4.11.0.dylib
./tools/ResourceUpdater/res_updater
- name: Cache MaaDeps
if: steps.resupd-cache.outputs.cache-hit != 'true'
id: maadeps-cache
uses: actions/cache@v4
with:
path: |
./MaaDeps
key: ${{ runner.os }}-arm64-maadeps-${{ hashFiles('tools/maadeps-download.py') }}
- name: Bootstrap MaaDeps
if: steps.resupd-cache.outputs.cache-hit != 'true' && steps.maadeps-cache.outputs.cache-hit != 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
python3 tools/maadeps-download.py arm64-osx
- name: Config cmake
if: steps.resupd-cache.outputs.cache-hit != 'true'
run: |
cd tools/ResourceUpdater
mkdir -p build
cmake -B build -GNinja \
-DCMAKE_BUILD_TYPE=Release \
-DMAADEPS_TRIPLET='maa-arm64-osx' \
-DWITH_HASH_VERSION=ON
- name: Build
if: steps.resupd-cache.outputs.cache-hit != 'true'
run: |
cmake --build tools/ResourceUpdater/build --config Release --parallel $(sysctl -n hw.logicalcpu)
- name: Install
if: steps.resupd-cache.outputs.cache-hit != 'true'
run: |
cmake --install tools/ResourceUpdater/build --prefix tools/ResourceUpdater --config Release
- name: Save ResourceUpdater to cache
if: always() && steps.resupd-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
key: ResourceUpdater-${{ runner.os }}-${{ hashFiles('tools/ResourceUpdater/main.cpp') }}
path: |
./tools/ResourceUpdater/libopencv_world4.4.11.0.dylib
./tools/ResourceUpdater/res_updater
- name: Download txwy
id: download-txwy
uses: actions/download-artifact@v5
continue-on-error: true
with:
name: txwy
path: ./tools/ResourceUpdater/Overseas/tw/gamedata/excel
- name: Delay txwy
if: steps.download-txwy.outcome == 'failure'
run: |
sleep 10
- name: Re-download txwy
if: steps.download-txwy.outcome == 'failure'
uses: actions/download-artifact@v5
with:
name: txwy
path: ./tools/ResourceUpdater/Overseas/tw/gamedata/excel
- name: Download Overseas
id: download-overseas
uses: actions/download-artifact@v5
continue-on-error: true
with:
name: overseas
path: ./tools/ResourceUpdater/Overseas
- name: Delay Overseas
if: steps.download-overseas.outcome == 'failure'
run: |
sleep 10
- name: Re-download Overseas
if: steps.download-overseas.outcome == 'failure'
uses: actions/download-artifact@v5
with:
name: overseas
path: ./tools/ResourceUpdater/Overseas
- name: Download Official
id: download-official
uses: actions/download-artifact@v5
continue-on-error: true
with:
name: official
path: ./tools/ResourceUpdater/Official
- name: Delay Official
if: steps.download-official.outcome == 'failure'
run: |
sleep 10
- name: Re-download Official
if: steps.download-official.outcome == 'failure'
uses: actions/download-artifact@v5
with:
name: official
path: ./tools/ResourceUpdater/Official
- name: Run Resource Updater
run: |
./tools/ResourceUpdater/res_updater
.\tools\ResourceUpdater\x64\Release\ResourceUpdater.exe
- name: Task Sorting
id: task_sorting
- name: Overseas Tasks Ordering
run: |
python3 tools/TaskSorter/TaskSorter.py
echo "gitdiff=$(echo $(git diff --name-only --diff-filter=ACM 2>/dev/null | grep '\.json$'))" >> $GITHUB_OUTPUT
- name: Run prettier
uses: Nerixyz/actionsx-prettier@v3-adj
with:
args: -w ${{ steps.task_sorting.outputs.gitdiff }}
- name: Update version.json date if necessary
id: update_version
- name: Check if only sorted
id: check_only_sorted
run: |
./tools/ResourceUpdater/version.zsh
git status
- name: Setup python
if: steps.update_version.outputs.contains_png == 'True'
uses: actions/setup-python@v6
with:
python-version: "3.11"
$diff = $(git diff --numstat HEAD | findstr -i resource)
if ($LASTEXITCODE -ne 0) {
echo "no diff"
exit 0
}
- name: Cache Python packages
if: always() && steps.update_version.outputs.contains_png == 'True'
id: cache_python
uses: actions/cache@v4
with:
path: ${{ env.pythonLocation }}/Lib/site-packages
key: ${{ runner.os }}-pip-optimize-templates-${{ hashFiles('./tools/OptimizeTemplates/requirements.txt') }}
echo "diff: "$diff
$sp = $($diff -split "\s+")
$numbers = $($sp | Where-Object { $_ -match "^\d+$" })
echo "numbers: "$numbers
- name: Install dependencies
if: steps.cache_python.outputs.cache-hit != 'true' && steps.update_version.outputs.contains_png == 'True'
run: |
pip install -r tools/OptimizeTemplates/requirements.txt
$length = $numbers.Length
$noDiff = $true
for ($i = 0; $i -lt $length; $i += 2) {
$firstNumber = $numbers[$i]
$secondNumber = $numbers[$i+1]
- name: Setup oxipng
if: steps.update_version.outputs.contains_png == 'True'
uses: baptiste0928/cargo-install@v3
with:
crate: oxipng
if ($firstNumber -gt 1) {
$noDiff = $false
break
}
if ($firstNumber -ne $secondNumber) {
$noDiff = $false
break
}
}
echo "noDiff: "$noDiff
echo "only_sorted=$noDiff" >> $env:GITHUB_OUTPUT
- name: Run optimize_templates
if: steps.update_version.outputs.contains_png == 'True'
run: |
python3 tools/OptimizeTemplates/optimize_templates.py -p resource/template/items/ resource/template/infrast/
- name: Cancelling
if: steps.check_only_sorted.outputs.only_sorted == 'True'
uses: andymckay/cancel-action@0.3
- name: Add files to git
if: steps.update_version.outputs.changes == 'True'
if: steps.check_only_sorted.outputs.only_sorted != 'True'
id: add_files
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git status
git config user.name "$env:GITHUB_ACTOR"
git config user.email "$env:GITHUB_ACTOR@users.noreply.github.com"
git add .
commit_msg="${{ github.event.inputs.commit_message }}"
if [ -z "$commit_msg" ]; then
commit_msg="chore: Auto Update Game Resources - $(date '+%Y-%m-%d')"
else
commit_msg=$(echo "$commit_msg" | xargs) # Trim whitespace
fi
$commit_msg = "${{ github.event.inputs.commit_message }}"
if (-not [string]::IsNullOrWhiteSpace($commit_msg)) {
$commit_msg = $commit_msg.Trim()
} else {
$commit_msg = "chore: Auto Update Game Resources - $(Get-Date -Format 'yyyy-MM-dd')"
}
git commit -m "$commit_msg" -m "[skip changelog]"
if ($LASTEXITCODE -eq 0) {
echo "have_commits=True" >> $env:GITHUB_OUTPUT
}
run_url="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
git pull origin $(git rev-parse --abbrev-ref HEAD) --unshallow --rebase
git commit -m "$commit_msg" -m "$run_url" -m "[skip changelog]"
if [ $? -eq 0 ]; then
echo "have_commits=True" >> $GITHUB_OUTPUT
fi
- name: Cancelling
if: steps.add_files.outputs.have_commits != 'True'
uses: andymckay/cancel-action@0.3
git pull origin ${{ github.ref_name }} --rebase
- name: Push changes
- name: Push changes # push the output folder to your repo
if: steps.add_files.outputs.have_commits == 'True'
uses: ad-m/github-push-action@master
with:
branch: ${{ github.ref }}
github_token: ${{ secrets.MAA_RESOURCE_SYNC }}
github_token: ${{ secrets.MISTEOWORKFLOW }}
# - name: Update OTA resource
# if: steps.update_version.outputs.update_resources == 'True'
# env:
# GH_TOKEN: ${{ secrets.MISTEOWORKFLOW }}
# run: |
# gh workflow --repo MaaAssistantArknights/MaaRelease run update-resource.yml
- name: Update OTA resource
if: steps.add_files.outputs.have_commits == 'True'
run: |
gh workflow --repo MaaAssistantArknights/MaaRelease run update-resource.yml
- name: Add cancelled status
if: steps.update_version.outputs.changes != 'True' || steps.add_files.outputs.have_commits != 'True'
uses: andymckay/cancel-action@0.5
# - name: Release # ref: https://docs.github.com/en/actions/using-workflows/triggering-a-workflow#triggering-a-workflow-from-a-workflow
# if: steps.add_files.outputs.have_commits == 'True'
# run: |
# gh workflow run release-nightly-ota -f release_body="Auto Release of Resource Updates"
# - name: Release # ref: https://docs.github.com/en/actions/using-workflows/triggering-a-workflow#triggering-a-workflow-from-a-workflow
# if: steps.add_files.outputs.have_commits == 'True'
# run: |
# gh workflow run release-nightly-ota -f release_body="Auto Release of Resource Updates"
# env:
# GH_TOKEN: ${{ github.token }}

View File

@@ -1,128 +1,78 @@
name: smoke-testing
name: test
on:
push:
paths:
- ".github/workflows/smoke-testing.yml"
- "3rdparty/include/**"
- "include/**"
- "src/Cpp/**"
- "src/MaaCore/**"
- "resource/**"
- "!**/*.md"
- "src/**"
- "cmake/**"
- "CMakeLists.txt"
- "tools/maadeps-download.py"
- "MAA.sln"
- "resource/**"
- "MaaDeps/**"
- "!**/*.md"
pull_request:
paths:
- ".github/workflows/smoke-testing.yml"
- "3rdparty/include/**"
- "include/**"
- "src/Cpp/**"
- "src/MaaCore/**"
- "resource/**"
- "!**/*.md"
- "src/**"
- "cmake/**"
- "CMakeLists.txt"
- "tools/maadeps-download.py"
- "MAA.sln"
- "resource/**"
- "MaaDeps/**"
- "!**/*.md"
workflow_dispatch:
jobs:
smoke-testing:
# Prevent duplicate runs on organization branches with PRs
if: github.event_name != 'pull_request' ||
github.event.pull_request.head.repo.full_name !=
github.event.pull_request.base.repo.full_name
runs-on: macos-latest
runs-on: windows-latest
steps:
- name: Checkout code
uses: actions/checkout@v5
uses: actions/checkout@v4
with:
show-progress: false
- name: Generate cache key
id: cache_key
run: |
echo "key=Smoke-testing-${{ hashFiles('src/Cpp/**', 'src/MaaCore/**', '3rdparty/include/**', 'include/**', 'cmake/**', 'CMakeLists.txt', 'tools/maadeps-download.py', 'tools/linux-toolchain-download.py') }}" >> $GITHUB_OUTPUT
- name: Restore cache smoke-testing
id: smoke-cache
uses: actions/cache/restore@v4
with:
key: ${{ steps.cache_key.outputs.key }}
path: |
./install/libfastdeploy_ppocr.dylib
./install/libMaaCore.dylib
./install/libonnxruntime.1.19.2.dylib
./install/libopencv_world4.4.11.0.dylib
./install/smoke_test
- name: Fetch submodules
if: steps.smoke-cache.outputs.cache-hit != 'true'
run: |
git submodule update --init --depth 1 3rdparty/EmulatorExtras
- name: Cache MaaDeps
if: steps.smoke-cache.outputs.cache-hit != 'true'
id: maadeps-cache
uses: actions/cache@v4
with:
path: ./MaaDeps
key: ${{ runner.os }}-arm64-maadeps-${{ hashFiles('tools/maadeps-download.py') }}
submodules: recursive
- name: Restore dependencies
run: dotnet restore
- name: Bootstrap MaaDeps
if: steps.smoke-cache.outputs.cache-hit != 'true' && steps.maadeps-cache.outputs.cache-hit != 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
python3 tools/maadeps-download.py arm64-osx
python3 maadeps-download.py x64-windows
- name: Config cmake
if: steps.smoke-cache.outputs.cache-hit != 'true'
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1
- name: Build MaaSample
run: |
mkdir -p build
cmake -B build -GNinja \
-DCMAKE_BUILD_TYPE=Debug \
-DMAADEPS_TRIPLET='maa-arm64-osx' \
-DBUILD_SMOKE_TEST=ON \
-DINSTALL_RESOURCE=ON \
-DWITH_HASH_VERSION=ON
MSBUILD src/Cpp/MaaSample.slnf /t:rebuild /p:Configuration="Debug" /p:Platform="x64" /m
- name: Build
if: steps.smoke-cache.outputs.cache-hit != 'true'
- name: Run tests - Official #用来判断是不是国服资源出错导致外服全炸
run: |
cmake --build build --config Debug --parallel $(sysctl -n hw.logicalcpu)
.\x64\Debug\Sample.exe
- name: Install
if: steps.smoke-cache.outputs.cache-hit != 'true'
- name: Run tests - YostarJP
run: |
mkdir -p install
cmake --install build --prefix install --config Debug
- name: Make link for cache smoke-testing
if: steps.smoke-cache.outputs.cache-hit == 'true'
.\x64\Debug\Sample.exe YostarJP
- name: Run tests - YostarEN
run: |
ln -s "$(pwd)/resource" install/resource
- name: Run tests
.\x64\Debug\Sample.exe YostarEN
- name: Run tests - YostarKR
run: |
./tools/SmokeTesting/run_tests.zsh
- name: Save cache smoke-testing (only in dev)
if: steps.smoke-cache.outputs.cache-hit != 'true' && github.ref == 'refs/heads/dev'
uses: actions/cache/save@v4
with:
key: ${{ steps.cache_key.outputs.key }}
path: |
./install/libfastdeploy_ppocr.dylib
./install/libMaaCore.dylib
./install/libonnxruntime.1.19.2.dylib
./install/libopencv_world4.4.11.0.dylib
./install/smoke_test
.\x64\Debug\Sample.exe YostarKR
- name: Run tests - txwy
run: |
.\x64\Debug\Sample.exe txwy
- name: Upload logs
if: always()
uses: actions/upload-artifact@v4
with:
name: logs
path: ./install/debug
name: log
path: .\x64\Debug\debug

View File

@@ -1,39 +0,0 @@
name: "Inactive Issues Closer"
on:
schedule:
- cron: "0 0 * * *" # Runs daily at UTC 00:00
workflow_dispatch: # Allows manual triggering
env: # config
daysBeforeStale: 90 # Number of days of inactivity before marking as stale
daysBeforeClose: 7 # Number of days to wait after marking as stale before closing
jobs:
stale:
if: github.repository_owner == 'MaaAssistantArknights'
runs-on: ubuntu-latest
permissions:
actions: write # Workaround for https://github.com/actions/stale/issues/1090
issues: write
# Completely disable stalling for PRs
pull-requests: none
contents: none
steps:
- name: Close inactive issues
uses: actions/stale@v10
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: ${{ env.daysBeforeStale }}
days-before-close: ${{ env.daysBeforeClose }}
stale-issue-label: "stale"
stale-issue-message: |
This issue has been inactive for a prolonged period and will be closed automatically in ${{ env.daysBeforeClose }} days.
该问题已长时间处于闲置状态,${{ env.daysBeforeClose }} 天后将自动关闭。
exempt-issue-labels: "keep-open, MAA Team, enhancement"
days-before-pr-stale: -1 # Completely disable stalling for PRs
days-before-pr-close: -1 # Completely disable closing for PRs
# Temporary to reduce the huge issues number
operations-per-run: 100
debug-only: false

View File

@@ -1,33 +1,32 @@
name: sync-resource
on:
workflow_dispatch:
push:
branches:
- dev
paths:
- "resource/**"
- ".github/workflows/sync-resource.yml"
workflow_dispatch:
jobs:
sync-resource:
if: github.repository_owner == 'MaaAssistantArknights'
sync-reource:
runs-on: ubuntu-latest
steps:
- name: Checkout MaaAssistantArknights
uses: actions/checkout@v5
uses: actions/checkout@v4
with:
show-progress: false
- name: Setup Git
run: |
git config --global user.name 'github-actions[bot]'
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
git config --global user.name "$GITHUB_ACTOR"
git config --global user.email "$GITHUB_ACTOR@users.noreply.github.com"
git show -s
- name: Checkout MaaResource
uses: actions/checkout@v5
uses: actions/checkout@v4
with:
repository: MaaAssistantArknights/MaaResource
show-progress: false
@@ -49,3 +48,9 @@ jobs:
git status
git commit -m "$commit_msg" || exit 0
git push
- name: Setup resource update
env:
GH_TOKEN: ${{ secrets.MISTEOWORKFLOW }}
run: |
gh workflow --repo MaaAssistantArknights/MaaRelease run update-resource.yml

View File

@@ -8,65 +8,102 @@ on:
paths:
- ".github/workflows/website-workflow.yml"
- "docs/**"
- "website/**"
pull_request:
paths:
- ".github/workflows/website-workflow.yml"
- "docs/**"
- "website/**"
workflow_dispatch:
inputs:
deploy-to-prod:
description: "Deploy to prod"
deploy-to-prod-env:
description: "Deploy to production environment"
default: false
required: true
type: boolean
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 20
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Check out code
uses: actions/checkout@v4
with:
show-progress: false
- name: Setup Pages
uses: actions/configure-pages@v5
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10
version: 9
run_install: false
- name: Setup Node.js environment
uses: actions/setup-node@v5
uses: actions/setup-node@v4
with:
node-version: 24
node-version: 20
cache: pnpm
cache-dependency-path: "./docs/pnpm-lock.yaml"
cache-dependency-path: './website/pnpm-lock.yaml'
- name: Install dependencies
run: pnpm install --frozen-lockfile
working-directory: "./docs"
working-directory: "./website"
- name: Build documentation
- name: Build
run: pnpm run build
working-directory: "./docs"
working-directory: "./website"
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
- name: Upload artifact to GitHub
uses: actions/upload-artifact@v4
with:
path: "./docs/.vuepress/dist"
name: dist
path: "./website/dist"
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v4
if: ${{ inputs.deploy-to-prod == true || github.ref == 'refs/heads/master' }}
publish:
runs-on: ubuntu-latest
needs: build
if: github.event_name != 'pull_request'
steps:
- name: Download website artifacts
uses: actions/download-artifact@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: "./docs/.vuepress/dist"
publish_branch: gh-pages
name: dist
- name: Set deployment environment
id: set-deployment-env
run: |
if [[ "${{ github.event_name }}" != "workflow_dispatch" && "${{ github.ref }}" == "refs/heads/master" ]] || [[ "${{ github.event.inputs.deploy-to-prod-env }}" == "true" ]]; then
echo "AZURE_TARGET_ENV=prod" >> $GITHUB_ENV
else
echo "AZURE_TARGET_ENV=dev" >> $GITHUB_ENV
fi
- name: Show environment
run: echo ${{ env.AZURE_TARGET_ENV }}
- name: Deploy to Azure (prod)
id: deploy-prod
uses: Azure/static-web-apps-deploy@v1
if: env.AZURE_TARGET_ENV == 'prod'
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_MAA_WEBSITE }}
repo_token: ${{ secrets.GITHUB_TOKEN }}
action: "upload"
app_location: "."
api_location: ""
skip_app_build: true
skip_api_build: true
- name: Deploy to Azure (dev)
id: deploy-dev
uses: Azure/static-web-apps-deploy@v1
if: env.AZURE_TARGET_ENV == 'dev'
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_MAA_WEBSITE }}
repo_token: ${{ secrets.GITHUB_TOKEN }}
action: "upload"
deployment_environment: dev
app_location: "."
api_location: ""
skip_app_build: true
skip_api_build: true

30
.gitignore vendored
View File

@@ -437,9 +437,6 @@ tools/**/*.png
.vscode
enc_temp_folder/*
# RoguelikeRecruitmentTool 导出的 Excel 文件
tools/RoguelikeRecruitmentTool/output
# Nuke
.nuke/temp/*
@@ -451,30 +448,3 @@ tools/RoguelikeRecruitmentTool/output
# CF 活动关卡(异格夜刀),手动改的地图
/resource/Arknights-Tile-Pos/act24side_09-activities-act24side-level_act24side_09.json
/src/MaaWpfGui/FodyWeavers.xml
*.lnk
# 链接检查缓存
.lycheecache
# MaaDeps
/MaaDeps/*
# ResourceUpdater workflow
/original/*
# Windows Explorer Shits
desktop.ini
Thumbs.db
# macOS Finder Shit
.DS_Store
# MaaSupportExtension config
/config/maa_pi_config.json
# build & install
build
install
# pnpm cache
.pnpm-store

5
.gitmodules vendored
View File

@@ -4,6 +4,11 @@
[submodule "src/MaaMacGui"]
path = src/MaaMacGui
url = https://github.com/MaaAssistantArknights/MaaMacGui.git
[submodule "MaaDeps"]
path = MaaDeps
url = https://github.com/MaaAssistantArknights/MaaDeps
shallow = true
branch = master
[submodule "src/maa-cli"]
path = src/maa-cli
url = https://github.com/MaaAssistantArknights/maa-cli.git

5
.linkspector.yml Normal file
View File

@@ -0,0 +1,5 @@
dirs:
- .
useGitIgnore: true
ignorePatterns:
- pattern: "^https?://127.0.0.1(:\\d+)?/"

132
.nuke/build.schema.json Normal file
View File

@@ -0,0 +1,132 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Build Schema",
"$ref": "#/definitions/build",
"definitions": {
"build": {
"type": "object",
"properties": {
"Continue": {
"type": "boolean",
"description": "Indicates to continue a previously failed build attempt"
},
"Help": {
"type": "boolean",
"description": "Shows the help text for this build assembly"
},
"Host": {
"type": "string",
"description": "Host for execution. Default is 'automatic'",
"enum": [
"AppVeyor",
"AzurePipelines",
"Bamboo",
"Bitbucket",
"Bitrise",
"GitHubActions",
"GitLab",
"Jenkins",
"Rider",
"SpaceAutomation",
"TeamCity",
"Terminal",
"TravisCI",
"VisualStudio",
"VSCode"
]
},
"NoLogo": {
"type": "boolean",
"description": "Disables displaying the NUKE logo"
},
"Partition": {
"type": "string",
"description": "Partition to use on CI"
},
"Plan": {
"type": "boolean",
"description": "Shows the execution plan (HTML)"
},
"Profile": {
"type": "array",
"description": "Defines the profiles to load",
"items": {
"type": "string"
}
},
"Root": {
"type": "string",
"description": "Root directory during build execution"
},
"Skip": {
"type": "array",
"description": "List of targets to be skipped. Empty list skips all dependencies",
"items": {
"type": "string",
"enum": [
"Default",
"DevBuild",
"DevBuildDefault",
"DevBuildReleaseSimulation",
"ReleaseMaa",
"SetMaaChangeLog",
"SetPackageBundled",
"SetVersion",
"UseClean",
"UseCommitVersion",
"UseMaaChangeLog",
"UseMaaDevBundle",
"UseMaaRelease",
"UsePublishArtifact",
"UsePublishRelease",
"UseRsVersion",
"UseTagVersion",
"WithCompileCoreRelease",
"WithCompileWpfRelease",
"WithSyncRes"
]
}
},
"Target": {
"type": "array",
"description": "List of targets to be invoked. Default is '{default_target}'",
"items": {
"type": "string",
"enum": [
"Default",
"DevBuild",
"DevBuildDefault",
"DevBuildReleaseSimulation",
"ReleaseMaa",
"SetMaaChangeLog",
"SetPackageBundled",
"SetVersion",
"UseClean",
"UseCommitVersion",
"UseMaaChangeLog",
"UseMaaDevBundle",
"UseMaaRelease",
"UsePublishArtifact",
"UsePublishRelease",
"UseRsVersion",
"UseTagVersion",
"WithCompileCoreRelease",
"WithCompileWpfRelease",
"WithSyncRes"
]
}
},
"Verbosity": {
"type": "string",
"description": "Logging verbosity during build execution. Default is 'Normal'",
"enum": [
"Minimal",
"Normal",
"Quiet",
"Verbose"
]
}
}
}
}
}

4
.nuke/parameters.json Normal file
View File

@@ -0,0 +1,4 @@
{
"$schema": "./build.schema.json",
"Solution": "tools/MaaBuilder.sln"
}

View File

@@ -1,39 +0,0 @@
default_install_hook_types: [pre-commit, prepare-commit-msg]
ci:
autofix_commit_msg: "chore: Auto update by pre-commit hooks [skip changelog]"
autofix_prs: true
repos:
- repo: https://github.com/shssoichiro/oxipng
rev: v9.1.4
hooks:
- id: oxipng
args: ["-q", "-o", "2", "-s", "--ng"]
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v20.1.0
hooks:
- id: clang-format
files: ^src/MaaCore/.*
args: ["--assume-filename", ".clang-format"]
- repo: https://github.com/rbubley/mirrors-prettier
rev: v3.5.3
hooks:
- id: prettier
name: prettier (config files)
files: ^((\.github/ISSUE_TEMPLATE|resource|src|tools)/.*|\.pre-commit-config\.yaml|package-definition\.json)
types_or:
- yaml
- json
- repo: https://github.com/rbubley/mirrors-prettier
rev: v3.5.3
hooks:
- id: prettier
name: prettier (docs)
files: ^docs/.*
- repo: https://github.com/DavidAnson/markdownlint-cli2
rev: v0.17.2
hooks:
- id: markdownlint-cli2
files: ^docs/.*|^README\.md$
types:
- markdown
args: ["--fix", "--config", "docs/.markdownlint.yaml", "#**/node_modules"]

View File

@@ -1,18 +0,0 @@
**/node_modules/
**/pnpm-lock.yaml
docs/**/*.md
MaaDeps/
3rdparty/
src/maa-cli
src/MaaMacGui
# website/
# docs/
resource/Arknights-Tile-Pos/
tools/OptimizeTemplates/optimize_templates.json
CITATION.cff
CHANGELOG.md
## FUCK FUCK

View File

@@ -1,23 +0,0 @@
{
"tabWidth": 4,
"printWidth": 120,
"useTabs": false,
"bracketSameLine": true,
"bracketSpacing": true,
"endOfLine": "auto",
"overrides": [
{
"files": [".clang-format", "**/*.yml", "**/*.yaml"],
"options": {
"parser": "yaml",
"tabWidth": 2
}
},
{
"files": ["**/*.md"],
"options": {
"tabWidth": 2
}
}
]
}

View File

@@ -2,8 +2,7 @@
"json.schemas": [
{
"fileMatch": [
"resource/tasks/**/*.json",
"resource/global/**/resource/tasks/**/*.json",
"resource/tasks.json"
],
"url": "./docs/maa_tasks_schema.json"
}
@@ -12,8 +11,5 @@
"MaaDeps/vcpkg/buildtrees": true,
"MaaDeps/vcpkg/packages": true
},
"files.associations": {
"**/resource/tasks/**/*.json": "jsonc"
},
"C_Cpp.exclusionPolicy": "checkFilesAndFolders"
}

View File

@@ -39,8 +39,8 @@ inline matrix4x4 camera_matrix_from_trans(
const vec3d& euler,
double ratio,
double fov_2_y = 20 * degree,
double far_c = 1000,
double near_c = 0.3)
double far = 1000,
double near = 0.3)
{
const double cos_y = std::cos(euler[0]);
const double sin_y = std::sin(euler[0]);
@@ -66,11 +66,11 @@ inline matrix4x4 camera_matrix_from_trans(
0, -sin_x, -cos_x, 0, //
0, 0, 0, 1,
};
const matrix4x4 proj = matrix4x4 {
const matrix4x4 proj = {
// clang-format off
ratio / tan_f, 0, 0, 0,
0, 1 / tan_f, 0, 0,
0, 0, -(far_c + near_c) / (far_c - near_c), -(far_c * near_c * 2) / (far_c - near_c),
0, 0, -(far + near) / (far - near), -(far * near * 2) / (far - near),
0, 0, -1, 0,
// clang-format on
};
@@ -78,13 +78,14 @@ inline matrix4x4 camera_matrix_from_trans(
return proj * matrixX * matrixY * translate;
}
inline cv::Point world_to_screen(const Level& level, const vec3d& world_pos, bool side, const vec3d& offset = {})
inline cv::Point
world_to_screen(const Level& level, const vec3d& world_pos, bool side, const vec3d& offset = {})
{
static constexpr int width = 1280;
static constexpr int height = 720;
static constexpr double width = 1280;
static constexpr double height = 720;
const vec3d pos_cam = camera_pos(level, side, width, height) + offset;
const vec3d euler = camera_euler_angles_yxz(level, side);
const matrix4x4 matrix = camera_matrix_from_trans(pos_cam, euler, static_cast<double>(height) / width);
const matrix4x4 matrix = camera_matrix_from_trans(pos_cam, euler, height / width);
auto result = matrix * cv::Point3d(world_pos);
result = result / result(3);
result = (result + cv::Vec4d::ones()) / 2.;
@@ -106,7 +107,12 @@ inline vec3d get_tile_world_pos(const Level& level, int tile_y, int tile_x)
};
}
inline auto get_tile_screen_pos(const Level& level, int tile_y, int tile_x, bool side = false, const vec3d& offset = {})
inline auto get_tile_screen_pos(
const Level& level,
int tile_y,
int tile_x,
bool side = false,
const vec3d& offset = {})
{
return world_to_screen(level, get_tile_world_pos(level, tile_y, tile_x), side, offset);
}

View File

@@ -1,5 +1,3 @@
// IWYU pragma: private, include <meojson/json.hpp>
#pragma once
#include <initializer_list>
@@ -7,7 +5,6 @@
#include <ostream>
#include <string>
#include <tuple>
#include <type_traits>
#include <vector>
#include "exception.hpp"
@@ -40,109 +37,37 @@ public:
// explicit basic_array(const basic_value<string_t>& val);
// explicit basic_array(basic_value<string_t>&& val);
template <
typename jsonization_t,
std::enable_if_t<
_utils::has_to_json_in_templ_spec<jsonization_t, string_t>::value
&& !_utils::has_to_json_array_in_templ_spec<jsonization_t, string_t>::value,
bool> = true>
basic_array(const jsonization_t& value)
: basic_array(ext::jsonization<string_t, jsonization_t>().to_json(value))
{
}
template <
typename jsonization_t,
std::enable_if_t<
_utils::has_to_json_array_in_templ_spec<jsonization_t, string_t>::value,
bool> = true>
basic_array(const jsonization_t& value)
: basic_array(ext::jsonization<string_t, jsonization_t>().to_json_array(value))
{
}
template <
typename jsonization_t,
std::enable_if_t<
std::is_rvalue_reference_v<jsonization_t&&>
&& _utils::has_move_to_json_in_templ_spec<jsonization_t, string_t>::value
&& !_utils::has_move_to_json_array_in_templ_spec<jsonization_t, string_t>::value,
bool> = true>
basic_array(jsonization_t&& value)
: basic_array(ext::jsonization<string_t, jsonization_t>().move_to_json(std::move(value)))
{
}
//template <
// typename jsonization_t,
// std::enable_if_t<
// std::is_rvalue_reference_v<jsonization_t&&>
// && _utils::has_move_to_json_array_in_templ_spec<jsonization_t, string_t>::value,
// bool> = true>
//basic_array(jsonization_t&& value)
// : basic_array(
// ext::jsonization<string_t, jsonization_t>().move_to_json_array(std::move(value)))
//{
//}
template <typename collection_t,
std::enable_if_t<_utils::is_collection<collection_t> &&
std::is_constructible_v<value_type, _utils::range_value_t<collection_t>>,
bool> = true>
basic_array(collection_t arr)
: _array_data(std::make_move_iterator(arr.begin()), std::make_move_iterator(arr.end()))
{}
template <typename jsonization_t,
std::enable_if_t<_utils::has_to_json_in_member<jsonization_t>::value, bool> = true>
basic_array(const jsonization_t& value) : basic_array(value.to_json())
{}
template <typename jsonization_t,
std::enable_if_t<_utils::has_to_json_in_templ_spec<jsonization_t>::value, bool> = true>
basic_array(const jsonization_t& value) : basic_array(ext::jsonization<jsonization_t>().to_json(value))
{}
~basic_array() noexcept = default;
bool empty() const noexcept { return _array_data.empty(); }
size_t size() const noexcept { return _array_data.size(); }
bool contains(size_t pos) const { return pos < _array_data.size(); }
bool exists(size_t pos) const { return contains(pos); }
const basic_value<string_t>& at(size_t pos) const;
string_t dumps(std::optional<size_t> indent = std::nullopt) const
{
return indent ? format(*indent) : to_string();
}
string_t dumps(std::optional<size_t> indent = std::nullopt) const { return indent ? format(*indent) : to_string(); }
string_t to_string() const;
string_t format(size_t indent = 4) const { return format(indent, 0); }
template <typename value_t>
bool all() const;
template <typename value_t, template <typename...> typename collection_t = std::vector>
collection_t<value_t> as_collection() const;
template <
typename value_t,
size_t Size,
template <typename, size_t> typename fixed_array_t = std::array>
fixed_array_t<value_t, Size> as_fixed_array() const;
template <typename... elem_ts>
std::tuple<elem_ts...> as_tuple() const;
template <typename first_t, typename second_t>
std::pair<first_t, second_t> as_pair() const;
template <
typename value_t,
std::enable_if_t<
_utils::has_from_json_array_in_templ_spec<value_t, string_t>::value,
bool> = true>
value_t as() const&
{
value_t res;
ext::jsonization<string_t, value_t>().from_json_array(*this, res);
return res;
}
template <
typename value_t,
std::enable_if_t<
_utils::has_move_from_json_array_in_templ_spec<value_t, string_t>::value,
bool> = true>
value_t as() &&
{
value_t res;
ext::jsonization<string_t, value_t>().move_from_json_array(std::move(*this), res);
return res;
}
// Usage: get(key_1, key_2, ..., default_value);
template <typename... key_then_default_value_t>
@@ -187,93 +112,37 @@ public:
basic_array<string_t>& operator=(const basic_array<string_t>&) = default;
basic_array<string_t>& operator=(basic_array<string_t>&&) noexcept = default;
template <
typename value_t,
std::enable_if_t<std::is_convertible_v<value_t, basic_array<string_t>>, bool> = true>
template <typename value_t, std::enable_if_t<std::is_convertible_v<value_t, basic_array<string_t>>, bool> = true>
basic_array<string_t>& operator=(value_t rhs)
{
return *this = basic_array<string_t>(std::move(rhs));
}
bool operator==(const basic_array<string_t>& rhs) const;
bool operator!=(const basic_array<string_t>& rhs) const { return !(*this == rhs); }
template <
typename value_t,
template <typename...> typename collection_t = std::vector,
std::enable_if_t<_utils::is_collection<collection_t<value_t>>, bool> = true>
template <typename value_t, template <typename...> typename collection_t = std::vector,
std::enable_if_t<_utils::is_collection<collection_t<value_t>>, bool> = true>
explicit operator collection_t<value_t>() const
{
return as_collection<value_t, collection_t>();
}
template <
typename value_t,
size_t Size,
template <typename, size_t> typename fixed_array_t = std::array,
std::enable_if_t<_utils::is_fixed_array<fixed_array_t<value_t, Size>>, bool> = true>
explicit operator fixed_array_t<value_t, Size>() const
{
return as<fixed_array_t<value_t, Size>>();
}
template <
typename jsonization_t,
std::enable_if_t<
_utils::has_from_json_in_templ_spec<jsonization_t, string_t>::value
&& !_utils::has_from_json_array_in_templ_spec<jsonization_t, string_t>::value,
bool> = true>
explicit operator jsonization_t() const&
template <typename jsonization_t,
std::enable_if_t<_utils::has_from_json_in_member<jsonization_t, string_t>::value, bool> = true>
explicit operator jsonization_t() const
{
jsonization_t dst {};
if (!ext::jsonization<string_t, jsonization_t>().from_json(*this, dst)) {
if (!dst.from_json(*this)) {
throw exception("Wrong JSON");
}
return dst;
}
template <
typename jsonization_t,
std::enable_if_t<
_utils::has_from_json_array_in_templ_spec<jsonization_t, string_t>::value,
bool> = true>
explicit operator jsonization_t() const&
template <typename jsonization_t,
std::enable_if_t<_utils::has_from_json_in_templ_spec<jsonization_t, string_t>::value, bool> = true>
explicit operator jsonization_t() const
{
jsonization_t dst {};
if (!ext::jsonization<string_t, jsonization_t>().from_json_array(*this, dst)) {
throw exception("Wrong JSON");
}
return dst;
}
template <
typename jsonization_t,
std::enable_if_t<
_utils::has_move_from_json_in_templ_spec<jsonization_t, string_t>::value
&& !_utils::has_move_from_json_array_in_templ_spec<jsonization_t, string_t>::value,
bool> = true>
explicit operator jsonization_t() &&
{
jsonization_t dst {};
if (!ext::jsonization<string_t, jsonization_t>().from_json(std::move(*this), dst)) {
throw exception("Wrong JSON");
}
return dst;
}
template <
typename jsonization_t,
std::enable_if_t<
_utils::has_move_from_json_array_in_templ_spec<jsonization_t, string_t>::value,
bool> = true>
explicit operator jsonization_t() &&
{
jsonization_t dst {};
if (!ext::jsonization<string_t, jsonization_t>().move_from_json_array(
std::move(*this),
dst)) {
if (!ext::jsonization<jsonization_t>().from_json(*this, dst)) {
throw exception("Wrong JSON");
}
return dst;
@@ -281,9 +150,8 @@ public:
private:
template <typename... key_then_default_value_t, size_t... keys_indexes_t>
auto
get(std::tuple<key_then_default_value_t...> keys_then_default_value,
std::index_sequence<keys_indexes_t...>) const;
auto get(std::tuple<key_then_default_value_t...> keys_then_default_value,
std::index_sequence<keys_indexes_t...>) const;
template <typename value_t, typename... rest_keys_t>
auto get_helper(const value_t& default_value, size_t pos, rest_keys_t&&... rest) const;
template <typename value_t>
@@ -296,20 +164,15 @@ private:
};
template <typename string_t>
inline basic_array<string_t>::basic_array(std::initializer_list<value_type> init_list)
: _array_data(init_list)
{
}
inline basic_array<string_t>::basic_array(std::initializer_list<value_type> init_list) : _array_data(init_list)
{}
template <typename string_t>
inline basic_array<string_t>::basic_array(typename raw_array::size_type size)
: _array_data(size)
{
}
inline basic_array<string_t>::basic_array(typename raw_array::size_type size) : _array_data(size)
{}
// template <typename string_t>
// inline basic_array<string_t>::basic_array(const basic_value<string_t>& val) :
// basic_array<string_t>(val.as_array())
// inline basic_array<string_t>::basic_array(const basic_value<string_t>& val) : basic_array<string_t>(val.as_array())
//{}
//
// template <typename string_t>
@@ -339,9 +202,8 @@ template <typename string_t>
template <typename... args_t>
inline decltype(auto) basic_array<string_t>::emplace_back(args_t&&... args)
{
static_assert(
std::is_constructible_v<value_type, args_t...>,
"Parameter can't be used to construct a raw_array::value_type");
static_assert(std::is_constructible_v<value_type, args_t...>,
"Parameter can't be used to construct a raw_array::value_type");
return _array_data.emplace_back(std::forward<args_t>(args)...);
}
@@ -402,65 +264,65 @@ inline bool basic_array<string_t>::all() const
return true;
}
namespace _as_collection_helper
{
template <typename T>
class has_emplace_back
{
template <typename U>
static auto test(int) -> decltype(std::declval<U>().emplace_back(), std::true_type());
template <typename U>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(0))::value;
};
}
template <typename string_t>
template <typename value_t, template <typename...> typename collection_t>
inline collection_t<value_t> basic_array<string_t>::as_collection() const
{
return as<collection_t<value_t>>();
}
template <typename string_t>
template <typename value_t, size_t Size, template <typename, size_t> typename fixed_array_t>
inline fixed_array_t<value_t, Size> basic_array<string_t>::as_fixed_array() const
{
return as<fixed_array_t<value_t, Size>>();
}
template <typename string_t>
template <typename... elem_ts>
inline std::tuple<elem_ts...> basic_array<string_t>::as_tuple() const
{
return as<std::tuple<elem_ts...>>();
}
template <typename string_t>
template <typename first_t, typename second_t>
inline std::pair<first_t, second_t> basic_array<string_t>::as_pair() const
{
return as<std::pair<first_t, second_t>>();
collection_t<value_t> result;
if constexpr (_as_collection_helper::has_emplace_back<collection_t<value_t>>::value) {
for (const auto& elem : _array_data) {
result.emplace_back(elem.template as<value_t>());
}
}
else {
for (const auto& elem : _array_data) {
result.emplace(elem.template as<value_t>());
}
}
return result;
}
template <typename string_t>
template <typename... key_then_default_value_t>
inline auto basic_array<string_t>::get(key_then_default_value_t&&... keys_then_default_value) const
{
return get(
std::forward_as_tuple(keys_then_default_value...),
std::make_index_sequence<sizeof...(keys_then_default_value) - 1> {});
return get(std::forward_as_tuple(keys_then_default_value...),
std::make_index_sequence<sizeof...(keys_then_default_value) - 1> {});
}
template <typename string_t>
template <typename... key_then_default_value_t, size_t... keys_indexes_t>
inline auto basic_array<string_t>::get(
std::tuple<key_then_default_value_t...> keys_then_default_value,
std::index_sequence<keys_indexes_t...>) const
inline auto basic_array<string_t>::get(std::tuple<key_then_default_value_t...> keys_then_default_value,
std::index_sequence<keys_indexes_t...>) const
{
constexpr unsigned long default_value_index = sizeof...(key_then_default_value_t) - 1;
return get_helper(
std::get<default_value_index>(keys_then_default_value),
std::get<keys_indexes_t>(keys_then_default_value)...);
return get_helper(std::get<default_value_index>(keys_then_default_value),
std::get<keys_indexes_t>(keys_then_default_value)...);
}
template <typename string_t>
template <typename value_t, typename... rest_keys_t>
inline auto basic_array<string_t>::get_helper(
const value_t& default_value,
size_t pos,
rest_keys_t&&... rest) const
inline auto basic_array<string_t>::get_helper(const value_t& default_value, size_t pos, rest_keys_t&&... rest) const
{
constexpr bool is_json = std::is_same_v<basic_value<string_t>, value_t>
|| std::is_same_v<basic_array<string_t>, value_t>
|| std::is_same_v<basic_object<string_t>, value_t>;
constexpr bool is_json = std::is_same_v<basic_value<string_t>, value_t> ||
std::is_same_v<basic_array<string_t>, value_t> ||
std::is_same_v<basic_object<string_t>, value_t>;
constexpr bool is_string = std::is_constructible_v<string_t, value_t> && !is_json;
if (!contains(pos)) {
@@ -479,9 +341,9 @@ template <typename string_t>
template <typename value_t>
inline auto basic_array<string_t>::get_helper(const value_t& default_value, size_t pos) const
{
constexpr bool is_json = std::is_same_v<basic_value<string_t>, value_t>
|| std::is_same_v<basic_array<string_t>, value_t>
|| std::is_same_v<basic_object<string_t>, value_t>;
constexpr bool is_json = std::is_same_v<basic_value<string_t>, value_t> ||
std::is_same_v<basic_array<string_t>, value_t> ||
std::is_same_v<basic_object<string_t>, value_t>;
constexpr bool is_string = std::is_constructible_v<string_t, value_t> && !is_json;
if (!contains(pos)) {
@@ -520,8 +382,7 @@ inline std::optional<value_t> basic_array<string_t>::find(size_t pos) const
return std::nullopt;
}
const auto& val = _array_data.at(pos);
return val.template is<value_t>() ? std::optional<value_t>(val.template as<value_t>())
: std::nullopt;
return val.template is<value_t>() ? std::optional<value_t>(val.template as<value_t>()) : std::nullopt;
}
template <typename string_t>
@@ -573,29 +434,25 @@ inline typename basic_array<string_t>::reverse_iterator basic_array<string_t>::r
}
template <typename string_t>
inline typename basic_array<string_t>::const_reverse_iterator
basic_array<string_t>::rbegin() const noexcept
inline typename basic_array<string_t>::const_reverse_iterator basic_array<string_t>::rbegin() const noexcept
{
return _array_data.rbegin();
}
template <typename string_t>
inline typename basic_array<string_t>::const_reverse_iterator
basic_array<string_t>::rend() const noexcept
inline typename basic_array<string_t>::const_reverse_iterator basic_array<string_t>::rend() const noexcept
{
return _array_data.rend();
}
template <typename string_t>
inline typename basic_array<string_t>::const_reverse_iterator
basic_array<string_t>::crbegin() const noexcept
inline typename basic_array<string_t>::const_reverse_iterator basic_array<string_t>::crbegin() const noexcept
{
return _array_data.crbegin();
}
template <typename string_t>
inline typename basic_array<string_t>::const_reverse_iterator
basic_array<string_t>::crend() const noexcept
inline typename basic_array<string_t>::const_reverse_iterator basic_array<string_t>::crend() const noexcept
{
return _array_data.crend();
}
@@ -613,8 +470,7 @@ inline const basic_value<string_t>& basic_array<string_t>::operator[](size_t pos
}
template <typename string_t>
inline basic_array<string_t>
basic_array<string_t>::operator+(const basic_array<string_t>& rhs) const&
inline basic_array<string_t> basic_array<string_t>::operator+(const basic_array<string_t>& rhs) const&
{
basic_array<string_t> temp = *this;
temp._array_data.insert(_array_data.end(), rhs.begin(), rhs.end());
@@ -625,10 +481,8 @@ template <typename string_t>
inline basic_array<string_t> basic_array<string_t>::operator+(basic_array<string_t>&& rhs) const&
{
basic_array<string_t> temp = *this;
temp._array_data.insert(
_array_data.end(),
std::make_move_iterator(rhs.begin()),
std::make_move_iterator(rhs.end()));
temp._array_data.insert(_array_data.end(), std::make_move_iterator(rhs.begin()),
std::make_move_iterator(rhs.end()));
return temp;
}
@@ -642,10 +496,7 @@ inline basic_array<string_t> basic_array<string_t>::operator+(const basic_array<
template <typename string_t>
inline basic_array<string_t> basic_array<string_t>::operator+(basic_array<string_t>&& rhs) &&
{
_array_data.insert(
_array_data.end(),
std::make_move_iterator(rhs.begin()),
std::make_move_iterator(rhs.end()));
_array_data.insert(_array_data.end(), std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end()));
return std::move(*this);
}
@@ -659,10 +510,7 @@ inline basic_array<string_t>& basic_array<string_t>::operator+=(const basic_arra
template <typename string_t>
inline basic_array<string_t>& basic_array<string_t>::operator+=(basic_array<string_t>&& rhs)
{
_array_data.insert(
_array_data.end(),
std::make_move_iterator(rhs.begin()),
std::make_move_iterator(rhs.end()));
_array_data.insert(_array_data.end(), std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end()));
return *this;
}
@@ -672,14 +520,11 @@ inline bool basic_array<string_t>::operator==(const basic_array<string_t>& rhs)
return _array_data == rhs._array_data;
}
template <
typename ostream_t,
typename string_t,
typename std_ostream_t = std::basic_ostream<
typename string_t::value_type,
std::char_traits<typename string_t::value_type>>,
typename enable_t = std::enable_if_t<
std::is_same_v<std_ostream_t, ostream_t> || std::is_base_of_v<std_ostream_t, ostream_t>>>
template <typename ostream_t, typename string_t,
typename std_ostream_t =
std::basic_ostream<typename string_t::value_type, std::char_traits<typename string_t::value_type>>,
typename enable_t =
std::enable_if_t<std::is_same_v<std_ostream_t, ostream_t> || std::is_base_of_v<std_ostream_t, ostream_t>>>
ostream_t& operator<<(ostream_t& out, const basic_array<string_t>& arr)
{
out << arr.format();

View File

@@ -1,5 +1,3 @@
// IWYU pragma: private, include <meojson/json.hpp>
#pragma once
#include <exception>
@@ -11,11 +9,7 @@ class exception : public std::exception
{
public:
exception() = default;
exception(const std::string& msg)
: _what(msg)
{
}
exception(const std::string& msg) : _what(msg) {}
exception(const exception&) = default;
exception& operator=(const exception&) = default;
@@ -24,10 +18,7 @@ public:
virtual ~exception() noexcept override = default;
virtual const char* what() const noexcept override
{
return _what.empty() ? "Unknown exception" : _what.c_str();
}
virtual const char* what() const noexcept override { return _what.empty() ? "Unknown exception" : _what.c_str(); }
protected:
std::string _what;

View File

@@ -1,5 +1,3 @@
// IWYU pragma: private, include <meojson/json.hpp>
#pragma once
#include <initializer_list>
@@ -38,101 +36,36 @@ public:
// explicit basic_object(const basic_value<string_t>& val);
// explicit basic_object(basic_value<string_t>&& val);
template <
typename jsonization_t,
std::enable_if_t<
_utils::has_to_json_in_templ_spec<jsonization_t, string_t>::value
&& !_utils::has_to_json_object_in_templ_spec<jsonization_t, string_t>::value,
bool> = true>
basic_object(const jsonization_t& value)
: basic_object(ext::jsonization<string_t, jsonization_t>().to_json(value))
{
}
template <
typename jsonization_t,
std::enable_if_t<
_utils::has_to_json_object_in_templ_spec<jsonization_t, string_t>::value,
bool> = true>
basic_object(const jsonization_t& value)
: basic_object(ext::jsonization<string_t, jsonization_t>().to_json_object(value))
{
}
template <
typename jsonization_t,
std::enable_if_t<
std::is_rvalue_reference_v<jsonization_t&&>
&& _utils::has_move_to_json_in_templ_spec<jsonization_t, string_t>::value
&& !_utils::has_move_to_json_object_in_templ_spec<jsonization_t, string_t>::value,
bool> = true>
basic_object(jsonization_t&& value)
: basic_object(ext::jsonization<string_t, jsonization_t>().move_to_json(std::move(value)))
{
}
//template <
// typename jsonization_t,
// std::enable_if_t<
// std::is_rvalue_reference_v<jsonization_t&&>
// && _utils::has_move_to_json_object_in_templ_spec<jsonization_t, string_t>::value,
// bool> = true>
//basic_object(jsonization_t&& value)
// : basic_object(
// ext::jsonization<string_t, jsonization_t>().move_to_json_object(std::move(value)))
//{
//}
template <typename map_t, std::enable_if_t<_utils::is_map<map_t> &&
std::is_constructible_v<value_type, _utils::range_value_t<map_t>>,
bool> = true>
basic_object(map_t map) : _object_data(std::make_move_iterator(map.begin()), std::make_move_iterator(map.end()))
{}
template <typename jsonization_t,
std::enable_if_t<_utils::has_to_json_in_member<jsonization_t>::value, bool> = true>
basic_object(const jsonization_t& value) : basic_object(value.to_json())
{}
template <typename jsonization_t,
std::enable_if_t<_utils::has_to_json_in_templ_spec<jsonization_t>::value, bool> = true>
basic_object(const jsonization_t& value) : basic_object(ext::jsonization<jsonization_t>().to_json(value))
{}
~basic_object() = default;
bool empty() const noexcept { return _object_data.empty(); }
size_t size() const noexcept { return _object_data.size(); }
bool contains(const string_t& key) const;
bool exists(const string_t& key) const { return contains(key); }
const basic_value<string_t>& at(const string_t& key) const;
string_t dumps(std::optional<size_t> indent = std::nullopt) const
{
return indent ? format(*indent) : to_string();
}
string_t dumps(std::optional<size_t> indent = std::nullopt) const { return indent ? format(*indent) : to_string(); }
string_t to_string() const;
string_t format(size_t indent = 4) const { return format(indent, 0); }
template <typename value_t>
bool all() const;
template <typename value_t, template <typename...> typename map_t = std::map>
map_t<string_t, value_t> as_map() const;
template <
typename value_t,
std::enable_if_t<
_utils::has_from_json_object_in_templ_spec<value_t, string_t>::value,
bool> = true>
value_t as() const&
{
value_t res;
ext::jsonization<string_t, value_t>().from_json_object(*this, res);
return res;
}
template <
typename value_t,
std::enable_if_t<
_utils::has_move_from_json_object_in_templ_spec<value_t, string_t>::value,
bool> = true>
value_t as() &&
{
value_t res;
ext::jsonization<string_t, value_t>().move_from_json_object(std::move(*this), res);
return res;
}
// Usage: get(key_1, key_2, ..., default_value);
template <typename... key_then_default_value_t>
auto get(key_then_default_value_t&&... keys_then_default_value) const;
@@ -169,83 +102,37 @@ public:
basic_object<string_t>& operator=(const basic_object<string_t>&) = default;
basic_object<string_t>& operator=(basic_object<string_t>&&) = default;
template <
typename value_t,
std::enable_if_t<std::is_convertible_v<value_t, basic_object<string_t>>, bool> = true>
template <typename value_t, std::enable_if_t<std::is_convertible_v<value_t, basic_object<string_t>>, bool> = true>
basic_object<string_t>& operator=(value_t rhs)
{
return *this = basic_object<string_t>(std::move(rhs));
}
bool operator==(const basic_object<string_t>& rhs) const;
bool operator!=(const basic_object<string_t>& rhs) const { return !(*this == rhs); }
template <
typename value_t,
template <typename...> typename map_t = std::map,
std::enable_if_t<_utils::is_map<map_t<string_t, value_t>>, bool> = true>
template <typename value_t, template <typename...> typename map_t = std::map,
std::enable_if_t<_utils::is_map<map_t<string_t, value_t>>, bool> = true>
explicit operator map_t<string_t, value_t>() const
{
return as_map<value_t, map_t>();
}
template <
typename jsonization_t,
std::enable_if_t<
_utils::has_from_json_in_templ_spec<jsonization_t, string_t>::value
&& !_utils::has_from_json_object_in_templ_spec<jsonization_t, string_t>::value,
bool> = true>
explicit operator jsonization_t() const&
template <typename jsonization_t,
std::enable_if_t<_utils::has_from_json_in_member<jsonization_t, string_t>::value, bool> = true>
explicit operator jsonization_t() const
{
jsonization_t dst {};
if (!ext::jsonization<string_t, jsonization_t>().from_json(*this, dst)) {
if (!dst.from_json(*this)) {
throw exception("Wrong JSON");
}
return dst;
}
template <
typename jsonization_t,
std::enable_if_t<
_utils::has_from_json_object_in_templ_spec<jsonization_t, string_t>::value,
bool> = true>
explicit operator jsonization_t() const&
template <typename jsonization_t,
std::enable_if_t<_utils::has_from_json_in_templ_spec<jsonization_t, string_t>::value, bool> = true>
explicit operator jsonization_t() const
{
jsonization_t dst {};
if (!ext::jsonization<string_t, jsonization_t>().from_json_object(*this, dst)) {
throw exception("Wrong JSON");
}
return dst;
}
template <
typename jsonization_t,
std::enable_if_t<
_utils::has_move_from_json_in_templ_spec<jsonization_t, string_t>::value
&& !_utils::has_move_from_json_object_in_templ_spec<jsonization_t, string_t>::value,
bool> = true>
explicit operator jsonization_t() &&
{
jsonization_t dst {};
if (!ext::jsonization<string_t, jsonization_t>().from_json(std::move(*this), dst)) {
throw exception("Wrong JSON");
}
return dst;
}
template <
typename jsonization_t,
std::enable_if_t<
_utils::has_move_from_json_object_in_templ_spec<jsonization_t, string_t>::value,
bool> = true>
explicit operator jsonization_t() &&
{
jsonization_t dst {};
if (!ext::jsonization<string_t, jsonization_t>().move_from_json_object(
std::move(*this),
dst)) {
if (!ext::jsonization<jsonization_t>().from_json(*this, dst)) {
throw exception("Wrong JSON");
}
return dst;
@@ -253,9 +140,8 @@ public:
private:
template <typename... key_then_default_value_t, size_t... keys_indexes_t>
auto
get(std::tuple<key_then_default_value_t...> keys_then_default_value,
std::index_sequence<keys_indexes_t...>) const;
auto get(std::tuple<key_then_default_value_t...> keys_then_default_value,
std::index_sequence<keys_indexes_t...>) const;
template <typename value_t, typename... rest_keys_t>
auto get_helper(const value_t& default_value, const string_t& key, rest_keys_t&&... rest) const;
template <typename value_t>
@@ -269,11 +155,8 @@ private:
template <typename string_t>
inline basic_object<string_t>::basic_object(std::initializer_list<value_type> init_list)
: _object_data(
std::make_move_iterator(init_list.begin()),
std::make_move_iterator(init_list.end()))
{
}
: _object_data(std::make_move_iterator(init_list.begin()), std::make_move_iterator(init_list.end()))
{}
// template <typename string_t>
// inline basic_object<string_t>::basic_object(const basic_value<string_t>& val) :
@@ -319,10 +202,9 @@ template <typename string_t>
template <typename... args_t>
inline decltype(auto) basic_object<string_t>::emplace(args_t&&... args)
{
static_assert(
std::is_constructible_v<value_type, args_t...>,
"Parameter can't be used to construct a raw_object::value_type");
return _object_data.insert_or_assign(std::forward<args_t>(args)...);
static_assert(std::is_constructible_v<value_type, args_t...>,
"Parameter can't be used to construct a raw_object::value_type");
return _object_data.emplace(std::forward<args_t>(args)...);
}
template <typename string_t>
@@ -338,8 +220,7 @@ inline string_t basic_object<string_t>::to_string() const
string_t str { '{' };
for (auto iter = _object_data.cbegin(); iter != _object_data.cend();) {
const auto& [key, val] = *iter;
str +=
char_t('"') + _utils::unescape_string(key) + string_t { '\"', ':' } + val.to_string();
str += char_t('"') + _utils::unescape_string(key) + string_t { '\"', ':' } + val.to_string();
if (++iter != _object_data.cend()) {
str += ',';
}
@@ -357,8 +238,8 @@ inline string_t basic_object<string_t>::format(size_t indent, size_t indent_time
string_t str { '{', '\n' };
for (auto iter = _object_data.cbegin(); iter != _object_data.cend();) {
const auto& [key, val] = *iter;
str += body_indent + char_t('"') + _utils::unescape_string(key)
+ string_t { '\"', ':', ' ' } + val.format(indent, indent_times + 1);
str += body_indent + char_t('"') + _utils::unescape_string(key) + string_t { '\"', ':', ' ' } +
val.format(indent, indent_times + 1);
if (++iter != _object_data.cend()) {
str += ',';
}
@@ -384,40 +265,39 @@ template <typename string_t>
template <typename value_t, template <typename...> typename map_t>
inline map_t<string_t, value_t> basic_object<string_t>::as_map() const
{
return as<map_t<string_t, value_t>>();
map_t<string_t, value_t> result;
for (const auto& [key, val] : _object_data) {
result.emplace(key, val.template as<value_t>());
}
return result;
}
template <typename string_t>
template <typename... key_then_default_value_t>
inline auto basic_object<string_t>::get(key_then_default_value_t&&... keys_then_default_value) const
{
return get(
std::forward_as_tuple(keys_then_default_value...),
std::make_index_sequence<sizeof...(keys_then_default_value) - 1> {});
return get(std::forward_as_tuple(keys_then_default_value...),
std::make_index_sequence<sizeof...(keys_then_default_value) - 1> {});
}
template <typename string_t>
template <typename... key_then_default_value_t, size_t... keys_indexes_t>
inline auto basic_object<string_t>::get(
std::tuple<key_then_default_value_t...> keys_then_default_value,
std::index_sequence<keys_indexes_t...>) const
inline auto basic_object<string_t>::get(std::tuple<key_then_default_value_t...> keys_then_default_value,
std::index_sequence<keys_indexes_t...>) const
{
constexpr unsigned long default_value_index = sizeof...(key_then_default_value_t) - 1;
return get_helper(
std::get<default_value_index>(keys_then_default_value),
std::get<keys_indexes_t>(keys_then_default_value)...);
return get_helper(std::get<default_value_index>(keys_then_default_value),
std::get<keys_indexes_t>(keys_then_default_value)...);
}
template <typename string_t>
template <typename value_t, typename... rest_keys_t>
inline auto basic_object<string_t>::get_helper(
const value_t& default_value,
const string_t& key,
rest_keys_t&&... rest) const
inline auto basic_object<string_t>::get_helper(const value_t& default_value, const string_t& key,
rest_keys_t&&... rest) const
{
constexpr bool is_json = std::is_same_v<basic_value<string_t>, value_t>
|| std::is_same_v<basic_array<string_t>, value_t>
|| std::is_same_v<basic_object<string_t>, value_t>;
constexpr bool is_json = std::is_same_v<basic_value<string_t>, value_t> ||
std::is_same_v<basic_array<string_t>, value_t> ||
std::is_same_v<basic_object<string_t>, value_t>;
constexpr bool is_string = std::is_constructible_v<string_t, value_t> && !is_json;
if (!contains(key)) {
@@ -434,12 +314,11 @@ inline auto basic_object<string_t>::get_helper(
template <typename string_t>
template <typename value_t>
inline auto
basic_object<string_t>::get_helper(const value_t& default_value, const string_t& key) const
inline auto basic_object<string_t>::get_helper(const value_t& default_value, const string_t& key) const
{
constexpr bool is_json = std::is_same_v<basic_value<string_t>, value_t>
|| std::is_same_v<basic_array<string_t>, value_t>
|| std::is_same_v<basic_object<string_t>, value_t>;
constexpr bool is_json = std::is_same_v<basic_value<string_t>, value_t> ||
std::is_same_v<basic_array<string_t>, value_t> ||
std::is_same_v<basic_object<string_t>, value_t>;
constexpr bool is_string = std::is_constructible_v<string_t, value_t> && !is_json;
if (!contains(key)) {
@@ -479,8 +358,7 @@ inline std::optional<value_t> basic_object<string_t>::find(const string_t& key)
return std::nullopt;
}
const auto& val = iter->second;
return val.template is<value_t>() ? std::optional<value_t>(val.template as<value_t>())
: std::nullopt;
return val.template is<value_t>() ? std::optional<value_t>(val.template as<value_t>()) : std::nullopt;
}
template <typename string_t>
@@ -496,8 +374,7 @@ inline typename basic_object<string_t>::iterator basic_object<string_t>::end() n
}
template <typename string_t>
inline typename basic_object<string_t>::const_iterator
basic_object<string_t>::begin() const noexcept
inline typename basic_object<string_t>::const_iterator basic_object<string_t>::begin() const noexcept
{
return _object_data.begin();
}
@@ -509,8 +386,7 @@ inline typename basic_object<string_t>::const_iterator basic_object<string_t>::e
}
template <typename string_t>
inline typename basic_object<string_t>::const_iterator
basic_object<string_t>::cbegin() const noexcept
inline typename basic_object<string_t>::const_iterator basic_object<string_t>::cbegin() const noexcept
{
return _object_data.cbegin();
}
@@ -534,8 +410,7 @@ inline basic_value<string_t>& basic_object<string_t>::operator[](string_t&& key)
}
template <typename string_t>
inline basic_object<string_t>
basic_object<string_t>::operator|(const basic_object<string_t>& rhs) const&
inline basic_object<string_t> basic_object<string_t>::operator|(const basic_object<string_t>& rhs) const&
{
basic_object<string_t> temp = *this;
temp._object_data.insert(rhs.begin(), rhs.end());
@@ -547,15 +422,12 @@ inline basic_object<string_t> basic_object<string_t>::operator|(basic_object<str
{
basic_object<string_t> temp = *this;
// temp._object_data.merge(std::move(rhs._object_data));
temp._object_data.insert(
std::make_move_iterator(rhs.begin()),
std::make_move_iterator(rhs.end()));
temp._object_data.insert(std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end()));
return temp;
}
template <typename string_t>
inline basic_object<string_t>
basic_object<string_t>::operator|(const basic_object<string_t>& rhs) &&
inline basic_object<string_t> basic_object<string_t>::operator|(const basic_object<string_t>& rhs) &&
{
_object_data.insert(rhs.begin(), rhs.end());
return std::move(*this);
@@ -589,14 +461,11 @@ inline bool basic_object<string_t>::operator==(const basic_object<string_t>& rhs
return _object_data == rhs._object_data;
}
template <
typename ostream_t,
typename string_t,
typename std_ostream_t = std::basic_ostream<
typename string_t::value_type,
std::char_traits<typename string_t::value_type>>,
typename enable_t = std::enable_if_t<
std::is_same_v<std_ostream_t, ostream_t> || std::is_base_of_v<std_ostream_t, ostream_t>>>
template <typename ostream_t, typename string_t,
typename std_ostream_t =
std::basic_ostream<typename string_t::value_type, std::char_traits<typename string_t::value_type>>,
typename enable_t =
std::enable_if_t<std::is_same_v<std_ostream_t, ostream_t> || std::is_base_of_v<std_ostream_t, ostream_t>>>
ostream_t& operator<<(ostream_t& out, const basic_object<string_t>& obj)
{
out << obj.format();

View File

@@ -1,5 +1,3 @@
// IWYU pragma: private, include <meojson/json.hpp>
#pragma once
#include <type_traits>
@@ -11,101 +9,96 @@ namespace json
{
namespace _serialization_helper
{
template <typename in_t, typename serializer_t>
class is_serializable
{
template <typename U>
static auto test(int)
-> decltype(std::declval<serializer_t>()(std::declval<U>()), std::true_type());
template <typename in_t, typename serializer_t>
class is_serializable
{
template <typename U>
static auto test(int) -> decltype(std::declval<serializer_t>()(std::declval<U>()), std::true_type());
template <typename U>
static std::false_type test(...);
template <typename U>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<in_t>(0))::value;
};
public:
static constexpr bool value = decltype(test<in_t>(0))::value;
};
struct empty_serializer
{
// sample:
// json::value operator()(const type_1&) const { return ...; }
// json::value operator()(const type_2&) const { return ...; }
// json::value operator()(const type_3&) const { return ...; }
};
struct empty_serializer
{
// sample:
// json::value operator()(const type_1&) const { return ...; }
// json::value operator()(const type_2&) const { return ...; }
// json::value operator()(const type_3&) const { return ...; }
};
template <typename T>
void unable_to_serialize()
{
static_assert(
!sizeof(T),
"Unable to serialize T. "
template <typename T>
void unable_to_serialize()
{
static_assert(!sizeof(T), "Unable to serialize T. "
#ifdef _MSC_VER
"See T below: " __FUNCSIG__
"See T below: " __FUNCSIG__
#else
// "See T below: " __PRETTY_FUNCTION__
// "See T below: " __PRETTY_FUNCTION__
#endif
);
}
);
}
}
namespace _serialization_helper
{
template <typename out_t, typename deserializer_t, typename string_t = default_string_t>
class is_deserializable
{
template <typename U>
static auto test(int)
-> decltype(std::declval<deserializer_t>()(std::declval<basic_value<string_t>>(), std::declval<U&>()), std::true_type());
template <typename out_t, typename deserializer_t, typename string_t = default_string_t>
class is_deserializable
{
template <typename U>
static auto test(int)
-> decltype(std::declval<deserializer_t>()(std::declval<basic_value<string_t>>(), std::declval<U&>()),
std::true_type());
template <typename U>
static std::false_type test(...);
template <typename U>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<out_t>(0))::value;
};
public:
static constexpr bool value = decltype(test<out_t>(0))::value;
};
struct empty_deserializer
{
// sample:
// bool operator()(const json::value&, type_1&) const { return ...; }
// bool operator()(const json::value&, type_2&) const { return ...; }
// bool operator()(const json::value&, type_3&) const { return ...; }
};
struct empty_deserializer
{
// sample:
// bool operator()(const json::value&, type_1&) const { return ...; }
// bool operator()(const json::value&, type_2&) const { return ...; }
// bool operator()(const json::value&, type_3&) const { return ...; }
};
template <typename T>
void unable_to_deserialize()
{
static_assert(
!sizeof(T),
"Unable to deserialize T. "
template <typename T>
void unable_to_deserialize()
{
static_assert(!sizeof(T), "Unable to deserialize T. "
#ifdef _MSC_VER
"See T below: " __FUNCSIG__
"See T below: " __FUNCSIG__
#else
// "See T below: " __PRETTY_FUNCTION__
// "See T below: " __PRETTY_FUNCTION__
#endif
);
}
);
}
}
template <
typename in_t,
typename serializer_t = _serialization_helper::empty_serializer,
typename string_t = default_string_t>
template <typename in_t, typename serializer_t = _serialization_helper::empty_serializer,
typename string_t = default_string_t>
basic_value<string_t> serialize(in_t&& in, const serializer_t& serializer = {})
{
if constexpr (_serialization_helper::is_serializable<in_t, serializer_t>::value) {
return serializer(std::forward<in_t>(in));
}
else if constexpr (
_utils::is_collection<std::decay_t<in_t>> || _utils::is_fixed_array<std::decay_t<in_t>>) {
else if constexpr (std::is_constructible_v<basic_value<string_t>, in_t>) {
return basic_value<string_t>(std::forward<in_t>(in));
}
else if constexpr (_utils::is_collection<std::decay_t<in_t>>) {
basic_array<string_t> arr;
for (auto&& elem : in) {
using elem_t = decltype(elem);
auto j_elem =
serialize<elem_t, serializer_t, string_t>(std::forward<elem_t>(elem), serializer);
auto j_elem = serialize<elem_t, serializer_t, string_t>(std::forward<elem_t>(elem), serializer);
arr.emplace_back(std::move(j_elem));
}
return arr;
@@ -116,32 +109,27 @@ basic_value<string_t> serialize(in_t&& in, const serializer_t& serializer = {})
using key_t = decltype(key);
using elem_t = decltype(elem);
auto j_elem =
serialize<elem_t, serializer_t, string_t>(std::forward<elem_t>(elem), serializer);
auto j_elem = serialize<elem_t, serializer_t, string_t>(std::forward<elem_t>(elem), serializer);
obj.emplace(std::forward<key_t>(key), std::move(j_elem));
}
return obj;
}
else if constexpr (std::is_constructible_v<basic_value<string_t>, in_t>) {
return basic_value<string_t>(std::forward<in_t>(in));
}
else {
_serialization_helper::unable_to_serialize<in_t>();
}
}
template <
typename out_t,
typename deserializer_t = _serialization_helper::empty_deserializer,
typename string_t = default_string_t>
bool deserialize(
const basic_value<string_t>& in,
out_t& out,
const deserializer_t& deserializer = {})
template <typename out_t, typename deserializer_t = _serialization_helper::empty_deserializer,
typename string_t = default_string_t>
bool deserialize(const basic_value<string_t>& in, out_t& out, const deserializer_t& deserializer = {})
{
if constexpr (_serialization_helper::is_deserializable<out_t, deserializer_t>::value) {
return deserializer(in, out);
}
else if constexpr (std::is_constructible_v<out_t, basic_value<string_t>>) {
out = out_t(in);
return true;
}
else if constexpr (_utils::is_collection<std::decay_t<out_t>>) {
if (!in.is_array()) {
return false;
@@ -161,45 +149,20 @@ bool deserialize(
}
return true;
}
else if constexpr (_utils::is_fixed_array<std::decay_t<out_t>>) {
if (!in.is_array()) {
return false;
}
auto&& in_as_arr = in.as_array();
constexpr size_t out_size = _utils::fixed_array_size<out_t>;
if (in_as_arr.size() != out_size) {
return false;
}
for (size_t i = 0; i < out_size; ++i) {
auto&& j_elem = in_as_arr.at(i);
using elem_t = typename out_t::value_type;
elem_t elem {};
if (!deserialize<elem_t, deserializer_t, string_t>(j_elem, elem, deserializer)) {
return false;
}
out.at(i) = std::move(elem);
}
return true;
}
else if constexpr (_utils::is_map<std::decay_t<out_t>>) {
if (!in.is_object()) {
return false;
}
for (auto&& [key, j_elem] : in.as_object()) {
using elem_t = typename out_t::mapped_type;
using elem_t = typename out_t::value_type;
elem_t elem {};
if (!deserialize<elem_t, deserializer_t, string_t>(j_elem, elem, deserializer)) {
return false;
}
out.emplace(std::forward<decltype(key)>(key), std::move(elem));
out.emplace(std::move(elem));
}
return true;
}
else if constexpr (std::is_constructible_v<out_t, basic_value<string_t>>) {
out = out_t(in);
return true;
}
else {
_serialization_helper::unable_to_deserialize<out_t>();
}

View File

@@ -1,7 +1,5 @@
// IWYU pragma: private, include <meojson/json.hpp>
#pragma once
#include "array.hpp"
#include "object.hpp"
#include "value.hpp"
#include "value.hpp"

View File

@@ -1,14 +1,7 @@
// IWYU pragma: private, include <meojson/json.hpp>
#pragma once
#include <iomanip>
#include <limits>
#include <sstream>
#include <string>
#include <type_traits>
#include <utility>
#include <variant>
namespace json
{
@@ -32,7 +25,7 @@ using wobject = basic_object<std::wstring>;
namespace json::ext
{
template <typename string_t, typename T, typename = void>
template <typename T>
class jsonization
{
public:
@@ -68,52 +61,18 @@ constexpr bool is_container<T, std::void_t<typename T::value_type, range_value_t
template <typename T, typename = void>
constexpr bool is_map = false;
template <typename T>
constexpr bool is_map<T, std::void_t<typename T::key_type, typename T::mapped_type>> =
is_container<T>;
template <typename T, typename = void>
constexpr bool is_fixed_array = false;
template <template <typename, size_t> typename arr_t, typename value_t, size_t size>
constexpr bool is_fixed_array<arr_t<value_t, size>> = true;
template <typename T, typename = std::enable_if_t<is_fixed_array<T>>>
constexpr size_t fixed_array_size = 0;
template <template <typename, size_t> typename arr_t, typename value_t, size_t size>
constexpr size_t fixed_array_size<arr_t<value_t, size>> = size;
constexpr bool is_map<T, std::void_t<typename T::key_type, typename T::mapped_type>> = is_container<T>;
template <typename T, typename = void>
constexpr bool is_collection = false;
template <typename T>
constexpr bool is_collection<T> = is_container<T> && !is_map<T> && !is_fixed_array<T>;
constexpr bool is_collection<T> = is_container<T> && !is_map<T>;
template <typename T>
constexpr bool is_variant = false;
template <typename... args_t>
constexpr bool is_variant<std::variant<args_t...>> = true;
template <typename T>
constexpr bool is_tuple = false;
template <typename... args_t>
constexpr bool is_tuple<std::tuple<args_t...>> = true;
template <typename T>
constexpr bool is_pair = false;
template <typename... args_t>
constexpr bool is_pair<std::pair<args_t...>> = true;
template <typename T, typename = void>
constexpr bool is_tuple_like = false;
template <template <typename...> typename tuple_t, typename... args_t>
constexpr bool is_tuple_like<
tuple_t<args_t...>,
std::void_t<decltype(std::tuple_size<tuple_t<args_t...>>::value)>> =
std::tuple_size<tuple_t<args_t...>>::value == sizeof...(args_t);
template <typename T>
class has_emplace_back
class has_to_json_in_member
{
template <typename U>
static auto test(int) -> decltype(std::declval<U>().emplace_back(), std::true_type());
static auto test(int) -> decltype(std::declval<U>().to_json(), std::true_type());
template <typename U>
static std::false_type test(...);
@@ -123,10 +82,10 @@ public:
};
template <typename T>
class has_to_json_in_member
class has_to_json_in_templ_spec
{
template <typename U>
static auto test(int) -> decltype(std::declval<U>().to_json(), std::true_type());
static auto test(int) -> decltype(std::declval<ext::jsonization<U>>().to_json(std::declval<U>()), std::true_type());
template <typename U>
static std::false_type test(...);
@@ -149,6 +108,21 @@ public:
static constexpr bool value = decltype(test<T>(0))::value;
};
template <typename T, typename string_t>
class has_check_json_in_templ_spec
{
template <typename U>
static auto test(int)
-> decltype(std::declval<ext::jsonization<U>>().check_json(std::declval<json::basic_value<string_t>>()),
std::true_type());
template <typename U>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(0))::value;
};
template <typename T, typename string_t>
class has_from_json_in_member
{
@@ -163,208 +137,14 @@ public:
static constexpr bool value = decltype(test<T>(0))::value;
};
template <typename T, typename string_t>
class has_to_json_in_templ_spec
{
template <typename U>
static auto test(int)
-> decltype(std::declval<ext::jsonization<string_t, U>>().to_json(std::declval<U>()), std::true_type());
template <typename U>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(0))::value;
};
template <typename T, typename string_t>
class has_check_json_in_templ_spec
{
template <typename U>
static auto test(int)
-> decltype(std::declval<ext::jsonization<string_t, U>>().check_json(std::declval<json::basic_value<string_t>>()), std::true_type());
template <typename U>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(0))::value;
};
template <typename T, typename string_t>
class has_from_json_in_templ_spec
{
template <typename U>
static auto test(int)
-> decltype(std::declval<ext::jsonization<string_t, U>>().from_json(std::declval<json::basic_value<string_t>>(), std::declval<U&>()), std::true_type());
template <typename U>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(0))::value;
};
template <typename T, typename string_t>
class has_move_to_json_in_templ_spec
{
template <typename U>
static auto test(int)
-> decltype(std::declval<ext::jsonization<string_t, U>>().move_to_json(std::declval<U>()), std::true_type());
template <typename U>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(0))::value;
};
template <typename T, typename string_t>
class has_move_from_json_in_templ_spec
{
template <typename U>
static auto test(int)
-> decltype(std::declval<ext::jsonization<string_t, U>>().move_from_json(std::declval<json::basic_value<string_t>>(), std::declval<U&>()), std::true_type());
template <typename U>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(0))::value;
};
template <typename T, typename string_t>
class has_to_json_array_in_templ_spec
{
template <typename U>
static auto test(int)
-> decltype(std::declval<ext::jsonization<string_t, U>>().to_json_array(std::declval<U>()), std::true_type());
template <typename U>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(0))::value;
};
template <typename T, typename string_t>
class has_check_json_array_in_templ_spec
{
template <typename U>
static auto test(int)
-> decltype(std::declval<ext::jsonization<string_t, U>>().check_json_array(std::declval<json::basic_array<string_t>>()), std::true_type());
template <typename U>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(0))::value;
};
template <typename T, typename string_t>
class has_from_json_array_in_templ_spec
{
template <typename U>
static auto test(int)
-> decltype(std::declval<ext::jsonization<string_t, U>>().from_json_array(std::declval<json::basic_array<string_t>>(), std::declval<U&>()), std::true_type());
template <typename U>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(0))::value;
};
template <typename T, typename string_t>
class has_move_to_json_array_in_templ_spec
{
template <typename U>
static auto test(int)
-> decltype(std::declval<ext::jsonization<string_t, U>>().move_to_json_array(std::declval<U>()), std::true_type());
template <typename U>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(0))::value;
};
template <typename T, typename string_t>
class has_move_from_json_array_in_templ_spec
{
template <typename U>
static auto test(int)
-> decltype(std::declval<ext::jsonization<string_t, U>>().move_from_json_array(std::declval<json::basic_array<string_t>>(), std::declval<U&>()), std::true_type());
template <typename U>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(0))::value;
};
template <typename T, typename string_t>
class has_to_json_object_in_templ_spec
{
template <typename U>
static auto test(int)
-> decltype(std::declval<ext::jsonization<string_t, U>>().to_json_object(std::declval<U>()), std::true_type());
template <typename U>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(0))::value;
};
template <typename T, typename string_t>
class has_check_json_object_in_templ_spec
{
template <typename U>
static auto test(int)
-> decltype(std::declval<ext::jsonization<string_t, U>>().check_json_object(std::declval<json::basic_object<string_t>>()), std::true_type());
template <typename U>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(0))::value;
};
template <typename T, typename string_t>
class has_from_json_object_in_templ_spec
{
template <typename U>
static auto test(int)
-> decltype(std::declval<ext::jsonization<string_t, U>>().from_json_object(std::declval<json::basic_object<string_t>>(), std::declval<U&>()), std::true_type());
template <typename U>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(0))::value;
};
template <typename T, typename string_t>
class has_move_to_json_object_in_templ_spec
{
template <typename U>
static auto test(int)
-> decltype(std::declval<ext::jsonization<string_t, U>>().move_to_json_object(std::declval<U>()), std::true_type());
template <typename U>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(0))::value;
};
template <typename T, typename string_t>
class has_move_from_json_object_in_templ_spec
{
template <typename U>
static auto test(int)
-> decltype(std::declval<ext::jsonization<string_t, U>>().move_from_json_object(std::declval<json::basic_object<string_t>>(), std::declval<U&>()), std::true_type());
-> decltype(std::declval<ext::jsonization<U>>().from_json(std::declval<json::basic_value<string_t>>(),
std::declval<U&>()),
std::true_type());
template <typename U>
static std::false_type test(...);
@@ -374,7 +154,7 @@ public:
};
template <typename string_t>
inline constexpr string_t unescape_string(const string_t& str)
static constexpr string_t unescape_string(const string_t& str)
{
using char_t = typename string_t::value_type;
@@ -422,41 +202,26 @@ inline constexpr string_t unescape_string(const string_t& str)
}
template <typename string_t>
inline constexpr string_t true_string()
static constexpr string_t true_string()
{
return { 't', 'r', 'u', 'e' };
}
template <typename string_t>
inline constexpr string_t false_string()
static constexpr string_t false_string()
{
return { 'f', 'a', 'l', 's', 'e' };
}
template <typename string_t>
inline constexpr string_t null_string()
static constexpr string_t null_string()
{
return { 'n', 'u', 'l', 'l' };
}
template <typename string_t, typename any_t>
inline string_t to_basic_string(any_t&& arg)
string_t to_basic_string(any_t&& arg)
{
#ifdef MEOJSON_KEEP_FLOATING_PRECISION
using real_type = std::remove_reference_t<any_t>;
if constexpr (std::is_floating_point_v<real_type>) {
if constexpr (std::is_same_v<string_t, std::string>) {
std::ostringstream oss;
oss << std::setprecision(std::numeric_limits<real_type>::max_digits10) << arg;
return oss.str();
}
else if constexpr (std::is_same_v<string_t, std::wstring>) {
std::wostringstream oss;
oss << std::setprecision(std::numeric_limits<real_type>::max_digits10) << arg;
return oss.str();
}
}
#endif
if constexpr (std::is_same_v<string_t, std::string>) {
return std::to_string(std::forward<any_t>(arg));
}
@@ -467,7 +232,4 @@ inline string_t to_basic_string(any_t&& arg)
static_assert(!sizeof(any_t), "Unsupported type");
}
}
} // namespace json::_utils
#include "../reflection/extensions.hpp"

View File

@@ -1,19 +1,13 @@
// IWYU pragma: private, include <meojson/json.hpp>
#pragma once
#include <cstddef>
#include <initializer_list>
#include <map>
#include <memory>
#include <optional>
#include <ostream>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility>
#include <variant>
#include <vector>
#include "exception.hpp"
#include "utils.hpp"
@@ -70,31 +64,31 @@ public:
template <typename... args_t>
basic_value(value_type type, args_t&&... args);
template <typename enum_t, std::enable_if_t<std::is_enum_v<enum_t>, bool> = true>
basic_value(enum_t e)
: basic_value(static_cast<std::underlying_type_t<enum_t>>(e))
{
}
template <typename collection_t,
std::enable_if_t<_utils::is_collection<collection_t> &&
std::is_constructible_v<typename basic_array<string_t>::value_type,
_utils::range_value_t<collection_t>>,
bool> = true>
basic_value(collection_t&& collection) : basic_value(basic_array<string_t>(std::forward<collection_t>(collection)))
{}
template <typename map_t, std::enable_if_t<_utils::is_map<map_t> &&
std::is_constructible_v<typename basic_object<string_t>::value_type,
_utils::range_value_t<map_t>>,
bool> = true>
basic_value(map_t&& map) : basic_value(basic_object<string_t>(std::forward<map_t>(map)))
{}
template <
typename jsonization_t,
std::enable_if_t<_utils::has_to_json_in_templ_spec<jsonization_t, string_t>::value, bool> =
true>
basic_value(const jsonization_t& value)
: basic_value(ext::jsonization<string_t, jsonization_t>().to_json(value))
{
}
template <typename jsonization_t,
std::enable_if_t<_utils::has_to_json_in_member<jsonization_t>::value, bool> = true>
basic_value(const jsonization_t& value) : basic_value(value.to_json())
{}
template <typename jsonization_t,
std::enable_if_t<_utils::has_to_json_in_templ_spec<jsonization_t>::value, bool> = true>
basic_value(const jsonization_t& value) : basic_value(ext::jsonization<jsonization_t>().to_json(value))
{}
template <
typename jsonization_t,
std::enable_if_t<
std::is_rvalue_reference_v<jsonization_t&&>
&& _utils::has_move_to_json_in_templ_spec<jsonization_t, string_t>::value,
bool> = true>
basic_value(jsonization_t&& value)
: basic_value(ext::jsonization<string_t, jsonization_t>().move_to_json(std::move(value)))
{
}
template <typename value_t, std::enable_if_t<!std::is_convertible_v<value_t, basic_value<string_t>>, bool> = true>
basic_value(value_t) = delete;
// I don't know if you want to convert char to string or number, so I delete these constructors.
basic_value(char) = delete;
@@ -105,21 +99,13 @@ public:
~basic_value();
bool valid() const noexcept { return _type != value_type::invalid; }
bool empty() const noexcept { return is_null(); }
bool is_null() const noexcept { return _type == value_type::null; }
bool is_number() const noexcept { return _type == value_type::number; }
bool is_boolean() const noexcept { return _type == value_type::boolean; }
bool is_string() const noexcept { return _type == value_type::string; }
bool is_array() const noexcept { return _type == value_type::array; }
bool is_object() const noexcept { return _type == value_type::object; }
template <typename value_t>
bool is() const noexcept;
@@ -128,13 +114,9 @@ public:
bool contains(const string_t& key) const;
bool contains(size_t pos) const;
bool exists(const string_t& key) const { return contains(key); }
bool exists(size_t pos) const { return contains(pos); }
value_type type() const noexcept { return _type; }
const basic_value<string_t>& at(size_t pos) const;
const basic_value<string_t>& at(const string_t& key) const;
@@ -166,19 +148,11 @@ public:
template <typename value_t, template <typename...> typename collection_t = std::vector>
collection_t<value_t> as_collection() const;
template <
typename value_t,
size_t Size,
template <typename, size_t> typename fixed_array_t = std::array>
fixed_array_t<value_t, Size> as_fixed_array() const;
template <typename value_t, template <typename...> typename map_t = std::map>
map_t<string_t, value_t> as_map() const;
template <typename value_t>
value_t as() const&;
template <typename value_t>
value_t as() &&;
value_t as() const;
basic_array<string_t>& as_array();
basic_object<string_t>& as_object();
@@ -188,29 +162,20 @@ public:
void clear() noexcept;
string_t dumps(std::optional<size_t> indent = std::nullopt) const
{
return indent ? format(*indent) : to_string();
}
string_t dumps(std::optional<size_t> indent = std::nullopt) const { return indent ? format(*indent) : to_string(); }
// return raw string
string_t to_string() const;
string_t format(size_t indent = 4) const { return format(indent, 0); }
basic_value<string_t>& operator=(const basic_value<string_t>& rhs);
basic_value<string_t>& operator=(basic_value<string_t>&&) noexcept;
// template <
// typename value_t,
// std::enable_if_t<std::is_convertible_v<value_t, basic_value<string_t>>, bool> = true>
// basic_value<string_t>& operator=(value_t rhs)
// {
// return *this = basic_value<string_t>(std::move(rhs));
// }
template <typename value_t, std::enable_if_t<std::is_convertible_v<value_t, basic_value<string_t>>, bool> = true>
basic_value<string_t>& operator=(value_t rhs)
{
return *this = basic_value<string_t>(std::move(rhs));
}
bool operator==(const basic_value<string_t>& rhs) const;
bool operator!=(const basic_value<string_t>& rhs) const { return !(*this == rhs); }
const basic_value<string_t>& operator[](size_t pos) const;
@@ -235,78 +200,48 @@ public:
basic_value<string_t>& operator+=(basic_array<string_t>&& rhs);
explicit operator bool() const { return as_boolean(); }
explicit operator int() const { return as_integer(); }
explicit operator unsigned() const { return as_unsigned(); }
explicit operator long() const { return as_long(); }
explicit operator unsigned long() const { return as_unsigned_long(); }
explicit operator long long() const { return as_long_long(); }
explicit operator unsigned long long() const { return as_unsigned_long_long(); }
explicit operator float() const { return as_float(); }
explicit operator double() const { return as_double(); }
explicit operator long double() const { return as_long_double(); }
explicit operator string_t() const { return as_string(); }
explicit operator basic_array<string_t>() const { return as_array(); }
explicit operator basic_object<string_t>() const { return as_object(); }
template <
typename value_t,
template <typename...> typename collection_t = std::vector,
std::enable_if_t<_utils::is_collection<collection_t<value_t>>, bool> = true>
template <typename value_t, template <typename...> typename collection_t = std::vector,
std::enable_if_t<_utils::is_collection<collection_t<value_t>>, bool> = true>
explicit operator collection_t<value_t>() const
{
return as_collection<value_t, collection_t>();
}
template <
typename value_t,
template <typename...> typename map_t = std::map,
std::enable_if_t<_utils::is_map<map_t<string_t, value_t>>, bool> = true>
template <typename value_t, template <typename...> typename map_t = std::map,
std::enable_if_t<_utils::is_map<map_t<string_t, value_t>>, bool> = true>
explicit operator map_t<string_t, value_t>() const
{
return as_map<value_t, map_t>();
}
template <typename enum_t, std::enable_if_t<std::is_enum_v<enum_t>, bool> = true>
explicit operator enum_t() const
{
return static_cast<enum_t>(static_cast<std::underlying_type_t<enum_t>>(*this));
}
template <
typename jsonization_t,
std::enable_if_t<
_utils::has_from_json_in_templ_spec<jsonization_t, string_t>::value,
bool> = true>
explicit operator jsonization_t() const&
template <typename jsonization_t,
std::enable_if_t<_utils::has_from_json_in_member<jsonization_t, string_t>::value, bool> = true>
explicit operator jsonization_t() const
{
jsonization_t dst {};
if (!ext::jsonization<string_t, jsonization_t>().from_json(*this, dst)) {
if (!dst.from_json(*this)) {
throw exception("Wrong JSON");
}
return dst;
}
template <
typename jsonization_t,
std::enable_if_t<
_utils::has_move_from_json_in_templ_spec<jsonization_t, string_t>::value,
bool> = true>
explicit operator jsonization_t() &&
template <typename jsonization_t,
std::enable_if_t<_utils::has_from_json_in_templ_spec<jsonization_t, string_t>::value, bool> = true>
explicit operator jsonization_t() const
{
jsonization_t dst {};
if (!ext::jsonization<string_t, jsonization_t>().move_from_json(std::move(*this), dst)) {
if (!ext::jsonization<jsonization_t>().from_json(*this, dst)) {
throw exception("Wrong JSON");
}
return dst;
@@ -321,9 +256,8 @@ private:
static var_t deep_copy(const var_t& src);
template <typename... key_then_default_value_t, size_t... keys_indexes_t>
auto
get(std::tuple<key_then_default_value_t...> keys_then_default_value,
std::index_sequence<keys_indexes_t...>) const;
auto get(std::tuple<key_then_default_value_t...> keys_then_default_value,
std::index_sequence<keys_indexes_t...>) const;
template <typename value_t, typename first_key_t, typename... rest_keys_t>
auto get_helper(const value_t& default_value, first_key_t&& first, rest_keys_t&&... rest) const;
@@ -342,125 +276,89 @@ inline basic_value<string_t>::basic_value() = default;
template <typename string_t>
inline basic_value<string_t>::basic_value(const basic_value<string_t>& rhs)
: _type(rhs._type)
, _raw_data(deep_copy(rhs._raw_data))
{
}
: _type(rhs._type), _raw_data(deep_copy(rhs._raw_data))
{}
template <typename string_t>
inline basic_value<string_t>::basic_value(basic_value<string_t>&& rhs) noexcept = default;
template <typename string_t>
inline basic_value<string_t>::basic_value(bool b)
: _type(value_type::boolean)
, _raw_data(string_t(b ? _utils::true_string<string_t>() : _utils::false_string<string_t>()))
{
}
: _type(value_type::boolean),
_raw_data(string_t(b ? _utils::true_string<string_t>() : _utils::false_string<string_t>()))
{}
template <typename string_t>
inline basic_value<string_t>::basic_value(int num)
: _type(value_type::number)
, _raw_data(_utils::to_basic_string<string_t>(num))
{
}
: _type(value_type::number), _raw_data(_utils::to_basic_string<string_t>(num))
{}
template <typename string_t>
inline basic_value<string_t>::basic_value(unsigned num)
: _type(value_type::number)
, _raw_data(_utils::to_basic_string<string_t>(num))
{
}
: _type(value_type::number), _raw_data(_utils::to_basic_string<string_t>(num))
{}
template <typename string_t>
inline basic_value<string_t>::basic_value(long num)
: _type(value_type::number)
, _raw_data(_utils::to_basic_string<string_t>(num))
{
}
: _type(value_type::number), _raw_data(_utils::to_basic_string<string_t>(num))
{}
template <typename string_t>
inline basic_value<string_t>::basic_value(unsigned long num)
: _type(value_type::number)
, _raw_data(_utils::to_basic_string<string_t>(num))
{
}
: _type(value_type::number), _raw_data(_utils::to_basic_string<string_t>(num))
{}
template <typename string_t>
inline basic_value<string_t>::basic_value(long long num)
: _type(value_type::number)
, _raw_data(_utils::to_basic_string<string_t>(num))
{
}
: _type(value_type::number), _raw_data(_utils::to_basic_string<string_t>(num))
{}
template <typename string_t>
inline basic_value<string_t>::basic_value(unsigned long long num)
: _type(value_type::number)
, _raw_data(_utils::to_basic_string<string_t>(num))
{
}
: _type(value_type::number), _raw_data(_utils::to_basic_string<string_t>(num))
{}
template <typename string_t>
inline basic_value<string_t>::basic_value(float num)
: _type(value_type::number)
, _raw_data(_utils::to_basic_string<string_t>(num))
{
}
: _type(value_type::number), _raw_data(_utils::to_basic_string<string_t>(num))
{}
template <typename string_t>
inline basic_value<string_t>::basic_value(double num)
: _type(value_type::number)
, _raw_data(_utils::to_basic_string<string_t>(num))
{
}
: _type(value_type::number), _raw_data(_utils::to_basic_string<string_t>(num))
{}
template <typename string_t>
inline basic_value<string_t>::basic_value(long double num)
: _type(value_type::number)
, _raw_data(_utils::to_basic_string<string_t>(num))
{
}
: _type(value_type::number), _raw_data(_utils::to_basic_string<string_t>(num))
{}
template <typename string_t>
inline basic_value<string_t>::basic_value(const char_t* str)
: _type(value_type::string)
, _raw_data(string_t(str))
{
}
inline basic_value<string_t>::basic_value(const char_t* str) : _type(value_type::string), _raw_data(string_t(str))
{}
template <typename string_t>
inline basic_value<string_t>::basic_value(string_t str)
: _type(value_type::string)
, _raw_data(std::move(str))
{
}
inline basic_value<string_t>::basic_value(string_t str) : _type(value_type::string), _raw_data(std::move(str))
{}
template <typename string_t>
inline basic_value<string_t>::basic_value(std::nullptr_t)
: _type(value_type::null)
{
}
inline basic_value<string_t>::basic_value(std::nullptr_t) : _type(value_type::null)
{}
template <typename string_t>
inline basic_value<string_t>::basic_value(basic_array<string_t> arr)
: _type(value_type::array)
, _raw_data(std::make_unique<basic_array<string_t>>(std::move(arr)))
{
}
: _type(value_type::array), _raw_data(std::make_unique<basic_array<string_t>>(std::move(arr)))
{}
template <typename string_t>
inline basic_value<string_t>::basic_value(basic_object<string_t> obj)
: _type(value_type::object)
, _raw_data(std::make_unique<basic_object<string_t>>(std::move(obj)))
{
}
: _type(value_type::object), _raw_data(std::make_unique<basic_object<string_t>>(std::move(obj)))
{}
template <typename string_t>
inline basic_value<string_t>::basic_value(
std::initializer_list<typename basic_object<string_t>::value_type> init_list)
: _type(value_type::object)
, _raw_data(std::make_unique<basic_object<string_t>>(init_list))
{
}
inline basic_value<string_t>::basic_value(std::initializer_list<typename basic_object<string_t>::value_type> init_list)
: _type(value_type::object), _raw_data(std::make_unique<basic_object<string_t>>(init_list))
{}
// for Pimpl
template <typename string_t>
@@ -473,13 +371,16 @@ inline bool basic_value<string_t>::is() const noexcept
if constexpr (std::is_same_v<basic_value<string_t>, value_t>) {
return true;
}
else if constexpr (_utils::has_check_json_in_member<value_t, string_t>::value) {
return value_t().check_json(*this);
}
else if constexpr (_utils::has_check_json_in_templ_spec<value_t, string_t>::value) {
return ext::jsonization<string_t, value_t>().check_json(*this);
return ext::jsonization<value_t>().check_json(*this);
}
else if constexpr (std::is_same_v<bool, value_t>) {
return is_boolean();
}
else if constexpr (std::is_arithmetic_v<value_t> || std::is_enum_v<value_t>) {
else if constexpr (std::is_arithmetic_v<value_t>) {
return is_number();
}
else if constexpr (std::is_constructible_v<string_t, value_t>) {
@@ -495,8 +396,8 @@ inline bool basic_value<string_t>::is() const noexcept
return is_object();
}
else if constexpr (_utils::is_map<value_t>) {
return is_object() && std::is_constructible_v<string_t, typename value_t::key_type>
&& all<typename value_t::mapped_type>();
return is_object() && std::is_constructible_v<string_t, typename value_t::key_type> &&
all<typename value_t::mapped_type>();
}
else {
static_assert(!sizeof(value_t), "Unsupported type");
@@ -543,42 +444,33 @@ template <typename string_t>
template <typename... key_then_default_value_t>
inline auto basic_value<string_t>::get(key_then_default_value_t&&... keys_then_default_value) const
{
return get(
std::forward_as_tuple(keys_then_default_value...),
std::make_index_sequence<sizeof...(keys_then_default_value) - 1> {});
return get(std::forward_as_tuple(keys_then_default_value...),
std::make_index_sequence<sizeof...(keys_then_default_value) - 1> {});
}
template <typename string_t>
template <typename... key_then_default_value_t, size_t... keys_indexes_t>
inline auto basic_value<string_t>::get(
std::tuple<key_then_default_value_t...> keys_then_default_value,
std::index_sequence<keys_indexes_t...>) const
inline auto basic_value<string_t>::get(std::tuple<key_then_default_value_t...> keys_then_default_value,
std::index_sequence<keys_indexes_t...>) const
{
constexpr unsigned long default_value_index = sizeof...(key_then_default_value_t) - 1;
return get_helper(
std::get<default_value_index>(keys_then_default_value),
std::get<keys_indexes_t>(keys_then_default_value)...);
return get_helper(std::get<default_value_index>(keys_then_default_value),
std::get<keys_indexes_t>(keys_then_default_value)...);
}
template <typename string_t>
template <typename value_t, typename first_key_t, typename... rest_keys_t>
inline auto basic_value<string_t>::get_helper(
const value_t& default_value,
first_key_t&& first,
rest_keys_t&&... rest) const
inline auto basic_value<string_t>::get_helper(const value_t& default_value, first_key_t&& first,
rest_keys_t&&... rest) const
{
if constexpr (std::is_constructible_v<string_t, first_key_t>) {
return is_object() ? as_object().get_helper(
default_value,
std::forward<first_key_t>(first),
std::forward<rest_keys_t>(rest)...)
return is_object() ? as_object().get_helper(default_value, std::forward<first_key_t>(first),
std::forward<rest_keys_t>(rest)...)
: default_value;
}
else if constexpr (std::is_integral_v<std::decay_t<first_key_t>>) {
return is_array() ? as_array().get_helper(
default_value,
std::forward<first_key_t>(first),
std::forward<rest_keys_t>(rest)...)
return is_array() ? as_array().get_helper(default_value, std::forward<first_key_t>(first),
std::forward<rest_keys_t>(rest)...)
: default_value;
}
else {
@@ -588,22 +480,16 @@ inline auto basic_value<string_t>::get_helper(
template <typename string_t>
template <typename value_t, typename unique_key_t>
inline auto
basic_value<string_t>::get_helper(const value_t& default_value, unique_key_t&& first) const
inline auto basic_value<string_t>::get_helper(const value_t& default_value, unique_key_t&& first) const
{
if constexpr (std::is_constructible_v<string_t, unique_key_t>) {
return is_object()
? as_object().get_helper(default_value, std::forward<unique_key_t>(first))
: default_value;
return is_object() ? as_object().get_helper(default_value, std::forward<unique_key_t>(first)) : default_value;
}
else if constexpr (std::is_integral_v<std::decay_t<unique_key_t>>) {
return is_array() ? as_array().get_helper(default_value, std::forward<unique_key_t>(first))
: default_value;
return is_array() ? as_array().get_helper(default_value, std::forward<unique_key_t>(first)) : default_value;
}
else {
static_assert(
!sizeof(unique_key_t),
"Parameter must be integral or string_t constructible");
static_assert(!sizeof(unique_key_t), "Parameter must be integral or string_t constructible");
}
}
@@ -796,33 +682,21 @@ inline basic_object<string_t>& basic_value<string_t>::as_object()
template <typename string_t>
template <typename value_t>
inline value_t basic_value<string_t>::as() const&
inline value_t basic_value<string_t>::as() const
{
if constexpr (std::is_same_v<basic_value<string_t>, value_t>) {
return *this;
}
else if constexpr (_utils::has_from_json_in_templ_spec<value_t, string_t>::value) {
else if constexpr (_utils::has_from_json_in_member<value_t, string_t>::value) {
value_t dst {};
if (!ext::jsonization<string_t, value_t>().from_json(*this, dst)) {
if (!dst.from_json(*this)) {
throw exception("Wrong JSON");
}
return dst;
}
else {
return static_cast<value_t>(*this);
}
}
template <typename string_t>
template <typename value_t>
inline value_t basic_value<string_t>::as() &&
{
if constexpr (std::is_same_v<basic_value<string_t>, value_t>) {
return std::move(*this);
}
else if constexpr (_utils::has_move_from_json_in_templ_spec<value_t, string_t>::value) {
else if constexpr (_utils::has_from_json_in_templ_spec<value_t, string_t>::value) {
value_t dst {};
if (!ext::jsonization<string_t, value_t>().move_from_json(std::move(*this), dst)) {
if (!ext::jsonization<value_t>().from_json(*this, dst)) {
throw exception("Wrong JSON");
}
return dst;
@@ -848,14 +722,10 @@ template <typename string_t>
template <typename... args_t>
inline decltype(auto) basic_value<string_t>::emplace(args_t&&... args)
{
constexpr bool is_array_args =
std::is_constructible_v<typename basic_array<string_t>::value_type, args_t...>;
constexpr bool is_object_args =
std::is_constructible_v<typename basic_object<string_t>::value_type, args_t...>;
constexpr bool is_array_args = std::is_constructible_v<typename basic_array<string_t>::value_type, args_t...>;
constexpr bool is_object_args = std::is_constructible_v<typename basic_object<string_t>::value_type, args_t...>;
static_assert(
is_array_args || is_object_args,
"Args can not constructure a array or object value");
static_assert(is_array_args || is_object_args, "Args can not constructure a array or object value");
if constexpr (is_array_args) {
return as_array().emplace_back(std::forward<args_t>(args)...);
@@ -931,13 +801,6 @@ inline collection_t<value_t> basic_value<string_t>::as_collection() const
return as_array().template as_collection<value_t, collection_t>();
}
template <typename string_t>
template <typename value_t, size_t Size, template <typename, size_t> typename fixed_array_t>
inline fixed_array_t<value_t, Size> basic_value<string_t>::as_fixed_array() const
{
return as_array().template as_fixed_array<value_t, Size>();
}
template <typename string_t>
template <typename value_t, template <typename...> typename map_t>
inline map_t<string_t, value_t> basic_value<string_t>::as_map() const
@@ -955,15 +818,12 @@ inline basic_value<string_t>& basic_value<string_t>::operator=(const basic_value
}
template <typename string_t>
inline basic_value<string_t>&
basic_value<string_t>::operator=(basic_value<string_t>&& rhs) noexcept = default;
inline basic_value<string_t>& basic_value<string_t>::operator=(basic_value<string_t>&& rhs) noexcept = default;
template <typename string_t>
inline bool basic_value<string_t>::operator==(const basic_value<string_t>& rhs) const
{
if (_type != rhs._type) {
return false;
}
if (_type != rhs._type) return false;
switch (_type) {
case value_type::null:
@@ -1018,8 +878,7 @@ inline basic_value<string_t>& basic_value<string_t>::operator[](string_t&& key)
}
template <typename string_t>
inline basic_value<string_t>
basic_value<string_t>::operator|(const basic_object<string_t>& rhs) const&
inline basic_value<string_t> basic_value<string_t>::operator|(const basic_object<string_t>& rhs) const&
{
return as_object() | rhs;
}
@@ -1057,8 +916,7 @@ inline basic_value<string_t>& basic_value<string_t>::operator|=(basic_object<str
}
template <typename string_t>
inline basic_value<string_t>
basic_value<string_t>::operator+(const basic_array<string_t>& rhs) const&
inline basic_value<string_t> basic_value<string_t>::operator+(const basic_array<string_t>& rhs) const&
{
return as_array() + rhs;
}
@@ -1098,12 +956,9 @@ inline basic_value<string_t>& basic_value<string_t>::operator+=(basic_array<stri
template <typename string_t>
template <typename... args_t>
inline basic_value<string_t>::basic_value(value_type type, args_t&&... args)
: _type(type)
, _raw_data(std::forward<args_t>(args)...)
: _type(type), _raw_data(std::forward<args_t>(args)...)
{
static_assert(
std::is_constructible_v<var_t, args_t...>,
"Parameter can't be used to construct a var_t");
static_assert(std::is_constructible_v<var_t, args_t...>, "Parameter can't be used to construct a var_t");
}
template <typename string_t>
@@ -1126,14 +981,11 @@ inline typename basic_value<string_t>::var_t basic_value<string_t>::deep_copy(co
return dst;
}
template <
typename ostream_t,
typename string_t,
typename std_ostream_t = std::basic_ostream<
typename string_t::value_type,
std::char_traits<typename string_t::value_type>>,
typename = std::enable_if_t<
std::is_same_v<std_ostream_t, ostream_t> || std::is_base_of_v<std_ostream_t, ostream_t>>>
template <typename ostream_t, typename string_t,
typename std_ostream_t =
std::basic_ostream<typename string_t::value_type, std::char_traits<typename string_t::value_type>>,
typename =
std::enable_if_t<std::is_same_v<std_ostream_t, ostream_t> || std::is_base_of_v<std_ostream_t, ostream_t>>>
ostream_t& operator<<(ostream_t& out, const basic_value<string_t>& val)
{
out << val.format();

View File

@@ -1,9 +1,6 @@
#pragma once
// IWYU pragma: begin_exports
#include "common/serialization.hpp"
#include "common/types.hpp"
#include "parser/parser.hpp"
#include "reflection/jsonization.hpp"
// IWYU pragma: end_exports

4
3rdparty/include/meojson/json5.hpp vendored Normal file
View File

@@ -0,0 +1,4 @@
#pragma once
#include "common/types.hpp"
#include "parser5/parser5.hpp"

View File

@@ -1,17 +1,13 @@
// IWYU pragma: private, include <meojson/json.hpp>
#pragma once
#if __cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
#include <bit>
namespace json::_bitops
{
using std::countl_one;
using std::countl_zero;
using std::countr_one;
using std::countr_zero;
inline constexpr bool is_little_endian()
{
return std::endian::native == std::endian::little;
@@ -19,37 +15,25 @@ inline constexpr bool is_little_endian()
}
#else
#include <cstdint>
namespace json::_bitops
{
#if defined(__GNUC__) || defined(__clang__)
inline constexpr int countl_zero(uint32_t x)
{
if constexpr (sizeof(uint32_t) == sizeof(unsigned int)) {
return x == 0 ? 32 : __builtin_clz(x);
}
if constexpr (sizeof(uint32_t) == sizeof(unsigned long)) {
return x == 0 ? 32 : __builtin_clzl(x);
}
if constexpr (sizeof(uint32_t) == sizeof(unsigned int)) return x == 0 ? 32 : __builtin_clz(x);
if constexpr (sizeof(uint32_t) == sizeof(unsigned long)) return x == 0 ? 32 : __builtin_clzl(x);
return x == 0 ? 32 : __builtin_clzll(x);
}
inline constexpr int countr_zero(uint32_t x)
{
if constexpr (sizeof(uint32_t) == sizeof(unsigned int)) {
return x == 0 ? 32 : __builtin_ctz(x);
}
if constexpr (sizeof(uint32_t) == sizeof(unsigned long)) {
return x == 0 ? 32 : __builtin_ctzl(x);
}
if constexpr (sizeof(uint32_t) == sizeof(unsigned int)) return x == 0 ? 32 : __builtin_ctz(x);
if constexpr (sizeof(uint32_t) == sizeof(unsigned long)) return x == 0 ? 32 : __builtin_ctzl(x);
return x == 0 ? 32 : __builtin_ctzll(x);
}
inline constexpr int countl_zero(uint64_t x)
{
return x == 0 ? 64 : __builtin_clzll(x);
}
inline constexpr int countr_zero(uint64_t x)
{
return x == 0 ? 64 : __builtin_ctzll(x);
@@ -61,17 +45,14 @@ inline int countl_zero(uint32_t x)
{
return __lzcnt(x);
}
inline int countr_zero(uint32_t x)
{
return _tzcnt_u32(x);
}
inline int countl_zero(uint64_t x)
{
return (int)__lzcnt64(x);
}
inline int countr_zero(uint64_t x)
{
return (int)_tzcnt_u64(x);
@@ -82,19 +63,16 @@ inline constexpr int countl_zero(uint32_t x)
unsigned long index = 0;
return _BitScanReverse(&index, x) ? 31 - index : 32;
}
inline constexpr int countr_zero(uint32_t x)
{
unsigned long index = 0;
return _BitScanForward(&index, x) ? index : 32;
}
inline constexpr int countl_zero(uint64_t x)
{
unsigned long index = 0;
return _BitScanReverse64(&index, x) ? 63 - index : 64;
}
inline constexpr int countr_zero(uint64_t x)
{
unsigned long index = 0;
@@ -108,17 +86,14 @@ inline int countl_one(uint32_t x)
{
return countl_zero(~x);
}
inline int countr_one(uint32_t x)
{
return countr_zero(~x);
}
inline int countl_one(uint64_t x)
{
return countl_zero(~x);
}
inline int countr_one(uint64_t x)
{
return countr_zero(~x);
@@ -127,12 +102,10 @@ inline int countr_one(uint64_t x)
// no constexpr endian awareness before C++20
inline bool is_little_endian()
{
union
{
union {
uint32_t u32;
uint8_t u8;
} u = { 0x01020304 };
return u.u8 == 4;
}
} // namespace json::_bitops

View File

@@ -1,5 +1,3 @@
// IWYU pragma: private, include <meojson/json.hpp>
#pragma once
#include <cstdint>
@@ -30,13 +28,11 @@ struct packed_bytes
};
}
#ifndef MEOJSON_DISABLE_PACKED_BYTES
#if defined(__SSE2__) || defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP)
#include "packed_bytes_x86.hpp"
#elif defined(__ARM_NEON) || defined(_M_ARM) || defined(_M_ARM64)
#include "packed_bytes_arm.hpp"
#endif
#endif
namespace json::_packed_bytes
{
@@ -70,19 +66,14 @@ struct packed_bytes_trait_uint64
return is_zero_memberwise((x) ^ (UINT64_C(0x0101010101010101) * (n)));
}
__packed_bytes_strong_inline static value_type bitwise_or(value_type a, value_type b)
{
return a | b;
}
__packed_bytes_strong_inline static value_type bitwise_or(value_type a, value_type b) { return a | b; }
__packed_bytes_strong_inline static size_t first_nonzero_byte(value_type x)
{
if (_bitops::is_little_endian()) {
if (_bitops::is_little_endian())
return _bitops::countr_zero(x) / 8;
}
else {
else
return _bitops::countl_zero(x) / 8;
}
}
};
@@ -117,22 +108,16 @@ struct packed_bytes_trait_uint32
return is_zero_memberwise((x) ^ (~UINT32_C(0) / 255 * (n)));
}
__packed_bytes_strong_inline static value_type bitwise_or(value_type a, value_type b)
{
return a | b;
}
__packed_bytes_strong_inline static value_type bitwise_or(value_type a, value_type b) { return a | b; }
__packed_bytes_strong_inline static size_t first_nonzero_byte(value_type x)
{
if (_bitops::is_little_endian()) {
if (_bitops::is_little_endian())
return _bitops::countr_zero(x) / 8;
}
else {
else
return _bitops::countl_zero(x) / 8;
}
}
};
template <>
struct packed_bytes<8>
{
@@ -148,14 +133,9 @@ struct packed_bytes<4>
template <size_t N>
using packed_bytes_trait = typename packed_bytes<N>::traits;
using packed_bytes_trait_max = std::conditional_t<
packed_bytes_trait<32>::available,
packed_bytes_trait<32>,
std::conditional_t<
packed_bytes_trait<16>::available,
packed_bytes_trait<16>,
std::conditional_t<
packed_bytes_trait<8>::available,
packed_bytes_trait<8>,
packed_bytes_trait<4>>>>;
using packed_bytes_trait_max =
std::conditional_t<packed_bytes_trait<32>::available, packed_bytes_trait<32>,
std::conditional_t<packed_bytes_trait<16>::available, packed_bytes_trait<16>,
std::conditional_t<packed_bytes_trait<8>::available, packed_bytes_trait<8>,
packed_bytes_trait<4>>>>;
} // namespace json::_packed_bytes

View File

@@ -1,5 +1,3 @@
// IWYU pragma: private, include <meojson/json.hpp>
#pragma once
// current NEON implementation doesn't outperform 64-bit scalar implementation
@@ -19,10 +17,7 @@ struct packed_bytes_trait_neon
static constexpr auto step = 16;
using value_type = uint8x16_t;
__packed_bytes_strong_inline static value_type load_unaligned(const void* ptr)
{
return vld1q_u8((uint8_t*)ptr);
}
__packed_bytes_strong_inline static value_type load_unaligned(const void* ptr) { return vld1q_u8((uint8_t*)ptr); }
__packed_bytes_strong_inline static value_type less(value_type x, uint8_t n)
{
@@ -31,31 +26,19 @@ struct packed_bytes_trait_neon
return is_less;
}
__packed_bytes_strong_inline static value_type equal(value_type x, uint8_t n)
{
return vceqq_u8(x, vdupq_n_u8(n));
}
__packed_bytes_strong_inline static value_type equal(value_type x, uint8_t n) { return vceqq_u8(x, vdupq_n_u8(n)); }
__packed_bytes_strong_inline static value_type equal(value_type x, value_type y)
{
return vceqq_u8(x, y);
}
__packed_bytes_strong_inline static value_type equal(value_type x, value_type y) { return vceqq_u8(x, y); }
__packed_bytes_strong_inline static value_type bitwise_or(value_type a, value_type b)
{
return vorrq_u8(a, b);
}
__packed_bytes_strong_inline static value_type bitwise_or(value_type a, value_type b) { return vorrq_u8(a, b); }
__packed_bytes_strong_inline static bool is_all_zero(value_type x)
{
#ifdef __packed_bytes_trait_arm64
return vmaxvq_u8(x) == 0;
#else
auto fold64 = vorr_u64(
vget_high_u64(vreinterpretq_u8_u64(x), 0),
vget_low_u64(vreinterpretq_u8_u64(x), 1));
auto fold32 = vget_lane_u32(vreinterpret_u64_u32(fold64), 0)
| vget_lane_u32(vreinterpret_u64_u32(fold64), 1);
auto fold64 = vorr_u64(vget_high_u64(vreinterpretq_u8_u64(x), 0), vget_low_u64(vreinterpretq_u8_u64(x), 1));
auto fold32 = vget_lane_u32(vreinterpret_u64_u32(fold64), 0) | vget_lane_u32(vreinterpret_u64_u32(fold64), 1);
return fold32 == 0;
#endif
}

View File

@@ -1,7 +1,4 @@
// IWYU pragma: private, include <meojson/json.hpp>
#pragma once
#include "packed_bytes.hpp"
#include <emmintrin.h>
@@ -38,15 +35,9 @@ struct packed_bytes_trait_sse
return _mm_cmpeq_epi8(x, _mm_set1_epi8(static_cast<char>(n)));
}
__packed_bytes_strong_inline static value_type equal(value_type x, value_type y)
{
return _mm_cmpeq_epi8(x, y);
}
__packed_bytes_strong_inline static value_type equal(value_type x, value_type y) { return _mm_cmpeq_epi8(x, y); }
__packed_bytes_strong_inline static value_type bitwise_or(value_type a, value_type b)
{
return _mm_or_si128(a, b);
}
__packed_bytes_strong_inline static value_type bitwise_or(value_type a, value_type b) { return _mm_or_si128(a, b); }
__packed_bytes_strong_inline static bool is_all_zero(value_type x)
{
@@ -106,20 +97,14 @@ struct packed_bytes_trait_avx2
return _mm256_cmpeq_epi8(x, _mm256_set1_epi8(static_cast<char>(n)));
}
__packed_bytes_strong_inline static value_type equal(value_type x, value_type y)
{
return _mm256_cmpeq_epi8(x, y);
}
__packed_bytes_strong_inline static value_type equal(value_type x, value_type y) { return _mm256_cmpeq_epi8(x, y); }
__packed_bytes_strong_inline static value_type bitwise_or(value_type a, value_type b)
{
return _mm256_or_si256(a, b);
}
__packed_bytes_strong_inline static bool is_all_zero(value_type x)
{
return (bool)_mm256_testz_si256(x, x);
}
__packed_bytes_strong_inline static bool is_all_zero(value_type x) { return (bool)_mm256_testz_si256(x, x); }
__packed_bytes_strong_inline static size_t first_nonzero_byte(value_type x)
{

View File

@@ -1,8 +1,5 @@
// IWYU pragma: private, include <meojson/json.hpp>
#pragma once
#include <cctype>
#include <fstream>
#include <optional>
#include <ostream>
@@ -18,11 +15,8 @@ namespace json
// * parser declare *
// ****************************
template <
bool accept_jsonc = false,
typename string_t = default_string_t,
typename parsing_t = void,
typename accel_traits = _packed_bytes::packed_bytes_trait_max>
template <typename string_t = default_string_t, typename parsing_t = void,
typename accel_traits = _packed_bytes::packed_bytes_trait_max>
class parser
{
public:
@@ -34,12 +28,7 @@ public:
static std::optional<basic_value<string_t>> parse(const parsing_t& content);
private:
parser(parsing_iter_t cbegin, parsing_iter_t cend) noexcept
: _cur(cbegin)
, _end(cend)
{
;
}
parser(parsing_iter_t cbegin, parsing_iter_t cend) noexcept : _cur(cbegin), _end(cend) { ; }
std::optional<basic_value<string_t>> parse();
basic_value<string_t> parse_value();
@@ -57,9 +46,7 @@ private:
bool skip_string_literal_with_accel();
bool skip_whitespace() noexcept;
bool skip_comment() noexcept;
bool skip_digit();
bool skip_unicode_escape(uint16_t& pair_high, string_t& result);
private:
parsing_iter_t _cur;
@@ -76,34 +63,26 @@ auto parse(const parsing_t& content);
template <typename char_t>
auto parse(char_t* content);
template <typename parsing_t>
auto parsec(const parsing_t& content);
template <typename char_t>
auto parsec(char_t* content);
template <
typename istream_t,
typename = std::enable_if_t<
std::is_base_of_v<std::basic_istream<typename istream_t::char_type>, istream_t>>>
auto parse(istream_t& istream, bool check_bom = false, bool with_commets = false);
template <typename istream_t,
typename = std::enable_if_t<std::is_base_of_v<std::basic_istream<typename istream_t::char_type>, istream_t>>>
auto parse(istream_t& istream, bool check_bom);
template <typename ifstream_t = std::ifstream, typename path_t = void>
auto open(const path_t& path, bool check_bom = false, bool with_commets = false);
auto open(const path_t& path, bool check_bom = false);
namespace literals
{
value operator""_json(const char* str, size_t len);
wvalue operator""_json(const wchar_t* str, size_t len);
value operator""_json(const char* str, size_t len);
wvalue operator""_json(const wchar_t* str, size_t len);
value operator""_jvalue(const char* str, size_t len);
wvalue operator""_jvalue(const wchar_t* str, size_t len);
value operator""_jvalue(const char* str, size_t len);
wvalue operator""_jvalue(const wchar_t* str, size_t len);
array operator""_jarray(const char* str, size_t len);
warray operator""_jarray(const wchar_t* str, size_t len);
array operator""_jarray(const char* str, size_t len);
warray operator""_jarray(const wchar_t* str, size_t len);
object operator""_jobject(const char* str, size_t len);
wobject operator""_jobject(const wchar_t* str, size_t len);
object operator""_jobject(const char* str, size_t len);
wobject operator""_jobject(const wchar_t* str, size_t len);
}
template <typename string_t = default_string_t>
@@ -113,17 +92,14 @@ const basic_value<string_t> invalid_value();
// * parser impl *
// *************************
template <bool accept_jsonc, typename string_t, typename parsing_t, typename accel_traits>
inline std::optional<basic_value<string_t>>
parser<accept_jsonc, string_t, parsing_t, accel_traits>::parse(const parsing_t& content)
template <typename string_t, typename parsing_t, typename accel_traits>
inline std::optional<basic_value<string_t>> parser<string_t, parsing_t, accel_traits>::parse(const parsing_t& content)
{
return parser<accept_jsonc, string_t, parsing_t, accel_traits>(content.cbegin(), content.cend())
.parse();
return parser<string_t, parsing_t, accel_traits>(content.cbegin(), content.cend()).parse();
}
template <bool accept_jsonc, typename string_t, typename parsing_t, typename accel_traits>
inline std::optional<basic_value<string_t>>
parser<accept_jsonc, string_t, parsing_t, accel_traits>::parse()
template <typename string_t, typename parsing_t, typename accel_traits>
inline std::optional<basic_value<string_t>> parser<string_t, parsing_t, accel_traits>::parse()
{
if (!skip_whitespace()) {
return std::nullopt;
@@ -145,7 +121,8 @@ inline std::optional<basic_value<string_t>>
return std::nullopt;
}
// After the parsing is complete, there should be no more content other than spaces behind
// After the parsing is complete, there should be no more content other than
// spaces behind
if (skip_whitespace()) {
return std::nullopt;
}
@@ -153,8 +130,8 @@ inline std::optional<basic_value<string_t>>
return result_value;
}
template <bool accept_jsonc, typename string_t, typename parsing_t, typename accel_traits>
inline basic_value<string_t> parser<accept_jsonc, string_t, parsing_t, accel_traits>::parse_value()
template <typename string_t, typename parsing_t, typename accel_traits>
inline basic_value<string_t> parser<string_t, parsing_t, accel_traits>::parse_value()
{
switch (*_cur) {
case 'n':
@@ -185,8 +162,8 @@ inline basic_value<string_t> parser<accept_jsonc, string_t, parsing_t, accel_tra
}
}
template <bool accept_jsonc, typename string_t, typename parsing_t, typename accel_traits>
inline basic_value<string_t> parser<accept_jsonc, string_t, parsing_t, accel_traits>::parse_null()
template <typename string_t, typename parsing_t, typename accel_traits>
inline basic_value<string_t> parser<string_t, parsing_t, accel_traits>::parse_null()
{
for (const auto& ch : _utils::null_string<string_t>()) {
if (_cur != _end && *_cur == ch) {
@@ -200,9 +177,8 @@ inline basic_value<string_t> parser<accept_jsonc, string_t, parsing_t, accel_tra
return basic_value<string_t>();
}
template <bool accept_jsonc, typename string_t, typename parsing_t, typename accel_traits>
inline basic_value<string_t>
parser<accept_jsonc, string_t, parsing_t, accel_traits>::parse_boolean()
template <typename string_t, typename parsing_t, typename accel_traits>
inline basic_value<string_t> parser<string_t, parsing_t, accel_traits>::parse_boolean()
{
switch (*_cur) {
case 't':
@@ -230,8 +206,8 @@ inline basic_value<string_t>
}
}
template <bool accept_jsonc, typename string_t, typename parsing_t, typename accel_traits>
inline basic_value<string_t> parser<accept_jsonc, string_t, parsing_t, accel_traits>::parse_number()
template <typename string_t, typename parsing_t, typename accel_traits>
inline basic_value<string_t> parser<string_t, parsing_t, accel_traits>::parse_number()
{
const auto first = _cur;
if (*_cur == '-') {
@@ -269,20 +245,18 @@ inline basic_value<string_t> parser<accept_jsonc, string_t, parsing_t, accel_tra
return basic_value<string_t>(basic_value<string_t>::value_type::number, string_t(first, _cur));
}
template <bool accept_jsonc, typename string_t, typename parsing_t, typename accel_traits>
inline basic_value<string_t> parser<accept_jsonc, string_t, parsing_t, accel_traits>::parse_string()
template <typename string_t, typename parsing_t, typename accel_traits>
inline basic_value<string_t> parser<string_t, parsing_t, accel_traits>::parse_string()
{
auto string_opt = parse_stdstring();
if (!string_opt) {
return invalid_value<string_t>();
}
return basic_value<string_t>(
basic_value<string_t>::value_type::string,
std::move(string_opt).value());
return basic_value<string_t>(basic_value<string_t>::value_type::string, std::move(string_opt).value());
}
template <bool accept_jsonc, typename string_t, typename parsing_t, typename accel_traits>
inline basic_value<string_t> parser<accept_jsonc, string_t, parsing_t, accel_traits>::parse_array()
template <typename string_t, typename parsing_t, typename accel_traits>
inline basic_value<string_t> parser<string_t, parsing_t, accel_traits>::parse_array()
{
if (*_cur == '[') {
++_cur;
@@ -306,12 +280,6 @@ inline basic_value<string_t> parser<accept_jsonc, string_t, parsing_t, accel_tra
return invalid_value<string_t>();
}
if constexpr (accept_jsonc) {
if (*_cur == ']') {
break;
}
}
basic_value<string_t> val = parse_value();
if (!val.valid() || !skip_whitespace()) {
@@ -338,8 +306,8 @@ inline basic_value<string_t> parser<accept_jsonc, string_t, parsing_t, accel_tra
return basic_array<string_t>(std::move(result));
}
template <bool accept_jsonc, typename string_t, typename parsing_t, typename accel_traits>
inline basic_value<string_t> parser<accept_jsonc, string_t, parsing_t, accel_traits>::parse_object()
template <typename string_t, typename parsing_t, typename accel_traits>
inline basic_value<string_t> parser<string_t, parsing_t, accel_traits>::parse_object()
{
if (*_cur == '{') {
++_cur;
@@ -363,12 +331,6 @@ inline basic_value<string_t> parser<accept_jsonc, string_t, parsing_t, accel_tra
return invalid_value<string_t>();
}
if constexpr (accept_jsonc) {
if (*_cur == '}') {
break;
}
}
auto key_opt = parse_stdstring();
if (key_opt && skip_whitespace() && *_cur == ':') {
@@ -388,10 +350,7 @@ inline basic_value<string_t> parser<accept_jsonc, string_t, parsing_t, accel_tra
return invalid_value<string_t>();
}
auto emplaced = result.emplace(std::move(*key_opt), std::move(val)).second;
if (!emplaced) {
return invalid_value<string_t>();
}
result.emplace(std::move(*key_opt), std::move(val));
if (*_cur == ',') {
++_cur;
@@ -411,9 +370,8 @@ inline basic_value<string_t> parser<accept_jsonc, string_t, parsing_t, accel_tra
return basic_object<string_t>(std::move(result));
}
template <bool accept_jsonc, typename string_t, typename parsing_t, typename accel_traits>
inline std::optional<string_t>
parser<accept_jsonc, string_t, parsing_t, accel_traits>::parse_stdstring()
template <typename string_t, typename parsing_t, typename accel_traits>
inline std::optional<string_t> parser<string_t, parsing_t, accel_traits>::parse_stdstring()
{
if (*_cur == '"') {
++_cur;
@@ -424,7 +382,6 @@ inline std::optional<string_t>
string_t result;
auto no_escape_beg = _cur;
uint16_t pair_high = 0;
while (_cur != _end) {
if constexpr (sizeof(*_cur) == 1 && accel_traits::available) {
@@ -442,9 +399,6 @@ inline std::optional<string_t>
if (_cur == _end) {
return std::nullopt;
}
if (pair_high && *_cur != 'u') {
return std::nullopt;
}
switch (*_cur) {
case '"':
result.push_back('"');
@@ -470,11 +424,9 @@ inline std::optional<string_t>
case 't':
result.push_back('\t');
break;
case 'u':
if (!skip_unicode_escape(pair_high, result)) {
return std::nullopt;
}
break;
// case 'u':
// result.push_back('\u');
// break;
default:
// Illegal backslash escape
return std::nullopt;
@@ -483,16 +435,10 @@ inline std::optional<string_t>
break;
}
case '"': {
if (pair_high) {
return std::nullopt;
}
result += string_t(no_escape_beg, _cur++);
return result;
}
default:
if (pair_high) {
return std::nullopt;
}
++_cur;
break;
}
@@ -500,106 +446,8 @@ inline std::optional<string_t>
return std::nullopt;
}
template <bool accept_jsonc, typename string_t, typename parsing_t, typename accel_traits>
inline bool parser<accept_jsonc, string_t, parsing_t, accel_traits>::skip_unicode_escape(
uint16_t& pair_high,
string_t& result)
{
uint16_t cp = 0;
for (int i = 0; i < 4; ++i) {
if (++_cur == _end) {
return false;
}
if (!std::isxdigit(static_cast<unsigned char>(*_cur))) {
return false;
}
cp <<= 4;
if ('0' <= *_cur && *_cur <= '9') {
cp |= *_cur - '0';
}
else if ('a' <= *_cur && *_cur <= 'f') {
cp |= *_cur - 'a' + 10;
}
else if ('A' <= *_cur && *_cur <= 'F') {
cp |= *_cur - 'A' + 10;
}
else {
return false;
}
}
uint32_t ext_cp = cp;
uint16_t hi_cp = 0, lo_cp = 0;
if (0xD800 <= cp && cp <= 0xDBFF) {
if (pair_high) {
return false;
}
pair_high = cp;
return true;
}
if (0xDC00 <= cp && cp <= 0xDFFF) {
if (!pair_high) {
return false;
}
ext_cp = (((pair_high - 0xD800) << 10) | (cp - 0xDC00)) + 0x10000;
hi_cp = pair_high;
lo_cp = cp;
pair_high = 0;
}
if constexpr (std::is_same_v<typename string_t::value_type, char>) {
// utf8
if (ext_cp <= 0x7F) {
result.push_back(static_cast<char>(ext_cp));
}
else if (ext_cp <= 0x7FF) {
result.push_back(static_cast<char>(((ext_cp >> 6) & 0b00011111) | 0b11000000u));
result.push_back(static_cast<char>((ext_cp & 0b00111111) | 0b10000000u));
}
else if (ext_cp <= 0xFFFF) {
result.push_back(static_cast<char>(((ext_cp >> 12) & 0b00001111) | 0b11100000u));
result.push_back(static_cast<char>(((ext_cp >> 6) & 0b00111111) | 0b10000000u));
result.push_back(static_cast<char>((ext_cp & 0b00111111) | 0b10000000u));
}
else {
result.push_back(static_cast<char>(((ext_cp >> 18) & 0b00000111) | 0b11110000u));
result.push_back(static_cast<char>(((ext_cp >> 12) & 0b00111111) | 0b10000000u));
result.push_back(static_cast<char>(((ext_cp >> 6) & 0b00111111) | 0b10000000u));
result.push_back(static_cast<char>((ext_cp & 0b00111111) | 0b10000000u));
}
}
else if constexpr (std::is_same_v<typename string_t::value_type, wchar_t>) {
if constexpr (sizeof(wchar_t) == 4) {
result.push_back(static_cast<wchar_t>(ext_cp));
}
else if constexpr (sizeof(wchar_t) == 2) {
if (ext_cp <= 0xFFFF) {
result.push_back(static_cast<wchar_t>(ext_cp));
}
else {
result.push_back(static_cast<wchar_t>(hi_cp));
result.push_back(static_cast<wchar_t>(lo_cp));
}
}
else {
static_assert(!sizeof(typename string_t::value_type), "Unsupported wchar");
}
}
else {
static_assert(!sizeof(typename string_t::value_type), "Unsupported type");
}
return true;
}
template <bool accept_jsonc, typename string_t, typename parsing_t, typename accel_traits>
inline bool
parser<accept_jsonc, string_t, parsing_t, accel_traits>::skip_string_literal_with_accel()
template <typename string_t, typename parsing_t, typename accel_traits>
inline bool parser<string_t, parsing_t, accel_traits>::skip_string_literal_with_accel()
{
if constexpr (sizeof(*_cur) != 1) {
return false;
@@ -608,10 +456,8 @@ inline bool
while (_end - _cur >= accel_traits::step) {
auto pack = accel_traits::load_unaligned(&(*_cur));
auto result = accel_traits::less(pack, 32);
result =
accel_traits::bitwise_or(result, accel_traits::equal(pack, static_cast<uint8_t>('"')));
result =
accel_traits::bitwise_or(result, accel_traits::equal(pack, static_cast<uint8_t>('\\')));
result = accel_traits::bitwise_or(result, accel_traits::equal(pack, static_cast<uint8_t>('"')));
result = accel_traits::bitwise_or(result, accel_traits::equal(pack, static_cast<uint8_t>('\\')));
if (accel_traits::is_all_zero(result)) {
_cur += accel_traits::step;
@@ -626,8 +472,8 @@ inline bool
return _cur != _end;
}
template <bool accept_jsonc, typename string_t, typename parsing_t, typename accel_traits>
inline bool parser<accept_jsonc, string_t, parsing_t, accel_traits>::skip_whitespace() noexcept
template <typename string_t, typename parsing_t, typename accel_traits>
inline bool parser<string_t, parsing_t, accel_traits>::skip_whitespace() noexcept
{
while (_cur != _end) {
switch (*_cur) {
@@ -637,17 +483,6 @@ inline bool parser<accept_jsonc, string_t, parsing_t, accel_traits>::skip_whites
case '\n':
++_cur;
break;
case '/':
if constexpr (accept_jsonc) {
if (!skip_comment()) {
return false;
}
// else continue;
}
else {
return false;
}
break;
case '\0':
return false;
default:
@@ -657,59 +492,8 @@ inline bool parser<accept_jsonc, string_t, parsing_t, accel_traits>::skip_whites
return false;
}
template <bool accept_jsonc, typename string_t, typename parsing_t, typename accel_traits>
bool json::parser<accept_jsonc, string_t, parsing_t, accel_traits>::skip_comment() noexcept
{
if (_cur == _end || *_cur != '/') {
return false;
}
if (++_cur == _end) {
return false;
}
enum class comment_type
{
invalid,
line,
block,
} t = comment_type::invalid;
switch (*_cur++) {
case '/':
t = comment_type::line;
break;
case '*':
t = comment_type::block;
break;
default:
return false;
}
while (_cur != _end) {
switch (*_cur++) {
case '\n':
if (t == comment_type::line) {
return true;
}
break;
case '*':
if (t == comment_type::block && _cur != _end && *_cur == '/') {
++_cur;
return true;
}
break;
default:
break;
}
}
// _cur == _end
return t == comment_type::line;
}
template <bool accept_jsonc, typename string_t, typename parsing_t, typename accel_traits>
inline bool parser<accept_jsonc, string_t, parsing_t, accel_traits>::skip_digit()
template <typename string_t, typename parsing_t, typename accel_traits>
inline bool parser<string_t, parsing_t, accel_traits>::skip_digit()
{
// At least one digit
if (_cur != _end && std::isdigit(*_cur)) {
@@ -739,7 +523,7 @@ template <typename parsing_t>
auto parse(const parsing_t& content)
{
using string_t = std::basic_string<typename parsing_t::value_type>;
return parser<false, string_t, parsing_t>::parse(content);
return parser<string_t, parsing_t>::parse(content);
}
template <typename char_t>
@@ -749,7 +533,7 @@ auto parse(char_t* content)
}
template <typename istream_t, typename _>
auto parse(istream_t& ifs, bool check_bom, bool with_commets)
auto parse(istream_t& ifs, bool check_bom)
{
using string_t = std::basic_string<typename istream_t::char_type>;
@@ -767,16 +551,16 @@ auto parse(istream_t& ifs, bool check_bom, bool with_commets)
static constexpr uchar Bom_1 = 0xBB;
static constexpr uchar Bom_2 = 0xBF;
if (str.size() >= 3 && static_cast<uchar>(str.at(0)) == Bom_0
&& static_cast<uchar>(str.at(1)) == Bom_1 && static_cast<uchar>(str.at(2)) == Bom_2) {
if (str.size() >= 3 && static_cast<uchar>(str.at(0)) == Bom_0 && static_cast<uchar>(str.at(1)) == Bom_1 &&
static_cast<uchar>(str.at(2)) == Bom_2) {
str.assign(str.begin() + 3, str.end());
}
}
return with_commets ? parsec(str) : parse(str);
return parse(str);
}
template <typename ifstream_t, typename path_t>
auto open(const path_t& filepath, bool check_bom, bool with_commets)
auto open(const path_t& filepath, bool check_bom)
{
using char_t = typename ifstream_t::char_type;
using string_t = std::basic_string<char_t>;
@@ -787,76 +571,57 @@ auto open(const path_t& filepath, bool check_bom, bool with_commets)
if (!ifs.is_open()) {
return return_t(std::nullopt);
}
auto opt = parse(ifs, check_bom, with_commets);
auto opt = parse(ifs, check_bom);
ifs.close();
return opt;
}
template <typename parsing_t>
auto parsec(const parsing_t& content)
{
using string_t = std::basic_string<typename parsing_t::value_type>;
return parser<true, string_t, parsing_t>::parse(content);
}
template <typename char_t>
auto parsec(char_t* content)
{
return parsec(std::basic_string_view<std::decay_t<char_t>> { content });
}
namespace literals
{
inline value operator""_json(const char* str, size_t len)
{
return operator""_jvalue(str, len);
}
inline value operator""_json(const char* str, size_t len)
{
return operator""_jvalue(str, len);
}
inline wvalue operator""_json(const wchar_t* str, size_t len)
{
return operator""_jvalue(str, len);
}
inline wvalue operator""_json(const wchar_t* str, size_t len)
{
return operator""_jvalue(str, len);
}
inline value operator""_jvalue(const char* str, size_t len)
{
return parse(std::string_view(str, len)).value_or(value());
}
inline wvalue operator""_jvalue(const wchar_t* str, size_t len)
{
return parse(std::wstring_view(str, len)).value_or(wvalue());
}
inline value operator""_jvalue(const char* str, size_t len)
{
return parse(std::string_view(str, len)).value_or(value());
}
inline array operator""_jarray(const char* str, size_t len)
{
auto val = parse(std::string_view(str, len)).value_or(value());
return val.is_array() ? val.as_array() : array();
}
inline warray operator""_jarray(const wchar_t* str, size_t len)
{
auto val = parse(std::wstring_view(str, len)).value_or(wvalue());
return val.is_array() ? val.as_array() : warray();
}
inline wvalue operator""_jvalue(const wchar_t* str, size_t len)
{
return parse(std::wstring_view(str, len)).value_or(wvalue());
}
inline array operator""_jarray(const char* str, size_t len)
{
auto val = parse(std::string_view(str, len)).value_or(value());
return val.is_array() ? val.as_array() : array();
}
inline warray operator""_jarray(const wchar_t* str, size_t len)
{
auto val = parse(std::wstring_view(str, len)).value_or(wvalue());
return val.is_array() ? val.as_array() : warray();
}
inline object operator""_jobject(const char* str, size_t len)
{
auto val = parse(std::string_view(str, len)).value_or(value());
return val.is_object() ? val.as_object() : object();
}
inline wobject operator""_jobject(const wchar_t* str, size_t len)
{
auto val = parse(std::wstring_view(str, len)).value_or(wvalue());
return val.is_object() ? val.as_object() : wobject();
}
inline object operator""_jobject(const char* str, size_t len)
{
auto val = parse(std::string_view(str, len)).value_or(value());
return val.is_object() ? val.as_object() : object();
}
inline wobject operator""_jobject(const wchar_t* str, size_t len)
{
auto val = parse(std::wstring_view(str, len)).value_or(wvalue());
return val.is_object() ? val.as_object() : wobject();
}
} // namespace literals
template <typename string_t>
const basic_value<string_t> invalid_value()
{
return basic_value<string_t>(
basic_value<string_t>::value_type::invalid,
typename basic_value<string_t>::var_t());
return basic_value<string_t>(basic_value<string_t>::value_type::invalid, typename basic_value<string_t>::var_t());
}
} // namespace json

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,656 +0,0 @@
// IWYU pragma: private, include <meojson/json.hpp>
#pragma once
#include <cstddef>
#include <filesystem>
#include <queue>
#include <tuple>
#include <type_traits>
#include <utility>
#include <variant>
#include "../common/types.hpp"
namespace json::ext
{
template <typename string_t, typename impl_t, typename var_t, size_t len> // (size_t)-1 for no
// restriction
class __jsonization_array
{
public:
json::basic_value<string_t> to_json(const var_t& value) const
{
return static_cast<const impl_t*>(this)->to_json_array(value);
}
bool check_json(const json::basic_value<string_t>& json) const
{
if (!json.is_array()) {
return false;
}
const auto& arr = json.as_array();
if constexpr (len != static_cast<size_t>(-1)) {
if (len != arr.size()) {
return false;
}
}
return static_cast<const impl_t*>(this)->check_json_array(arr);
}
bool from_json(const json::basic_value<string_t>& json, var_t& value) const
{
if (!json.is_array()) {
return false;
}
const auto& arr = json.as_array();
if constexpr (len != static_cast<size_t>(-1)) {
if (len != arr.size()) {
return false;
}
}
return static_cast<const impl_t*>(this)->from_json_array(arr, value);
}
json::basic_value<string_t> move_to_json(var_t value) const
{
return static_cast<const impl_t*>(this)->move_to_json_array(std::move(value));
}
bool move_from_json(json::basic_value<string_t> json, var_t& value) const
{
if (!json.is_array()) {
return false;
}
auto& arr = json.as_array();
if constexpr (len != static_cast<size_t>(-1)) {
if (len != arr.size()) {
return false;
}
}
return static_cast<const impl_t*>(this)->move_from_json_array(std::move(arr), value);
}
};
template <typename string_t, typename impl_t, typename var_t>
class __jsonization_object
{
public:
json::basic_value<string_t> to_json(const var_t& value) const
{
return static_cast<const impl_t*>(this)->to_json_object(value);
}
bool check_json(const json::basic_value<string_t>& json) const
{
if (!json.is_object()) {
return false;
}
const auto& obj = json.as_object();
return static_cast<const impl_t*>(this)->check_json_object(obj);
}
bool from_json(const json::basic_value<string_t>& json, var_t& value) const
{
if (!json.is_object()) {
return false;
}
const auto& obj = json.as_object();
return static_cast<const impl_t*>(this)->from_json_object(obj, value);
}
json::basic_value<string_t> move_to_json(var_t value) const
{
return static_cast<const impl_t*>(this)->move_to_json_object(std::move(value));
}
bool move_from_json(json::basic_value<string_t> json, var_t& value) const
{
if (!json.is_object()) {
return false;
}
auto& obj = json.as_object();
return static_cast<const impl_t*>(this)->move_from_json_object(std::move(obj), value);
}
};
template <typename string_t>
class jsonization<string_t, std::nullptr_t>
{
public:
json::basic_value<string_t> to_json(const std::nullptr_t&) const
{
return json::basic_value<string_t> {};
}
bool check_json(const json::basic_value<string_t>& json) const { return json.is_null(); }
bool from_json(const json::basic_value<string_t>& json, std::nullptr_t&)
{
return check_json(json);
}
};
template <typename string_t>
class jsonization<
string_t,
std::filesystem::path,
std::enable_if_t<
std::is_same_v<string_t, std::filesystem::path::string_type>
|| std::is_same_v<string_t, std::string>>>
{
public:
json::basic_value<string_t> to_json(const std::filesystem::path& path) const
{
if constexpr (std::is_same_v<string_t, std::filesystem::path::string_type>) {
return path.native();
}
else if constexpr (std::is_same_v<string_t, std::string>) {
#if __cplusplus >= 202002L
std::u8string u8str = path.u8string();
return std::string { u8str.begin(), u8str.end() };
#else
return path.u8string();
#endif
}
#if __cplusplus >= 202002L
else if constexpr (std::is_same_v<string_t, std::u8string>) {
return path.u8string();
}
#endif
}
bool check_json(const json::basic_value<string_t>& json) const { return json.is_string(); }
bool from_json(const json::basic_value<string_t>& json, std::filesystem::path& path) const
{
path = json.as_string();
return true;
}
};
template <
typename string_t,
template <typename, size_t> typename arr_t,
typename value_t,
size_t size>
class jsonization<string_t, arr_t<value_t, size>>
: public __jsonization_array<
string_t,
jsonization<string_t, arr_t<value_t, size>>,
arr_t<value_t, size>,
size>
{
public:
json::basic_array<string_t> to_json_array(const arr_t<value_t, size>& value) const
{
json::basic_array<string_t> result;
for (size_t i = 0; i < size; i++) {
result.emplace_back(value.at(i));
}
return result;
}
bool check_json_array(const json::basic_array<string_t>& arr) const
{
return arr.template all<value_t>();
}
bool from_json_array(const json::basic_array<string_t>& arr, arr_t<value_t, size>& value) const
{
if (!check_json_array(arr)) {
return false;
}
for (size_t i = 0; i < size; i++) {
value.at(i) = arr[i].template as<value_t>();
}
return true;
}
json::basic_array<string_t> move_to_json_array(arr_t<value_t, size> value) const
{
json::basic_array<string_t> result;
for (size_t i = 0; i < size; i++) {
result.emplace_back(std::move(value.at(i)));
}
return result;
}
bool move_from_json_array(json::basic_array<string_t> arr, arr_t<value_t, size>& value) const
{
if (!check_json_array(arr)) {
return false;
}
for (size_t i = 0; i < size; i++) {
value.at(i) = std::move(arr[i]).template as<value_t>();
}
return true;
}
};
template <typename string_t, typename collection_t>
class jsonization<string_t, collection_t, std::enable_if_t<_utils::is_collection<collection_t>>>
: public __jsonization_array<
string_t,
jsonization<string_t, collection_t>,
collection_t,
(size_t)-1>
{
public:
json::basic_array<string_t> to_json_array(const collection_t& value) const
{
json::basic_array<string_t> result;
for (const auto& val : value) {
result.emplace_back(val);
}
return result;
}
bool check_json_array(const json::basic_array<string_t>& arr) const
{
return arr.template all<typename collection_t::value_type>();
}
bool from_json_array(const json::basic_array<string_t>& arr, collection_t& value) const
{
if (!check_json_array(arr)) {
return false;
}
value = {};
for (const auto& val : arr) {
if constexpr (_utils::has_emplace_back<collection_t>::value) {
value.emplace_back(val.template as<typename collection_t::value_type>());
}
else {
value.emplace(val.template as<typename collection_t::value_type>());
}
}
return true;
}
json::basic_array<string_t> move_to_json_array(collection_t value) const
{
json::basic_array<string_t> result;
for (auto& val : value) {
result.emplace_back(std::move(val));
}
return result;
}
bool move_from_json_array(json::basic_array<string_t> arr, collection_t& value) const
{
if (!check_json_array(arr)) {
return false;
}
for (auto& val : arr) {
if constexpr (_utils::has_emplace_back<collection_t>::value) {
value.emplace_back(std::move(val).template as<typename collection_t::value_type>());
}
else {
value.emplace(std::move(val).template as<typename collection_t::value_type>());
}
}
return true;
}
};
template <typename string_t, template <typename...> typename tuple_t, typename... args_t>
class jsonization<
string_t,
tuple_t<args_t...>,
std::enable_if_t<_utils::is_tuple_like<tuple_t<args_t...>>>>
: public __jsonization_array<
string_t,
jsonization<string_t, tuple_t<args_t...>>,
tuple_t<args_t...>,
std::tuple_size_v<tuple_t<args_t...>>>
{
public:
constexpr static size_t tuple_size = std::tuple_size_v<tuple_t<args_t...>>;
json::basic_array<string_t> to_json_array(const tuple_t<args_t...>& value) const
{
json::basic_array<string_t> result;
to_json_impl(result, value, std::make_index_sequence<tuple_size>());
return result;
}
template <std::size_t... Is>
void to_json_impl(
json::basic_array<string_t>& arr,
const tuple_t<args_t...>& t,
std::index_sequence<Is...>) const
{
using std::get;
(arr.emplace_back(get<Is>(t)), ...);
}
bool check_json_array(const json::basic_array<string_t>& arr) const
{
return check_json_impl(arr, std::make_index_sequence<tuple_size>());
}
template <std::size_t... Is>
bool check_json_impl(const json::basic_array<string_t>& arr, std::index_sequence<Is...>) const
{
return (arr[Is].template is<std::tuple_element_t<Is, tuple_t<args_t...>>>() && ...);
}
bool from_json_array(const json::basic_array<string_t>& arr, tuple_t<args_t...>& value) const
{
if (!check_json_array(arr)) {
return false;
}
from_json_impl(arr, value, std::make_index_sequence<tuple_size>());
return true;
}
template <std::size_t... Is>
void from_json_impl(
const json::basic_array<string_t>& arr,
tuple_t<args_t...>& t,
std::index_sequence<Is...>) const
{
using std::get;
((get<Is>(t) = arr[Is].template as<std::tuple_element_t<Is, tuple_t<args_t...>>>()), ...);
}
json::basic_array<string_t> move_to_json_array(tuple_t<args_t...> value) const
{
json::basic_array<string_t> result;
move_to_json_impl(result, std::move(value), std::make_index_sequence<tuple_size>());
return result;
}
template <std::size_t... Is>
void move_to_json_impl(
json::basic_array<string_t>& arr,
tuple_t<args_t...> t,
std::index_sequence<Is...>) const
{
using std::get;
(arr.emplace_back(std::move(get<Is>(t))), ...);
}
bool move_from_json_array(json::basic_array<string_t> arr, tuple_t<args_t...>& value) const
{
if (!check_json_array(arr)) {
return false;
}
move_from_json_impl(arr, value, std::make_index_sequence<tuple_size>());
return true;
}
template <std::size_t... Is>
void move_from_json_impl(
json::basic_array<string_t> arr,
tuple_t<args_t...>& t,
std::index_sequence<Is...>) const
{
using std::get;
((get<Is>(t) =
std::move(arr[Is]).template as<std::tuple_element_t<Is, tuple_t<args_t...>>>()),
...);
}
};
template <typename string_t, typename map_t>
class jsonization<
string_t,
map_t,
std::enable_if_t<_utils::is_map<map_t> && std::is_same_v<typename map_t::key_type, string_t>>>
: public __jsonization_object<string_t, jsonization<string_t, map_t>, map_t>
{
public:
json::basic_object<string_t> to_json_object(const map_t& value) const
{
json::basic_object<string_t> result;
for (const auto& [key, val] : value) {
result.emplace(key, val);
}
return result;
}
bool check_json_object(const json::basic_object<string_t>& arr) const
{
for (const auto& [key, val] : arr) {
if (!val.template is<typename map_t::mapped_type>()) {
return false;
}
}
return true;
}
bool from_json_object(const json::basic_object<string_t>& arr, map_t& value) const
{
// TODO: 是不是直接from不check了算了
if (!check_json_object(arr)) {
return false;
}
value = {};
for (const auto& [key, val] : arr) {
value.emplace(key, val.template as<typename map_t::mapped_type>());
}
return true;
}
json::basic_object<string_t> move_to_json_object(map_t value) const
{
json::basic_object<string_t> result;
for (auto& [key, val] : value) {
result.emplace(key, std::move(val));
}
return result;
}
bool move_from_json_object(json::basic_object<string_t> arr, map_t& value) const
{
// TODO: 是不是直接from不check了算了
if (!check_json_object(arr)) {
return false;
}
value = {};
for (auto& [key, val] : arr) {
value.emplace(key, std::move(val).template as<typename map_t::mapped_type>());
}
return true;
}
};
template <typename string_t, typename... args_t>
class jsonization<string_t, std::variant<args_t...>>
{
public:
using variant_t = std::variant<args_t...>;
constexpr static size_t variant_size = std::variant_size_v<variant_t>;
json::basic_value<string_t> to_json(const variant_t& value) const
{
json::basic_value<string_t> result;
to_json_impl(result, value, std::make_index_sequence<variant_size>());
return result;
}
template <std::size_t... Is>
void to_json_impl(
json::basic_value<string_t>& val,
const variant_t& t,
std::index_sequence<Is...>) const
{
using std::get;
std::ignore = ((t.index() == Is ? (val = get<Is>(t), true) : false) || ...);
}
bool check_json(const json::basic_value<string_t>& json) const
{
return check_json_impl(json, std::make_index_sequence<variant_size>());
}
template <std::size_t... Is>
bool check_json_impl(const json::basic_value<string_t>& val, std::index_sequence<Is...>) const
{
return (val.template is<std::variant_alternative_t<Is, variant_t>>() || ...);
}
bool from_json(const json::basic_value<string_t>& json, variant_t& value) const
{
if (!check_json_impl(json, std::make_index_sequence<variant_size>())) {
return false;
}
from_json_impl(json, value, std::make_index_sequence<variant_size>());
return true;
}
template <std::size_t... Is>
void from_json_impl(
const json::basic_value<string_t>& json,
variant_t& t,
std::index_sequence<Is...>) const
{
std::ignore =
((json.template is<std::variant_alternative_t<Is, variant_t>>()
? (t = json.template as<std::variant_alternative_t<Is, variant_t>>(), true)
: false)
|| ...);
}
json::basic_value<string_t> move_to_json(variant_t value) const
{
json::basic_value<string_t> result;
move_to_json_impl(result, std::move(value), std::make_index_sequence<variant_size>());
return result;
}
template <std::size_t... Is>
void
move_to_json_impl(json::basic_value<string_t>& val, variant_t t, std::index_sequence<Is...>)
const
{
using std::get;
std::ignore = ((t.index() == Is ? (val = std::move(get<Is>(t)), true) : false) || ...);
}
bool move_from_json(json::basic_value<string_t> json, variant_t& value) const
{
if (!check_json_impl(json, std::make_index_sequence<variant_size>())) {
return false;
}
move_from_json_impl(std::move(json), value, std::make_index_sequence<variant_size>());
return true;
}
template <std::size_t... Is>
void move_from_json_impl(
json::basic_value<string_t> json,
variant_t& t,
std::index_sequence<Is...>) const
{
std::ignore =
((json.template is<std::variant_alternative_t<Is, variant_t>>()
? (t = std::move(json).template as<std::variant_alternative_t<Is, variant_t>>(),
true)
: false)
|| ...);
}
};
// TODO: check if has move_xxx in member
template <typename string_t, typename var_t>
class jsonization<
string_t,
var_t,
std::enable_if_t<
_utils::has_to_json_in_member<var_t>::value
&& _utils::has_check_json_in_member<var_t, string_t>::value
&& _utils::has_from_json_in_member<var_t, string_t>::value>>
{
public:
json::basic_value<string_t> to_json(const var_t& value) const { return value.to_json(); }
bool check_json(const json::basic_value<string_t>& json) const
{
var_t value;
return value.check_json(json);
}
bool from_json(const json::basic_value<string_t>& json, var_t& value) const
{
return value.from_json(json);
}
json::basic_value<string_t> move_to_json(var_t value) const { return to_json(value); }
bool move_from_json(json::basic_value<string_t> json, var_t& value) const
{
return from_json(json, value);
}
};
// really need this fucking queue?
template <typename string_t, typename value_t>
class jsonization<string_t, std::queue<value_t>>
: public __jsonization_array<
string_t,
jsonization<string_t, std::queue<value_t>>,
std::queue<value_t>,
(size_t)-1>
{
public:
json::basic_array<string_t> to_json_array(const std::queue<value_t>& value) const
{
return move_to_json_array(value);
}
bool check_json_array(const json::basic_array<string_t>& arr) const
{
return arr.template all<value_t>();
}
bool from_json_array(const json::basic_array<string_t>& arr, std::queue<value_t>& value) const
{
if (!check_json_array(arr)) {
return false;
}
value = {};
for (const auto& val : arr) {
value.emplace(val.template as<value_t>());
}
return true;
}
json::basic_array<string_t> move_to_json_array(std::queue<value_t> value) const
{
json::basic_array<string_t> result;
while (!value.empty()) {
result.emplace_back(std::move(value.front()));
value.pop();
}
return result;
}
bool move_from_json_array(json::basic_array<string_t> arr, std::queue<value_t>& value) const
{
if (!check_json_array(arr)) {
return false;
}
for (auto& val : arr) {
value.emplace(std::move(val).template as<value_t>());
}
return true;
}
};
}

View File

@@ -1,298 +1,94 @@
// IWYU pragma: private, include <meojson/json.hpp>
#pragma once
#include <string>
#include <type_traits>
#include <utility>
#include "../common/types.hpp"
#include "extensions.hpp"
namespace json::_jsonization_helper
{
template <typename value_t>
struct is_optional_t : public std::false_type
{
};
template <typename value_t>
struct is_optional_t<std::optional<value_t>> : public std::true_type
{
};
template <typename value_t>
inline constexpr bool is_optional_v = is_optional_t<value_t>::value;
struct next_is_optional_t
{
};
struct next_override_key_t
{
const char* key;
};
struct next_state_t
{
bool is_optional = false;
const char* override_key = nullptr;
};
{};
struct va_arg_end
{
};
template <typename tag_t>
struct is_tag_t : public std::false_type
{
};
template <>
struct is_tag_t<next_is_optional_t> : public std::true_type
{
};
template <>
struct is_tag_t<next_override_key_t> : public std::true_type
{
};
{};
struct dumper
{
void _to_json(json::object&, va_arg_end) const {}
template <typename var_t, typename... rest_t>
json::value _to_json(const char* key, const var_t& var, rest_t&&... rest) const
{
json::value result = _to_json(std::forward<rest_t>(rest)...);
result.emplace(key, var);
return result;
}
template <typename... rest_t>
void _to_json(json::object& result, const char* key, rest_t&&... rest) const
json::value _to_json(const char*, next_is_optional_t, rest_t&&... rest) const
{
_to_json(result, next_state_t {}, key, std::forward<rest_t>(rest)...);
}
template <
typename var_t,
typename... rest_t,
typename _ = std::enable_if_t<!is_tag_t<var_t>::value, void>>
void _to_json(
json::object& result,
next_state_t state,
const char* key,
const var_t& var,
rest_t&&... rest) const
{
if (state.override_key) {
key = state.override_key;
}
if constexpr (is_optional_v<var_t>) {
if (!state.is_optional) {
throw exception("std::optional must be used with MEO_OPT");
}
if (var.has_value()) {
result.emplace(key, var.value());
}
}
else {
result.emplace(key, var);
}
_to_json(result, std::forward<rest_t>(rest)...);
}
template <typename... rest_t>
void _to_json(
json::object& result,
next_state_t state,
const char*,
next_is_optional_t,
rest_t&&... rest) const
{
state.is_optional = true;
_to_json(result, state, std::forward<rest_t>(rest)...);
}
template <typename... rest_t>
void _to_json(
json::object& result,
next_state_t state,
const char*,
next_override_key_t override_key,
rest_t&&... rest) const
{
state.override_key = override_key.key;
_to_json(result, state, std::forward<rest_t>(rest)...);
return _to_json(std::forward<rest_t>(rest)...);
}
json::value _to_json(va_arg_end) const { return {}; }
};
struct checker
{
bool _check_json(const json::value&, std::string&, va_arg_end) const { return true; }
template <typename... rest_t>
bool _check_json(
const json::value& in,
std::string& error_key,
const char* key,
rest_t&&... rest) const
template <typename var_t, typename... rest_t>
bool _check_json(const json::value& in, std::string& error_key, const char* key, const var_t&,
rest_t&&... rest) const
{
return _check_json(in, error_key, next_state_t {}, key, std::forward<rest_t>(rest)...);
}
template <
typename var_t,
typename... rest_t,
typename _ = std::enable_if_t<!is_tag_t<var_t>::value, void>>
bool _check_json(
const json::value& in,
std::string& error_key,
next_state_t state,
const char* key,
const var_t&,
rest_t&&... rest) const
{
if (state.override_key) {
key = state.override_key;
}
auto opt = in.find(key);
if constexpr (is_optional_v<var_t>) {
if (!state.is_optional) {
throw exception("std::optional must be used with MEO_OPT");
}
if (opt && !opt->is<typename var_t::value_type>()) {
error_key = key;
return false;
}
}
else {
if (state.is_optional) {
if (opt && !opt->is<var_t>()) {
error_key = key;
return false;
} // is_optional, ignore key not found
}
else if (!opt || !opt->is<var_t>()) {
error_key = key;
return false;
}
if (!opt || !opt->is<var_t>()) {
error_key = key;
return false;
}
return _check_json(in, error_key, std::forward<rest_t>(rest)...);
}
template <typename... rest_t>
bool _check_json(
const json::value& in,
std::string& error_key,
next_state_t state,
const char*,
next_is_optional_t,
rest_t&&... rest) const
template <typename var_t, typename... rest_t>
bool _check_json(const json::value& in, std::string& error_key, const char*, next_is_optional_t, const char* key,
const var_t&, rest_t&&... rest) const
{
state.is_optional = true;
return _check_json(in, error_key, state, std::forward<rest_t>(rest)...);
}
auto opt = in.find(key);
if (opt) {
if (!opt->is<var_t>()) {
error_key = key;
return false;
}
} // next_is_optional_t, ignore key not found
template <typename... rest_t>
bool _check_json(
const json::value& in,
std::string& error_key,
next_state_t state,
const char*,
next_override_key_t override_key,
rest_t&&... rest) const
{
state.override_key = override_key.key;
return _check_json(in, error_key, state, std::forward<rest_t>(rest)...);
return _check_json(in, error_key, std::forward<rest_t>(rest)...);
}
bool _check_json(const json::value&, std::string&, va_arg_end) const { return true; }
};
struct loader
{
bool _from_json(const json::value&, std::string&, va_arg_end) const { return true; }
template <typename... rest_t>
bool
_from_json(const json::value& in, std::string& error_key, const char* key, rest_t&&... rest)
template <typename var_t, typename... rest_t>
bool _from_json(const json::value& in, std::string& error_key, const char* key, var_t& var, rest_t&&... rest) const
{
return _from_json(in, error_key, next_state_t {}, key, std::forward<rest_t>(rest)...);
}
template <
typename var_t,
typename... rest_t,
typename _ = std::enable_if_t<!is_tag_t<var_t>::value, void>>
bool _from_json(
const json::value& in,
std::string& error_key,
next_state_t state,
const char* key,
var_t& var,
rest_t&&... rest)
{
if (state.override_key) {
key = state.override_key;
}
auto opt = in.find(key);
if constexpr (is_optional_v<var_t>) {
if (!state.is_optional) {
throw exception("std::optional must be used with MEO_OPT");
}
if (opt && !opt->is<typename var_t::value_type>()) {
error_key = key;
return false;
}
if (opt) {
var = std::move(opt)->as<typename var_t::value_type>();
}
else {
var = std::nullopt;
}
}
else {
if (state.is_optional) {
if (opt && !opt->is<var_t>()) {
error_key = key;
return false;
} // is_optional, ignore key not found
}
else if (!opt || !opt->is<var_t>()) {
error_key = key;
return false;
}
if (opt) {
var = std::move(opt)->as<var_t>();
}
if (!opt || !opt->is<var_t>()) {
error_key = key;
return false;
}
var = std::move(opt)->as<var_t>();
return _from_json(in, error_key, std::forward<rest_t>(rest)...);
}
template <typename... rest_t>
bool _from_json(
const json::value& in,
std::string& error_key,
next_state_t state,
const char*,
next_is_optional_t,
rest_t&&... rest)
template <typename var_t, typename... rest_t>
bool _from_json(const json::value& in, std::string& error_key, const char*, next_is_optional_t, const char* key,
var_t& var, rest_t&&... rest) const
{
state.is_optional = true;
return _from_json(in, error_key, state, std::forward<rest_t>(rest)...);
}
auto opt = in.find(key);
if (opt) {
if (!opt->is<var_t>()) {
error_key = key;
return false;
}
var = std::move(opt)->as<var_t>();
} // next_is_optional_t, ignore key not found
template <typename... rest_t>
bool _from_json(
const json::value& in,
std::string& error_key,
next_state_t state,
const char*,
next_override_key_t override_key,
rest_t&&... rest)
{
state.override_key = override_key.key;
return _from_json(in, error_key, state, std::forward<rest_t>(rest)...);
return _from_json(in, error_key, std::forward<rest_t>(rest)...);
}
bool _from_json(const json::value&, std::string&, va_arg_end) const { return true; }
};
} // namespace json::_jsonization_helper
@@ -313,326 +109,124 @@ namespace json::_private_macro
#define _MEOJSON_EXPAND(x) x
#define _MEOJSON_FOR_EACH_1(pred, x) pred(x)
#define _MEOJSON_FOR_EACH_2(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_1(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_3(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_2(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_4(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_3(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_5(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_4(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_6(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_5(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_7(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_6(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_8(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_7(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_9(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_8(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_10(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_9(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_11(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_10(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_12(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_11(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_13(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_12(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_14(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_13(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_15(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_14(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_16(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_15(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_17(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_16(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_18(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_17(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_19(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_18(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_20(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_19(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_21(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_20(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_22(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_21(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_23(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_22(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_24(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_23(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_25(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_24(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_26(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_25(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_27(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_26(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_28(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_27(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_29(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_28(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_30(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_29(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_31(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_30(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_32(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_31(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_33(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_32(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_34(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_33(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_35(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_34(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_36(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_35(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_37(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_36(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_38(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_37(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_39(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_38(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_40(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_39(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_41(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_40(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_42(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_41(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_43(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_42(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_44(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_43(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_45(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_44(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_46(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_45(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_47(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_46(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_48(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_47(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_49(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_48(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_50(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_49(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_51(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_50(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_52(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_51(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_53(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_52(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_54(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_53(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_55(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_54(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_56(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_55(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_57(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_56(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_58(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_57(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_59(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_58(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_60(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_59(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_61(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_60(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_62(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_61(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_63(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_62(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_64(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_63(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_0(pred, ...)
#define _MEOJSON_FOR_EACH_1(pred, x, ...) pred(x)
#define _MEOJSON_FOR_EACH_2(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_1(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_3(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_2(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_4(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_3(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_5(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_4(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_6(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_5(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_7(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_6(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_8(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_7(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_9(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_8(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_10(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_9(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_11(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_10(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_12(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_11(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_13(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_12(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_14(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_13(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_15(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_14(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_16(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_15(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_17(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_16(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_18(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_17(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_19(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_18(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_20(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_19(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_21(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_20(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_22(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_21(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_23(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_22(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_24(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_23(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_25(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_24(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_26(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_25(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_27(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_26(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_28(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_27(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_29(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_28(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_30(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_29(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_31(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_30(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_32(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_31(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_33(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_32(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_34(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_33(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_35(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_34(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_36(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_35(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_37(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_36(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_38(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_37(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_39(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_38(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_40(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_39(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_41(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_40(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_42(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_41(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_43(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_42(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_44(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_43(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_45(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_44(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_46(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_45(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_47(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_46(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_48(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_47(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_49(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_48(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_50(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_49(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_51(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_50(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_52(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_51(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_53(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_52(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_54(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_53(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_55(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_54(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_56(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_55(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_57(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_56(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_58(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_57(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_59(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_58(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_60(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_59(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_61(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_60(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_62(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_61(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_63(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_62(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_64(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_63(pred, __VA_ARGS__))
#define _MEOJSON_ARG_COUNT(...) \
_MEOJSON_EXPAND(_MEOJSON_ARG_COUNT1( \
0, \
##__VA_ARGS__, \
64, \
63, \
62, \
61, \
60, \
59, \
58, \
57, \
56, \
55, \
54, \
53, \
52, \
51, \
50, \
49, \
48, \
47, \
46, \
45, \
44, \
43, \
42, \
41, \
40, \
39, \
38, \
37, \
36, \
35, \
34, \
33, \
32, \
31, \
30, \
29, \
28, \
27, \
26, \
25, \
24, \
23, \
22, \
21, \
20, \
19, \
18, \
17, \
16, \
15, \
14, \
13, \
12, \
11, \
10, \
9, \
8, \
7, \
6, \
5, \
4, \
3, \
2, \
1, \
0))
#define _MEOJSON_ARG_COUNT1( \
_0, \
_1, \
_2, \
_3, \
_4, \
_5, \
_6, \
_7, \
_8, \
_9, \
_10, \
_11, \
_12, \
_13, \
_14, \
_15, \
_16, \
_17, \
_18, \
_19, \
_20, \
_21, \
_22, \
_23, \
_24, \
_25, \
_26, \
_27, \
_28, \
_29, \
_30, \
_31, \
_32, \
_33, \
_34, \
_35, \
_36, \
_37, \
_38, \
_39, \
_40, \
_41, \
_42, \
_43, \
_44, \
_45, \
_46, \
_47, \
_48, \
_49, \
_50, \
_51, \
_52, \
_53, \
_54, \
_55, \
_56, \
_57, \
_58, \
_59, \
_60, \
_61, \
_62, \
_63, \
_64, \
N, \
...) \
#define _MEOJSON_ARG_COUNT(...) \
_MEOJSON_EXPAND(_MEOJSON_ARG_COUNT1(0, ##__VA_ARGS__, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, \
49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, \
30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, \
11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
#define _MEOJSON_ARG_COUNT1(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, \
_20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, \
_38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, \
_56, _57, _58, _59, _60, _61, _62, _63, _64, N, ...) \
N
#define _MEOJSON_FOR_EACH_(N, pred, ...) \
_MEOJSON_EXPAND(_MEOJSON_CONCATENATE(_MEOJSON_FOR_EACH_, N)(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_(N, pred, ...) _MEOJSON_EXPAND(_MEOJSON_CONCATENATE(_MEOJSON_FOR_EACH_, N)(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH(pred, ...) \
_MEOJSON_EXPAND( \
_MEOJSON_FOR_EACH_(_MEOJSON_EXPAND(_MEOJSON_ARG_COUNT(__VA_ARGS__)), pred, __VA_ARGS__))
_MEOJSON_EXPAND(_MEOJSON_FOR_EACH_(_MEOJSON_EXPAND(_MEOJSON_ARG_COUNT(__VA_ARGS__)), pred, __VA_ARGS__))
#define _MEOJSON_VARNAME(x) _MEOJSON_CONCATENATE(_meojson_jsonization_, x)
#define _MEOJSON_KEY_VALUE(x) _MEOJSON_STRINGIZE(x), x,
} // namespace json::_private_macro
#define MEO_TOJSON(...) \
json::value to_json() const \
{ \
json::object result; \
json::_jsonization_helper::dumper()._to_json( \
result, \
_MEOJSON_EXPAND(_MEOJSON_FOR_EACH(_MEOJSON_KEY_VALUE, __VA_ARGS__)) \
json::_jsonization_helper::va_arg_end {}); \
return result; \
#define MEO_TOJSON(...) \
json::value to_json() const \
{ \
return json::_jsonization_helper::dumper()._to_json(_MEOJSON_EXPAND( \
_MEOJSON_FOR_EACH(_MEOJSON_KEY_VALUE, __VA_ARGS__)) json::_jsonization_helper::va_arg_end {}); \
}
#define MEO_CHECKJSON(...) \
bool check_json(const json::value& _MEOJSON_VARNAME(in)) const \
{ \
std::string _MEOJSON_VARNAME(error_key); \
return check_json(_MEOJSON_VARNAME(in), _MEOJSON_VARNAME(error_key)); \
} \
bool check_json( \
const json::value& _MEOJSON_VARNAME(in), \
std::string& _MEOJSON_VARNAME(error_key)) const \
{ \
return json::_jsonization_helper::checker()._check_json( \
_MEOJSON_VARNAME(in), \
_MEOJSON_VARNAME(error_key), \
_MEOJSON_EXPAND(_MEOJSON_FOR_EACH(_MEOJSON_KEY_VALUE, __VA_ARGS__)) \
json::_jsonization_helper::va_arg_end {}); \
#define MEO_CHECKJSON(...) \
bool check_json(const json::value& _MEOJSON_VARNAME(in)) const \
{ \
std::string _MEOJSON_VARNAME(error_key); \
return check_json(_MEOJSON_VARNAME(in), _MEOJSON_VARNAME(error_key)); \
} \
bool check_json(const json::value& _MEOJSON_VARNAME(in), std::string& _MEOJSON_VARNAME(error_key)) const \
{ \
return json::_jsonization_helper::checker()._check_json( \
_MEOJSON_VARNAME(in), _MEOJSON_VARNAME(error_key), \
_MEOJSON_EXPAND(_MEOJSON_FOR_EACH(_MEOJSON_KEY_VALUE, __VA_ARGS__)) \
json::_jsonization_helper::va_arg_end {}); \
}
#define MEO_FROMJSON(...) \
bool from_json(const json::value& _MEOJSON_VARNAME(in)) \
{ \
std::string _MEOJSON_VARNAME(error_key); \
return from_json(_MEOJSON_VARNAME(in), _MEOJSON_VARNAME(error_key)); \
} \
bool from_json( \
const json::value& _MEOJSON_VARNAME(in), \
std::string& _MEOJSON_VARNAME(error_key)) \
{ \
return json::_jsonization_helper::loader()._from_json( \
_MEOJSON_VARNAME(in), \
_MEOJSON_VARNAME(error_key), \
_MEOJSON_EXPAND(_MEOJSON_FOR_EACH(_MEOJSON_KEY_VALUE, __VA_ARGS__)) \
json::_jsonization_helper::va_arg_end {}); \
#define MEO_FROMJSON(...) \
bool from_json(const json::value& _MEOJSON_VARNAME(in)) \
{ \
std::string _MEOJSON_VARNAME(error_key); \
return from_json(_MEOJSON_VARNAME(in), _MEOJSON_VARNAME(error_key)); \
} \
bool from_json(const json::value& _MEOJSON_VARNAME(in), std::string& _MEOJSON_VARNAME(error_key)) \
{ \
return json::_jsonization_helper::loader()._from_json( \
_MEOJSON_VARNAME(in), _MEOJSON_VARNAME(error_key), \
_MEOJSON_EXPAND(_MEOJSON_FOR_EACH(_MEOJSON_KEY_VALUE, __VA_ARGS__)) \
json::_jsonization_helper::va_arg_end {}); \
}
#define MEO_JSONIZATION(...) \
@@ -641,7 +235,6 @@ namespace json::_private_macro
_MEOJSON_EXPAND(MEO_FROMJSON(__VA_ARGS__))
#define MEO_OPT json::_jsonization_helper::next_is_optional_t {},
#define MEO_KEY(key) json::_jsonization_helper::next_override_key_t { key },
#if defined(__clang__)
#pragma clang diagnostic pop // -Wgnu-zero-variadic-macro-arguments

View File

@@ -1,49 +1,15 @@
## v5.26.0-beta.1
### 新增 | New
* 次生预案十里坡剑神 @ABA2396
* 设置指引添加更新设置 @ABA2396
* 设置指引添加性能设置 @ABA2396
### 修复 | Fix
* 文档首页语言选择按钮的宽度定义方式 (#14199) @lucienshawls
* 傀影肉鸽无法识别四结局 (#14193) @Saratoga-Official
* GamePassSkip2 识别到错误的跳过 @Saratoga-Official
* 萨米肉鸽不期而遇避战 @Saratoga-Official
* Google Play Games Developer shutdown @Constrat
* manual set resource version time @MistEO
* prettier @Constrat
## v5.4.1
### 文档 | Docs
* 补充vsc插件繁中文档 @Rbqwow
*复文档站 readme 盾换行 @Rbqwow
* 调整文档站的标题和尾注文本显示 (#14213) @lucienshawls
* 更新网页开发相关文档 (#14167) @Rbqwow @Manicsteiner
* 完善任务流程协议文档 (#13232) @zzyyyl
* 回调消息协议文档视觉更新 @SherkeyXD
* 集成文档视觉更新 @SherkeyXD
* 文档启用 b 站视频播放功能 @SherkeyXD
* 文档添加字段容器功能 @SherkeyXD
* 文档添加功能 @SherkeyXD
* 更新文档编写指南 @SherkeyXD
* 标题 MAA 统一采用缩写 @MistEO
* 再次调整文档站标题( @MistEO
* 调整文档站标题 @MistEO
* Update JP(#14227) @wallsman
* markdown pre-commit @zzyyyl
* add extension's evaluating feature @neko-para
* add telegram icon @SherkeyXD
* website docs (#9287) @ABA2396 @Rbqwow @Constrat @wangl-cc @HX3N @SherkeyXD
*改win7相关问题描述&更新运行库 @Rbqwow
* fix a bad link @Rbqwow
* make i18n warnings show only once @Rbqwow
* 修复字体和评论区分类 @Rbqwow
### 其他 | Other
### For Overseas
* 统一显示效果 @ABA2396
* 水月萨米肉鸽不期而遇避战 @Saratoga-Official
* 重写完成后动作仅一次的 ui 字符串 (#14196) @Rbqwow
* 贸易站没其他好用的人再用锏 @ABA2396
* YostarJP Sarkaz roguelike StageEncounter (#14223) @Manicsteiner
* YostarJP sami roguelike 720p (#14210) @Manicsteiner
* YostarJP Mizuki StageEncounter (#14206) @Manicsteiner
* devcontainer.json (#14169) @Rbqwow @lucienshawls
#### YostarEN
* YoStarEN resolution warning on client switch (#9539) @Constrat @ABA2396

View File

@@ -1,61 +1,191 @@
cmake_minimum_required(VERSION 3.28)
project(MAA)
cmake_minimum_required(VERSION 3.21)
project(MaaAssistantArknights)
if(NOT CMAKE_BUILD_TYPE)
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build." FORCE)
endif()
endif ()
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/modules")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
option(BUILD_WPF_GUI "build MaaWpfGui" ${WIN32})
option(BUILD_DEBUG_DEMO "build debug demo" OFF)
option(BUILD_TEST "build a demo" OFF)
option(BUILD_XCFRAMEWORK "build xcframework for macOS app" OFF)
option(BUILD_SMOKE_TEST "build smoke_test" OFF)
option(BUILD_UNIVERSAL "build both arm64 and x86_64 on macOS" OFF)
option(INSTALL_PYTHON "install python ffi" OFF)
option(INSTALL_RESOURCE "install resource" OFF)
option(INSTALL_DEVEL "install development files" OFF)
option(INSTALL_FLATTEN "do not use bin lib include directory" ON)
option(INSTALL_THIRD_LIBS "install third party libraries" ON)
option(USE_MAADEPS "use third-party libraries built by MaaDeps" ON)
option(USE_RANGE_V3 "use range-v3" OFF)
option(WITH_EMULATOR_EXTRAS "build with emulator extras" ${WIN32})
option(WITH_HASH_VERSION "generate version from git hash" OFF)
option(WITH_THRIFT "build with thrift" OFF)
option(WITH_ASST_DEBUG "build with ASST_DEBUG defined" OFF)
include(${PROJECT_SOURCE_DIR}/MaaDeps/maadeps.cmake)
include(${PROJECT_SOURCE_DIR}/cmake/config.cmake)
include(${PROJECT_SOURCE_DIR}/cmake/utils.cmake)
include(${PROJECT_SOURCE_DIR}/cmake/version.cmake)
include(${PROJECT_SOURCE_DIR}/cmake/thrift-gen.cmake)
if(USE_MAADEPS)
include(${PROJECT_SOURCE_DIR}/MaaDeps/maadeps.cmake)
endif()
add_library(header_only_libraries INTERFACE)
target_include_directories(header_only_libraries INTERFACE 3rdparty/include 3rdparty/EmulatorExtras)
file(GLOB_RECURSE maa_src src/MaaCore/*.cpp)
add_library(MaaCore SHARED ${maa_src})
if (MSVC)
target_compile_options(MaaCore PRIVATE "/utf-8")
target_compile_options(MaaCore PRIVATE "/MP")
target_compile_options(MaaCore PRIVATE "/W4;/WX")
target_compile_options(MaaCore PRIVATE "/wd4127") # conditional expression is constant
target_compile_options(MaaCore PRIVATE "/Wv:19.35.32217") # disable warning introduced after this version
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
else ()
target_compile_options(MaaCore PRIVATE "-Wall;-Werror;-Wextra;-Wpedantic;-Wno-missing-field-initializers")
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13)
target_compile_options(MaaCore PRIVATE "-Wno-restrict")
endif()
endif ()
if (WIN32)
#注意相比VS版本缺少了 -D_CONSOLE -D_WINDLL 两项
target_compile_definitions(MaaCore PRIVATE ASST_DLL_EXPORTS _UNICODE UNICODE)
endif ()
target_include_directories(MaaCore PUBLIC include PRIVATE src/MaaCore)
set(MaaCore_PUBLIC_HEADERS include/AsstCaller.h include/AsstPort.h)
target_sources(MaaCore PUBLIC ${MaaCore_PUBLIC_HEADERS})
set_target_properties(MaaCore PROPERTIES
CXX_STANDARD 20
CXX_STANDARD_REQUIRED ON
PUBLIC_HEADER "${MaaCore_PUBLIC_HEADERS}"
)
if(APPLE)
include(${PROJECT_SOURCE_DIR}/cmake/macos.cmake)
set_target_properties(MaaCore PROPERTIES INSTALL_RPATH "@loader_path/")
elseif(UNIX)
set_target_properties(MaaCore PROPERTIES INSTALL_RPATH "$ORIGIN/")
endif()
if (BUILD_TEST)
add_executable(test src/Cpp/main.cpp)
set_target_properties(test PROPERTIES
CXX_STANDARD 20
CXX_STANDARD_REQUIRED ON
)
target_link_libraries(test MaaCore)
endif (BUILD_TEST)
find_package(OpenCV REQUIRED COMPONENTS core imgproc imgcodecs videoio)
find_package(ZLIB REQUIRED)
find_package(cpr CONFIG REQUIRED)
list(APPEND maa_libs ${OpenCV_LIBS} ZLIB::ZLIB cpr::cpr header_only_libraries)
if(USE_MAADEPS)
find_package(asio REQUIRED)
list(APPEND maa_libs asio::asio)
endif()
find_package(onnxruntime CONFIG REQUIRED) # provided by onnxruntime>=1.16
list(APPEND maa_libs onnxruntime::onnxruntime)
if(DEFINED fastdeploy_SOURCE_DIR)
# TODO: FetchContent github.com/MaaAssistantArknights/FastDeploy
if(NOT DEFINED fastdeploy_BINARY_DIR)
set(fastdeploy_BINARY_DIR ${CMAKE_BINARY_DIR}/fastdeploy)
endif()
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
add_subdirectory(${fastdeploy_SOURCE_DIR} ${fastdeploy_BINARY_DIR} EXCLUDE_FROM_ALL SYSTEM)
if(NOT DEFINED fastdeploy_INCLUDE_DIRS)
set(fastdeploy_INCLUDE_DIRS ${fastdeploy_SOURCE_DIR})
endif()
target_include_directories(MaaCore SYSTEM PRIVATE ${fastdeploy_INCLUDE_DIRS})
get_target_property(fastdeploy_type fastdeploy_ppocr TYPE)
if(fastdeploy_type STREQUAL "SHARED_LIBRARY")
install(TARGETS fastdeploy_ppocr)
endif()
else()
find_package(fastdeploy_ppocr REQUIRED)
endif()
list(APPEND maa_libs fastdeploy_ppocr)
target_link_libraries(MaaCore ${maa_libs})
if(WITH_EMULATOR_EXTRAS AND NOT EXISTS ${PROJECT_SOURCE_DIR}/3rdparty/EmulatorExtras/Mumu)
message(WARNING "EmulatorExtras not found, please run `git submodule update --init 3rdparty/EmulatorExtras`")
set(WITH_EMULATOR_EXTRAS OFF)
endif()
target_compile_definitions(MaaCore PRIVATE ASST_WITH_EMULATOR_EXTRAS=$<BOOL:${WITH_EMULATOR_EXTRAS}>)
if(WITH_THRIFT)
find_package(Thrift CONFIG REQUIRED)
add_subdirectory(src/MaaThriftController)
target_link_libraries(MaaCore MaaThriftController)
endif(WITH_THRIFT)
if (WITH_ASST_DEBUG)
target_compile_definitions(MaaCore PRIVATE ASST_DEBUG)
endif ()
if(WIN32)
target_link_libraries(MaaCore ws2_32)
endif()
if (USE_RANGE_V3)
target_compile_definitions(MaaCore PRIVATE ASST_USE_RANGES_RANGE_V3)
find_package(range-v3 REQUIRED)
target_link_libraries(MaaCore range-v3::range-v3)
endif ()
if(INSTALL_DEVEL)
set(MaaCore_install_extra_args PUBLIC_HEADER DESTINATION devel/include ARCHIVE DESTINATION devel/lib)
endif()
if(INSTALL_FLATTEN)
set(MaaCore_install_flatten_args RUNTIME DESTINATION . LIBRARY DESTINATION . PUBLIC_HEADER DESTINATION .)
endif()
add_library(HeaderOnlyLibraries INTERFACE)
target_include_directories(HeaderOnlyLibraries INTERFACE 3rdparty/include)
install(TARGETS MaaCore ${MaaCore_install_flatten_args} ${MaaCore_install_extra_args})
find_package(OpenCV REQUIRED COMPONENTS core imgproc imgcodecs)
find_package(Boost REQUIRED CONFIG COMPONENTS system)
find_package(ZLIB REQUIRED)
find_package(fastdeploy_ppocr REQUIRED)
find_package(ONNXRuntime REQUIRED)
add_subdirectory(src/MaaCore)
if(BUILD_WPF_GUI)
include_external_msproject(MaaWpfGui ${PROJECT_SOURCE_DIR}/src/MaaWpfGui/MaaWpfGui.csproj)
add_dependencies(MaaWpfGui MaaCore)
if(INSTALL_THIRD_LIBS AND USE_MAADEPS)
maadeps_install()
endif()
if(INSTALL_PYTHON)
if (INSTALL_PYTHON)
install(DIRECTORY src/Python DESTINATION .)
endif()
if(INSTALL_RESOURCE)
endif (INSTALL_PYTHON)
if (INSTALL_RESOURCE)
install(DIRECTORY resource DESTINATION .)
endif()
endif (INSTALL_RESOURCE)
if(BUILD_DEBUG_DEMO OR BUILD_SMOKE_TEST)
add_subdirectory(src/Cpp)
endif()
if (APPLE)
include(${PROJECT_SOURCE_DIR}/cmake/macos.cmake)
endif (APPLE)
# define MAA_VERSION from git
if (NOT DEFINED MAA_VERSION)
find_package(Git)
endif ()
if (NOT DEFINED MAA_VERSION AND GIT_FOUND)
execute_process(
COMMAND "${GIT_EXECUTABLE}" rev-parse HEAD
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE result
OUTPUT_VARIABLE output
ERROR_VARIABLE err
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if (result EQUAL 0)
set(MAA_VERSION "${output}")
else ()
message(WARNING "git rev-parse returning ${result}, output:\n${err}")
endif ()
endif ()
if (NOT MAA_VERSION)
set(MAA_VERSION "DEBUG VERSION")
endif ()
message(STATUS "MAA_VERSION=${MAA_VERSION}")
add_compile_definitions(MAA_VERSION="${MAA_VERSION}")

15
MAA.DotSettings Normal file
View File

@@ -0,0 +1,15 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=Arknights/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Bilibili/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Infrast/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=oper/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=opers/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Pallas/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Pormpt/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Rougelike/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=templ/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=thres/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Todays/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=txwy/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=vuvm/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=XYAZ/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

106
MAA.sln Normal file
View File

@@ -0,0 +1,106 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.2.32616.157
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MaaWpfGui", "src\MaaWpfGui\MaaWpfGui.csproj", "{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}"
ProjectSection(ProjectDependencies) = postProject
{362D1E30-F5AE-4279-9985-65C27B3BA300} = {362D1E30-F5AE-4279-9985-65C27B3BA300}
{F860C043-4D86-41B6-A97E-4A75C9A6C4EC} = {F860C043-4D86-41B6-A97E-4A75C9A6C4EC}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MaaCore", "src\MaaCore\MaaCore.vcxproj", "{362D1E30-F5AE-4279-9985-65C27B3BA300}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MaaThriftController", "src\MaaThriftController\MaaThriftController.vcxproj", "{8238EDB1-19BF-4E3B-AF5B-016120D59D7B}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{11F02235-5785-408B-9651-8A4B41FF36F4}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SyncRes", "src\SyncRes\SyncRes.csproj", "{F860C043-4D86-41B6-A97E-4A75C9A6C4EC}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Sample", "src\Cpp\MaaSample.vcxproj", "{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}"
ProjectSection(ProjectDependencies) = postProject
{362D1E30-F5AE-4279-9985-65C27B3BA300} = {362D1E30-F5AE-4279-9985-65C27B3BA300}
{F860C043-4D86-41B6-A97E-4A75C9A6C4EC} = {F860C043-4D86-41B6-A97E-4A75C9A6C4EC}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM64 = Debug|ARM64
Debug|x64 = Debug|x64
Release|ARM64 = Release|ARM64
Release|x64 = Release|x64
RelWithDebInfo|ARM64 = RelWithDebInfo|ARM64
RelWithDebInfo|x64 = RelWithDebInfo|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Debug|ARM64.ActiveCfg = Debug|ARM64
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Debug|ARM64.Build.0 = Debug|ARM64
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Debug|x64.ActiveCfg = Debug|x64
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Debug|x64.Build.0 = Debug|x64
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|ARM64.ActiveCfg = Release|ARM64
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|ARM64.Build.0 = Release|ARM64
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|x64.ActiveCfg = Release|x64
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|x64.Build.0 = Release|x64
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.RelWithDebInfo|ARM64.ActiveCfg = RelWithDebInfo|ARM64
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.RelWithDebInfo|ARM64.Build.0 = RelWithDebInfo|ARM64
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Debug|ARM64.ActiveCfg = Debug|ARM64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Debug|ARM64.Build.0 = Debug|ARM64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Debug|x64.ActiveCfg = Debug|x64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Debug|x64.Build.0 = Debug|x64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|ARM64.ActiveCfg = Release|ARM64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|ARM64.Build.0 = Release|ARM64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|x64.ActiveCfg = Release|x64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|x64.Build.0 = Release|x64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.RelWithDebInfo|ARM64.ActiveCfg = RelWithDebInfo|ARM64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.RelWithDebInfo|ARM64.Build.0 = RelWithDebInfo|ARM64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
{8238EDB1-19BF-4E3B-AF5B-016120D59D7B}.Debug|ARM64.ActiveCfg = Debug|ARM64
{8238EDB1-19BF-4E3B-AF5B-016120D59D7B}.Debug|ARM64.Build.0 = Debug|ARM64
{8238EDB1-19BF-4E3B-AF5B-016120D59D7B}.Debug|x64.ActiveCfg = Debug|x64
{8238EDB1-19BF-4E3B-AF5B-016120D59D7B}.Debug|x64.Build.0 = Debug|x64
{8238EDB1-19BF-4E3B-AF5B-016120D59D7B}.Release|ARM64.ActiveCfg = Release|ARM64
{8238EDB1-19BF-4E3B-AF5B-016120D59D7B}.Release|ARM64.Build.0 = Release|ARM64
{8238EDB1-19BF-4E3B-AF5B-016120D59D7B}.Release|x64.ActiveCfg = Release|x64
{8238EDB1-19BF-4E3B-AF5B-016120D59D7B}.Release|x64.Build.0 = Release|x64
{8238EDB1-19BF-4E3B-AF5B-016120D59D7B}.RelWithDebInfo|ARM64.ActiveCfg = RelWithDebInfo|ARM64
{8238EDB1-19BF-4E3B-AF5B-016120D59D7B}.RelWithDebInfo|ARM64.Build.0 = RelWithDebInfo|ARM64
{8238EDB1-19BF-4E3B-AF5B-016120D59D7B}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
{8238EDB1-19BF-4E3B-AF5B-016120D59D7B}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
{F860C043-4D86-41B6-A97E-4A75C9A6C4EC}.Debug|ARM64.ActiveCfg = Debug|ARM64
{F860C043-4D86-41B6-A97E-4A75C9A6C4EC}.Debug|ARM64.Build.0 = Debug|ARM64
{F860C043-4D86-41B6-A97E-4A75C9A6C4EC}.Debug|x64.ActiveCfg = Debug|x64
{F860C043-4D86-41B6-A97E-4A75C9A6C4EC}.Debug|x64.Build.0 = Debug|x64
{F860C043-4D86-41B6-A97E-4A75C9A6C4EC}.Release|ARM64.ActiveCfg = Release|ARM64
{F860C043-4D86-41B6-A97E-4A75C9A6C4EC}.Release|ARM64.Build.0 = Release|ARM64
{F860C043-4D86-41B6-A97E-4A75C9A6C4EC}.Release|x64.ActiveCfg = Release|x64
{F860C043-4D86-41B6-A97E-4A75C9A6C4EC}.Release|x64.Build.0 = Release|x64
{F860C043-4D86-41B6-A97E-4A75C9A6C4EC}.RelWithDebInfo|ARM64.ActiveCfg = RelWithDebInfo|ARM64
{F860C043-4D86-41B6-A97E-4A75C9A6C4EC}.RelWithDebInfo|ARM64.Build.0 = RelWithDebInfo|ARM64
{F860C043-4D86-41B6-A97E-4A75C9A6C4EC}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
{F860C043-4D86-41B6-A97E-4A75C9A6C4EC}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.Debug|ARM64.ActiveCfg = Debug|ARM64
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.Debug|ARM64.Build.0 = Debug|ARM64
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.Debug|x64.ActiveCfg = Debug|x64
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.Debug|x64.Build.0 = Debug|x64
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.Release|ARM64.ActiveCfg = Release|ARM64
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.Release|ARM64.Build.0 = Release|ARM64
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.Release|x64.ActiveCfg = Release|x64
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.Release|x64.Build.0 = Release|x64
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.RelWithDebInfo|ARM64.ActiveCfg = RelWithDebInfo|ARM64
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.RelWithDebInfo|ARM64.Build.0 = RelWithDebInfo|ARM64
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4F2C0E4B-4FE9-47C6-A878-6BD2FAD8B9B2}
EndGlobalSection
EndGlobal

122
MAA.sln.DotSettings Normal file
View File

@@ -0,0 +1,122 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GUI/@EntryIndexedValue">GUI</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SWMINIMIZE/@EntryIndexedValue">SWMINIMIZE</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=AP/@EntryIndexedValue">AP</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=AP_002D/@EntryIndexedValue">AP-</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=CA/@EntryIndexedValue">CA</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=CA_002D/@EntryIndexedValue">CA-</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=CE/@EntryIndexedValue">CE</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=CE_002D/@EntryIndexedValue">CE-</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=EN/@EntryIndexedValue">EN</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=IS/@EntryIndexedValue">IS</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=JP/@EntryIndexedValue">JP</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=KR/@EntryIndexedValue">KR</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=LD/@EntryIndexedValue">LD</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=LS/@EntryIndexedValue">LS</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=LS_002D/@EntryIndexedValue">LS-</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=PR_002DA/@EntryIndexedValue">PR-A</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=PR_002DA_002D/@EntryIndexedValue">PR-A-</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=PR_002DB/@EntryIndexedValue">PR-B</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=PR_002DB_002D/@EntryIndexedValue">PR-B-</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=PR_002DC/@EntryIndexedValue">PR-C</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=PR_002DC_002D/@EntryIndexedValue">PR-C-</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=PR_002DD/@EntryIndexedValue">PR-D</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=PR_002DD_002D/@EntryIndexedValue">PR-D-</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=SK/@EntryIndexedValue">SK</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=SK_002D/@EntryIndexedValue">SK-</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=SSS/@EntryIndexedValue">SSS</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=WSA/@EntryIndexedValue">WSA</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/Abbreviations/=XYAZ/@EntryIndexedValue">XYAZ</s:String>
<s:Boolean x:Key="/Default/UserDictionary/Words/=acast/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Aero/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=aguard/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=amedic/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=amiya/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=apionr/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=arget/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Arknights/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=arkplanner/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=asnipe/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=autofill/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Bilibili/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Bluestacks/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=bsconsole/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ctrler/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=desp/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=dnplayer/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Ehem/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=esource/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Favourite/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=findstr/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=FLASHW/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=FLASHWINFO/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=foldartal/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Foldartals/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=framerate/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=furni/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Gacha/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Gavial/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Grandet/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Hotkey/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=hwnd/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Infrast/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Inited/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ldconsole/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Lolicon/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=lpwndpl/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ls_005B_0022sub/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=luestacks/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=maatouch/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=memuc/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Minitouch/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Mizuki/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Mumu/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Nemu/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Netease/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=netstat/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Nonfriend/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=notstationed/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=oper/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=opers/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Originite/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Originium/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=originiums/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Orundum/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Orundums/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=o_FF9Fv_FF9F/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Pallas/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=pidl/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Pormpt/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ppidl/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Prts/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=pwfi/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=rcast/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=rdfend/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=rguard/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=rmean/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=rmedic/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Roguelike/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=rsnipe/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Sami/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Screencap/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=serilog/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Showminimized/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Shownormal/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=specialaccess/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=SSS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=STGM/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=strlen/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Stylet/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=subtask/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Suppressions/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=SWMINIMIZE/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=taskchain/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Todays/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=txwy/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ucrtbase/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=XYAZ/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Yahei/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=yituliu/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0020_0020_0020wp_002ELength_0020/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0020_003D_0020stri/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

1
MaaDeps Submodule

Submodule MaaDeps added at 10d51f5832

105
README.md
View File

@@ -2,9 +2,9 @@
<div align="center">
<img alt="LOGO" src="./docs/.vuepress/public/images/maa-logo_512x512.png" width="256" height="256" />
<img alt="LOGO" src="https://cdn.jsdelivr.net/gh/MaaAssistantArknights/design@main/logo/maa-logo_512x512.png" width="256" height="256" />
# MAA
# MaaAssistantArknights
<br>
<div>
@@ -25,7 +25,7 @@
<!-- markdownlint-restore -->
[简体中文](https://docs.maa.plus/zh-cn/) | [繁體中文](https://docs.maa.plus/zh-tw/) | [English](https://docs.maa.plus/en-us/) | [日本語](https://docs.maa.plus/ja-jp/) | [한국어](https://docs.maa.plus/ko-kr/)
[简体中文](https://maa.plus/docs/zh-cn/) | [繁體中文](https://maa.plus/docs/zh-tw/) | [English](https://maa.plus/docs/en-us/) | [日本語](https://maa.plus/docs/ja-jp/) | [한국어](https://maa.plus/docs/ko-kr/)
MAA 的意思是 MAA Assistant Arknights
@@ -33,20 +33,16 @@ MAA 的意思是 MAA Assistant Arknights
基于图像识别技术,一键完成全部日常任务!
绝赞更新中 ✿✿ヽ(°▽°)ノ✿
绝赞更新中 ✿✿ヽ(°▽°)ノ✿
</div>
## 下载与安装
请阅读 [文档](https://docs.maa.plus/zh-cn/manual/newbie.html) 后前往 [官网](https://maa.plus) 或 [Releases](https://github.com/MaaAssistantArknights/MaaAssistantArknights/releases) 下载,并参考 [新手上路](https://docs.maa.plus/zh-cn/manual/newbie.html) 进行安装。
## 亮点功能
- 刷理智,掉落识别及上传 [企鹅物流](https://penguin-stats.cn/)[一图流](https://ark.yituliu.cn/)
- 智能基建换班,自动计算干员效率,单设施内最优解;同时也支持 [自定义排班](https://docs.maa.plus/zh-cn/protocol/base-scheduling-schema.html)
- 智能基建换班,自动计算干员效率,单设施内最优解;同时也支持 [自定义排班](https://maa.plus/docs/zh-cn/protocol/base-scheduling-schema.html)
- 自动公招,可选使用加急许可,一次全部刷完!公招数据自动上传 [企鹅物流](https://penguin-stats.cn/result/stage/recruit/recruit)[一图流](https://ark.yituliu.cn/survey/maarecruitdata)
- 支持手动识别公招界面,方便对高星公招做出选择 ~~(你的这个高回费出的是推王呢还是推王呢)~~
- 支持手动识别公招界面,方便对高星公招做出选择 ~~(你的这个高姿回费出的是推王呢还是推王呢)~~
- 支持识别干员列表,统计已有和未有干员及潜能,并在公招识别显示
- 支持识别养成材料,并导出至 [企鹅物流刷图规划](https://penguin-stats.cn/planner)、[明日方舟工具箱](https://arkntools.app/#/material)、[ARK-NIGHTS 干员培养表](https://ark-nights.com/settings)
- 访问好友、收取信用及购物、领取日常奖励等,一键全日常自动长草
@@ -59,40 +55,59 @@ MAA 的意思是 MAA Assistant Arknights
<details><summary>话不多说,看图!</summary>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./docs/.vuepress/public/images/zh-cn/readme/1-dark.png">
<img alt="zh1" src="./docs/.vuepress/public/images/zh-cn/readme/1-light.png">
<source media="(prefers-color-scheme: dark)" srcset="./docs/.vuepress/public/image/zh-cn/readme/1-dark.png">
<img alt="zh1" src="./docs/.vuepress/public/image/zh-cn/readme/1-light.png">
</picture>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./docs/.vuepress/public/images/zh-cn/readme/2-dark.png">
<img alt="zh2" src="./docs/.vuepress/public/images/zh-cn/readme/2-light.png">
<source media="(prefers-color-scheme: dark)" srcset="./docs/.vuepress/public/image/zh-cn/readme/2-dark.png">
<img alt="zh2" src="./docs/.vuepress/public/image/zh-cn/readme/2-light.png">
</picture>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./docs/.vuepress/public/images/zh-cn/readme/3-dark.png">
<img alt="zh3" src="./docs/.vuepress/public/images/zh-cn/readme/3-light.png">
<source media="(prefers-color-scheme: dark)" srcset="./docs/.vuepress/public/image/zh-cn/readme/3-dark.png">
<img alt="zh3" src="./docs/.vuepress/public/image/zh-cn/readme/3-light.png">
</picture>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./docs/.vuepress/public/images/zh-cn/readme/4-dark.png">
<img alt="zh4" src="./docs/.vuepress/public/images/zh-cn/readme/4-light.png">
<source media="(prefers-color-scheme: dark)" srcset="./docs/.vuepress/public/image/zh-cn/readme/4-dark.png">
<img alt="zh4" src="./docs/.vuepress/public/image/zh-cn/readme/4-light.png">
</picture>
</details>
<!-- markdownlint-restore -->
## 下载地址
前往[官网](https://maa.plus)自动匹配镜像源并下载稳定版,或:
- [稳定版/公测版](https://github.com/MaaAssistantArknights/MaaAssistantArknights/releases)
- [内测版](https://github.com/MaaAssistantArknights/MaaRelease/releases)
## 使用说明
### 功能介绍
### 基本说明
请参阅 [用户手册](https://docs.maa.plus/zh-cn/manual/)。
请参阅 [新手上路](https://maa.plus/docs/zh-cn/manual/newbie.html) 与 [功能介绍](https://maa.plus/docs/zh-cn/manual/introduction/)。
### 常见问题
- 软件一打开就闪退;
- 连接错误、不知道 ADB 路径怎么填写;
- 连接成功了,但没反应;
- 如何连接自定义端口;
- 下载速度慢,且镜像站无法打开网页;
- 下载到一半提示“登陆”/“鉴权”;
- 连接正常,任务开始了,但是没反应。
请参阅 [常见问题](https://maa.plus/docs/zh-cn/manual/faq.html)
### 外服支持
目前国际服(美服)、日服、韩服、繁中服的绝大部分功能均已支持。但由于外服用户较少及项目人手不足,很多功能并没有进行全面的测试,所以请自行体验。
若您遇到了 Bug或对某个功能有强需求欢迎在 [Issues](https://github.com/MaaAssistantArknights/MaaAssistantArknights/issues) 和 [讨论区](https://github.com/MaaAssistantArknights/MaaAssistantArknights/discussions) 催更;或加入我们一起建设 MAA请参阅 [外服适配教程](https://docs.maa.plus/zh-cn/develop/overseas-client-adaptation.html)
若您遇到了 Bug或对某个功能有强需求欢迎在 [Issues](https://github.com/MaaAssistantArknights/MaaAssistantArknights/issues) 和 [讨论区](https://github.com/MaaAssistantArknights/MaaAssistantArknights/discussions) 催更;或加入我们一起建设 MAA请参阅 [外服适配教程](https://maa.plus/docs/zh-cn/develop/overseas-client-adaptation.html)
### CLI 支持
MAA 支持命令行界面CLI操作支持 LinuxmacOS 和 Windows可用于自动化脚本或在无图形界面的服务器上使用。请参阅 [CLI 使用指南](https://docs.maa.plus/zh-cn/manual/cli/)
MAA 支持命令行界面CLI操作支持 LinuxmacOS 和 Windows可用于自动化脚本或在无图形界面的服务器上使用。请参阅 [CLI 使用指南](https://maa.plus/docs/zh-cn/manual/cli/intro.html)
## 加入我们
@@ -101,6 +116,7 @@ MAA 支持命令行界面CLI操作支持 LinuxmacOS 和 Windows
**目前项目组非常缺前端大佬,若您有相关经验,欢迎加入我们!**
- 全新框架:[MaaFramework](https://github.com/MaaXYZ/MaaFramework)
- 全新 GUI[MaaX](https://github.com/MaaAssistantArknights/MaaX)
- [作业站](https://prts.plus) 前端:[maa-copilot-frontend](https://github.com/MaaAssistantArknights/maa-copilot-frontend)
- [作业站](https://prts.plus) 后端:[MaaBackendCenter](https://github.com/MaaAssistantArknights/MaaBackendCenter)
- [官网](https://maa.plus)[前端](https://github.com/MaaAssistantArknights/maa-website)
@@ -108,17 +124,21 @@ MAA 支持命令行界面CLI操作支持 LinuxmacOS 和 Windows
### 多语言 (i18n)
MAA 支持多国语言,并使用 Weblate 进行本地化管理。如果您通晓多门语言,欢迎前往 [MAA Weblate](https://weblate.maa-org.net) 帮助我们进行翻译。
MAA 以中文(简体)为第一语言,翻译词条均以中文(简体)为准。
[![Weblate](https://weblate.maa-org.net/widget/maa/wpf-gui/multi-auto.svg)](https://weblate.maa-org.net/engage/maa/)
### 参与开发
#### Windows
请参阅 [开始开发](https://docs.maa.plus/zh-cn/develop/development.html)。
请参阅 [开始开发](https://maa.plus/docs/zh-cn/develop/development.html)。
#### Linux | macOS
请参阅 [Linux 编译教程](https://docs.maa.plus/zh-cn/develop/linux-tutorial.html)。
请参阅 [Linux 编译教程](https://maa.plus/docs/zh-cn/develop/linux-tutorial.html)。
#### API
@@ -131,22 +151,22 @@ MAA 以中文(简体)为第一语言,翻译词条均以中文(简体)
- [Rust 接口](src/Rust/src/maa_sys)[HTTP 接口](src/Rust)
- [TypeScript 接口](https://github.com/MaaAssistantArknights/MaaX/tree/main/packages/main/coreLoader)
- [Woolang 接口](src/Woolang/maa.wo)[集成示例](src/Woolang/demo.wo)
- [集成文档](https://docs.maa.plus/zh-cn/protocol/integration.html)
- [回调消息协议](https://docs.maa.plus/zh-cn/protocol/callback-schema.html)
- [任务流程协议](https://docs.maa.plus/zh-cn/protocol/task-schema.html)
- [自动抄作业协议](https://docs.maa.plus/zh-cn/protocol/copilot-schema.html)
- [集成文档](https://maa.plus/docs/zh-cn/protocol/integration.html)
- [回调消息协议](https://maa.plus/docs/zh-cn/protocol/callback-schema.html)
- [任务流程协议](https://maa.plus/docs/zh-cn/protocol/task-schema.html)
- [自动抄作业协议](https://maa.plus/docs/zh-cn/protocol/copilot-schema.html)
#### 外服适配
请参阅 [外服适配教程](https://docs.maa.plus/zh-cn/develop/overseas-client-adaptation.html),对于国服已支持的功能,绝大部分的外服适配工作仅需要截图 + 简单的 JSON 修改即可。
请参阅 [外服适配教程](https://maa.plus/docs/zh-cn/develop/overseas-client-adaptation.html),对于国服已支持的功能,绝大部分的外服适配工作仅需要截图 + 简单的 JSON 修改即可。
#### 想参与开发,但不太会用 GitHub?
[GitHub Pull Request 流程简述](https://docs.maa.plus/zh-cn/develop/development.html#github-pull-request-流程简述)
[GitHub Pull Request 流程简述](https://maa.plus/docs/zh-cn/develop/development.html#github-pull-request-流程简述)
#### Issue bot
请参阅 [Issue Bot 使用方法](https://docs.maa.plus/zh-cn/develop/issue-bot-usage.html)
请参阅 [Issue Bot 使用方法](https://maa.plus/docs/zh-cn/develop/issue-bot-usage.html)
## 致谢
@@ -178,33 +198,28 @@ MAA 以中文(简体)为第一语言,翻译词条均以中文(简体)
- ~~干员及基建数据:[PRTS Wiki](http://prts.wiki/)~~
- 关卡数据:[企鹅物流数据统计](https://penguin-stats.cn/)
- 游戏数据及资源:[明日方舟客户端素材](https://github.com/yuanyan3060/ArknightsGameResource)
- 游戏数据:[《明日方舟》Yostar游戏数据](https://github.com/ArknightsAssets/ArknightsGamedata)
- ~~游戏数据:[《明日方舟》游戏数据](https://github.com/Kengxxiao/ArknightsGameData)~~
### 贡献/参与者
感谢所有参与到开发/测试中的朋友们,是大家的帮助让 MAA 越来越好! (\*´▽`)
[![Contributors](https://contributors-img.web.app/image?repo=MaaAssistantArknights/MaaAssistantArknights&max=105&columns=15)](https://github.com/MaaAssistantArknights/MaaAssistantArknights/graphs/contributors)
[![Contributors](https://contributors-img.web.app/image?repo=MaaAssistantArknights/MaaAssistantArknights&max=114514&columns=15)](https://github.com/MaaAssistantArknights/MaaAssistantArknights/graphs/contributors)
## 声明
- 本软件使用 [GNU Affero General Public License v3.0 only](https://spdx.org/licenses/AGPL-3.0-only.html) 开源,并附带额外 [用户协议](https://github.com/MaaAssistantArknights/MaaAssistantArknights/blob/dev/terms-of-service.md)
- 本软件 logo 并非使用 AGPL 3.0 协议开源,[耗毛](https://weibo.com/u/3251357314)、vie 两位画师及软件全体开发者保留所有权利。不得以 AGPL 3.0 协议已授权为由在未经授权的情况下使用本软件 logo不得在未经授权的情况下将本软件 logo 用于任何商业用途。
- 本软件开源、免费,仅供学习交流使用。若您遇到商家使用本软件进行代练并收费,可能设备时间等费用,产生的问题及后果与本软件无关。
### DirectML 支持说明
本软件支持 GPU 加速功能,其在 Windows 平台上依赖于 Microsoft 提供的独立组件 [DirectML](https://learn.microsoft.com/en-us/windows/ai/directml/)。DirectML 并非本项目的开源部分,也不受 AGPL 3.0 的约束。为方便用户,我们随安装包附带了一个未经修改的 DirectML.dll 文件。如果您无需 GPU 加速功能,可安全删除该 DLL 文件,软件的核心功能仍可正常运行。
- 本软件使用 [GNU Affero General Public License v3.0 only](https://spdx.org/licenses/AGPL-3.0-only.html) 开源。
- 本软件 logo 并非使用 AGPL 3.0 协议开源,[耗毛](https://weibo.com/u/3251357314)、vie 两位画师及软件全体开发者保留所有权利。不得以 AGPL 3.0 协议已授权为由在未经授权的情况下使用本软件 logo不得在未经授权的情况下将本软件 logo 用于任何用途。
- 本软件开源、免费,仅供学习交流使用。若您遇到商家使用本软件进行代练并收费,可能由于设备时间等原因,产生的任何问题及后果与本软件无关。
## 广告
用户交流 QQ 群:[MAA 使用 & 粥游交流 QQ 群](https://api.maa.plus/MaaAssistantArknights/api/qqgroup/index.html)
Discord 服务器: [邀请链接](https://discord.gg/23DfZ9uA4V)
用户交流 QQ 群:[MAA 使用 & 粥游交流 QQ 群](https://ota.maa.plus/MaaAssistantArknights/api/qqgroup/index.html)
用户交流 TG 群:[Telegram 群](https://t.me/+Mgc2Zngr-hs3ZjU1)
自动战斗 JSON 作业分享:[prts.plus](https://prts.plus)
Bilibili 直播间:[MrEO 直播间](https://live.bilibili.com/2808861) 直播敲代码 & [MAA-Official 直播间](https://live.bilibili.com/27548877) 游戏/杂谈
自动战斗 JSON 作业分享:[prts.plus](https://prts.plus) 或 [抄作业.com](http://抄作业.com)
Bilibili 直播间:[直播间](https://live.bilibili.com/2808861) 每晚直播敲代码,近期很长一段时间应该都是在写本软件~
技术群(舟无关、禁水):[内卷地狱!(QQ 群)](https://jq.qq.com/?_wv=1027&k=ypbzXcA2)
开发者群:[QQ 群](https://jq.qq.com/?_wv=1027&k=JM9oCk3C)
开发者群:[QQ 群](https://jq.qq.com/?_wv=1027&k=JM9oCk3C)
如果觉得软件对你有帮助,帮忙点个 Star 吧!~(网页最上方右上角的小星星),这就是对我们最大的支持了!

7
build.cmd Normal file
View File

@@ -0,0 +1,7 @@
:; set -eo pipefail
:; SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
:; ${SCRIPT_DIR}/build.sh "$@"
:; exit $?
@ECHO OFF
powershell -ExecutionPolicy ByPass -NoProfile -File "%~dp0build.ps1" %*

69
build.ps1 Normal file
View File

@@ -0,0 +1,69 @@
[CmdletBinding()]
Param(
[Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
[string[]]$BuildArguments
)
Write-Output "PowerShell $($PSVersionTable.PSEdition) version $($PSVersionTable.PSVersion)"
Set-StrictMode -Version 2.0; $ErrorActionPreference = "Stop"; $ConfirmPreference = "None"; trap { Write-Error $_ -ErrorAction Continue; exit 1 }
$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
###########################################################################
# CONFIGURATION
###########################################################################
$BuildProjectFile = "$PSScriptRoot\tools\MaaBuilder\MaaBuilder.csproj"
$TempDirectory = "$PSScriptRoot\\.nuke\temp"
$DotNetGlobalFile = "$PSScriptRoot\\global.json"
$DotNetInstallUrl = "https://dot.net/v1/dotnet-install.ps1"
$DotNetChannel = "Current"
$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 1
$env:DOTNET_CLI_TELEMETRY_OPTOUT = 1
$env:DOTNET_MULTILEVEL_LOOKUP = 0
###########################################################################
# EXECUTION
###########################################################################
function ExecSafe([scriptblock] $cmd) {
& $cmd
if ($LASTEXITCODE) { exit $LASTEXITCODE }
}
# If dotnet CLI is installed globally and it matches requested version, use for execution
if ($null -ne (Get-Command "dotnet" -ErrorAction SilentlyContinue) -and `
$(dotnet --version) -and $LASTEXITCODE -eq 0) {
$env:DOTNET_EXE = (Get-Command "dotnet").Path
}
else {
# Download install script
$DotNetInstallFile = "$TempDirectory\dotnet-install.ps1"
New-Item -ItemType Directory -Path $TempDirectory -Force | Out-Null
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
(New-Object System.Net.WebClient).DownloadFile($DotNetInstallUrl, $DotNetInstallFile)
# If global.json exists, load expected version
if (Test-Path $DotNetGlobalFile) {
$DotNetGlobal = $(Get-Content $DotNetGlobalFile | Out-String | ConvertFrom-Json)
if ($DotNetGlobal.PSObject.Properties["sdk"] -and $DotNetGlobal.sdk.PSObject.Properties["version"]) {
$DotNetVersion = $DotNetGlobal.sdk.version
}
}
# Install by channel or version
$DotNetDirectory = "$TempDirectory\dotnet-win"
if (!(Test-Path variable:DotNetVersion)) {
ExecSafe { & powershell $DotNetInstallFile -InstallDir $DotNetDirectory -Channel $DotNetChannel -NoPath }
} else {
ExecSafe { & powershell $DotNetInstallFile -InstallDir $DotNetDirectory -Version $DotNetVersion -NoPath }
}
$env:DOTNET_EXE = "$DotNetDirectory\dotnet.exe"
}
Write-Output "Microsoft (R) .NET SDK version $(& $env:DOTNET_EXE --version)"
ExecSafe { & $env:DOTNET_EXE build $BuildProjectFile /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet }
ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile --no-build -- $BuildArguments }

62
build.sh Normal file
View File

@@ -0,0 +1,62 @@
#!/usr/bin/env bash
bash --version 2>&1 | head -n 1
set -eo pipefail
SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
###########################################################################
# CONFIGURATION
###########################################################################
BUILD_PROJECT_FILE="$SCRIPT_DIR/tools/MaaBuilder/MaaBuilder.csproj"
TEMP_DIRECTORY="$SCRIPT_DIR//.nuke/temp"
DOTNET_GLOBAL_FILE="$SCRIPT_DIR//global.json"
DOTNET_INSTALL_URL="https://dot.net/v1/dotnet-install.sh"
DOTNET_CHANNEL="Current"
export DOTNET_CLI_TELEMETRY_OPTOUT=1
export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
export DOTNET_MULTILEVEL_LOOKUP=0
###########################################################################
# EXECUTION
###########################################################################
function FirstJsonValue {
perl -nle 'print $1 if m{"'"$1"'": "([^"]+)",?}' <<< "${@:2}"
}
# If dotnet CLI is installed globally and it matches requested version, use for execution
if [ -x "$(command -v dotnet)" ] && dotnet --version &>/dev/null; then
export DOTNET_EXE="$(command -v dotnet)"
else
# Download install script
DOTNET_INSTALL_FILE="$TEMP_DIRECTORY/dotnet-install.sh"
mkdir -p "$TEMP_DIRECTORY"
curl -Lsfo "$DOTNET_INSTALL_FILE" "$DOTNET_INSTALL_URL"
chmod +x "$DOTNET_INSTALL_FILE"
# If global.json exists, load expected version
if [[ -f "$DOTNET_GLOBAL_FILE" ]]; then
DOTNET_VERSION=$(FirstJsonValue "version" "$(cat "$DOTNET_GLOBAL_FILE")")
if [[ "$DOTNET_VERSION" == "" ]]; then
unset DOTNET_VERSION
fi
fi
# Install by channel or version
DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix"
if [[ -z ${DOTNET_VERSION+x} ]]; then
"$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --channel "$DOTNET_CHANNEL" --no-path
else
"$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --version "$DOTNET_VERSION" --no-path
fi
export DOTNET_EXE="$DOTNET_DIRECTORY/dotnet"
fi
echo "Microsoft (R) .NET SDK version $("$DOTNET_EXE" --version)"
"$DOTNET_EXE" build "$BUILD_PROJECT_FILE" /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet
"$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" --no-build -- "$@"

View File

@@ -1,83 +0,0 @@
set(debug_comp_defs "_DEBUG;ASST_DEBUG")
add_compile_definitions("$<$<CONFIG:Debug>:${debug_comp_defs}>")
if(APPLE)
set(CMAKE_INSTALL_RPATH "@loader_path;@executable_path")
set(CMAKE_BUILD_RPATH "@loader_path;@executable_path")
elseif(UNIX)
set(CMAKE_INSTALL_RPATH "$ORIGIN")
set(CMAKE_BUILD_RPATH "$ORIGIN")
endif()
if(MSVC)
add_compile_options("/utf-8")
add_compile_options("/MP")
add_compile_options("/W4;/WX;/Gy;/permissive-;/sdl")
add_compile_options("/wd4127") # conditional expression is constant
add_compile_options("/wd4251") # export dll with templates
add_compile_options("/DWINVER=0x0A00")
add_compile_options("/D_WIN32_WINNT=0x0A00")
# https://github.com/actions/runner-images/issues/10004 https://github.com/microsoft/STL/releases/tag/vs-2022-17.10
add_compile_definitions("_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR")
set(release_link_options "/OPT:REF;/OPT:ICF")
add_link_options("$<$<CONFIG:Release>:${release_link_options}>")
SET(CMAKE_MAP_IMPORTED_CONFIG_RELWITHDEBINFO "RelWithDebInfo;Release;")
SET(CMAKE_MAP_IMPORTED_CONFIG_MINSIZEREL "MinSizeRel;Release;")
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
else()
add_compile_options("-Wall;-Werror;-Wextra;-Wpedantic;-Wno-missing-field-initializers")
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13)
add_compile_options("-Wno-restrict")
endif()
endif()
if(LINUX)
function(copy_and_add_rpath_library LIBNAME)
execute_process(
COMMAND ${CMAKE_CXX_COMPILER} -print-file-name=${LIBNAME}.so.1 -target ${CMAKE_CXX_COMPILER_TARGET} --sysroot=${CMAKE_SYSROOT}
OUTPUT_VARIABLE LIB_PATH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if("${LIB_PATH}" STREQUAL "${LIBNAME}.so.1")
message(FATAL_ERROR "Could not locate ${LIBNAME}.so.1 using compiler")
endif()
file(READ_SYMLINK "${LIB_PATH}" LINK_TARGET)
if(NOT LINK_TARGET)
set(LIB_PATH_REAL "${LIB_PATH}")
elseif(NOT IS_ABSOLUTE "${LINK_TARGET}")
get_filename_component(LIB_PATH_DIR "${LIB_PATH}" DIRECTORY)
file(REAL_PATH "${LIB_PATH_DIR}/${LINK_TARGET}" LIB_PATH_REAL)
else()
set(LIB_PATH_REAL "${LINK_TARGET}")
endif()
if(NOT EXISTS "${LIB_PATH_REAL}")
message(FATAL_ERROR "File not found: ${LIB_PATH_REAL}")
endif()
message(STATUS "${LIBNAME}.so.1 path: ${LIB_PATH_REAL}")
install(FILES "${LIB_PATH_REAL}" DESTINATION . RENAME "${LIBNAME}.so.1" COMPONENT libcxx)
get_filename_component(LIB_PATH_DIR "${LIB_PATH_REAL}" DIRECTORY)
list(APPEND CMAKE_BUILD_RPATH "${LIB_PATH_DIR}")
set(CMAKE_BUILD_RPATH "${CMAKE_BUILD_RPATH}" PARENT_SCOPE)
endfunction()
copy_and_add_rpath_library(libc++)
copy_and_add_rpath_library(libc++abi)
copy_and_add_rpath_library(libunwind)
endif()
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)

View File

@@ -7,12 +7,12 @@ if (BUILD_XCFRAMEWORK)
add_custom_command(OUTPUT OpenCV.xcframework
COMMAND rm -rf OpenCV.xcframework
COMMAND xcodebuild -create-xcframework -library "${PROJECT_SOURCE_DIR}/MaaDeps/runtime/${MAADEPS_TRIPLET}/libopencv_world4.408.dylib" -output OpenCV.xcframework
COMMAND xcodebuild -create-xcframework -library "${PROJECT_SOURCE_DIR}/MaaDeps/runtime/${MAADEPS_TRIPLET}/libopencv_world4.407.dylib" -output OpenCV.xcframework
)
add_custom_command(OUTPUT ONNXRuntime.xcframework
COMMAND rm -rf ONNXRuntime.xcframework
COMMAND xcodebuild -create-xcframework -library "${PROJECT_SOURCE_DIR}/MaaDeps/runtime/${MAADEPS_TRIPLET}/libonnxruntime.1.18.0.dylib" -output ONNXRuntime.xcframework
COMMAND xcodebuild -create-xcframework -library "${PROJECT_SOURCE_DIR}/MaaDeps/runtime/${MAADEPS_TRIPLET}/libonnxruntime.1.14.1.dylib" -output ONNXRuntime.xcframework
)
add_custom_command(OUTPUT fastdeploy_ppocr.xcframework
@@ -25,3 +25,6 @@ if (BUILD_XCFRAMEWORK)
)
endif (BUILD_XCFRAMEWORK)
target_compile_options(MaaCore PRIVATE
-Wno-deprecated-declarations
-Wno-gnu-zero-variadic-macro-arguments)

View File

@@ -1,41 +0,0 @@
find_path(ONNXRuntime_INCLUDE_DIR NAMES onnxruntime/onnxruntime_c_api.h)
find_library(ONNXRuntime_LIBRARY_IMP NAMES onnxruntime)
if (WIN32)
get_filename_component(ONNXRuntime_PATH_LIB ${ONNXRuntime_LIBRARY_IMP} DIRECTORY)
find_file(ONNXRuntime_LIBRARY NAMES onnxruntime_maa.dll PATHS "${ONNXRuntime_PATH_LIB}/../bin")
find_file(ONNXRuntime_LIBRARY_IMP_DEBUG NAMES onnxruntime.lib PATHS "${ONNXRuntime_PATH_LIB}/../debug/lib")
find_file(ONNXRuntime_LIBRARY_DEBUG NAMES onnxruntime_maa.dll PATHS "${ONNXRuntime_PATH_LIB}/../debug/bin")
else ()
set(ONNXRuntime_LIBRARY ${ONNXRuntime_LIBRARY_IMP})
endif (WIN32)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
ONNXRuntime
REQUIRED_VARS ONNXRuntime_LIBRARY_IMP ONNXRuntime_INCLUDE_DIR
)
if(ONNXRuntime_FOUND)
set(ONNXRuntime_INCLUDE_DIRS ${ONNXRuntime_INCLUDE_DIR})
if(NOT TARGET ONNXRuntime::ONNXRuntime)
add_library(ONNXRuntime::ONNXRuntime SHARED IMPORTED)
set_property(TARGET ONNXRuntime::ONNXRuntime APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
if (WIN32)
set_property(TARGET ONNXRuntime::ONNXRuntime APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(ONNXRuntime::ONNXRuntime PROPERTIES
IMPORTED_IMPLIB_RELEASE "${ONNXRuntime_LIBRARY_IMP}"
)
set_target_properties(ONNXRuntime::ONNXRuntime PROPERTIES
IMPORTED_IMPLIB_DEBUG "${ONNXRuntime_LIBRARY_IMP_DEBUG}"
IMPORTED_LOCATION_DEBUG "${ONNXRuntime_LIBRARY_DEBUG}"
)
endif (WIN32)
set_target_properties(ONNXRuntime::ONNXRuntime PROPERTIES
IMPORTED_LOCATION_RELEASE "${ONNXRuntime_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${ONNXRuntime_INCLUDE_DIR}"
)
endif()
endif()

54
cmake/opencv.cmake Normal file
View File

@@ -0,0 +1,54 @@
set(OPENCV_URL_PREFIX "https://github.com/MaaAssistantArknights/build-opencv/releases/download")
set(OPENCV_TAG "4.5.3")
set(COMPRESSED_SUFFIX ".tar.gz")
if(WIN32)
set(OPENCV_FILENAME "OpenCV-Windows")
set(OPENCV_CHECKSUM "bf736b243bbdaa020f139e4dfa1e4f15633f4ce7a8ad885524645e660de47a8b")
elseif(APPLE)
if (CURRENT_OSX_ARCH STREQUAL "arm64")
set(OPENCV_FILENAME "OpenCV-macOS-arm64")
set(OPENCV_CHECKSUM "31beb633c033dd4ee789ffa50911c29c9580860f9a91f334f03d8aa9c85e9700")
else()
set(OPENCV_FILENAME "OpenCV-macOS-x86_64")
set(OPENCV_CHECKSUM "249c5c97cc52257b68d35acf499b1cf1037f5e6f3b40752f82ad5abe7884bea9")
endif()
else(UNIX)
set(OPENCV_FILENAME "OpenCV-Linux")
set(OPENCV_CHECKSUM "edc4138456189c9e8bdf29114ad2be8ec152e8e31087d98e633f6cda59b141ea")
endif(WIN32)
set(OPENCV_URL ${OPENCV_URL_PREFIX}/${OPENCV_TAG}/${OPENCV_FILENAME}${COMPRESSED_SUFFIX})
if(OPENCV_DIRECTORY)
set(OpenCV_DIR ${OPENCV_DIRECTORY})
find_package(OpenCV REQUIRED PATHS ${OpenCV_DIR})
include_directories(${OpenCV_INCLUDE_DIRS})
list(APPEND DEPEND_LIBS ${OpenCV_LIBS})
else()
download_and_decompress(${OPENCV_URL}
${CMAKE_CURRENT_BINARY_DIR}/${OPENCV_FILENAME}${COMPRESSED_SUFFIX}
${OPENCV_CHECKSUM}
${THIRD_PARTY_PATH}/install/)
set(OPENCV_FILENAME opencv)
set(OpenCV_DIR ${THIRD_PARTY_PATH}/install/${OPENCV_FILENAME})
set(OPENCV_DIRECTORY ${OpenCV_DIR})
if (WIN32)
set(OpenCV_DIR ${OpenCV_DIR}/lib)
endif()
find_package(OpenCV REQUIRED PATHS ${OpenCV_DIR} NO_DEFAULT_PATH)
include_directories(${OpenCV_INCLUDE_DIRS})
list(APPEND DEPEND_LIBS ${OpenCV_LIBS})
endif(OPENCV_DIRECTORY)
if (INSTALL_THIRD_LIBS)
if (OpenCV_SHARED)
install(DIRECTORY ${OpenCV_INSTALL_PATH}/lib/
DESTINATION .
USE_SOURCE_PERMISSIONS PATTERN "cmake" EXCLUDE)
endif (OpenCV_SHARED)
endif (INSTALL_THIRD_LIBS)

44
cmake/thrift-gen.cmake Normal file
View File

@@ -0,0 +1,44 @@
macro(GENERATE_THRIFT_LIB LIB_NAME FILENAME OUTPUTDIR SOURCES)
file(MAKE_DIRECTORY ${OUTPUTDIR})
detect_host_triplet(HOST_TRIPLET)
if (CMAKE_CROSSCOMPILING)
if (CMAKE_HOST_WIN32)
set(_host_executable_suffix ".exe")
else()
set(_host_executable_suffix "")
endif()
else()
set(_host_executable_suffix ${CMAKE_EXECUTABLE_SUFFIX})
endif()
if(EXISTS ${PROJECT_SOURCE_DIR}/MaaDeps/vcpkg/installed/maa-${HOST_TRIPLET}/tools/thrift/thrift${_host_executable_suffix})
set(THRIFT_COMPILER ${PROJECT_SOURCE_DIR}/MaaDeps/vcpkg/installed/maa-${HOST_TRIPLET}/tools/thrift/thrift${_host_executable_suffix})
else()
find_program(THRIFT_COMPILER thrift)
endif()
if(NOT THRIFT_COMPILER)
message(FATAL_ERROR "Thrift compiler not found")
endif()
get_filename_component(THRIFT_IDL_NAME ${FILENAME} NAME_WE)
set(THRIFT_IDL_TARGET "${LIB_NAME}_${THRIFT_IDL_NAME}_idl")
set("${THRIFT_IDL_NAME}-gen-cpp"
${OUTPUTDIR}/${THRIFT_IDL_NAME}.cpp
${OUTPUTDIR}/${THRIFT_IDL_NAME}.h
${OUTPUTDIR}/${THRIFT_IDL_NAME}_types.cpp
${OUTPUTDIR}/${THRIFT_IDL_NAME}_types.h)
add_custom_command(OUTPUT ${${THRIFT_IDL_NAME}-gen-cpp}
DEPENDS ${FILENAME}
COMMAND ${THRIFT_COMPILER} --gen cpp:no_skeleton -out ${OUTPUTDIR} ${FILENAME}
VERBATIM)
add_custom_target(${THRIFT_IDL_TARGET} DEPENDS ${${THRIFT_IDL_NAME}-gen-cpp})
add_library(${LIB_NAME} STATIC ${${THRIFT_IDL_NAME}-gen-cpp})
add_dependencies(${LIB_NAME} ${THRIFT_IDL_TARGET})
set_target_properties(${LIB_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_link_libraries(${LIB_NAME} PUBLIC thrift::thrift)
target_include_directories(${LIB_NAME} PUBLIC ${OUTPUTDIR})
set(${SOURCES} ${${SOURCES}} ${GENERATED_SOURCES} PARENT_SCOPE)
endmacro(GENERATE_THRIFT_LIB)
if (WITH_THRIFT)
add_compile_definitions(WITH_THRIFT)
endif (WITH_THRIFT)

View File

@@ -1,73 +1,50 @@
function(download_and_decompress url filename sha256_checksum decompress_dir)
if(EXISTS ${filename})
file(SHA256 ${filename} CHECKSUM_VARIABLE)
endif()
if(NOT EXISTS ${filename} OR NOT CHECKSUM_VARIABLE STREQUAL sha256_checksum)
message("Downloading file from ${url} to ${filename} ...")
file(
DOWNLOAD ${url} "${filename}.tmp"
SHOW_PROGRESS
EXPECTED_HASH SHA256=${sha256_checksum})
file(RENAME "${filename}.tmp" ${filename})
endif()
if(NOT EXISTS ${decompress_dir})
file(MAKE_DIRECTORY ${decompress_dir})
endif()
message("Decompress file ${filename} ...")
execute_process(COMMAND ${CMAKE_COMMAND} -E tar -xf ${filename} WORKING_DIRECTORY ${decompress_dir})
if(EXISTS ${filename})
file(SHA256 ${filename} CHECKSUM_VARIABLE)
endif()
if(NOT EXISTS ${filename} OR NOT CHECKSUM_VARIABLE STREQUAL sha256_checksum)
message("Downloading file from ${url} to ${filename} ...")
file(DOWNLOAD ${url} "${filename}.tmp" SHOW_PROGRESS EXPECTED_HASH SHA256=${sha256_checksum})
file(RENAME "${filename}.tmp" ${filename})
endif()
if(NOT EXISTS ${decompress_dir})
file(MAKE_DIRECTORY ${decompress_dir})
endif()
message("Decompress file ${filename} ...")
execute_process(COMMAND ${CMAKE_COMMAND} -E tar -xf ${filename} WORKING_DIRECTORY ${decompress_dir})
endfunction()
function(get_osx_architecture)
if(CMAKE_OSX_ARCHITECTURES STREQUAL "arm64")
set(CURRENT_OSX_ARCH
"arm64"
PARENT_SCOPE)
elseif(CMAKE_OSX_ARCHITECTURES STREQUAL "x86_64")
set(CURRENT_OSX_ARCH
"x86_64"
PARENT_SCOPE)
else()
set(CURRENT_OSX_ARCH
${CMAKE_HOST_SYSTEM_PROCESSOR}
PARENT_SCOPE)
endif()
if (CMAKE_OSX_ARCHITECTURES STREQUAL "arm64")
set(CURRENT_OSX_ARCH "arm64" PARENT_SCOPE)
elseif(CMAKE_OSX_ARCHITECTURES STREQUAL "x86_64")
set(CURRENT_OSX_ARCH "x86_64" PARENT_SCOPE)
else()
set(CURRENT_OSX_ARCH ${CMAKE_HOST_SYSTEM_PROCESSOR} PARENT_SCOPE)
endif()
endfunction()
if(APPLE)
set(CMAKE_OSX_DEPLOYMENT_TARGET 13.3) # for to_chars
get_osx_architecture()
endif(APPLE)
function(detect_host_triplet outvar)
string(TOLOWER "${CMAKE_HOST_SYSTEM_NAME}" host_triplet_system)
string(TOLOWER "${CMAKE_HOST_SYSTEM_PROCESSOR}" host_triplet_arch)
if(host_triplet_system STREQUAL "darwin")
set(host_triplet_system "osx")
endif()
message("host_triplet_system: ${host_triplet_system}")
message("host_triplet_arch: ${host_triplet_arch}")
if(host_triplet_arch MATCHES "(amd64|x86_64)")
set(host_triplet_arch "x64")
elseif(host_triplet_arch MATCHES "i[3456]86")
set(host_triplet_arch "x86")
elseif(host_triplet_arch MATCHES "(aarch64|armv8l|arm64)")
set(host_triplet_arch "arm64")
else()
message(FATAL_ERROR "Unrecognized CMAKE_HOST_SYSTEM_PROCESSOR: ${CMAKE_HOST_SYSTEM_PROCESSOR}")
endif()
set(${outvar} "${host_triplet_arch}-${host_triplet_system}" PARENT_SCOPE)
endfunction()
if(NOT DEFINED MAADEPS_TRIPLET)
detect_maadeps_triplet(MAADEPS_TRIPLET)
endif()
# 创建资源目录链接的函数
function(create_resource_link TARGET_NAME OUTPUT_DIR)
if(WIN32)
# Windows 使用 mklink /J 创建目录链接(不需要管理员权限)
add_custom_command(
TARGET ${TARGET_NAME}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo "Creating resource directory link for ${TARGET_NAME}..."
COMMAND ${CMAKE_COMMAND} -E remove_directory "${OUTPUT_DIR}/resource"
COMMAND cmd /c "mklink /J \"${OUTPUT_DIR}/resource\" \"${PROJECT_SOURCE_DIR}/resource\""
COMMAND ${CMAKE_COMMAND} -E echo "Resource directory link created successfully"
COMMENT "Creating junction for resource directory for ${TARGET_NAME}"
)
else()
# Unix/Linux/macOS 使用符号链接
add_custom_command(
TARGET ${TARGET_NAME}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo "Creating resource directory link for ${TARGET_NAME}..."
COMMAND ${CMAKE_COMMAND} -E remove "${OUTPUT_DIR}/resource"
COMMAND ${CMAKE_COMMAND} -E create_symlink "${PROJECT_SOURCE_DIR}/resource" "${OUTPUT_DIR}/resource"
COMMAND ${CMAKE_COMMAND} -E echo "Resource directory link created successfully"
COMMENT "Creating symlink for resource directory for ${TARGET_NAME}"
)
endif()
endfunction()
if (APPLE)
set(CMAKE_OSX_DEPLOYMENT_TARGET 12.0)
get_osx_architecture()
endif (APPLE)

View File

@@ -1,27 +0,0 @@
# define MAA_HASH_VERSION from git
set(MAA_HASH_VERSION
"DEBUG_VERSION"
CACHE STRING "maa version")
if(WITH_HASH_VERSION AND MAA_HASH_VERSION STREQUAL "DEBUG_VERSION")
find_package(Git)
if(GIT_FOUND)
execute_process(
COMMAND "${GIT_EXECUTABLE}" rev-parse HEAD
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE result
OUTPUT_VARIABLE output
ERROR_VARIABLE err
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(result EQUAL 0)
set(MAA_HASH_VERSION "${output}")
else()
message(WARNING "git rev-parse returning ${result}, output:\n${err}")
endif()
endif()
endif()
message(STATUS "MAA_HASH_VERSION=${MAA_HASH_VERSION}")
add_compile_definitions(MAA_VERSION="${MAA_HASH_VERSION}")

View File

@@ -223,39 +223,6 @@ MD052: true
# MD053/link-image-reference-definitions - Link and image reference definitions should be needed
MD053:
# Ignored definitions
ignored_definitions: ["//"]
# MD054/link-image-style - Link and image style
MD054:
# Allow autolinks
autolink: true
# Allow collapsed reference links and images
collapsed: true
# Allow full reference links and images
full: true
# Allow inline links and images
inline: true
# Allow shortcut reference links and images
shortcut: true
# Allow URLs as inline links
url_inline: true
# MD055/table-pipe-style - Table pipe style
MD055:
# Table pipe style
style: "consistent"
# MD056/table-column-count - Table column count
MD056: true
# MD057 - Table column count inconsistencies with table header column count
# (Not documented in official rules list - MD057 appears to be missing or deprecated)
# MD058/blanks-around-tables - Tables should be surrounded by blank lines
MD058: true
# MD059/descriptive-link-text - Link text should be descriptive
MD059:
false
# Prohibited link texts
#prohibited_texts: ["click here", "here", "link", "more"]
ignored_definitions: [
"//"
]

View File

@@ -1,2 +0,0 @@
**/pnpm-lock.yaml
**/*.md

View File

@@ -1,40 +0,0 @@
module.exports = {
printWidth: 120,
tabWidth: 2,
useTabs: false,
bracketSpacing: true,
bracketSameLine: false,
endOfLine: 'auto',
semi: false,
singleQuote: true,
trailingComma: 'all',
arrowParens: 'always',
overrides: [
{
files: ['**/*.ts'],
options: {
semi: true,
},
},
{
files: ['**/*.*css'],
options: {
singleQuote: false,
},
},
{
files: ['**/*.yml', '**/*.yaml'],
options: {
parser: 'yaml',
singleQuote: false,
},
},
{
files: ['**/*.json'],
options: {
tabWidth: 4,
},
},
],
}

View File

@@ -1,11 +1,8 @@
import { defineClientConfig } from 'vuepress/client';
import ImageGrid from './components/ImageGrid.vue';
import './styles/index.scss';
import { defineClientConfig } from "vuepress/client";
import ImageGrid from "../components/ImageGrid.vue";
export default defineClientConfig({
enhance: ({ app }) => {
app.component('ImageGrid', ImageGrid);
app.component("ImageGrid", ImageGrid);
},
});

View File

@@ -1,72 +0,0 @@
<template>
<CardGrid>
<ImageCard v-for="(item, index) of displayImageList" :key="index" :image="item" />
</CardGrid>
</template>
<script lang="ts">
import { PropType, defineComponent, computed, ref, onMounted, onUnmounted } from 'vue'
import { withBase } from 'vuepress/client'
export default defineComponent({
name: 'ImageCardGrid',
props: {
imageList: {
type: Array as PropType<Array<{ light: string; dark: string } | string>>,
required: true,
},
},
setup(props) {
const isDarkMode = ref(false)
let observer: MutationObserver | null = null
let mediaQuery: MediaQueryList | null = null
const updateDarkMode = () => {
if (typeof window !== 'undefined') {
const html = document.documentElement
isDarkMode.value =
html.classList.contains('dark') ||
html.getAttribute('data-theme') === 'dark' ||
window.matchMedia('(prefers-color-scheme: dark)').matches
}
}
onMounted(() => {
updateDarkMode()
if (typeof window !== 'undefined') {
// 监听DOM变化主题切换通常会改变class或data-theme属性
observer = new MutationObserver(updateDarkMode)
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ['class', 'data-theme'],
})
// 监听系统主题变化
mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
mediaQuery.addEventListener('change', updateDarkMode)
}
})
onUnmounted(() => {
if (observer) {
observer.disconnect()
}
if (mediaQuery) {
mediaQuery.removeEventListener('change', updateDarkMode)
}
})
const displayImageList = computed(() => {
return props.imageList.map((item) => {
const src = typeof item === 'string' ? item : isDarkMode.value ? item.dark : item.light
return withBase(src)
})
})
return {
displayImageList,
}
},
})
</script>

View File

@@ -1,70 +1,77 @@
import { viteBundler } from '@vuepress/bundler-vite';
import { defineUserConfig } from 'vuepress';
import { googleAnalyticsPlugin } from '@vuepress/plugin-google-analytics';
import { plumeTheme } from 'vuepress-theme-plume';
import DocSearchConfig from './plugins/search';
const isProd = process.env.NODE_ENV === 'production';
import { defineUserConfig } from "vuepress";
import { viteBundler } from "@vuepress/bundler-vite";
import { googleAnalyticsPlugin } from "@vuepress/plugin-google-analytics";
import Theme from "./theme";
export default defineUserConfig({
base: '/',
lang: 'zh-CN',
title: 'MAA 文档站',
description: 'MAA —「明日方舟」小助手',
host: '0.0.0.0',
base: "/docs/",
lang: "zh-CN",
title: "MaaAssistantArknights",
description: "MAA",
port: 3001,
locales: {
'/zh-cn/': {
lang: 'zh-CN',
title: 'MAA 文档站',
description: '文档',
"/zh-cn/": {
lang: "zh-CN",
description: "文档",
},
'/zh-tw/': {
lang: 'zh-TW',
title: 'MAA 文件站',
description: '文件',
"/zh-tw/": {
lang: "zh-TW",
description: "文件",
},
'/en-us/': {
lang: 'en-US',
title: 'MAA Documentation Site',
description: 'Documentation',
"/en-us/": {
lang: "en-US",
description: "Documentation",
},
'/ja-jp/': {
lang: 'ja-JP',
title: 'MAA ドキュメントサイト',
description: 'ドキュメント',
"/ja-jp/": {
lang: "ja-JP",
description: "ドキュメンテーション",
},
'/ko-kr/': {
lang: 'ko-KR',
title: 'MAA 문서 사이트',
description: '문서',
"/ko-kr/": {
lang: "ko-KR",
description: "선적 서류 비치",
},
},
markdown: {
headers: {
level: [2, 3, 4, 5],
},
},
theme: Theme,
plugins: [
googleAnalyticsPlugin({
id: "G-FJQDKG394Z",
}),
],
head: [
['link', { rel: 'preconnect', href: 'https://fonts.googleapis.com' }],
['link', { rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: '' }],
["link", { rel: "preconnect", href: "https://fonts.googleapis.com" }],
[
'link',
"link",
{ rel: "preconnect", href: "https://fonts.gstatic.com", crossorigin: "" },
],
[
"link",
{
href: 'https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@100..900&display=swap',
rel: 'stylesheet',
href: "https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@100..900&display=swap",
rel: "stylesheet",
},
],
[
'link',
"link",
{
href: 'https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@200..900&display=swap',
rel: 'stylesheet',
href: "https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@200..900&display=swap",
rel: "stylesheet",
},
],
[
'link',
"link",
{
href: 'https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&display=swap',
rel: 'stylesheet',
href: "https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&display=swap",
rel: "stylesheet",
},
],
],
@@ -73,63 +80,4 @@ export default defineUserConfig({
viteOptions: {},
vuePluginOptions: {},
}),
shouldPrefetch: false,
theme: plumeTheme({
hostname: 'https://docs.maa.plus',
docsRepo: 'MaaAssistantArknights/MaaAssistantArknights',
docsDir: '/docs',
docsBranch: 'dev',
editLink: true,
lastUpdated: false,
contributors: false,
changelog: false,
blog: false,
cache: 'filesystem',
search: DocSearchConfig,
codeHighlighter: {
themes: { light: 'one-light', dark: 'one-dark-pro' },
},
markdown: {
image: {
lazyload: true,
mark: true,
size: true,
},
icon: { provider: 'iconify' },
plot: true,
field: true,
bilibili: true,
},
watermark: false,
comment: {
provider: 'Giscus',
repo: 'MaaAssistantArknights/maa-website',
repoId: 'R_kgDOHY7Gyg',
category: 'Comments',
categoryId: 'DIC_kwDOHY7Gys4CgoVH',
mapping: 'pathname',
strict: false,
lazyLoading: true,
},
//replaceAssets: isProd ? "https://cdn.maa.plus" : false,
}),
plugins: [
googleAnalyticsPlugin({
id: 'G-FJQDKG394Z',
}),
],
});

View File

@@ -1,5 +0,0 @@
declare module '*.vue' {
import { DefineComponent } from 'vue';
const component: DefineComponent<{}, {}, any>;
export default component;
}

View File

@@ -1,19 +1,29 @@
import { defineNavbarConfig } from 'vuepress-theme-plume';
import { navbar } from "vuepress-theme-hope";
export const enusNavbar = defineNavbarConfig([
export const enusNavbar = navbar([
{
text: 'User Manual',
icon: 'mdi:user',
link: '/en-us/manual/newbie.html',
text: "Home",
icon: "ic:round-home",
link: "/en-us/",
},
{
text: 'Development Docs',
icon: 'ph:code-bold',
link: '/en-us/develop/development.html',
text: "User Manual",
icon: "mdi:user",
link: "/en-us/manual/",
},
{
text: 'Protocol Docs',
icon: 'basil:document-solid',
link: '/en-us/protocol/integration.html',
text: "Development Docs",
icon: "ph:code-bold",
link: "/en-us/develop/",
},
{
text: "Protocol Docs",
icon: "basil:document-solid",
link: "/en-us/protocol/",
},
{
text: "MAA Website",
icon: "mdi:cow",
link: "https://maa.plus",
},
]);

View File

@@ -1,5 +1,5 @@
export * from './zh-cn';
export * from './zh-tw';
export * from './en-us';
export * from './ja-jp';
export * from './ko-kr';
export * from "./zh-cn";
export * from "./zh-tw";
export * from "./en-us";
export * from "./ja-jp";
export * from "./ko-kr";

View File

@@ -1,19 +1,29 @@
import { defineNavbarConfig } from 'vuepress-theme-plume';
import { navbar } from "vuepress-theme-hope";
export const jajpNavbar = defineNavbarConfig([
export const jajpNavbar = navbar([
{
text: '使用説明',
icon: 'mdi:user',
link: '/ja-jp/manual/newbie.html',
text: "ホームページ",
icon: "ic:round-home",
link: "/ja-jp/",
},
{
text: '開発関連',
icon: 'ph:code-bold',
link: '/ja-jp/develop/development.html',
text: "使用説明",
icon: "mdi:user",
link: "/ja-jp/manual/",
},
{
text: 'プロトコルドキュメント',
icon: 'basil:document-solid',
link: '/ja-jp/protocol/integration.html',
text: "開発関連",
icon: "ph:code-bold",
link: "/ja-jp/develop/",
},
{
text: "プロトコルドキュメント",
icon: "basil:document-solid",
link: "/ja-jp/protocol/",
},
{
text: "MAA 公式サイト",
icon: "mdi:cow",
link: "https://maa.plus",
},
]);

View File

@@ -1,19 +1,29 @@
import { defineNavbarConfig } from 'vuepress-theme-plume';
import { navbar } from "vuepress-theme-hope";
export const kokrNavbar = defineNavbarConfig([
export const kokrNavbar = navbar([
{
text: '사용자 설명서',
icon: 'mdi:user',
link: '/ko-kr/manual/newbie.html',
text: "홈페이지",
icon: "ic:round-home",
link: "/ko-kr/",
},
{
text: '개발 문서',
icon: 'ph:code-bold',
link: '/ko-kr/develop/development.html',
text: "사용자 설명서",
icon: "mdi:user",
link: "/ko-kr/manual/",
},
{
text: '프로토콜 문서',
icon: 'basil:document-solid',
link: '/ko-kr/protocol/integration.html',
text: "개발 문서",
icon: "ph:code-bold",
link: "/ko-kr/develop/",
},
{
text: "프로토콜 문서",
icon: "basil:document-solid",
link: "/ko-kr/protocol/",
},
{
text: "MAA 공식 홈페이지",
icon: "mdi:cow",
link: "https://maa.plus",
},
]);

Some files were not shown because too many files have changed in this diff Show More