mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-11 07:20:24 +08:00
Compare commits
1 Commits
v6.2.2
...
feat/githu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
02961e60e9 |
@@ -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
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
FROM mcr.microsoft.com/devcontainers/base:ubuntu
|
||||
|
||||
USER vscode
|
||||
|
||||
ENV PATH="/home/vscode/.local/bin:${PATH}"
|
||||
|
||||
ARG PYTHON_VERSION=3.12.11
|
||||
ARG NODEJS_VERSION=24
|
||||
|
||||
# Install and setup mise and uv
|
||||
RUN curl https://mise.run | sh
|
||||
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
|
||||
# Activate mise
|
||||
RUN echo 'eval "$(mise activate bash)"' >> ~/.bashrc
|
||||
|
||||
# Setup Python and Node.js
|
||||
RUN mise use -g node@$NODEJS_VERSION
|
||||
RUN uv python install $PYTHON_VERSION
|
||||
|
||||
# Create and activate venv
|
||||
RUN uv venv --clear ~/.venv/maa
|
||||
RUN echo "source ~/.venv/maa/bin/activate" >> ~/.bashrc
|
||||
|
||||
# Install tools
|
||||
RUN uv tool install prek
|
||||
@@ -1,48 +0,0 @@
|
||||
// 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 Docs Env (Light)",
|
||||
// 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"
|
||||
},
|
||||
// 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/0/post-create.sh",
|
||||
|
||||
// Configure tool-specific properties.
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"nekosu.maa-support",
|
||||
"esbenp.prettier-vscode",
|
||||
"DavidAnson.vscode-markdownlint",
|
||||
"yzhang.markdown-all-in-one",
|
||||
"vue.volar",
|
||||
"mkxml.vscode-filesize"
|
||||
],
|
||||
"settings": {
|
||||
// Color theme
|
||||
"workbench.colorTheme": "Default Dark Modern",
|
||||
|
||||
// Editor formatting
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
|
||||
// Performance optimizations
|
||||
"search.exclude": {
|
||||
"**/node_modules": true,
|
||||
"**/3rdparty": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
|
||||
// "remoteUser": "root"
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
#!/bin/bash
|
||||
WORKSPACE=$(pwd)
|
||||
|
||||
echo "===================="
|
||||
cd "$WORKSPACE"
|
||||
echo "Setting up git safe.directory..."
|
||||
git config --global --add safe.directory "$WORKSPACE"
|
||||
git submodule foreach --recursive 'git config --global --add safe.directory "$toplevel/$path"'
|
||||
|
||||
echo "===================="
|
||||
cd "$WORKSPACE"
|
||||
echo "Updating submodules..."
|
||||
git submodule update --init --recursive
|
||||
|
||||
echo "===================="
|
||||
cd "$WORKSPACE"/docs
|
||||
echo "Installing node modules..."
|
||||
npm install -g pnpm
|
||||
pnpm install --frozen-lockfile
|
||||
@@ -1,41 +0,0 @@
|
||||
FROM mcr.microsoft.com/devcontainers/base:ubuntu
|
||||
|
||||
USER vscode
|
||||
|
||||
ENV PATH="/home/vscode/.local/bin:${PATH}"
|
||||
|
||||
ARG CLANGD_VERSION=20
|
||||
ARG PYTHON_VERSION=3.12.11
|
||||
ARG NODEJS_VERSION=24
|
||||
|
||||
# Install system dependencies
|
||||
RUN sudo apt update \
|
||||
&& sudo apt upgrade -y \
|
||||
&& sudo apt install -y \
|
||||
cmake \
|
||||
fish \
|
||||
&& sudo rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Initialize fish
|
||||
RUN fish -c exit
|
||||
|
||||
# Install and setup mise and uv
|
||||
RUN curl https://mise.run | sh
|
||||
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
|
||||
# Activate mise
|
||||
RUN echo 'eval "$(mise activate bash)"' >> ~/.bashrc
|
||||
RUN echo 'mise activate fish | source' >> ~/.config/fish/config.fish
|
||||
|
||||
# Setup Python and Node.js
|
||||
RUN mise use -g node@$NODEJS_VERSION
|
||||
RUN uv python install $PYTHON_VERSION
|
||||
|
||||
# Create and activate venv
|
||||
RUN uv venv --clear ~/.venv/maa
|
||||
RUN echo "source ~/.venv/maa/bin/activate" >> ~/.bashrc
|
||||
RUN echo "source ~/.venv/maa/bin/activate.fish" >> ~/.config/fish/config.fish
|
||||
|
||||
# Install tools
|
||||
RUN uv tool install prek
|
||||
RUN uv tool install ruff
|
||||
@@ -1,82 +0,0 @@
|
||||
// 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 Core Env (Full)",
|
||||
// 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"
|
||||
},
|
||||
// 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/1/post-create.sh",
|
||||
|
||||
// Configure tool-specific properties.
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"nekosu.maa-support",
|
||||
"ms-vscode.cmake-tools",
|
||||
"xaver.clang-format",
|
||||
"llvm-vs-code-extensions.vscode-clangd",
|
||||
"ms-python.python",
|
||||
"charliermarsh.ruff",
|
||||
"esbenp.prettier-vscode",
|
||||
"DavidAnson.vscode-markdownlint",
|
||||
"yzhang.markdown-all-in-one",
|
||||
"vue.volar",
|
||||
"mkxml.vscode-filesize"
|
||||
],
|
||||
"settings": {
|
||||
// Color theme
|
||||
"workbench.colorTheme": "Default Dark Modern",
|
||||
|
||||
// Editor formatting
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
|
||||
// Language-specific formatting
|
||||
"[python]": {
|
||||
"editor.defaultFormatter": "charliermarsh.ruff",
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.organizeImports": "explicit"
|
||||
}
|
||||
},
|
||||
"[cpp]": {
|
||||
"editor.defaultFormatter": "xaver.clang-format"
|
||||
},
|
||||
"[c]": {
|
||||
"editor.defaultFormatter": "xaver.clang-format"
|
||||
},
|
||||
|
||||
// Python runtime
|
||||
"python.terminal.launchArgs": ["-u"],
|
||||
"python.defaultInterpreterPath": "/home/vscode/.venv/maa/bin/python",
|
||||
"python.terminal.activateEnvironment": false,
|
||||
|
||||
// CMake settings
|
||||
"cmake.configureSettings": {
|
||||
"BUILD_DEBUG_DEMO": "ON",
|
||||
"CMAKE_TOOLCHAIN_FILE": "src/MaaUtils/MaaDeps/cmake/maa-x64-linux-toolchain.cmake"
|
||||
},
|
||||
"cmake.configureOnOpen": false,
|
||||
|
||||
// Performance optimizations
|
||||
"search.exclude": {
|
||||
"**/node_modules": true,
|
||||
"**/build": true,
|
||||
"**/install": true,
|
||||
"**/MaaDeps": true,
|
||||
"**/3rdparty": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
|
||||
// "remoteUser": "root"
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
#!/bin/bash
|
||||
WORKSPACE=$(pwd)
|
||||
|
||||
echo "===================="
|
||||
cd "$WORKSPACE"
|
||||
echo "Setting up git safe.directory..."
|
||||
git config --global --add safe.directory "$WORKSPACE"
|
||||
git submodule foreach --recursive 'git config --global --add safe.directory "$toplevel/$path"'
|
||||
|
||||
echo "===================="
|
||||
cd "$WORKSPACE"
|
||||
echo "Updating submodules..."
|
||||
git submodule update --init --recursive
|
||||
|
||||
echo "===================="
|
||||
cd "$WORKSPACE"/docs
|
||||
echo "Installing node modules..."
|
||||
npm install -g pnpm
|
||||
pnpm install --frozen-lockfile
|
||||
|
||||
echo "===================="
|
||||
cd "$WORKSPACE"
|
||||
echo "Installing Python dependencies..."
|
||||
# Install Python dependencies from all tools
|
||||
for req_file in tools/*/requirements.txt; do
|
||||
if [ -f "$req_file" ]; then
|
||||
echo "Installing from $req_file"
|
||||
uv pip install -r "$req_file"
|
||||
fi
|
||||
done
|
||||
|
||||
for req_file in tools/*/requirements-dev.txt; do
|
||||
if [ -f "$req_file" ]; then
|
||||
echo "Installing from $req_file"
|
||||
uv pip install -r "$req_file"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "===================="
|
||||
cd "$WORKSPACE"
|
||||
echo "Installing MaaDeps..."
|
||||
python tools/maadeps-download.py
|
||||
# Link clang-format & clangd to /usr/local/bin for easy access
|
||||
sudo ln -s $WORKSPACE/src/MaaUtils/MaaDeps/x-tools/llvm/bin/clang-format /usr/local/bin/clang-format
|
||||
sudo ln -s $WORKSPACE/src/MaaUtils/MaaDeps/x-tools/llvm/bin/clangd /usr/local/bin/clangd
|
||||
@@ -1,13 +1,16 @@
|
||||
{
|
||||
"name": "Plain Env (Nothing Installed)",
|
||||
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
|
||||
"postCreateCommand": "bash .devcontainer/post-create.sh",
|
||||
"image": "mcr.microsoft.com/devcontainers/cpp:ubuntu-22.04",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/python:1": {},
|
||||
"ghcr.io/devcontainers/features/sshd:1": {}
|
||||
},
|
||||
"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": {
|
||||
"settings": {
|
||||
// Color theme
|
||||
"workbench.colorTheme": "Default Dark Modern"
|
||||
}
|
||||
"extensions": [
|
||||
"llvm-vs-code-extensions.vscode-clangd",
|
||||
"DavidAnson.vscode-markdownlint"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
#!/bin/bash
|
||||
WORKSPACE=$(pwd)
|
||||
|
||||
echo "===================="
|
||||
cd "$WORKSPACE"
|
||||
echo "Setting up git safe.directory..."
|
||||
git config --global --add safe.directory "$WORKSPACE"
|
||||
git submodule foreach --recursive 'git config --global --add safe.directory "$toplevel/$path"'
|
||||
|
||||
echo "===================="
|
||||
cd "$WORKSPACE"
|
||||
echo "Updating submodules..."
|
||||
git submodule update --init --recursive
|
||||
@@ -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,28 +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
|
||||
|
||||
# c# 统一使用文件范围限定的 namespace
|
||||
76252d42e3febae1aef396e8ee5482fa46d565c6
|
||||
|
||||
# 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
|
||||
ca9807ce099e5cae133293df8dfcd2b56b0e06bd
|
||||
|
||||
3
.gitattributes
vendored
3
.gitattributes
vendored
@@ -8,7 +8,4 @@
|
||||
|
||||
*.json text eol=lf
|
||||
*.md text eol=lf
|
||||
*.yml text eol=lf
|
||||
*.yaml text eol=lf
|
||||
|
||||
*.sh text eol=lf
|
||||
|
||||
1
.github/.last-blame-ignore-commit
vendored
1
.github/.last-blame-ignore-commit
vendored
@@ -1 +0,0 @@
|
||||
1944164d9c47549d71c3b25987e9299404cc16f3
|
||||
60
.github/ISSUE_TEMPLATE/cn-bug-report.yaml
vendored
60
.github/ISSUE_TEMPLATE/cn-bug-report.yaml
vendored
@@ -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,45 +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 -> 设置 -> 问题反馈中找到生成日志压缩包按钮,点击并上传压缩包**
|
||||
**若待上传压缩包大于 25MB,请转而上传该压缩包同日期文件夹中的若干小压缩包**
|
||||
若正在使用 macOS,请点击屏幕左上角的“文件”,点击“打开日志文件夹”
|
||||
placeholder: |
|
||||
请确认上传文件前已关闭 MAA
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: configuration
|
||||
attributes:
|
||||
label: 配置信息
|
||||
description: |
|
||||
请说明操作系统及版本、模拟器品牌、模拟器分辨率、DPI、帧率
|
||||
若正在使用 MuMu 或雷电 9,请说明截图增强是否开启
|
||||
最后请说明 GPU 加速推理是否开启,若开启请提供 GPU 型号。
|
||||
**请在关闭MAA后,上传 `debug` 文件夹中的 `asst.log` 和 `gui.log` 日志文件,并说明问题出现的大致时间点**
|
||||
**请直接将完整的文件拖拽进来,而非自己裁切或复制的片段;若文件体积过大可压缩后再上传**
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: screenshots
|
||||
attributes:
|
||||
label: 截图或录屏
|
||||
label: 截图
|
||||
description: |
|
||||
可上传屏幕截图或录制以帮助解释你的问题,包括但不限于 MAA 软件截图、游戏画面截图
|
||||
若是**识别相关问题**,请尽可能提供模拟器自带的截图工具截取的无遮挡的**原图**(或通过 adb 截取原图)
|
||||
用其他的工具(如QQ/微信)截取的图片包含窗口边框且长宽比、分辨率不固定,不利于我们排除bug
|
||||
若文件体积过大可压缩后再上传
|
||||
如果有,添加屏幕截图以帮助解释你的问题,包括但不限于 MAA 软件截图、游戏画面截图
|
||||
若是**识别相关问题**,请尽可能提供模拟器自带的截图工具截取的无遮挡的**原图**(或通过 adb 截取原图)
|
||||
用其他的工具(如QQ)截取的图片包含窗口边框,不利于我们排除bug
|
||||
`debug` 文件夹下有一些自动截图的错误图片,若有相关的,请一并打包上传
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
@@ -74,6 +59,7 @@ body:
|
||||
attributes:
|
||||
label: 还有别的吗?
|
||||
description: |
|
||||
使用的模拟器?操作系统?相关的配置?链接?参考资料?
|
||||
任何能让我们对你所遇到的问题有更多了解的东西
|
||||
validations:
|
||||
required: false
|
||||
|
||||
18
.github/ISSUE_TEMPLATE/cn-feature-request.yaml
vendored
18
.github/ISSUE_TEMPLATE/cn-feature-request.yaml
vendored
@@ -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:
|
||||
|
||||
85
.github/ISSUE_TEMPLATE/cn-ld-report.yaml
vendored
85
.github/ISSUE_TEMPLATE/cn-ld-report.yaml
vendored
@@ -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
|
||||
63
.github/ISSUE_TEMPLATE/cn-mumu-report.yaml
vendored
63
.github/ISSUE_TEMPLATE/cn-mumu-report.yaml
vendored
@@ -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
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/cn-others.yaml
vendored
2
.github/ISSUE_TEMPLATE/cn-others.yaml
vendored
@@ -1,6 +1,6 @@
|
||||
name: 其他议题(使用中文)
|
||||
description: 提出问题,而不是 Bug 反馈或需求建议
|
||||
labels: ["question"]
|
||||
labels: ['question']
|
||||
body:
|
||||
- type: textarea
|
||||
id: describe
|
||||
|
||||
103
.github/ISSUE_TEMPLATE/en-bug-report.yaml
vendored
103
.github/ISSUE_TEMPLATE/en-bug-report.yaml
vendored
@@ -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,58 +39,56 @@ 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**
|
||||
**If the archive to upload is larger than 25MB, please upload smaller archives from the same date folder instead.**
|
||||
If you are using macOS, 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.
|
||||
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.**
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: screenshots
|
||||
attributes:
|
||||
label: Screenshots or recordings
|
||||
description: |
|
||||
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.
|
||||
screenshots of game screens.
|
||||
|
||||
If the problem is **recognition related**, please help by providing
|
||||
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.
|
||||
If the file size is too large, you may compress it before uploading.
|
||||
(or via adb).
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
|
||||
20
.github/ISSUE_TEMPLATE/en-feature-request.yaml
vendored
20
.github/ISSUE_TEMPLATE/en-feature-request.yaml
vendored
@@ -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:
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/en-others.yaml
vendored
2
.github/ISSUE_TEMPLATE/en-others.yaml
vendored
@@ -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
|
||||
|
||||
19
.github/dependabot.yaml
vendored
19
.github/dependabot.yaml
vendored
@@ -1,19 +0,0 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: github-actions
|
||||
directory: /.github/workflows
|
||||
schedule:
|
||||
interval: weekly
|
||||
commit-message:
|
||||
prefix: ci
|
||||
assignees:
|
||||
- AnnAngela
|
||||
- Constrat
|
||||
- lucienshawls
|
||||
groups:
|
||||
github-actions:
|
||||
patterns:
|
||||
- "*"
|
||||
ignore:
|
||||
- dependency-name: "Nerixyz/actionsx-prettier"
|
||||
versions: ["3.0.0"]
|
||||
1057
.github/issue-checker.yml
vendored
1057
.github/issue-checker.yml
vendored
File diff suppressed because it is too large
Load Diff
46
.github/pr_cache_remover.ps1
vendored
46
.github/pr_cache_remover.ps1
vendored
@@ -1,46 +0,0 @@
|
||||
$totalClearedSize = 0
|
||||
$cacheList = gh cache list --json id,ref,sizeInBytes | ConvertFrom-Json
|
||||
$branchSet = @{}
|
||||
git ls-remote --heads origin | ForEach-Object {
|
||||
if ($_ -match 'refs/heads/(.+)$') { $branchSet[$matches[1]] = $true }
|
||||
}
|
||||
|
||||
foreach ($cache in $cacheList) {
|
||||
$shouldDelete = $false
|
||||
|
||||
if ($cache.ref -match "refs/pull/(\d+)/merge") {
|
||||
$prNumber = $matches[1]
|
||||
Write-Host "PR #${prNumber}: " -NoNewline
|
||||
|
||||
try {
|
||||
$prStatus = (gh pr view $prNumber --json state | ConvertFrom-Json).state
|
||||
Write-Host "$prStatus" -NoNewline
|
||||
$shouldDelete = $prStatus -in @("MERGED", "CLOSED")
|
||||
}
|
||||
catch {
|
||||
Write-Host "NOT FOUND" -NoNewline
|
||||
$shouldDelete = $true
|
||||
}
|
||||
}
|
||||
elseif ($cache.ref -match "refs/heads/(.+)" -and $matches[1] -ne "dev") {
|
||||
$branchName = $matches[1]
|
||||
$exists = $branchSet.ContainsKey($branchName)
|
||||
|
||||
Write-Host "Branch '$branchName': $(if ($exists) { 'EXISTS' } else { 'DELETED' })" -NoNewline
|
||||
$shouldDelete = -not $exists
|
||||
}
|
||||
else {
|
||||
continue
|
||||
}
|
||||
|
||||
if ($shouldDelete) {
|
||||
Write-Host " -> DELETING"
|
||||
gh cache delete $cache.id
|
||||
$totalClearedSize += $cache.sizeInBytes
|
||||
}
|
||||
else {
|
||||
Write-Host ""
|
||||
}
|
||||
}
|
||||
|
||||
Write-Output "Cleared size: $("{0:N2}" -f ($totalClearedSize / 1MB)) MB"
|
||||
1
.github/release_reviewers.yaml
vendored
1
.github/release_reviewers.yaml
vendored
@@ -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
|
||||
|
||||
76
.github/stale_cache_cleanup.ps1
vendored
76
.github/stale_cache_cleanup.ps1
vendored
@@ -1,76 +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",
|
||||
"prek-v1|Linux|X64"
|
||||
)
|
||||
|
||||
# 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"
|
||||
60
.github/stale_cache_dev.ps1
vendored
60
.github/stale_cache_dev.ps1
vendored
@@ -1,60 +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",
|
||||
"prek-v1|Linux|X64"
|
||||
)
|
||||
|
||||
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"
|
||||
51
.github/workflows/blame-ignore.yml
vendored
51
.github/workflows/blame-ignore.yml
vendored
@@ -1,51 +0,0 @@
|
||||
name: Blame Ignore Update
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "45 21 * * *" # Runs daily at 22:00 UTC
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
blame-ignore:
|
||||
name: Update Git Blame Ignore Revs
|
||||
if: github.repository_owner == 'MaaAssistantArknights'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false # Needed to bypass protection rules in Push changes
|
||||
|
||||
- name: Check blame
|
||||
id: check_changes
|
||||
continue-on-error: true
|
||||
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 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
|
||||
40
.github/workflows/cache-delete.yml
vendored
40
.github/workflows/cache-delete.yml
vendored
@@ -1,40 +0,0 @@
|
||||
name: Cache Cleanup
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [closed]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
pr_number:
|
||||
description: "PR Number"
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
cache-delete:
|
||||
name: Delete PR Cache
|
||||
# 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 PR cache
|
||||
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
|
||||
461
.github/workflows/ci.yml
vendored
461
.github/workflows/ci.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: Release Pipeline
|
||||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -7,74 +7,70 @@ on:
|
||||
branches-ignore:
|
||||
- "master"
|
||||
paths:
|
||||
- ".github/workflows/ci.yml"
|
||||
- "3rdparty/include/**"
|
||||
- "cmake/**"
|
||||
- "CMakeLists.txt"
|
||||
- "include/**"
|
||||
- "src/**"
|
||||
- "tools/maadeps-download.py"
|
||||
- "cmake/**"
|
||||
- "CMakeLists.txt"
|
||||
- "MAA.sln"
|
||||
- ".github/workflows/ci.yml"
|
||||
- "!**/*.md"
|
||||
pull_request:
|
||||
branches:
|
||||
- "dev"
|
||||
paths:
|
||||
- ".github/workflows/ci.yml"
|
||||
- "3rdparty/include/**"
|
||||
- "cmake/**"
|
||||
- "CMakeLists.txt"
|
||||
- "include/**"
|
||||
- "src/**"
|
||||
- "tools/maadeps-download.py"
|
||||
- "cmake/**"
|
||||
- "CMakeLists.txt"
|
||||
- "MAA.sln"
|
||||
- "!**/*.md"
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.head.repo.full_name || github.repository }}-${{ github.head_ref || github.ref_name }}${{ github.ref == 'refs/heads/dev' && format('-{0}', github.sha) || '' }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
meta:
|
||||
name: Gather Meta Information
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
tag: ${{ steps.set_tag.outputs.tag }}
|
||||
prerelease: ${{ steps.set_pre.outputs.prerelease }}
|
||||
steps:
|
||||
- name: Show concurrency group
|
||||
run: |
|
||||
echo "Concurrency Group: ${{ github.workflow }}-${{ github.event.pull_request.head.repo.full_name || github.repository }}-${{ github.head_ref || github.ref_name }}${{ github.ref == 'refs/heads/dev' && format('-{0}', github.sha) || '' }}"
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
path: temp
|
||||
show-progress: false
|
||||
|
||||
- name: Fetch history
|
||||
if: ${{ !startsWith(github.ref, 'refs/pull/') }}
|
||||
run: |
|
||||
git init
|
||||
cp $GITHUB_WORKSPACE/temp/.git/config ./.git
|
||||
rm -rf $GITHUB_WORKSPACE/temp
|
||||
# git config remote.origin.fetch '+refs/*:refs/*'
|
||||
git fetch --filter=tree:0 # --update-head-ok
|
||||
git reset --hard origin/$(git branch --show-current) || true
|
||||
git checkout ${{ github.ref_name }}
|
||||
|
||||
- name: Set tag
|
||||
id: set_tag
|
||||
run: |
|
||||
if [[ "${{ github.ref }}" == refs/tags/v* ]]; then
|
||||
# For tag pushes, use the tag name
|
||||
tag="${{ github.ref_name }}"
|
||||
else
|
||||
# For PRs and branch pushes, use git describe or fallback
|
||||
tag=$(git describe --tags --match "v*" HEAD 2>/dev/null || echo "v0.0.1-$(git rev-parse --short HEAD)")
|
||||
fi
|
||||
echo "tag=${tag}" | tee -a $GITHUB_OUTPUT
|
||||
${{ startsWith(github.ref, 'refs/pull/') && 'cd temp' || '' }}
|
||||
echo tag=$(git describe --tags --match "v*" ${{ github.ref }} || git rev-parse --short HEAD) | tee -a $GITHUB_OUTPUT
|
||||
exit ${PIPESTATUS[0]}
|
||||
|
||||
- name: Check if it is a pre-release
|
||||
- name: Judge pre-release
|
||||
id: set_pre
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
|
||||
run: |
|
||||
if [[ '${{ steps.set_tag.outputs.tag }}' =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
echo "prerelease=false" | tee -a $GITHUB_OUTPUT
|
||||
echo prerelease=false | tee -a $GITHUB_OUTPUT
|
||||
else
|
||||
echo "prerelease=true" | tee -a $GITHUB_OUTPUT
|
||||
echo prerelease=true | tee -a $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Finalize changelog
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
- name: Generate changelog
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
|
||||
run: |
|
||||
this_tag=${{ steps.set_tag.outputs.tag }}
|
||||
if [[ '${{ steps.set_pre.outputs.prerelease }}' != 'false' ]]; then
|
||||
@@ -84,81 +80,64 @@ 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@v6
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
- name: Upload changelog to Github
|
||||
uses: actions/upload-artifact@v4
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
|
||||
with:
|
||||
name: changelog
|
||||
path: CHANGELOG.md
|
||||
|
||||
windows:
|
||||
name: Build for Windows
|
||||
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 repository
|
||||
uses: actions/checkout@v6
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
show-progress: false
|
||||
|
||||
- name: Fetch submodules
|
||||
run: |
|
||||
git submodule update --init --depth 1 src/MaaUtils
|
||||
git submodule update --init --depth 1 3rdparty/EmulatorExtras
|
||||
|
||||
- name: Cache MaaDeps
|
||||
id: cache-maadeps
|
||||
uses: actions/cache@v5
|
||||
continue-on-error: true
|
||||
with:
|
||||
path: |
|
||||
./src/MaaUtils/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=RelWithDebInfo -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 RelWithDebInfo --parallel $env:NUMBER_OF_PROCESSORS
|
||||
|
||||
- name: Install
|
||||
run: |
|
||||
mkdir -p install
|
||||
cmake --install build --prefix install --config RelWithDebInfo
|
||||
submodules: recursive
|
||||
|
||||
- name: Cache .nuke/temp, ~/.nuget/packages
|
||||
id: cache-nuget
|
||||
uses: actions/cache@v5
|
||||
continue-on-error: true
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
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
|
||||
@@ -175,113 +154,89 @@ 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 -p:Platform=${{ matrix.arch == 'arm64' && 'ARM64' || 'x64' }} -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: Collect PDB files
|
||||
- name: Cleanup checksum file
|
||||
run: |
|
||||
cp build/bin/RelWithDebInfo/*.pdb install/
|
||||
Compress-Archive -Path install/*.pdb -DestinationPath install/MAAComponent-DebugSymbol-${{ needs.meta.outputs.tag }}-win-${{ matrix.arch }}.zip
|
||||
continue-on-error: true
|
||||
|
||||
- name: Upload PDB files
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: MAAComponent-DebugSymbol-win-${{ matrix.arch }}
|
||||
path: install/MAAComponent-DebugSymbol-${{ needs.meta.outputs.tag }}-win-${{ matrix.arch }}.zip
|
||||
|
||||
- name: Organize install files
|
||||
rm -vf ./artifacts/checksum.json
|
||||
shell: bash
|
||||
run: |
|
||||
rm -rf install/MAAComponent-DebugSymbol-*.zip
|
||||
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@v6
|
||||
- name: Upload MAA to Github
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: MAA-win-${{ matrix.arch }}
|
||||
path: install/MAA-*.zip
|
||||
name: MAA-win-${{ matrix.lowercase_target }}
|
||||
path: artifacts
|
||||
|
||||
ubuntu:
|
||||
name: Build for Ubuntu
|
||||
needs: meta
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [aarch64, x86_64]
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
- name: Checkout code
|
||||
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 src/MaaUtils
|
||||
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@v5
|
||||
continue-on-error: true
|
||||
- name: Setup ccache
|
||||
uses: Chocobo1/setup-ccache-action@v1
|
||||
with:
|
||||
path: ./src/MaaUtils/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=RelWithDebInfo \
|
||||
-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=src/MaaUtils/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 RelWithDebInfo --parallel $(nproc)
|
||||
env:
|
||||
CLICOLOR_FORCE: 1
|
||||
|
||||
- name: Install
|
||||
run: |
|
||||
mkdir -p install
|
||||
cmake --install build --prefix install --config RelWithDebInfo
|
||||
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
|
||||
- name: Setup Cross Compile Toolchains for CLI
|
||||
uses: ./src/maa-cli/.github/actions/setup
|
||||
with:
|
||||
os: ubuntu-latest
|
||||
target_arch: ${{ matrix.arch }}
|
||||
|
||||
- name: Build CLI
|
||||
run: |
|
||||
cargo build --release --locked --package maa-cli --features git2/vendored-openssl
|
||||
cargo build --release --locked --package maa-cli --features vendored-openssl
|
||||
cp -v target/$CARGO_BUILD_TARGET/release/maa $GITHUB_WORKSPACE/install/maa
|
||||
cargo build --release --locked --package maa-cli --no-default-features \
|
||||
--features git2,git2/vendored-openssl
|
||||
--features git2,vendored-openssl
|
||||
cp -v target/$CARGO_BUILD_TARGET/release/maa $GITHUB_WORKSPACE/appimage-maa
|
||||
working-directory: src/maa-cli
|
||||
|
||||
@@ -313,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
|
||||
|
||||
@@ -327,8 +282,8 @@ jobs:
|
||||
cd install
|
||||
tar czvf $GITHUB_WORKSPACE/release/MAA-${{ needs.meta.outputs.tag }}-linux-${{ matrix.arch }}.tar.gz .
|
||||
|
||||
- name: Upload MAA to GitHub
|
||||
uses: actions/upload-artifact@v6
|
||||
- name: Upload MAA to Github
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: MAA-linux-${{ matrix.arch }}
|
||||
path: |
|
||||
@@ -336,151 +291,88 @@ jobs:
|
||||
release/*.tar.gz
|
||||
|
||||
macOS-Core:
|
||||
name: Build Core for macOS
|
||||
needs: meta
|
||||
runs-on: macos-26
|
||||
runs-on: macos-14
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [arm64, x86_64]
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
show-progress: false
|
||||
|
||||
- name: Fetch submodules
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
git submodule update --init --depth 1 src/MaaUtils
|
||||
|
||||
# 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@v5
|
||||
continue-on-error: true
|
||||
with:
|
||||
path: ./src/MaaUtils/MaaDeps
|
||||
key: ${{ runner.os }}-${{ matrix.arch == 'x86_64' && 'x64' || 'arm64' }}-maadeps-${{ hashFiles('tools/maadeps-download.py') }}
|
||||
brew install ninja
|
||||
|
||||
- name: Bootstrap MaaDeps
|
||||
run: |
|
||||
python3 tools/maadeps-download.py ${{ matrix.arch == 'x86_64' && 'x64' || 'arm64' }}-osx
|
||||
[[ ${{ matrix.arch }} = "arm64" ]] && triplet="arm64-osx" || triplet="x64-osx"
|
||||
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=RelWithDebInfo \
|
||||
-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 RelWithDebInfo --parallel $(sysctl -n hw.logicalcpu)
|
||||
cmake --build build
|
||||
cmake --install build --prefix install
|
||||
|
||||
- name: Install
|
||||
run: |
|
||||
cmake --install build --prefix install --config RelWithDebInfo
|
||||
|
||||
- name: Upload MAA to GitHub
|
||||
uses: actions/upload-artifact@v6
|
||||
- name: Upload MAA to Github
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: MAACore-macos-${{ matrix.arch }}
|
||||
path: "install/*.dylib"
|
||||
|
||||
macOS-GUI:
|
||||
name: Build GUI for macOS
|
||||
needs: [meta, macOS-Core]
|
||||
runs-on: macos-26
|
||||
runs-on: macos-14
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
show-progress: false
|
||||
submodules: recursive
|
||||
|
||||
- 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
|
||||
|
||||
- name: Download MAA (arm64) from GitHub
|
||||
uses: actions/download-artifact@v7
|
||||
- name: Download Arm64 MAA from Github
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: MAACore-macos-arm64
|
||||
path: install-arm64
|
||||
|
||||
- name: Download MAA (x64) from GitHub
|
||||
uses: actions/download-artifact@v7
|
||||
- name: Download x64 MAA from Github
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: MAACore-macos-x86_64
|
||||
path: install-x86_64
|
||||
|
||||
- name: Install Developer ID certificate
|
||||
- name: Install Developer ID Certificate
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
uses: apple-actions/import-codesign-certs@v6
|
||||
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@v5
|
||||
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: false
|
||||
run: |
|
||||
sudo xcode-select -s /Applications/Xcode_16.1.app/Contents/Developer
|
||||
|
||||
- name: Build universal binaries
|
||||
- name: Build Universal Binaries
|
||||
run: |
|
||||
mkdir build
|
||||
for LIB_NAME in $(ls install-arm64); do
|
||||
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@v6
|
||||
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
|
||||
xcodebuild -create-xcframework -library libMaaUtils.dylib -output MaaUtils.xcframework
|
||||
xcodebuild -create-xcframework -library libfastdeploy_ppocr.dylib -output fastdeploy_ppocr.xcframework
|
||||
xcodebuild -create-xcframework -library libonnxruntime.*.dylib -output ONNXRuntime.xcframework
|
||||
xcodebuild -create-xcframework -library libopencv*.dylib -output OpenCV.xcframework
|
||||
working-directory: build
|
||||
|
||||
- name: Setup GUI version
|
||||
- name: Setup GUI Version
|
||||
run: |
|
||||
RELEASE_COUNT=$(git ls-remote --tags origin | grep refs/tags/v | awk 'END{print NR}')
|
||||
echo 'MARKETING_VERSION = ${{ needs.meta.outputs.tag }}' | tee src/MaaMacGui/Version.xcconfig
|
||||
@@ -489,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
|
||||
|
||||
@@ -501,20 +393,22 @@ jobs:
|
||||
xcodebuild -exportArchive -archivePath MAA.xcarchive -exportOptionsPlist ExportOptions.plist -exportPath Export
|
||||
working-directory: src/MaaMacGui
|
||||
|
||||
- name: Create disk image
|
||||
- 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
|
||||
- name: Archive Debug Symbols
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
run: |
|
||||
ditto -c -k --keepParent MAA.app.dSYM MAA.app.dSYM.zip
|
||||
working-directory: src/MaaMacGui/MAA.xcarchive/dSYMs
|
||||
|
||||
- name: Place packages
|
||||
- name: Place Packages
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
run: |
|
||||
GIT_TAG=${{ needs.meta.outputs.tag }}
|
||||
@@ -524,47 +418,37 @@ jobs:
|
||||
mv src/MaaMacGui/MAA.dmg release/${APP_DMG}
|
||||
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
|
||||
- name: Notarize Image
|
||||
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
|
||||
uses: actions/upload-artifact@v6
|
||||
- name: Upload MAA to Github
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: MAA-macos-universal
|
||||
path: ${{ startsWith(github.ref, 'refs/tags/v') && 'release/MAA*' || 'src/MaaMacGui/MAA.xcarchive/**' }}
|
||||
|
||||
release:
|
||||
name: Publish Release
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
needs: [meta, windows, ubuntu, macOS-Core, macOS-GUI]
|
||||
needs: [meta, windows, ubuntu, macOS-GUI]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download MAA from GitHub
|
||||
uses: actions/download-artifact@v7
|
||||
- name: Download MAA from Github
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: assets
|
||||
|
||||
- name: Clean up files
|
||||
- name: Cleanup files
|
||||
run: |
|
||||
mv -vf assets/changelog/* .
|
||||
rm -rf assets/MAACore-macos-*
|
||||
@@ -572,35 +456,16 @@ jobs:
|
||||
# find . -type f | xargs mv -fvt .
|
||||
find . -type f | while read f; do mv -fvt . $f; done
|
||||
|
||||
- name: Publish release to GitHub
|
||||
uses: softprops/action-gh-release@v2.5.0
|
||||
- name: Release to Github
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
body_path: CHANGELOG.md
|
||||
files: |
|
||||
assets/*
|
||||
prerelease: ${{ needs.meta.outputs.prerelease != 'false' }}
|
||||
|
||||
- name: Trigger release distribution workflows
|
||||
- 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-package-distribution.yml \
|
||||
-f release_tag="${{ needs.meta.outputs.tag }}" \
|
||||
-f mirrorchyan=true \
|
||||
-f winget=${{ needs.meta.outputs.prerelease == 'false' }}
|
||||
gh workflow run --repo $GITHUB_REPOSITORY mirrorchyan_release_note.yml
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Trigger OTA release workflow # 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.yml
|
||||
gh workflow run --repo $GITHUB_REPOSITORY release-ota
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.MISTEOWORKFLOW }}
|
||||
|
||||
- name: Create issue on failure
|
||||
if: failure()
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: "create-issue"
|
||||
title: "Errors occured during release ${{ needs.meta.outputs.tag }}"
|
||||
body: |
|
||||
${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
|
||||
98
.github/workflows/gen-changelog.yml
vendored
Normal file
98
.github/workflows/gen-changelog.yml
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
name: gen-changelog
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
- ready_for_review
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
gen:
|
||||
# startsWith 表达式不区分大小写
|
||||
if: github.event.pull_request.draft == false && startsWith(github.event.pull_request.title, 'Release v')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
show-progress: false
|
||||
|
||||
- name: Extract tag name
|
||||
id: extract_tag
|
||||
env:
|
||||
PR_BODY: ${{ format('{0}/{1}', runner.temp, 'output' ) }}
|
||||
run: |
|
||||
tag_name=$(echo "${{ github.event.pull_request.title }}" | sed -E 's/(Release|release)//' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
|
||||
echo "tag_name=$tag_name" >> $GITHUB_OUTPUT
|
||||
|
||||
pr_title="docs: Auto Update Changelogs of "$tag_name
|
||||
echo "pr_title=$pr_title" >> $GITHUB_OUTPUT
|
||||
|
||||
latest_stable_tag=$(git tag -l 'v*' | grep -v '-' | sort -V | tail -n 1) # 上一个 stable 版本
|
||||
newest_tag=$(git describe --tags --match "v*" --abbrev=0) # 最新版本
|
||||
echo "latest_stable_tag=$latest_stable_tag" >> $GITHUB_OUTPUT
|
||||
echo "newest_tag=$newest_tag" >> $GITHUB_OUTPUT
|
||||
|
||||
if [[ $tag_name == *-* ]]; then # 判断新版本是否为 beta 版本
|
||||
latest=$newest_tag # 若是,则将 latest 参数设置为最新版本
|
||||
else
|
||||
latest=$latest_stable_tag # 若否,则设置为上一个 stable 版本
|
||||
fi
|
||||
|
||||
echo "latest=$latest" >> $GITHUB_OUTPUT
|
||||
|
||||
cat $GITHUB_OUTPUT
|
||||
|
||||
echo '======='
|
||||
|
||||
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
|
||||
echo '```' >> $PR_BODY
|
||||
sed 's/=/: /1' $GITHUB_OUTPUT >> $PR_BODY
|
||||
echo '```' >> $PR_BODY
|
||||
echo '' >> $PR_BODY
|
||||
echo '</details>' >> $PR_BODY
|
||||
|
||||
cat $PR_BODY
|
||||
|
||||
- name: Generate Changelog
|
||||
run: |
|
||||
git switch dev
|
||||
python3 tools/ChangelogGenerator/changelog_generator.py --tag "${{ steps.extract_tag.outputs.tag_name }}" --latest "${{ steps.extract_tag.outputs.latest }}"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Add files to git
|
||||
run: |
|
||||
git status
|
||||
|
||||
git config user.name "$GITHUB_ACTOR"
|
||||
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
|
||||
git add .
|
||||
|
||||
commit_msg="docs: Auto Generate Changelog of Release ""${{ steps.extract_tag.outputs.tag_name }}"
|
||||
git commit -m "$commit_msg"
|
||||
|
||||
- name: Create PR
|
||||
uses: peter-evans/create-pull-request@v5
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
title: ${{ steps.extract_tag.outputs.pr_title }}
|
||||
body-path: ${{ format('{0}/{1}', runner.temp, 'output' ) }}
|
||||
base: "dev"
|
||||
branch: "changelog"
|
||||
delete-branch: true
|
||||
reviewers: |
|
||||
AnnAngela
|
||||
assignees: |
|
||||
AnnAngela
|
||||
|
||||
- name: Add reviewers to release PR
|
||||
uses: kentaro-m/auto-assign-action@v1.2.5
|
||||
with:
|
||||
configuration-path: ".github/release_reviewers.yaml"
|
||||
153
.github/workflows/issue-checkbox-checker.yml
vendored
153
.github/workflows/issue-checkbox-checker.yml
vendored
@@ -1,153 +0,0 @@
|
||||
name: Issue Review
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
check-then-close-or-fold:
|
||||
name: Review and Modify Issues
|
||||
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 for issue checkboxes
|
||||
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 low-quality 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
|
||||
});
|
||||
7
.github/workflows/issue-checker.yml
vendored
7
.github/workflows/issue-checker.yml
vendored
@@ -1,5 +1,4 @@
|
||||
name: Issue Triage
|
||||
|
||||
name: "Issue Checker"
|
||||
on:
|
||||
issues:
|
||||
types: [opened, edited]
|
||||
@@ -15,11 +14,9 @@ permissions:
|
||||
|
||||
jobs:
|
||||
triage:
|
||||
name: Triage Issues and PRs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Label issues and PRs Automatically
|
||||
uses: MaaAssistantArknights/issue-checker@v1.14
|
||||
- uses: zzyyyl/issue-checker@v1.8
|
||||
with:
|
||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
configuration-path: .github/issue-checker.yml
|
||||
|
||||
76
.github/workflows/markdown-checker.yml
vendored
76
.github/workflows/markdown-checker.yml
vendored
@@ -1,63 +1,49 @@
|
||||
name: Markdown Link Check
|
||||
name: Lint Markdown files
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * 2" # Every Tuesday at 00:00 UTC
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
paths:
|
||||
- ".github/workflows/markdown-checker.yml"
|
||||
- "docs/**"
|
||||
- "**/*.md"
|
||||
- ".github/workflows/lint-markdown.yml"
|
||||
pull_request:
|
||||
branches:
|
||||
- dev
|
||||
paths:
|
||||
- ".github/workflows/markdown-checker.yml"
|
||||
- "docs/**"
|
||||
- "**/*.md"
|
||||
- ".github/workflows/lint-markdown.yml"
|
||||
schedule:
|
||||
- cron: "44 7 * * 2"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
check-links:
|
||||
name: Check Dead Links
|
||||
if: github.repository_owner == 'MaaAssistantArknights' && github.event.head_commit.author.email != '41898282+github-actions[bot]@users.noreply.github.com'
|
||||
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: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
show-progress: false
|
||||
|
||||
- name: Cache lychee responses
|
||||
uses: actions/cache@v5
|
||||
continue-on-error: true
|
||||
- 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 internal 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
|
||||
|
||||
19
.github/workflows/mirrorchyan_release_note.yml
vendored
19
.github/workflows/mirrorchyan_release_note.yml
vendored
@@ -1,19 +0,0 @@
|
||||
name: Release Note Distribution
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types: [edited]
|
||||
|
||||
jobs:
|
||||
mirrorchyan:
|
||||
name: Upload to MirrorChyan
|
||||
runs-on: macos-latest
|
||||
|
||||
steps:
|
||||
- name: Upload release notes to MirrorChyan
|
||||
uses: MirrorChyan/release-note-action@v1
|
||||
with:
|
||||
mirrorchyan_rid: MAA
|
||||
|
||||
upload_token: ${{ secrets.MirrorChyanUploadToken }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
110
.github/workflows/optimize-templates.yml
vendored
110
.github/workflows/optimize-templates.yml
vendored
@@ -1,110 +0,0 @@
|
||||
name: PNG Image Optimization
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "dev"
|
||||
paths:
|
||||
- "docs/.vuepress/public/images/**"
|
||||
- "resource/**/*.png"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
commit_message:
|
||||
description: "Commit Message"
|
||||
type: string
|
||||
required: false
|
||||
|
||||
jobs:
|
||||
optimize-png:
|
||||
name: Optimize PNG Images
|
||||
# Skip workflow to prevent double consecutive runs
|
||||
if: github.repository_owner == 'MaaAssistantArknights' && github.event.head_commit.author.email != '41898282+github-actions[bot]@users.noreply.github.com'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Skip workflow on PR merges
|
||||
- name: Check if it is a direct push
|
||||
id: check_push
|
||||
run: |
|
||||
if [[ "${{ github.event_name }}" != "workflow_dispatch" ]]; then
|
||||
pr_count=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
|
||||
"https://api.github.com/repos/${{ github.repository }}/commits/${{ github.event.after }}/pulls" \
|
||||
| jq 'length')
|
||||
|
||||
if [[ "$pr_count" == "0" ]]; 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@v6
|
||||
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
|
||||
# continue-on-error: true
|
||||
# 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: Optimize png images
|
||||
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 }}
|
||||
16
.github/workflows/pr-auto-tag.yml
vendored
16
.github/workflows/pr-auto-tag.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: Release Version Tagging
|
||||
name: Auto Tag Release PR
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
@@ -9,29 +9,27 @@ on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: "Name of the tag to create for the release"
|
||||
type: string
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
auto_tag_release:
|
||||
name: Tag Release
|
||||
if: github.event.pull_request.merged == true && (startsWith(github.event.pull_request.title, 'Release v') || startsWith(github.event.pull_request.title, 'release v')) || github.event_name == 'workflow_dispatch'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.MAARELEASE_RELEASE }}
|
||||
|
||||
- name: Configure git
|
||||
- name: Git config
|
||||
run: |
|
||||
git config user.name "$GITHUB_ACTOR"
|
||||
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
|
||||
|
||||
- name: Determine tag name
|
||||
- name: Extract tag name
|
||||
id: extract_tag
|
||||
run: |
|
||||
if ${{ github.event_name != 'workflow_dispatch' }}; then
|
||||
@@ -41,12 +39,12 @@ jobs:
|
||||
echo "tag_name=${{ inputs.tag }}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Create and push release tag
|
||||
- name: Create release tag and push
|
||||
run: |
|
||||
git tag -a "${{ steps.extract_tag.outputs.tag_name }}" -m "${{ steps.extract_tag.outputs.tag_name }}" -f
|
||||
git push origin "${{ steps.extract_tag.outputs.tag_name }}"
|
||||
|
||||
- name: Merge tag into dev and push
|
||||
- name: Merge into dev and push
|
||||
run: |
|
||||
git switch dev
|
||||
git merge "${{ steps.extract_tag.outputs.tag_name }}"
|
||||
|
||||
18
.github/workflows/pr-checker.yml
vendored
18
.github/workflows/pr-checker.yml
vendored
@@ -1,17 +1,17 @@
|
||||
name: PR Commit Check
|
||||
name: PR Checker
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, edited, ready_for_review, reopened, synchronize]
|
||||
|
||||
|
||||
jobs:
|
||||
check_commit_name_in_pr:
|
||||
name: Check Commits in PR
|
||||
if: ${{ !github.event.pull_request.merged && github.base_ref != 'master' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clean up previous comment
|
||||
uses: actions/github-script@v8
|
||||
- name: Cleanup Previous Comment
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const { data: comments } = await github.rest.issues.listComments({
|
||||
@@ -28,8 +28,8 @@ jobs:
|
||||
comment_id: previousComment.id
|
||||
});
|
||||
}
|
||||
- name: Check commits
|
||||
uses: actions/github-script@v8
|
||||
- name: Check Commits
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const { data: commits } = await github.rest.pulls.listCommits({
|
||||
@@ -39,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)`);
|
||||
@@ -52,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")}`);
|
||||
}
|
||||
}
|
||||
36
.github/workflows/pre-commit-scheduled.yml
vendored
36
.github/workflows/pre-commit-scheduled.yml
vendored
@@ -1,36 +0,0 @@
|
||||
name: Scheduled Pre-commit
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# 每天 UTC 21:00 运行(北京时间 5:00)
|
||||
- cron: "0 21 * * *"
|
||||
workflow_dispatch: # 允许手动触发
|
||||
|
||||
jobs:
|
||||
pre-commit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
show-progress: false
|
||||
|
||||
- name: Setup and run Prek
|
||||
uses: j178/prek-action@v1
|
||||
id: pre-commit
|
||||
continue-on-error: true
|
||||
with:
|
||||
extra-args: '--all-files'
|
||||
|
||||
- name: Commit and push changes
|
||||
if: steps.pre-commit.outcome == 'failure' && github.repository_owner == 'MaaAssistantArknights'
|
||||
uses: actions-js/push@master
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
message: "chore: Auto update by pre-commit hooks
|
||||
|
||||
https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
|
||||
[skip changelog]"
|
||||
branch: ${{ github.ref }}
|
||||
385
.github/workflows/release-nightly-ota.yml
vendored
385
.github/workflows/release-nightly-ota.yml
vendored
@@ -1,8 +1,6 @@
|
||||
name: Release Pipeline (Nightly OTA)
|
||||
name: release-nightly-ota
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 22 * * *" # Runs daily at 22:00 UTC
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
release_body:
|
||||
@@ -13,256 +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:
|
||||
name: Build Nightly for Windows
|
||||
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:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
- 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 src/MaaUtils
|
||||
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@v5
|
||||
continue-on-error: true
|
||||
with:
|
||||
path: |
|
||||
./src/MaaUtils/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=RelWithDebInfo -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 RelWithDebInfo --parallel $env:NUMBER_OF_PROCESSORS
|
||||
|
||||
- name: Install
|
||||
run: |
|
||||
mkdir -p install
|
||||
cmake --install build --prefix install --config RelWithDebInfo
|
||||
|
||||
- name: Cache .nuke/temp, ~/.nuget/packages
|
||||
id: cache-nuget
|
||||
uses: actions/cache@v5
|
||||
continue-on-error: true
|
||||
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 -p:Platform=${{ matrix.arch == 'arm64' && 'ARM64' || 'x64' }} -o install
|
||||
|
||||
- name: Collect PDB files
|
||||
run: |
|
||||
cp build/bin/RelWithDebInfo/*.pdb install/
|
||||
Compress-Archive -Path install/*.pdb -DestinationPath install/MAAComponent-DebugSymbol-${{ steps.set_tag.outputs.tag }}-win-${{ matrix.arch }}.zip
|
||||
continue-on-error: true
|
||||
|
||||
- name: Upload PDB files
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: MAAComponent-DebugSymbol-win-${{ matrix.arch }}
|
||||
path: install/MAAComponent-DebugSymbol-${{ steps.set_tag.outputs.tag }}-win-${{ matrix.arch }}.zip
|
||||
|
||||
- name: Organize install files
|
||||
shell: bash
|
||||
run: |
|
||||
rm -rf install/MAAComponent-DebugSymbol-*.zip
|
||||
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@v6
|
||||
with:
|
||||
name: MAA-win-${{ matrix.arch }}
|
||||
path: install
|
||||
|
||||
- name: Push tag to main repo
|
||||
id: push_main_tag
|
||||
run: |
|
||||
@@ -274,14 +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:
|
||||
name: Push Tag to MaaRelease
|
||||
if: github.repository_owner == 'MaaAssistantArknights'
|
||||
needs: build-win-nightly
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout MaaRelease
|
||||
uses: actions/checkout@v6
|
||||
- name: Fetch MaaRelease
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: ${{ format('{0}/{1}', github.repository_owner, 'MaaRelease') }}
|
||||
fetch-depth: 0
|
||||
@@ -299,46 +185,35 @@ jobs:
|
||||
git push --tags origin HEAD:refs/tags/${{ needs.build-win-nightly.outputs.tag }}
|
||||
|
||||
make-ota:
|
||||
name: Build and Upload Nightly OTA for Windows
|
||||
if: github.repository_owner == 'MaaAssistantArknights'
|
||||
needs: [build-win-nightly, push-tag]
|
||||
strategy:
|
||||
matrix:
|
||||
target: [x64]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Show tag version
|
||||
- name: Echo tag version
|
||||
run: |
|
||||
echo ${{ needs.build-win-nightly.outputs.tag }}
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: MaaAssistantArknights
|
||||
token: ${{ secrets.MAARELEASE_RELEASE }}
|
||||
show-progress: false
|
||||
|
||||
- name: Download MAA from GitHub
|
||||
uses: actions/download-artifact@v7
|
||||
- name: Download MAA from Github
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: MAA-win-${{ matrix.target }}
|
||||
path: ${{ format('{0}/{1}', 'build-ota', needs.build-win-nightly.outputs.tag) }}
|
||||
|
||||
- name: Fetch release information
|
||||
- name: Fetch release info
|
||||
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
|
||||
@@ -358,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"
|
||||
@@ -366,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:
|
||||
@@ -376,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 }}
|
||||
|
||||
94
.github/workflows/release-ota.yml
vendored
94
.github/workflows/release-ota.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: Release Pipeline (OTA)
|
||||
name: release-ota
|
||||
|
||||
on:
|
||||
release:
|
||||
@@ -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:
|
||||
@@ -22,11 +22,10 @@ env:
|
||||
|
||||
jobs:
|
||||
create-tag:
|
||||
name: Create OTA Release Tag in MaaRelease
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout MaaRelease
|
||||
uses: actions/checkout@v6
|
||||
- name: Fetch MaaRelease
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
show-progress: false
|
||||
repository: ${{ format('{0}/{1}', github.repository_owner, 'MaaRelease') }}
|
||||
@@ -34,22 +33,12 @@ jobs:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.MAARELEASE_RELEASE }}
|
||||
|
||||
- name: Fetch release information
|
||||
- name: Fetch release info
|
||||
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
|
||||
@@ -77,7 +66,7 @@ jobs:
|
||||
PUSH_REMOTE: https://github-actions[bot]:${{ secrets.MAARELEASE_RELEASE }}@github.com/${{ github.repository_owner }}/MaaRelease
|
||||
|
||||
- name: Upload release config to GitHub
|
||||
uses: actions/upload-artifact@v6
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: MaaReleaseConfig
|
||||
path: ./build-ota/config
|
||||
@@ -87,7 +76,6 @@ jobs:
|
||||
release_tag: ${{ steps.fetchReleaseInfo.outputs.release_tag }}
|
||||
|
||||
make-ota:
|
||||
name: Build and Upload OTA for Windows
|
||||
needs: create-tag
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
@@ -96,13 +84,10 @@ jobs:
|
||||
- x64
|
||||
steps:
|
||||
- name: Download release config
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: MaaReleaseConfig
|
||||
path: ./MaaReleaseConfig
|
||||
uses: actions/download-artifact@v4
|
||||
|
||||
- name: Checkout MaaRelease
|
||||
uses: actions/checkout@v6
|
||||
- name: Fetch MaaRelease
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
show-progress: false
|
||||
repository: ${{ format('{0}/{1}', github.repository_owner, 'MaaRelease') }}
|
||||
@@ -110,8 +95,8 @@ jobs:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.MAARELEASE_RELEASE }}
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
show-progress: false
|
||||
path: MaaAssistantArknights
|
||||
@@ -139,21 +124,11 @@ jobs:
|
||||
prerelease: ${{ fromJSON(needs.create-tag.outputs.prerelease) }}
|
||||
overwrite: true
|
||||
|
||||
- name: Create issue on failure
|
||||
if: failure()
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: "create-issue"
|
||||
title: "Failed to make OTA release for Windows"
|
||||
body: |
|
||||
${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
|
||||
make-ota-mac:
|
||||
name: Build and Upload OTA for macOS
|
||||
needs: create-tag
|
||||
runs-on: macos-14
|
||||
steps:
|
||||
- name: Fetch release information
|
||||
- name: Fetch release info
|
||||
run: gh release list --repo 'MaaAssistantArknights/MaaAssistantArknights' --limit ${{ inputs.limit || 31 }} | tee ./release_maa.txt
|
||||
|
||||
- name: Download release packages
|
||||
@@ -169,7 +144,7 @@ jobs:
|
||||
run: |
|
||||
gh release download --repo 'sparkle-project/Sparkle' --clobber -O - -p 'Sparkle-*.tar.xz' | tar xf -
|
||||
|
||||
- name: Generate update packages
|
||||
- name: Generate Update Packages
|
||||
run: |
|
||||
if [ $(head -n 1 release_maa.txt | awk '{ print $2 }') = 'Pre-release' ]; then
|
||||
echo ${{ secrets.SPARKLE_PRIV_KEY }} | ./bin/generate_appcast --channel beta --ed-key-file - ./packages
|
||||
@@ -177,10 +152,35 @@ jobs:
|
||||
echo ${{ secrets.SPARKLE_PRIV_KEY }} | ./bin/generate_appcast --ed-key-file - ./packages
|
||||
fi
|
||||
|
||||
- name: Clean up files
|
||||
- name: Cleanup files
|
||||
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:
|
||||
@@ -192,17 +192,7 @@ jobs:
|
||||
prerelease: ${{ fromJSON(needs.create-tag.outputs.prerelease) }}
|
||||
overwrite: true
|
||||
|
||||
- name: Create issue on failure
|
||||
if: failure()
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: "create-issue"
|
||||
title: "Failed to make OTA release for macOS"
|
||||
body: |
|
||||
${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
|
||||
release:
|
||||
name: Publish to Release Mirrors
|
||||
needs:
|
||||
- make-ota
|
||||
- make-ota-mac
|
||||
|
||||
122
.github/workflows/release-package-distribution.yml
vendored
122
.github/workflows/release-package-distribution.yml
vendored
@@ -1,122 +0,0 @@
|
||||
name: Release Package Distribution
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
release_tag:
|
||||
description: "Release Tag (empty for latest)"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
mirrorchyan:
|
||||
description: "Upload to MirrorChyan"
|
||||
type: boolean
|
||||
required: false
|
||||
default: true
|
||||
winget:
|
||||
description: "Upload to WinGet"
|
||||
type: boolean
|
||||
required: false
|
||||
default: true
|
||||
|
||||
env:
|
||||
RELEASE_TAG_RAW: ${{ github.event.inputs.release_tag || 'latest' }}
|
||||
|
||||
jobs:
|
||||
meta:
|
||||
name: Define Release Tag
|
||||
if: ${{ github.repository_owner == 'MaaAssistantArknights' }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
outputs:
|
||||
RELEASE_TAG: ${{ steps.define_release_tag.outputs.RELEASE_TAG }}
|
||||
|
||||
steps:
|
||||
- name: Get latest release tag
|
||||
id: get_latest
|
||||
if: ${{ env.RELEASE_TAG_RAW == 'latest' }}
|
||||
uses: pozetroninc/github-action-get-latest-release@master
|
||||
with:
|
||||
owner: ${{ github.repository_owner }}
|
||||
repo: ${{ github.event.repository.name }}
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
excludes: "draft"
|
||||
|
||||
- name: Define release tag
|
||||
id: define_release_tag
|
||||
run: |
|
||||
if [ "${{ env.RELEASE_TAG_RAW }}" == "latest" ]; then
|
||||
echo "RELEASE_TAG=${{ steps.get_latest.outputs.release }}" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "RELEASE_TAG=${{ env.RELEASE_TAG_RAW }}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
mirrorchyan:
|
||||
name: Upload to MirrorChyan
|
||||
needs: meta
|
||||
if: ${{ github.event.inputs.mirrorchyan == 'true' }}
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: win
|
||||
arch: x64
|
||||
filename: "*MAA-*-win-x64.zip"
|
||||
extra_zip: false
|
||||
- os: win
|
||||
arch: arm64
|
||||
filename: "*MAA-*-win-arm64.zip"
|
||||
extra_zip: false
|
||||
- os: macos
|
||||
arch: arm64
|
||||
filename: "MAA-*-macos-universal.dmg"
|
||||
extra_zip: true
|
||||
- os: macos
|
||||
arch: x64
|
||||
filename: "MAA-*-macos-universal.dmg"
|
||||
extra_zip: true
|
||||
|
||||
env:
|
||||
RELEASE_TAG: ${{ needs.meta.outputs.RELEASE_TAG }}
|
||||
|
||||
steps:
|
||||
- name: Upload MAA ${{ matrix.os }} ${{ matrix.arch }}
|
||||
uses: MirrorChyan/uploading-action@v1
|
||||
continue-on-error: true
|
||||
with:
|
||||
filetype: latest-release
|
||||
filename: ${{ matrix.filename }}
|
||||
extra_zip: ${{ matrix.extra_zip }}
|
||||
tag: ${{ env.RELEASE_TAG }}
|
||||
mirrorchyan_rid: MAA
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
owner: ${{ github.repository_owner }}
|
||||
repo: ${{ github.event.repository.name }}
|
||||
upload_token: ${{ secrets.MirrorChyanUploadToken }}
|
||||
os: ${{ matrix.os }}
|
||||
arch: ${{ matrix.arch }}
|
||||
|
||||
winget:
|
||||
name: Upload to WinGet
|
||||
needs: meta
|
||||
if: ${{ github.event.inputs.winget == 'true' }}
|
||||
runs-on: windows-latest
|
||||
continue-on-error: true
|
||||
|
||||
env:
|
||||
RELEASE_TAG: ${{ needs.meta.outputs.RELEASE_TAG }}
|
||||
|
||||
steps:
|
||||
- name: Upload MAA to WinGet
|
||||
uses: vedantmgoyal9/winget-releaser@main
|
||||
with:
|
||||
identifier: MaaAssistantArknights.MaaAssistantArknights
|
||||
version: ""
|
||||
installers-regex: "-win-"
|
||||
max-versions-to-keep: 0
|
||||
release-tag: ${{ env.RELEASE_TAG }}
|
||||
fork-user: MaaAssistantArknights
|
||||
token: ${{ secrets.MAABOT_WINGET_TOKEN }}
|
||||
111
.github/workflows/release-preparation.yml
vendored
111
.github/workflows/release-preparation.yml
vendored
@@ -1,111 +0,0 @@
|
||||
name: Release Preparation
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
- ready_for_review
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
generate-changelog:
|
||||
name: Generate Changelog
|
||||
# startsWith 表达式不区分大小写
|
||||
if: github.event.pull_request.draft == false && startsWith(github.event.pull_request.title, 'Release v')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
show-progress: false
|
||||
|
||||
- name: Extract release information
|
||||
id: extract_tag
|
||||
env:
|
||||
PR_BODY: ${{ format('{0}/{1}', runner.temp, 'output' ) }}
|
||||
run: |
|
||||
tag_name=$(echo "${{ github.event.pull_request.title }}" | sed -E 's/(Release|release)//' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
|
||||
echo "tag_name=$tag_name" >> $GITHUB_OUTPUT
|
||||
|
||||
pr_title="docs: Auto Update Changelogs of "$tag_name
|
||||
echo "pr_title=$pr_title" >> $GITHUB_OUTPUT
|
||||
|
||||
latest_stable_tag=$(git tag -l 'v*' | grep -v '-' | sort -V | tail -n 1) # 上一个 stable 版本
|
||||
newest_tag=$(git describe --tags --match "v*" --abbrev=0) # 最新版本
|
||||
echo "latest_stable_tag=$latest_stable_tag" >> $GITHUB_OUTPUT
|
||||
echo "newest_tag=$newest_tag" >> $GITHUB_OUTPUT
|
||||
|
||||
if [[ $tag_name == *-* ]]; then # 判断新版本是否为 beta 版本
|
||||
latest=$newest_tag # 若是,则将 latest 参数设置为最新版本
|
||||
else
|
||||
latest=$latest_stable_tag # 若否,则设置为上一个 stable 版本
|
||||
fi
|
||||
|
||||
echo "latest=$latest" >> $GITHUB_OUTPUT
|
||||
|
||||
cat $GITHUB_OUTPUT
|
||||
|
||||
echo '======='
|
||||
|
||||
echo 'Target PR: ${{ github.event.pull_request.html_url }}' >> $PR_BODY
|
||||
echo '' >> $PR_BODY
|
||||
echo '<details><summary>Debug information</summary>' >> $PR_BODY
|
||||
echo '' >> $PR_BODY
|
||||
echo '```' >> $PR_BODY
|
||||
sed 's/=/: /1' $GITHUB_OUTPUT >> $PR_BODY
|
||||
echo '```' >> $PR_BODY
|
||||
echo '' >> $PR_BODY
|
||||
echo '</details>' >> $PR_BODY
|
||||
|
||||
cat $PR_BODY
|
||||
|
||||
- name: Generate changelog
|
||||
run: |
|
||||
git switch dev
|
||||
python3 tools/ChangelogGenerator/changelog_generator.py --tag "${{ steps.extract_tag.outputs.tag_name }}" --latest "${{ steps.extract_tag.outputs.latest }}"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Commit changes
|
||||
run: |
|
||||
git status
|
||||
|
||||
git config user.name "$GITHUB_ACTOR"
|
||||
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
|
||||
git add .
|
||||
|
||||
commit_msg="docs: Auto Generate Changelog of Release ""${{ steps.extract_tag.outputs.tag_name }}"
|
||||
git commit -m "$commit_msg"
|
||||
|
||||
- name: Create changelog PR
|
||||
uses: peter-evans/create-pull-request@v8
|
||||
with:
|
||||
sign-commits: true
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
title: ${{ steps.extract_tag.outputs.pr_title }}
|
||||
body-path: ${{ format('{0}/{1}', runner.temp, 'output' ) }}
|
||||
base: "dev"
|
||||
branch: "changelog"
|
||||
delete-branch: true
|
||||
reviewers: |
|
||||
AnnAngela
|
||||
assignees: |
|
||||
AnnAngela
|
||||
|
||||
- name: Assign reviewers to release PR
|
||||
uses: kentaro-m/auto-assign-action@v2.0.0
|
||||
with:
|
||||
configuration-path: ".github/release_reviewers.yaml"
|
||||
|
||||
update-submodules:
|
||||
name: Update Submodules
|
||||
if: github.event.pull_request.draft == false && startsWith(github.event.pull_request.title, 'Release v')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Trigger submodule update workflow
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
gh workflow run --repo $GITHUB_REPOSITORY update-submodules.yml
|
||||
442
.github/workflows/res-update-game.yml
vendored
442
.github/workflows/res-update-game.yml
vendored
@@ -1,8 +1,8 @@
|
||||
name: Game Resource Update
|
||||
name: res-update-game
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "*/20 * * * *" # Runs every 20 minutes
|
||||
- cron: "*/20 * * * *"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
commit_message:
|
||||
@@ -11,19 +11,38 @@ on:
|
||||
required: false
|
||||
|
||||
jobs:
|
||||
clone-resources-official:
|
||||
name: Download Official Resources
|
||||
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@v6
|
||||
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
|
||||
@@ -35,345 +54,136 @@ jobs:
|
||||
/gamedata/excel/gacha_table.json
|
||||
/gamedata/excel/roguelike_topic_table.json
|
||||
/gamedata/excel/activity_table.json
|
||||
|
||||
- name: Upload Official resources
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: official
|
||||
path: ./Official
|
||||
compression-level: 0
|
||||
|
||||
clone-resources-overseas:
|
||||
name: Download Overseas Resources
|
||||
if: github.repository_owner == 'MaaAssistantArknights'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone ArknightsGameResource_Yostar for Overseas
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
show-progress: false
|
||||
repository: ArknightsAssets/ArknightsGamedata
|
||||
ref: master
|
||||
path: ./Overseas
|
||||
sparse-checkout-cone-mode: false
|
||||
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
|
||||
|
||||
- name: Upload Overseas resources
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: overseas
|
||||
path: ./Overseas
|
||||
compression-level: 0
|
||||
|
||||
clone-resources-txwy:
|
||||
name: Download Taiwan Resources
|
||||
if: github.repository_owner == 'MaaAssistantArknights'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone arknights-toolbox-update for Taiwan
|
||||
uses: actions/checkout@v6
|
||||
- name: Clone ArknightsGameResource_Yostar for Overseas
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
show-progress: false
|
||||
repository: arkntools/arknights-data-tw-for-maa
|
||||
repository: Kengxxiao/ArknightsGameData_Yostar
|
||||
ref: main
|
||||
path: ./excel
|
||||
path: .\tools\ResourceUpdater\x64\Release\Overseas
|
||||
sparse-checkout: |
|
||||
/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: Download stages.json from Penguin Stats
|
||||
run: |
|
||||
cd "./excel"
|
||||
|
||||
baseUrl="https://penguin-stats.io/PenguinStats/api/v2/stages?server="
|
||||
|
||||
parameters=("CN" "US" "JP" "KR")
|
||||
|
||||
pids=()
|
||||
for param in "${parameters[@]}"; do
|
||||
{
|
||||
if curl -f -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
|
||||
} &
|
||||
pids+=($!)
|
||||
done
|
||||
|
||||
failed=0
|
||||
for pid in "${pids[@]}"; do
|
||||
if ! wait "$pid"; then
|
||||
failed=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $failed -ne 0 ]; then
|
||||
echo "One or more downloads failed" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Upload Taiwan resources
|
||||
uses: actions/upload-artifact@v6
|
||||
- name: Clone arknights-toolbox-update for Taiwan
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
name: txwy
|
||||
path: ./excel
|
||||
compression-level: 0
|
||||
|
||||
update-game-resources:
|
||||
name: Update Game Resources
|
||||
if: github.repository_owner == 'MaaAssistantArknights'
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
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
|
||||
repository: arkntools/arknights-toolbox-update
|
||||
ref: data-tw
|
||||
path: .\tools\ResourceUpdater\x64\Release\Overseas\zh_TW\gamedata\excel
|
||||
token: ${{ secrets.ARKNTOOLS_MAA_RESOURCE_UPDATER}}
|
||||
|
||||
- name: Fetch submodules
|
||||
- name: Run Resource Updater
|
||||
run: |
|
||||
git submodule update --init --depth 1 src/MaaUtils
|
||||
.\tools\ResourceUpdater\x64\Release\ResourceUpdater.exe
|
||||
|
||||
- name: Restore ResourceUpdater from cache
|
||||
id: resupd-cache
|
||||
uses: actions/cache/restore@v5
|
||||
continue-on-error: true
|
||||
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@v5
|
||||
continue-on-error: true
|
||||
with:
|
||||
path: |
|
||||
./src/MaaUtils/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@v5
|
||||
continue-on-error: true
|
||||
with:
|
||||
key: ResourceUpdater-${{ runner.os }}-${{ hashFiles('tools/ResourceUpdater/main.cpp') }}
|
||||
path: |
|
||||
./tools/ResourceUpdater/libopencv_world4.4.11.0.dylib
|
||||
./tools/ResourceUpdater/res_updater
|
||||
|
||||
- name: Wait for resource cloning
|
||||
uses: yogeshlonkar/wait-for-jobs@v0
|
||||
with:
|
||||
ignore-skipped: 'false'
|
||||
jobs: |
|
||||
Download Official Resources
|
||||
Download Overseas Resources
|
||||
Download Taiwan Resources
|
||||
ttl: 15
|
||||
|
||||
- name: Download txwy
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: txwy
|
||||
path: ./tools/ResourceUpdater/Overseas/tw/gamedata/excel
|
||||
|
||||
- name: Download Overseas
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: overseas
|
||||
path: ./tools/ResourceUpdater/Overseas
|
||||
|
||||
- name: Download Official
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: official
|
||||
path: ./tools/ResourceUpdater/Official
|
||||
|
||||
- name: Update resources
|
||||
run: |
|
||||
./tools/ResourceUpdater/res_updater
|
||||
|
||||
- name: Sort tasks
|
||||
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: |
|
||||
sh ./tools/ResourceUpdater/version.sh
|
||||
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@v5
|
||||
continue-on-error: true
|
||||
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: Optimize png images
|
||||
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: Commit changes
|
||||
if: steps.update_version.outputs.changes == 'True'
|
||||
- name: Add files to git
|
||||
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: 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.yml -f release_body="Auto Release of Resource Updates"
|
||||
|
||||
- name: Upsert failure comment (single active)
|
||||
if: failure() && github.ref == 'refs/heads/dev'
|
||||
- name: Update OTA resource
|
||||
if: steps.add_files.outputs.have_commits == 'True'
|
||||
run: |
|
||||
run_url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
||||
latest_id=$(gh api --paginate repos/${{ github.repository }}/issues/14493/comments | jq -r '.[] | select(.user.login=="github-actions[bot]") | .id' | tail -n 1)
|
||||
if [ -n "$latest_id" ]; then
|
||||
body=$(gh api repos/${{ github.repository }}/issues/comments/$latest_id --jq '.body')
|
||||
if echo "$body" | grep -q '/actions/runs/'; then
|
||||
# Count existing run URLs
|
||||
count=$(echo "$body" | grep -o 'https://github.com/[^[:space:]]*' | wc -l)
|
||||
# Collapse existing content
|
||||
old_content=$(echo "$body" | sed 's|https://github.com/[^[:space:]]*|<details>\n<summary>⚠️ Previous failures ('"$count"')</summary>\n\n###### &\n\n</details>|g')
|
||||
new_body="$run_url
|
||||
gh workflow --repo MaaAssistantArknights/MaaRelease run update-resource.yml
|
||||
|
||||
@MistEO @ABA2396 @Constrat
|
||||
|
||||
$old_content"
|
||||
gh api repos/${{ github.repository }}/issues/comments/$latest_id -X PATCH -f body="$new_body" || echo "Patch failed"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
# Create new failure comment if none suitable
|
||||
gh issue comment 14493 -R ${{ github.repository }} --body "$run_url
|
||||
|
||||
@MistEO @ABA2396 @Constrat"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Minimize failure comment on success/cancelled
|
||||
if: ${{ !failure() && github.ref == 'refs/heads/dev' }}
|
||||
run: |
|
||||
latest_node=$(gh api --paginate repos/${{ github.repository }}/issues/14493/comments | jq -r '.[] | select(.user.login=="github-actions[bot]") | .node_id' | tail -n 1)
|
||||
if [ -n "$latest_node" ]; then
|
||||
gh api graphql -f query='mutation { minimizeComment(input: {subjectId: "'"$latest_node"'", classifier: OUTDATED}) { minimizedComment { isMinimized } } }' || true
|
||||
fi
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
# - 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 }}
|
||||
|
||||
140
.github/workflows/smoke-testing.yml
vendored
140
.github/workflows/smoke-testing.yml
vendored
@@ -1,140 +1,78 @@
|
||||
name: Smoke Test
|
||||
permissions:
|
||||
contents: read
|
||||
name: test
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- ".github/workflows/smoke-testing.yml"
|
||||
- "3rdparty/include/**"
|
||||
- "include/**"
|
||||
- "src/**"
|
||||
- "cmake/**"
|
||||
- "CMakeLists.txt"
|
||||
- "include/**"
|
||||
- "MAA.sln"
|
||||
- "resource/**"
|
||||
- "src/Cpp/**"
|
||||
- "src/MaaCore/**"
|
||||
- "tools/maadeps-download.py"
|
||||
- "tools/SmokeTesting/**"
|
||||
- "MaaDeps/**"
|
||||
- "!**/*.md"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/smoke-testing.yml"
|
||||
- "3rdparty/include/**"
|
||||
- "include/**"
|
||||
- "src/**"
|
||||
- "cmake/**"
|
||||
- "CMakeLists.txt"
|
||||
- "include/**"
|
||||
- "MAA.sln"
|
||||
- "resource/**"
|
||||
- "src/Cpp/**"
|
||||
- "src/MaaCore/**"
|
||||
- "tools/maadeps-download.py"
|
||||
- "tools/SmokeTesting/**"
|
||||
- "MaaDeps/**"
|
||||
- "!**/*.md"
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.head.repo.full_name || github.repository }}-${{ github.head_ref || github.ref_name }}${{ github.ref == 'refs/heads/dev' && format('-{0}', github.sha) || '' }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
smoke-testing:
|
||||
name: Run Smoke Test
|
||||
runs-on: macos-latest
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
show-progress: false
|
||||
|
||||
- name: Generate cache key
|
||||
id: cache_key
|
||||
continue-on-error: true
|
||||
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 for Smoke Test
|
||||
if: ${{ steps.cache_key.outputs.key != '' }}
|
||||
id: smoke-cache
|
||||
uses: actions/cache/restore@v5
|
||||
continue-on-error: true
|
||||
with:
|
||||
key: ${{ steps.cache_key.outputs.key }}
|
||||
path: |
|
||||
./install/libfastdeploy_ppocr.dylib
|
||||
./install/libMaaCore.dylib
|
||||
./install/libMaaUtils.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 src/MaaUtils
|
||||
|
||||
- name: Cache MaaDeps
|
||||
if: steps.smoke-cache.outputs.cache-hit != 'true'
|
||||
id: maadeps-cache
|
||||
uses: actions/cache@v5
|
||||
continue-on-error: true
|
||||
with:
|
||||
path: ./src/MaaUtils/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 to Smoke Test cache
|
||||
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: |
|
||||
sh ./tools/SmokeTesting/run_tests.sh
|
||||
|
||||
- name: Save cache for Smoke Test (only in dev)
|
||||
if: steps.smoke-cache.outputs.cache-hit != 'true' && github.ref == 'refs/heads/dev'
|
||||
uses: actions/cache/save@v5
|
||||
continue-on-error: true
|
||||
with:
|
||||
key: ${{ steps.cache_key.outputs.key }}
|
||||
path: |
|
||||
./install/libfastdeploy_ppocr.dylib
|
||||
./install/libMaaCore.dylib
|
||||
./install/libMaaUtils.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@v6
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: logs
|
||||
path: ./install/debug
|
||||
name: log
|
||||
path: .\x64\Debug\debug
|
||||
|
||||
40
.github/workflows/stale.yml
vendored
40
.github/workflows/stale.yml
vendored
@@ -1,40 +0,0 @@
|
||||
name: Issue Staleness Management
|
||||
|
||||
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:
|
||||
name: Handle Stale Issues
|
||||
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: Handle stale 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
|
||||
28
.github/workflows/sync-resource.yml
vendored
28
.github/workflows/sync-resource.yml
vendored
@@ -1,34 +1,32 @@
|
||||
name: Resource Sync
|
||||
name: sync-resource
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
paths:
|
||||
- ".github/workflows/sync-resource.yml"
|
||||
- "resource/**"
|
||||
workflow_dispatch:
|
||||
- ".github/workflows/sync-resource.yml"
|
||||
|
||||
jobs:
|
||||
sync-resource:
|
||||
name: Sync Resource to MaaResource
|
||||
if: github.repository_owner == 'MaaAssistantArknights'
|
||||
sync-reource:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
- name: Checkout MaaAssistantArknights
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
show-progress: false
|
||||
|
||||
- name: Configure git
|
||||
- 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@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: MaaAssistantArknights/MaaResource
|
||||
show-progress: false
|
||||
@@ -50,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
|
||||
|
||||
33
.github/workflows/update-submodules.yml
vendored
33
.github/workflows/update-submodules.yml
vendored
@@ -1,33 +0,0 @@
|
||||
name: Submodule Update
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "50 21 * * *" # Runs daily at 21:50 UTC (before `Release Pipeline (Nightly OTA)`)
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
update-submodules:
|
||||
name: Update Submodules
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'MaaAssistantArknights'
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Update submodules
|
||||
run: |
|
||||
git submodule update --remote src/MaaMacGui
|
||||
git submodule update --remote src/maa-cli
|
||||
|
||||
- name: Commit and push changes
|
||||
uses: actions-js/push@master
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
message: "feat: Update Submodules MaaMacGui, maa-cli
|
||||
|
||||
https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
|
||||
[skip changelog]"
|
||||
branch: ${{ github.ref }}
|
||||
96
.github/workflows/website-workflow.yml
vendored
96
.github/workflows/website-workflow.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: Documentation Site
|
||||
name: MaaWebsite Workflow
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -8,68 +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
|
||||
|
||||
permissions:
|
||||
# required for peaceiris/actions-gh-pages
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build and Deploy
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
show-progress: false
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
package_json_file: "./docs/package.json"
|
||||
version: 9
|
||||
run_install: false
|
||||
|
||||
- name: Setup node.js environment
|
||||
uses: actions/setup-node@v6
|
||||
- name: Setup Node.js environment
|
||||
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 node modules
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
working-directory: "./docs"
|
||||
working-directory: "./website"
|
||||
|
||||
- name: Build
|
||||
run: pnpm run build
|
||||
working-directory: "./docs"
|
||||
working-directory: "./website"
|
||||
|
||||
- name: Upload artifact to GitHub
|
||||
uses: actions/upload-artifact@v6
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dist
|
||||
path: "./docs/.vuepress/dist"
|
||||
path: "./website/dist"
|
||||
|
||||
- name: Deploy to GitHub Pages
|
||||
uses: peaceiris/actions-gh-pages@v4
|
||||
if: github.repository_owner == 'MaaAssistantArknights' && (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
|
||||
|
||||
31
.gitignore
vendored
31
.gitignore
vendored
@@ -437,9 +437,6 @@ tools/**/*.png
|
||||
.vscode
|
||||
enc_temp_folder/*
|
||||
|
||||
# RoguelikeRecruitmentTool 导出的 Excel 文件
|
||||
tools/RoguelikeRecruitmentTool/output
|
||||
|
||||
# Nuke
|
||||
.nuke/temp/*
|
||||
|
||||
@@ -451,31 +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
|
||||
src/MaaUtils/*
|
||||
|
||||
# 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
|
||||
|
||||
8
.gitmodules
vendored
8
.gitmodules
vendored
@@ -4,12 +4,14 @@
|
||||
[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
|
||||
[submodule "3rdparty/EmulatorExtras"]
|
||||
path = 3rdparty/EmulatorExtras
|
||||
url = https://github.com/MaaXYZ/EmulatorExtras.git
|
||||
[submodule "src/MaaUtils"]
|
||||
path = src/MaaUtils
|
||||
url = https://github.com/MaaXYZ/MaaUtils
|
||||
|
||||
5
.linkspector.yml
Normal file
5
.linkspector.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
dirs:
|
||||
- .
|
||||
useGitIgnore: true
|
||||
ignorePatterns:
|
||||
- pattern: "^https?://127.0.0.1(:\\d+)?/"
|
||||
132
.nuke/build.schema.json
Normal file
132
.nuke/build.schema.json
Normal 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
4
.nuke/parameters.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"$schema": "./build.schema.json",
|
||||
"Solution": "tools/MaaBuilder.sln"
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
default_install_hook_types: [pre-commit, prepare-commit-msg]
|
||||
repos:
|
||||
- repo: https://github.com/shssoichiro/oxipng
|
||||
rev: v10.0.0
|
||||
hooks:
|
||||
- id: oxipng
|
||||
name: PNG Image Compression
|
||||
args: ["-q", "-o", "2", "-s", "--ng"]
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: v21.1.8
|
||||
hooks:
|
||||
- id: clang-format
|
||||
name: Clang-Format (MaaCore)
|
||||
files: ^src/MaaCore/.*
|
||||
args: ["--assume-filename", ".clang-format"]
|
||||
|
||||
- repo: https://github.com/rbubley/mirrors-prettier
|
||||
rev: v3.7.4
|
||||
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
|
||||
- id: prettier
|
||||
name: Prettier (Documentation)
|
||||
files: ^docs/.*
|
||||
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.14.10
|
||||
hooks:
|
||||
- id: ruff-format
|
||||
name: Ruff format (Python)
|
||||
|
||||
- repo: https://github.com/DavidAnson/markdownlint-cli2
|
||||
rev: v0.18.1
|
||||
hooks:
|
||||
- id: markdownlint-cli2
|
||||
name: MarkdownLint (Documentation)
|
||||
files: ^docs/.*|^README\.md$
|
||||
types:
|
||||
- markdown
|
||||
args: ["--fix", "--config", "docs/.markdownlint.yaml"]
|
||||
@@ -1,12 +0,0 @@
|
||||
**/pnpm-lock.yaml
|
||||
|
||||
3rdparty/
|
||||
src/maa-cli
|
||||
src/MaaMacGui
|
||||
src/MaaUtils
|
||||
|
||||
resource/Arknights-Tile-Pos/
|
||||
tools/OptimizeTemplates/optimize_templates.json
|
||||
|
||||
CITATION.cff
|
||||
CHANGELOG.md
|
||||
23
.prettierrc
23
.prettierrc
@@ -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
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
@@ -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"
|
||||
}
|
||||
|
||||
2
3rdparty/EmulatorExtras
vendored
2
3rdparty/EmulatorExtras
vendored
Submodule 3rdparty/EmulatorExtras updated: 54d3a3ad44...42442b1183
@@ -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);
|
||||
}
|
||||
@@ -115,15 +121,15 @@ static constexpr double rel_pos_x = 1.3143386840820312;
|
||||
static constexpr double rel_pos_y = 1.314337134361267;
|
||||
static constexpr double rel_pos_z = -0.3967874050140381;
|
||||
|
||||
inline auto get_retreat_screen_pos(const Level& level, bool has_multi_stages = false)
|
||||
inline auto get_retreat_screen_pos(const Level& level)
|
||||
{
|
||||
const vec3d relative_pos = { -rel_pos_x + (has_multi_stages ? level.view[0].x : 0), +rel_pos_y, rel_pos_z };
|
||||
const vec3d relative_pos = { -rel_pos_x, +rel_pos_y, rel_pos_z };
|
||||
return world_to_screen(level, relative_pos, true);
|
||||
}
|
||||
|
||||
inline auto get_skill_screen_pos(const Level& level, bool has_multi_stages = false)
|
||||
inline auto get_skill_screen_pos(const Level& level)
|
||||
{
|
||||
const vec3d relative_pos = { +rel_pos_x + (has_multi_stages ? level.view[0].x : 0), -rel_pos_y, rel_pos_z };
|
||||
const vec3d relative_pos = { +rel_pos_x, -rel_pos_y, rel_pos_z };
|
||||
return world_to_screen(level, relative_pos, true);
|
||||
}
|
||||
|
||||
|
||||
533
3rdparty/include/meojson/common/array.hpp
vendored
Normal file
533
3rdparty/include/meojson/common/array.hpp
vendored
Normal file
@@ -0,0 +1,533 @@
|
||||
#pragma once
|
||||
|
||||
#include <initializer_list>
|
||||
#include <optional>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "exception.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
namespace json
|
||||
{
|
||||
template <typename string_t>
|
||||
class basic_array
|
||||
{
|
||||
friend class basic_value<string_t>;
|
||||
friend class basic_object<string_t>;
|
||||
|
||||
public:
|
||||
using raw_array = std::vector<basic_value<string_t>>;
|
||||
using value_type = typename raw_array::value_type;
|
||||
using iterator = typename raw_array::iterator;
|
||||
using const_iterator = typename raw_array::const_iterator;
|
||||
using reverse_iterator = typename raw_array::reverse_iterator;
|
||||
using const_reverse_iterator = typename raw_array::const_reverse_iterator;
|
||||
using char_t = typename string_t::value_type;
|
||||
|
||||
public:
|
||||
basic_array() = default;
|
||||
basic_array(const basic_array<string_t>& rhs) = default;
|
||||
basic_array(basic_array<string_t>&& rhs) noexcept = default;
|
||||
basic_array(std::initializer_list<value_type> init_list);
|
||||
basic_array(typename raw_array::size_type size);
|
||||
|
||||
// explicit basic_array(const basic_value<string_t>& val);
|
||||
// explicit basic_array(basic_value<string_t>&& val);
|
||||
|
||||
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 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;
|
||||
|
||||
// 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;
|
||||
|
||||
template <typename value_t = basic_value<string_t>>
|
||||
std::optional<value_t> find(size_t pos) const;
|
||||
|
||||
template <typename... args_t>
|
||||
decltype(auto) emplace_back(args_t&&... args);
|
||||
template <typename... args_t>
|
||||
decltype(auto) push_back(args_t&&... args);
|
||||
|
||||
void clear() noexcept;
|
||||
bool erase(size_t pos);
|
||||
bool erase(iterator iter);
|
||||
|
||||
iterator begin() noexcept;
|
||||
iterator end() noexcept;
|
||||
const_iterator begin() const noexcept;
|
||||
const_iterator end() const noexcept;
|
||||
const_iterator cbegin() const noexcept;
|
||||
const_iterator cend() const noexcept;
|
||||
|
||||
reverse_iterator rbegin() noexcept;
|
||||
reverse_iterator rend() noexcept;
|
||||
const_reverse_iterator rbegin() const noexcept;
|
||||
const_reverse_iterator rend() const noexcept;
|
||||
const_reverse_iterator crbegin() const noexcept;
|
||||
const_reverse_iterator crend() const noexcept;
|
||||
|
||||
const basic_value<string_t>& operator[](size_t pos) const;
|
||||
basic_value<string_t>& operator[](size_t pos);
|
||||
|
||||
basic_array<string_t> operator+(const basic_array<string_t>& rhs) const&;
|
||||
basic_array<string_t> operator+(basic_array<string_t>&& rhs) const&;
|
||||
basic_array<string_t> operator+(const basic_array<string_t>& rhs) &&;
|
||||
basic_array<string_t> operator+(basic_array<string_t>&& rhs) &&;
|
||||
|
||||
basic_array<string_t>& operator+=(const basic_array<string_t>& rhs);
|
||||
basic_array<string_t>& operator+=(basic_array<string_t>&& rhs);
|
||||
|
||||
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>
|
||||
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>
|
||||
explicit operator collection_t<value_t>() const
|
||||
{
|
||||
return as_collection<value_t, collection_t>();
|
||||
}
|
||||
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 (!dst.from_json(*this)) {
|
||||
throw exception("Wrong JSON");
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
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<jsonization_t>().from_json(*this, dst)) {
|
||||
throw exception("Wrong JSON");
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
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;
|
||||
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>
|
||||
auto get_helper(const value_t& default_value, size_t pos) const;
|
||||
|
||||
string_t format(size_t indent, size_t indent_times) const;
|
||||
|
||||
private:
|
||||
raw_array _array_data;
|
||||
};
|
||||
|
||||
template <typename string_t>
|
||||
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)
|
||||
{}
|
||||
|
||||
// template <typename string_t>
|
||||
// inline basic_array<string_t>::basic_array(const basic_value<string_t>& val) : basic_array<string_t>(val.as_array())
|
||||
//{}
|
||||
//
|
||||
// template <typename string_t>
|
||||
// inline basic_array<string_t>::basic_array(basic_value<string_t>&& val)
|
||||
// : basic_array<string_t>(std::move(val.as_array()))
|
||||
//{}
|
||||
|
||||
template <typename string_t>
|
||||
inline void basic_array<string_t>::clear() noexcept
|
||||
{
|
||||
_array_data.clear();
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline bool basic_array<string_t>::erase(size_t pos)
|
||||
{
|
||||
return erase(_array_data.begin() + pos);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline bool basic_array<string_t>::erase(iterator iter)
|
||||
{
|
||||
return _array_data.erase(iter) != _array_data.end();
|
||||
}
|
||||
|
||||
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");
|
||||
return _array_data.emplace_back(std::forward<args_t>(args)...);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
template <typename... args_t>
|
||||
inline decltype(auto) basic_array<string_t>::push_back(args_t&&... args)
|
||||
{
|
||||
return emplace_back(std::forward<args_t>(args)...);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline const basic_value<string_t>& basic_array<string_t>::at(size_t pos) const
|
||||
{
|
||||
return _array_data.at(pos);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline string_t basic_array<string_t>::to_string() const
|
||||
{
|
||||
string_t str { '[' };
|
||||
for (auto iter = _array_data.cbegin(); iter != _array_data.cend();) {
|
||||
str += iter->to_string();
|
||||
if (++iter != _array_data.cend()) {
|
||||
str += ',';
|
||||
}
|
||||
}
|
||||
str += char_t(']');
|
||||
return str;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline string_t basic_array<string_t>::format(size_t indent, size_t indent_times) const
|
||||
{
|
||||
const string_t tail_indent(indent * indent_times, ' ');
|
||||
const string_t body_indent(indent * (indent_times + 1), ' ');
|
||||
|
||||
string_t str { '[', '\n' };
|
||||
for (auto iter = _array_data.cbegin(); iter != _array_data.cend();) {
|
||||
str += body_indent + iter->format(indent, indent_times + 1);
|
||||
if (++iter != _array_data.cend()) {
|
||||
str += ',';
|
||||
}
|
||||
str += '\n';
|
||||
}
|
||||
str += tail_indent + char_t(']');
|
||||
return str;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
template <typename value_t>
|
||||
inline bool basic_array<string_t>::all() const
|
||||
{
|
||||
for (const auto& elem : _array_data) {
|
||||
if (!elem.template is<value_t>()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
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
|
||||
{
|
||||
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> {});
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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)...);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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)) {
|
||||
if constexpr (is_string) {
|
||||
return string_t(default_value);
|
||||
}
|
||||
else {
|
||||
return value_t(default_value);
|
||||
}
|
||||
}
|
||||
|
||||
return at(pos).get_helper(default_value, std::forward<rest_keys_t>(rest)...);
|
||||
}
|
||||
|
||||
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_string = std::is_constructible_v<string_t, value_t> && !is_json;
|
||||
|
||||
if (!contains(pos)) {
|
||||
if constexpr (is_string) {
|
||||
return string_t(default_value);
|
||||
}
|
||||
else {
|
||||
return value_t(default_value);
|
||||
}
|
||||
}
|
||||
|
||||
auto val = _array_data.at(pos);
|
||||
if (val.template is<value_t>()) {
|
||||
if constexpr (is_string) {
|
||||
return val.template as<string_t>();
|
||||
}
|
||||
else {
|
||||
return val.template as<value_t>();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if constexpr (is_string) {
|
||||
return string_t(default_value);
|
||||
}
|
||||
else {
|
||||
return value_t(default_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
template <typename value_t>
|
||||
inline std::optional<value_t> basic_array<string_t>::find(size_t pos) const
|
||||
{
|
||||
if (!contains(pos)) {
|
||||
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;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline typename basic_array<string_t>::iterator basic_array<string_t>::begin() noexcept
|
||||
{
|
||||
return _array_data.begin();
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline typename basic_array<string_t>::iterator basic_array<string_t>::end() noexcept
|
||||
{
|
||||
return _array_data.end();
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline typename basic_array<string_t>::const_iterator basic_array<string_t>::begin() const noexcept
|
||||
{
|
||||
return _array_data.begin();
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline typename basic_array<string_t>::const_iterator basic_array<string_t>::end() const noexcept
|
||||
{
|
||||
return _array_data.end();
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline typename basic_array<string_t>::const_iterator basic_array<string_t>::cbegin() const noexcept
|
||||
{
|
||||
return _array_data.cbegin();
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline typename basic_array<string_t>::const_iterator basic_array<string_t>::cend() const noexcept
|
||||
{
|
||||
return _array_data.cend();
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline typename basic_array<string_t>::reverse_iterator basic_array<string_t>::rbegin() noexcept
|
||||
{
|
||||
return _array_data.rbegin();
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline typename basic_array<string_t>::reverse_iterator basic_array<string_t>::rend() noexcept
|
||||
{
|
||||
return _array_data.rend();
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
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
|
||||
{
|
||||
return _array_data.rend();
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
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
|
||||
{
|
||||
return _array_data.crend();
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline basic_value<string_t>& basic_array<string_t>::operator[](size_t pos)
|
||||
{
|
||||
return _array_data[pos];
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline const basic_value<string_t>& basic_array<string_t>::operator[](size_t pos) const
|
||||
{
|
||||
return _array_data[pos];
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
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());
|
||||
return temp;
|
||||
}
|
||||
|
||||
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()));
|
||||
return temp;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline basic_array<string_t> basic_array<string_t>::operator+(const basic_array<string_t>& rhs) &&
|
||||
{
|
||||
_array_data.insert(_array_data.end(), rhs.begin(), rhs.end());
|
||||
return std::move(*this);
|
||||
}
|
||||
|
||||
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()));
|
||||
return std::move(*this);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline basic_array<string_t>& basic_array<string_t>::operator+=(const basic_array<string_t>& rhs)
|
||||
{
|
||||
_array_data.insert(_array_data.end(), rhs.begin(), rhs.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
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()));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline bool basic_array<string_t>::operator==(const basic_array<string_t>& rhs) const
|
||||
{
|
||||
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>>>
|
||||
ostream_t& operator<<(ostream_t& out, const basic_array<string_t>& arr)
|
||||
{
|
||||
out << arr.format();
|
||||
return out;
|
||||
}
|
||||
} // namespace json
|
||||
26
3rdparty/include/meojson/common/exception.hpp
vendored
Normal file
26
3rdparty/include/meojson/common/exception.hpp
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
namespace json
|
||||
{
|
||||
class exception : public std::exception
|
||||
{
|
||||
public:
|
||||
exception() = default;
|
||||
exception(const std::string& msg) : _what(msg) {}
|
||||
|
||||
exception(const exception&) = default;
|
||||
exception& operator=(const exception&) = default;
|
||||
exception(exception&&) = default;
|
||||
exception& operator=(exception&&) = default;
|
||||
|
||||
virtual ~exception() noexcept override = default;
|
||||
|
||||
virtual const char* what() const noexcept override { return _what.empty() ? "Unknown exception" : _what.c_str(); }
|
||||
|
||||
protected:
|
||||
std::string _what;
|
||||
};
|
||||
}
|
||||
474
3rdparty/include/meojson/common/object.hpp
vendored
Normal file
474
3rdparty/include/meojson/common/object.hpp
vendored
Normal file
@@ -0,0 +1,474 @@
|
||||
#pragma once
|
||||
|
||||
#include <initializer_list>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
#include "exception.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
namespace json
|
||||
{
|
||||
template <typename string_t>
|
||||
class basic_object
|
||||
{
|
||||
friend class basic_value<string_t>;
|
||||
friend class basic_array<string_t>;
|
||||
|
||||
public:
|
||||
using raw_object = std::map<string_t, basic_value<string_t>>;
|
||||
using key_type = typename raw_object::key_type;
|
||||
using mapped_type = typename raw_object::mapped_type;
|
||||
using value_type = typename raw_object::value_type;
|
||||
using iterator = typename raw_object::iterator;
|
||||
using const_iterator = typename raw_object::const_iterator;
|
||||
using char_t = typename string_t::value_type;
|
||||
|
||||
public:
|
||||
basic_object() = default;
|
||||
basic_object(const basic_object<string_t>& rhs) = default;
|
||||
basic_object(basic_object<string_t>&& rhs) noexcept = default;
|
||||
basic_object(std::initializer_list<value_type> init_list);
|
||||
|
||||
// explicit basic_object(const basic_value<string_t>& val);
|
||||
// explicit basic_object(basic_value<string_t>&& val);
|
||||
|
||||
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 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;
|
||||
|
||||
// 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;
|
||||
|
||||
template <typename value_t = basic_value<string_t>>
|
||||
std::optional<value_t> find(const string_t& key) const;
|
||||
|
||||
template <typename... args_t>
|
||||
decltype(auto) emplace(args_t&&... args);
|
||||
template <typename... args_t>
|
||||
decltype(auto) insert(args_t&&... args);
|
||||
|
||||
void clear() noexcept;
|
||||
bool erase(const string_t& key);
|
||||
bool erase(iterator iter);
|
||||
|
||||
iterator begin() noexcept;
|
||||
iterator end() noexcept;
|
||||
const_iterator begin() const noexcept;
|
||||
const_iterator end() const noexcept;
|
||||
const_iterator cbegin() const noexcept;
|
||||
const_iterator cend() const noexcept;
|
||||
|
||||
basic_value<string_t>& operator[](const string_t& key);
|
||||
basic_value<string_t>& operator[](string_t&& key);
|
||||
|
||||
basic_object<string_t> operator|(const basic_object<string_t>& rhs) const&;
|
||||
basic_object<string_t> operator|(basic_object<string_t>&& rhs) const&;
|
||||
basic_object<string_t> operator|(const basic_object<string_t>& rhs) &&;
|
||||
basic_object<string_t> operator|(basic_object<string_t>&& rhs) &&;
|
||||
|
||||
basic_object<string_t>& operator|=(const basic_object<string_t>& rhs);
|
||||
basic_object<string_t>& operator|=(basic_object<string_t>&& rhs);
|
||||
|
||||
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>
|
||||
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>
|
||||
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_member<jsonization_t, string_t>::value, bool> = true>
|
||||
explicit operator jsonization_t() const
|
||||
{
|
||||
jsonization_t dst {};
|
||||
if (!dst.from_json(*this)) {
|
||||
throw exception("Wrong JSON");
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
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<jsonization_t>().from_json(*this, dst)) {
|
||||
throw exception("Wrong JSON");
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
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;
|
||||
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>
|
||||
auto get_helper(const value_t& default_value, const string_t& key) const;
|
||||
|
||||
string_t format(size_t indent, size_t indent_times) const;
|
||||
|
||||
private:
|
||||
raw_object _object_data;
|
||||
};
|
||||
|
||||
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()))
|
||||
{}
|
||||
|
||||
// template <typename string_t>
|
||||
// inline basic_object<string_t>::basic_object(const basic_value<string_t>& val) :
|
||||
// basic_object<string_t>(val.as_object())
|
||||
//{}
|
||||
//
|
||||
// template <typename string_t>
|
||||
// inline basic_object<string_t>::basic_object(basic_value<string_t>&& val)
|
||||
// : basic_object<string_t>(std::move(val.as_object()))
|
||||
//{}
|
||||
|
||||
template <typename string_t>
|
||||
inline bool basic_object<string_t>::contains(const string_t& key) const
|
||||
{
|
||||
return _object_data.find(key) != _object_data.cend();
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline const basic_value<string_t>& basic_object<string_t>::at(const string_t& key) const
|
||||
{
|
||||
return _object_data.at(key);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline void basic_object<string_t>::clear() noexcept
|
||||
{
|
||||
_object_data.clear();
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline bool basic_object<string_t>::erase(const string_t& key)
|
||||
{
|
||||
return _object_data.erase(key) > 0 ? true : false;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline bool basic_object<string_t>::erase(iterator iter)
|
||||
{
|
||||
return _object_data.erase(iter) != _object_data.end();
|
||||
}
|
||||
|
||||
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.emplace(std::forward<args_t>(args)...);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
template <typename... args_t>
|
||||
inline decltype(auto) basic_object<string_t>::insert(args_t&&... args)
|
||||
{
|
||||
return emplace(std::forward<args_t>(args)...);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
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();
|
||||
if (++iter != _object_data.cend()) {
|
||||
str += ',';
|
||||
}
|
||||
}
|
||||
str += char_t('}');
|
||||
return str;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline string_t basic_object<string_t>::format(size_t indent, size_t indent_times) const
|
||||
{
|
||||
const string_t tail_indent(indent * indent_times, ' ');
|
||||
const string_t body_indent(indent * (indent_times + 1), ' ');
|
||||
|
||||
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);
|
||||
if (++iter != _object_data.cend()) {
|
||||
str += ',';
|
||||
}
|
||||
str += '\n';
|
||||
}
|
||||
str += tail_indent + char_t('}');
|
||||
return str;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
template <typename value_t>
|
||||
inline bool basic_object<string_t>::all() const
|
||||
{
|
||||
for (const auto& [_, val] : _object_data) {
|
||||
if (!val.template is<value_t>()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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> {});
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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)...);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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)) {
|
||||
if constexpr (is_string) {
|
||||
return string_t(default_value);
|
||||
}
|
||||
else {
|
||||
return value_t(default_value);
|
||||
}
|
||||
}
|
||||
|
||||
return at(key).get_helper(default_value, std::forward<rest_keys_t>(rest)...);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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)) {
|
||||
if constexpr (is_string) {
|
||||
return string_t(default_value);
|
||||
}
|
||||
else {
|
||||
return value_t(default_value);
|
||||
}
|
||||
}
|
||||
|
||||
auto val = _object_data.at(key);
|
||||
if (val.template is<value_t>()) {
|
||||
if constexpr (is_string) {
|
||||
return val.template as<string_t>();
|
||||
}
|
||||
else {
|
||||
return val.template as<value_t>();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if constexpr (is_string) {
|
||||
return string_t(default_value);
|
||||
}
|
||||
else {
|
||||
return value_t(default_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
template <typename value_t>
|
||||
inline std::optional<value_t> basic_object<string_t>::find(const string_t& key) const
|
||||
{
|
||||
auto iter = _object_data.find(key);
|
||||
if (iter == _object_data.end()) {
|
||||
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;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline typename basic_object<string_t>::iterator basic_object<string_t>::begin() noexcept
|
||||
{
|
||||
return _object_data.begin();
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline typename basic_object<string_t>::iterator basic_object<string_t>::end() noexcept
|
||||
{
|
||||
return _object_data.end();
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline typename basic_object<string_t>::const_iterator basic_object<string_t>::begin() const noexcept
|
||||
{
|
||||
return _object_data.begin();
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline typename basic_object<string_t>::const_iterator basic_object<string_t>::end() const noexcept
|
||||
{
|
||||
return _object_data.end();
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline typename basic_object<string_t>::const_iterator basic_object<string_t>::cbegin() const noexcept
|
||||
{
|
||||
return _object_data.cbegin();
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline typename basic_object<string_t>::const_iterator basic_object<string_t>::cend() const noexcept
|
||||
{
|
||||
return _object_data.cend();
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline basic_value<string_t>& basic_object<string_t>::operator[](const string_t& key)
|
||||
{
|
||||
return _object_data[key];
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline basic_value<string_t>& basic_object<string_t>::operator[](string_t&& key)
|
||||
{
|
||||
return _object_data[std::move(key)];
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
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());
|
||||
return temp;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline basic_object<string_t> basic_object<string_t>::operator|(basic_object<string_t>&& rhs) const&
|
||||
{
|
||||
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()));
|
||||
return temp;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
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);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline basic_object<string_t> basic_object<string_t>::operator|(basic_object<string_t>&& rhs) &&
|
||||
{
|
||||
//_object_data.merge(std::move(rhs._object_data));
|
||||
_object_data.insert(std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end()));
|
||||
return std::move(*this);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline basic_object<string_t>& basic_object<string_t>::operator|=(const basic_object<string_t>& rhs)
|
||||
{
|
||||
_object_data.insert(rhs.begin(), rhs.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline basic_object<string_t>& basic_object<string_t>::operator|=(basic_object<string_t>&& rhs)
|
||||
{
|
||||
_object_data.insert(std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end()));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline bool basic_object<string_t>::operator==(const basic_object<string_t>& rhs) const
|
||||
{
|
||||
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>>>
|
||||
ostream_t& operator<<(ostream_t& out, const basic_object<string_t>& obj)
|
||||
{
|
||||
out << obj.format();
|
||||
return out;
|
||||
}
|
||||
} // namespace json
|
||||
170
3rdparty/include/meojson/common/serialization.hpp
vendored
Normal file
170
3rdparty/include/meojson/common/serialization.hpp
vendored
Normal file
@@ -0,0 +1,170 @@
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "types.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
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 U>
|
||||
static std::false_type test(...);
|
||||
|
||||
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 ...; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void unable_to_serialize()
|
||||
{
|
||||
static_assert(!sizeof(T), "Unable to serialize T. "
|
||||
#ifdef _MSC_VER
|
||||
"See T below: " __FUNCSIG__
|
||||
#else
|
||||
// "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 U>
|
||||
static std::false_type test(...);
|
||||
|
||||
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 ...; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void unable_to_deserialize()
|
||||
{
|
||||
static_assert(!sizeof(T), "Unable to deserialize T. "
|
||||
#ifdef _MSC_VER
|
||||
"See T below: " __FUNCSIG__
|
||||
#else
|
||||
// "See T below: " __PRETTY_FUNCTION__
|
||||
|
||||
#endif
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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 (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);
|
||||
arr.emplace_back(std::move(j_elem));
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
else if constexpr (_utils::is_map<std::decay_t<in_t>>) {
|
||||
basic_object<string_t> obj;
|
||||
for (auto&& [key, elem] : in) {
|
||||
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);
|
||||
obj.emplace(std::forward<key_t>(key), std::move(j_elem));
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
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 = {})
|
||||
{
|
||||
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;
|
||||
}
|
||||
for (auto&& j_elem : in.as_array()) {
|
||||
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;
|
||||
}
|
||||
if constexpr (_as_collection_helper::has_emplace_back<out_t>::value) {
|
||||
out.emplace_back(std::move(elem));
|
||||
}
|
||||
else {
|
||||
out.emplace(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::value_type;
|
||||
elem_t elem {};
|
||||
if (!deserialize<elem_t, deserializer_t, string_t>(j_elem, elem, deserializer)) {
|
||||
return false;
|
||||
}
|
||||
out.emplace(std::move(elem));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
_serialization_helper::unable_to_deserialize<out_t>();
|
||||
}
|
||||
}
|
||||
} // namespace json
|
||||
5
3rdparty/include/meojson/common/types.hpp
vendored
Normal file
5
3rdparty/include/meojson/common/types.hpp
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "array.hpp"
|
||||
#include "object.hpp"
|
||||
#include "value.hpp"
|
||||
235
3rdparty/include/meojson/common/utils.hpp
vendored
Normal file
235
3rdparty/include/meojson/common/utils.hpp
vendored
Normal file
@@ -0,0 +1,235 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace json
|
||||
{
|
||||
template <typename string_t>
|
||||
class basic_value;
|
||||
template <typename string_t>
|
||||
class basic_array;
|
||||
template <typename string_t>
|
||||
class basic_object;
|
||||
|
||||
using default_string_t = std::string;
|
||||
|
||||
using value = basic_value<default_string_t>;
|
||||
using array = basic_array<default_string_t>;
|
||||
using object = basic_object<default_string_t>;
|
||||
|
||||
using wvalue = basic_value<std::wstring>;
|
||||
using warray = basic_array<std::wstring>;
|
||||
using wobject = basic_object<std::wstring>;
|
||||
}
|
||||
|
||||
namespace json::ext
|
||||
{
|
||||
template <typename T>
|
||||
class jsonization
|
||||
{
|
||||
public:
|
||||
// json::value to_json(const T&) const;
|
||||
// bool check_json(const json::value&) const;
|
||||
// bool from_json(const json::value&, T&) const;
|
||||
};
|
||||
}
|
||||
|
||||
namespace json::_utils
|
||||
{
|
||||
template <typename T>
|
||||
using iterator_t = decltype(std::declval<T&>().begin());
|
||||
template <typename T>
|
||||
using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
|
||||
template <typename T>
|
||||
using iter_value_t = typename std::iterator_traits<remove_cvref_t<T>>::value_type;
|
||||
template <typename R>
|
||||
using range_value_t = iter_value_t<iterator_t<R>>;
|
||||
|
||||
template <typename T, typename = void>
|
||||
constexpr bool is_string = false;
|
||||
template <typename T>
|
||||
constexpr bool is_string<T, std::void_t<typename T::traits_type>> =
|
||||
std::is_same_v<typename T::traits_type, std::char_traits<typename T::value_type>>;
|
||||
|
||||
template <typename T, typename = void>
|
||||
constexpr bool is_container = false;
|
||||
template <typename T>
|
||||
constexpr bool is_container<T, std::void_t<typename T::value_type, range_value_t<T>>> =
|
||||
std::is_same_v<typename T::value_type, range_value_t<T>> && !is_string<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_collection = false;
|
||||
template <typename T>
|
||||
constexpr bool is_collection<T> = is_container<T> && !is_map<T>;
|
||||
|
||||
template <typename T>
|
||||
class has_to_json_in_member
|
||||
{
|
||||
template <typename U>
|
||||
static auto test(int) -> decltype(std::declval<U>().to_json(), std::true_type());
|
||||
|
||||
template <typename U>
|
||||
static std::false_type test(...);
|
||||
|
||||
public:
|
||||
static constexpr bool value = decltype(test<T>(0))::value;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class has_to_json_in_templ_spec
|
||||
{
|
||||
template <typename U>
|
||||
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(...);
|
||||
|
||||
public:
|
||||
static constexpr bool value = decltype(test<T>(0))::value;
|
||||
};
|
||||
|
||||
template <typename T, typename string_t>
|
||||
class has_check_json_in_member
|
||||
{
|
||||
template <typename U>
|
||||
static auto test(int)
|
||||
-> decltype(std::declval<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_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
|
||||
{
|
||||
template <typename U>
|
||||
static auto test(int)
|
||||
-> decltype(std::declval<U>().from_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<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 string_t>
|
||||
static constexpr string_t unescape_string(const string_t& str)
|
||||
{
|
||||
using char_t = typename string_t::value_type;
|
||||
|
||||
string_t result {};
|
||||
auto cur = str.cbegin();
|
||||
auto end = str.cend();
|
||||
auto no_escape_beg = cur;
|
||||
char_t escape = 0;
|
||||
|
||||
for (; cur != end; ++cur) {
|
||||
switch (*cur) {
|
||||
case '"':
|
||||
escape = '"';
|
||||
break;
|
||||
case '\\':
|
||||
escape = '\\';
|
||||
break;
|
||||
case '\b':
|
||||
escape = 'b';
|
||||
break;
|
||||
case '\f':
|
||||
escape = 'f';
|
||||
break;
|
||||
case '\n':
|
||||
escape = 'n';
|
||||
break;
|
||||
case '\r':
|
||||
escape = 'r';
|
||||
break;
|
||||
case '\t':
|
||||
escape = 't';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (escape) {
|
||||
result += string_t(no_escape_beg, cur) + char_t('\\') + escape;
|
||||
no_escape_beg = cur + 1;
|
||||
escape = 0;
|
||||
}
|
||||
}
|
||||
result += string_t(no_escape_beg, cur);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
static constexpr string_t true_string()
|
||||
{
|
||||
return { 't', 'r', 'u', 'e' };
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
static constexpr string_t false_string()
|
||||
{
|
||||
return { 'f', 'a', 'l', 's', 'e' };
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
static constexpr string_t null_string()
|
||||
{
|
||||
return { 'n', 'u', 'l', 'l' };
|
||||
}
|
||||
|
||||
template <typename string_t, typename any_t>
|
||||
string_t to_basic_string(any_t&& arg)
|
||||
{
|
||||
if constexpr (std::is_same_v<string_t, std::string>) {
|
||||
return std::to_string(std::forward<any_t>(arg));
|
||||
}
|
||||
else if constexpr (std::is_same_v<string_t, std::wstring>) {
|
||||
return std::to_wstring(std::forward<any_t>(arg));
|
||||
}
|
||||
else {
|
||||
static_assert(!sizeof(any_t), "Unsupported type");
|
||||
}
|
||||
}
|
||||
} // namespace json::_utils
|
||||
994
3rdparty/include/meojson/common/value.hpp
vendored
Normal file
994
3rdparty/include/meojson/common/value.hpp
vendored
Normal file
@@ -0,0 +1,994 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <initializer_list>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <variant>
|
||||
|
||||
#include "exception.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
namespace json
|
||||
{
|
||||
template <typename string_t>
|
||||
class basic_value
|
||||
{
|
||||
using array_ptr = std::unique_ptr<basic_array<string_t>>;
|
||||
using object_ptr = std::unique_ptr<basic_object<string_t>>;
|
||||
|
||||
public:
|
||||
enum class value_type : char
|
||||
{
|
||||
invalid,
|
||||
null,
|
||||
boolean,
|
||||
string,
|
||||
number,
|
||||
array,
|
||||
object
|
||||
};
|
||||
|
||||
using var_t = std::variant<string_t, array_ptr, object_ptr>;
|
||||
using char_t = typename string_t::value_type;
|
||||
|
||||
public:
|
||||
basic_value();
|
||||
basic_value(const basic_value<string_t>& rhs);
|
||||
basic_value(basic_value<string_t>&& rhs) noexcept;
|
||||
|
||||
basic_value(bool b);
|
||||
|
||||
basic_value(int num);
|
||||
basic_value(unsigned num);
|
||||
basic_value(long num);
|
||||
basic_value(unsigned long num);
|
||||
basic_value(long long num);
|
||||
basic_value(unsigned long long num);
|
||||
basic_value(float num);
|
||||
basic_value(double num);
|
||||
basic_value(long double num);
|
||||
|
||||
basic_value(const char_t* str);
|
||||
basic_value(string_t str);
|
||||
basic_value(std::nullptr_t);
|
||||
|
||||
basic_value(basic_array<string_t> arr);
|
||||
basic_value(basic_object<string_t> obj);
|
||||
basic_value(std::initializer_list<typename basic_object<string_t>::value_type> init_list);
|
||||
|
||||
// Constructed from raw data
|
||||
template <typename... args_t>
|
||||
basic_value(value_type type, args_t&&... args);
|
||||
|
||||
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_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 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;
|
||||
basic_value(wchar_t) = delete;
|
||||
basic_value(char16_t) = delete;
|
||||
basic_value(char32_t) = delete;
|
||||
|
||||
~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;
|
||||
|
||||
template <typename value_t>
|
||||
bool all() const;
|
||||
|
||||
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;
|
||||
|
||||
bool erase(size_t pos);
|
||||
bool erase(const string_t& key);
|
||||
|
||||
// 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;
|
||||
|
||||
template <typename value_t = basic_value<string_t>>
|
||||
std::optional<value_t> find(size_t pos) const;
|
||||
template <typename value_t = basic_value<string_t>>
|
||||
std::optional<value_t> find(const string_t& key) const;
|
||||
|
||||
bool as_boolean() const;
|
||||
int as_integer() const;
|
||||
unsigned as_unsigned() const;
|
||||
long as_long() const;
|
||||
unsigned long as_unsigned_long() const;
|
||||
long long as_long_long() const;
|
||||
unsigned long long as_unsigned_long_long() const;
|
||||
float as_float() const;
|
||||
double as_double() const;
|
||||
long double as_long_double() const;
|
||||
string_t as_string() const;
|
||||
const basic_array<string_t>& as_array() const;
|
||||
const basic_object<string_t>& as_object() const;
|
||||
|
||||
template <typename value_t, template <typename...> typename collection_t = std::vector>
|
||||
collection_t<value_t> as_collection() 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;
|
||||
|
||||
basic_array<string_t>& as_array();
|
||||
basic_object<string_t>& as_object();
|
||||
|
||||
template <typename... args_t>
|
||||
decltype(auto) emplace(args_t&&... args);
|
||||
|
||||
void clear() noexcept;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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;
|
||||
basic_value<string_t>& operator[](size_t pos);
|
||||
basic_value<string_t>& operator[](const string_t& key);
|
||||
basic_value<string_t>& operator[](string_t&& key);
|
||||
|
||||
basic_value<string_t> operator|(const basic_object<string_t>& rhs) const&;
|
||||
basic_value<string_t> operator|(basic_object<string_t>&& rhs) const&;
|
||||
basic_value<string_t> operator|(const basic_object<string_t>& rhs) &&;
|
||||
basic_value<string_t> operator|(basic_object<string_t>&& rhs) &&;
|
||||
|
||||
basic_value<string_t>& operator|=(const basic_object<string_t>& rhs);
|
||||
basic_value<string_t>& operator|=(basic_object<string_t>&& rhs);
|
||||
|
||||
basic_value<string_t> operator+(const basic_array<string_t>& rhs) const&;
|
||||
basic_value<string_t> operator+(basic_array<string_t>&& rhs) const&;
|
||||
basic_value<string_t> operator+(const basic_array<string_t>& rhs) &&;
|
||||
basic_value<string_t> operator+(basic_array<string_t>&& rhs) &&;
|
||||
|
||||
basic_value<string_t>& operator+=(const basic_array<string_t>& rhs);
|
||||
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>
|
||||
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>
|
||||
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_member<jsonization_t, string_t>::value, bool> = true>
|
||||
explicit operator jsonization_t() const
|
||||
{
|
||||
jsonization_t dst {};
|
||||
if (!dst.from_json(*this)) {
|
||||
throw exception("Wrong JSON");
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
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<jsonization_t>().from_json(*this, dst)) {
|
||||
throw exception("Wrong JSON");
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class basic_array<string_t>;
|
||||
friend class basic_object<string_t>;
|
||||
|
||||
string_t format(size_t indent, size_t indent_times) const;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
template <typename value_t, typename unique_key_t>
|
||||
auto get_helper(const value_t& default_value, unique_key_t&& first) const;
|
||||
|
||||
const string_t& as_basic_type_str() const;
|
||||
string_t& as_basic_type_str();
|
||||
|
||||
value_type _type = value_type::null;
|
||||
var_t _raw_data;
|
||||
};
|
||||
|
||||
template <typename string_t>
|
||||
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))
|
||||
{}
|
||||
|
||||
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>()))
|
||||
{}
|
||||
|
||||
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))
|
||||
{}
|
||||
|
||||
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))
|
||||
{}
|
||||
|
||||
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))
|
||||
{}
|
||||
|
||||
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))
|
||||
{}
|
||||
|
||||
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))
|
||||
{}
|
||||
|
||||
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))
|
||||
{}
|
||||
|
||||
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))
|
||||
{}
|
||||
|
||||
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))
|
||||
{}
|
||||
|
||||
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))
|
||||
{}
|
||||
|
||||
template <typename string_t>
|
||||
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))
|
||||
{}
|
||||
|
||||
template <typename string_t>
|
||||
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)))
|
||||
{}
|
||||
|
||||
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)))
|
||||
{}
|
||||
|
||||
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))
|
||||
{}
|
||||
|
||||
// for Pimpl
|
||||
template <typename string_t>
|
||||
inline basic_value<string_t>::~basic_value() = default;
|
||||
|
||||
template <typename string_t>
|
||||
template <typename value_t>
|
||||
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<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>) {
|
||||
return is_number();
|
||||
}
|
||||
else if constexpr (std::is_constructible_v<string_t, value_t>) {
|
||||
return is_string();
|
||||
}
|
||||
else if constexpr (std::is_same_v<basic_array<string_t>, value_t>) {
|
||||
return is_array();
|
||||
}
|
||||
else if constexpr (_utils::is_collection<value_t>) {
|
||||
return is_array() && all<typename value_t::value_type>();
|
||||
}
|
||||
else if constexpr (std::is_same_v<basic_object<string_t>, value_t>) {
|
||||
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>();
|
||||
}
|
||||
else {
|
||||
static_assert(!sizeof(value_t), "Unsupported type");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline bool basic_value<string_t>::contains(const string_t& key) const
|
||||
{
|
||||
return is_object() && as_object().contains(key);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline bool basic_value<string_t>::contains(size_t pos) const
|
||||
{
|
||||
return is_array() && as_array().contains(pos);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline const basic_value<string_t>& basic_value<string_t>::at(size_t pos) const
|
||||
{
|
||||
return as_array().at(pos);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline const basic_value<string_t>& basic_value<string_t>::at(const string_t& key) const
|
||||
{
|
||||
return as_object().at(key);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline bool basic_value<string_t>::erase(size_t pos)
|
||||
{
|
||||
return as_array().erase(pos);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline bool basic_value<string_t>::erase(const string_t& key)
|
||||
{
|
||||
return as_object().erase(key);
|
||||
}
|
||||
|
||||
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> {});
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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)...);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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)...)
|
||||
: 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)...)
|
||||
: default_value;
|
||||
}
|
||||
else {
|
||||
static_assert(!sizeof(first_key_t), "Parameter must be integral or string_t constructible");
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
else {
|
||||
static_assert(!sizeof(unique_key_t), "Parameter must be integral or string_t constructible");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
template <typename value_t>
|
||||
inline std::optional<value_t> basic_value<string_t>::find(size_t pos) const
|
||||
{
|
||||
return is_array() ? as_array().template find<value_t>(pos) : std::nullopt;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
template <typename value_t>
|
||||
inline std::optional<value_t> basic_value<string_t>::find(const string_t& key) const
|
||||
{
|
||||
return is_object() ? as_object().template find<value_t>(key) : std::nullopt;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline bool basic_value<string_t>::as_boolean() const
|
||||
{
|
||||
if (is_boolean()) {
|
||||
if (const string_t& b_str = as_basic_type_str(); b_str == _utils::true_string<string_t>()) {
|
||||
return true;
|
||||
}
|
||||
else if (b_str == _utils::false_string<string_t>()) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
throw exception("Unknown Parse Error");
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw exception("Wrong Type");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline int basic_value<string_t>::as_integer() const
|
||||
{
|
||||
if (is_number()) {
|
||||
return std::stoi(as_basic_type_str());
|
||||
}
|
||||
else {
|
||||
throw exception("Wrong Type");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline unsigned basic_value<string_t>::as_unsigned() const
|
||||
{
|
||||
// I don't know why there is no std::stou.
|
||||
return static_cast<unsigned>(as_unsigned_long());
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline long basic_value<string_t>::as_long() const
|
||||
{
|
||||
if (is_number()) {
|
||||
return std::stol(as_basic_type_str());
|
||||
}
|
||||
else {
|
||||
throw exception("Wrong Type");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline unsigned long basic_value<string_t>::as_unsigned_long() const
|
||||
{
|
||||
if (is_number()) {
|
||||
return std::stoul(as_basic_type_str());
|
||||
}
|
||||
else {
|
||||
throw exception("Wrong Type");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline long long basic_value<string_t>::as_long_long() const
|
||||
{
|
||||
if (is_number()) {
|
||||
return std::stoll(as_basic_type_str());
|
||||
}
|
||||
else {
|
||||
throw exception("Wrong Type");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline unsigned long long basic_value<string_t>::as_unsigned_long_long() const
|
||||
{
|
||||
if (is_number()) {
|
||||
return std::stoull(as_basic_type_str());
|
||||
}
|
||||
else {
|
||||
throw exception("Wrong Type");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline float basic_value<string_t>::as_float() const
|
||||
{
|
||||
if (is_number()) {
|
||||
return std::stof(as_basic_type_str());
|
||||
}
|
||||
else {
|
||||
throw exception("Wrong Type");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline double basic_value<string_t>::as_double() const
|
||||
{
|
||||
if (is_number()) {
|
||||
return std::stod(as_basic_type_str());
|
||||
}
|
||||
else {
|
||||
throw exception("Wrong Type");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline long double basic_value<string_t>::as_long_double() const
|
||||
{
|
||||
if (is_number()) {
|
||||
return std::stold(as_basic_type_str());
|
||||
}
|
||||
else {
|
||||
throw exception("Wrong Type");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline string_t basic_value<string_t>::as_string() const
|
||||
{
|
||||
if (is_string()) {
|
||||
return as_basic_type_str();
|
||||
}
|
||||
else {
|
||||
throw exception("Wrong Type");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline const basic_array<string_t>& basic_value<string_t>::as_array() const
|
||||
{
|
||||
if (is_array()) {
|
||||
return *std::get<array_ptr>(_raw_data);
|
||||
}
|
||||
|
||||
throw exception("Wrong Type");
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline const basic_object<string_t>& basic_value<string_t>::as_object() const
|
||||
{
|
||||
if (is_object()) {
|
||||
return *std::get<object_ptr>(_raw_data);
|
||||
}
|
||||
|
||||
throw exception("Wrong Type or data empty");
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline basic_array<string_t>& basic_value<string_t>::as_array()
|
||||
{
|
||||
if (empty()) {
|
||||
*this = basic_array<string_t>();
|
||||
}
|
||||
|
||||
if (is_array()) {
|
||||
return *std::get<array_ptr>(_raw_data);
|
||||
}
|
||||
|
||||
throw exception("Wrong Type");
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline basic_object<string_t>& basic_value<string_t>::as_object()
|
||||
{
|
||||
if (empty()) {
|
||||
*this = basic_object<string_t>();
|
||||
}
|
||||
|
||||
if (is_object()) {
|
||||
return *std::get<object_ptr>(_raw_data);
|
||||
}
|
||||
|
||||
throw exception("Wrong Type or data empty");
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
template <typename value_t>
|
||||
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_member<value_t, string_t>::value) {
|
||||
value_t dst {};
|
||||
if (!dst.from_json(*this)) {
|
||||
throw exception("Wrong JSON");
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
else if constexpr (_utils::has_from_json_in_templ_spec<value_t, string_t>::value) {
|
||||
value_t dst {};
|
||||
if (!ext::jsonization<value_t>().from_json(*this, dst)) {
|
||||
throw exception("Wrong JSON");
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
else {
|
||||
return static_cast<value_t>(*this);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline const string_t& basic_value<string_t>::as_basic_type_str() const
|
||||
{
|
||||
return std::get<string_t>(_raw_data);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline string_t& basic_value<string_t>::as_basic_type_str()
|
||||
{
|
||||
return std::get<string_t>(_raw_data);
|
||||
}
|
||||
|
||||
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...>;
|
||||
|
||||
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)...);
|
||||
}
|
||||
else if constexpr (is_object_args) {
|
||||
return as_object().emplace(std::forward<args_t>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline void basic_value<string_t>::clear() noexcept
|
||||
{
|
||||
*this = basic_value<string_t>();
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline string_t basic_value<string_t>::to_string() const
|
||||
{
|
||||
switch (_type) {
|
||||
case value_type::null:
|
||||
return _utils::null_string<string_t>();
|
||||
case value_type::boolean:
|
||||
case value_type::number:
|
||||
return as_basic_type_str();
|
||||
case value_type::string:
|
||||
return char_t('"') + _utils::unescape_string(as_basic_type_str()) + char_t('"');
|
||||
case value_type::array:
|
||||
return as_array().to_string();
|
||||
case value_type::object:
|
||||
return as_object().to_string();
|
||||
default:
|
||||
throw exception("Unknown basic_value Type");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline string_t basic_value<string_t>::format(size_t indent, size_t indent_times) const
|
||||
{
|
||||
switch (_type) {
|
||||
case value_type::null:
|
||||
case value_type::boolean:
|
||||
case value_type::number:
|
||||
case value_type::string:
|
||||
return to_string();
|
||||
case value_type::array:
|
||||
return as_array().format(indent, indent_times);
|
||||
case value_type::object:
|
||||
return as_object().format(indent, indent_times);
|
||||
default:
|
||||
throw exception("Unknown basic_value Type");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
template <typename value_t>
|
||||
inline bool basic_value<string_t>::all() const
|
||||
{
|
||||
if (is_array()) {
|
||||
return as_array().template all<value_t>();
|
||||
}
|
||||
else if (is_object()) {
|
||||
return as_object().template all<value_t>();
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
template <typename value_t, template <typename...> typename collection_t>
|
||||
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, template <typename...> typename map_t>
|
||||
inline map_t<string_t, value_t> basic_value<string_t>::as_map() const
|
||||
{
|
||||
return as_object().template as_map<value_t, map_t>();
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline basic_value<string_t>& basic_value<string_t>::operator=(const basic_value<string_t>& rhs)
|
||||
{
|
||||
_type = rhs._type;
|
||||
_raw_data = deep_copy(rhs._raw_data);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
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;
|
||||
|
||||
switch (_type) {
|
||||
case value_type::null:
|
||||
return rhs.is_null();
|
||||
case value_type::boolean:
|
||||
case value_type::number:
|
||||
case value_type::string:
|
||||
return _raw_data == rhs._raw_data;
|
||||
case value_type::array:
|
||||
return as_array() == rhs.as_array();
|
||||
case value_type::object:
|
||||
return as_object() == rhs.as_object();
|
||||
default:
|
||||
throw exception("Unknown basic_value Type");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline const basic_value<string_t>& basic_value<string_t>::operator[](size_t pos) const
|
||||
{
|
||||
// basic_array not support to create by operator[]
|
||||
|
||||
return as_array()[pos];
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline basic_value<string_t>& basic_value<string_t>::operator[](size_t pos)
|
||||
{
|
||||
// basic_array not support to create by operator[]
|
||||
|
||||
return as_array()[pos];
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline basic_value<string_t>& basic_value<string_t>::operator[](const string_t& key)
|
||||
{
|
||||
if (empty()) {
|
||||
*this = basic_object<string_t>();
|
||||
}
|
||||
|
||||
return as_object()[key];
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline basic_value<string_t>& basic_value<string_t>::operator[](string_t&& key)
|
||||
{
|
||||
if (empty()) {
|
||||
*this = basic_object<string_t>();
|
||||
}
|
||||
|
||||
return as_object()[std::move(key)];
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline basic_value<string_t> basic_value<string_t>::operator|(const basic_object<string_t>& rhs) const&
|
||||
{
|
||||
return as_object() | rhs;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline basic_value<string_t> basic_value<string_t>::operator|(basic_object<string_t>&& rhs) const&
|
||||
{
|
||||
return as_object() | std::move(rhs);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline basic_value<string_t> basic_value<string_t>::operator|(const basic_object<string_t>& rhs) &&
|
||||
{
|
||||
return std::move(as_object()) | rhs;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline basic_value<string_t> basic_value<string_t>::operator|(basic_object<string_t>&& rhs) &&
|
||||
{
|
||||
return std::move(as_object()) | std::move(rhs);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline basic_value<string_t>& basic_value<string_t>::operator|=(const basic_object<string_t>& rhs)
|
||||
{
|
||||
as_object() |= rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline basic_value<string_t>& basic_value<string_t>::operator|=(basic_object<string_t>&& rhs)
|
||||
{
|
||||
as_object() |= std::move(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline basic_value<string_t> basic_value<string_t>::operator+(const basic_array<string_t>& rhs) const&
|
||||
{
|
||||
return as_array() + rhs;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline basic_value<string_t> basic_value<string_t>::operator+(basic_array<string_t>&& rhs) const&
|
||||
{
|
||||
return as_array() + std::move(rhs);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline basic_value<string_t> basic_value<string_t>::operator+(const basic_array<string_t>& rhs) &&
|
||||
{
|
||||
return std::move(as_array()) + rhs;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline basic_value<string_t> basic_value<string_t>::operator+(basic_array<string_t>&& rhs) &&
|
||||
{
|
||||
return std::move(as_array()) + std::move(rhs);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline basic_value<string_t>& basic_value<string_t>::operator+=(const basic_array<string_t>& rhs)
|
||||
{
|
||||
as_array() += rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline basic_value<string_t>& basic_value<string_t>::operator+=(basic_array<string_t>&& rhs)
|
||||
{
|
||||
as_array() += std::move(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
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)...)
|
||||
{
|
||||
static_assert(std::is_constructible_v<var_t, args_t...>, "Parameter can't be used to construct a var_t");
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline typename basic_value<string_t>::var_t basic_value<string_t>::deep_copy(const var_t& src)
|
||||
{
|
||||
var_t dst;
|
||||
if (const auto string_ptr = std::get_if<string_t>(&src)) {
|
||||
dst = *string_ptr;
|
||||
}
|
||||
else if (const auto arr_ptr = std::get_if<array_ptr>(&src)) {
|
||||
dst = std::make_unique<basic_array<string_t>>(**arr_ptr);
|
||||
}
|
||||
else if (const auto obj_ptr = std::get_if<object_ptr>(&src)) {
|
||||
dst = std::make_unique<basic_object<string_t>>(**obj_ptr);
|
||||
}
|
||||
else {
|
||||
// maybe invalid_value
|
||||
}
|
||||
|
||||
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>>>
|
||||
ostream_t& operator<<(ostream_t& out, const basic_value<string_t>& val)
|
||||
{
|
||||
out << val.format();
|
||||
return out;
|
||||
}
|
||||
} // namespace json
|
||||
6
3rdparty/include/meojson/json.hpp
vendored
Normal file
6
3rdparty/include/meojson/json.hpp
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/serialization.hpp"
|
||||
#include "common/types.hpp"
|
||||
#include "parser/parser.hpp"
|
||||
#include "reflection/jsonization.hpp"
|
||||
4
3rdparty/include/meojson/json5.hpp
vendored
Normal file
4
3rdparty/include/meojson/json5.hpp
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/types.hpp"
|
||||
#include "parser5/parser5.hpp"
|
||||
112
3rdparty/include/meojson/parser/bitops.hpp
vendored
Normal file
112
3rdparty/include/meojson/parser/bitops.hpp
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
#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);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
#elif defined(_MSC_VER)
|
||||
#ifdef __AVX2__
|
||||
// lzcnt intrinsics is not constexpr
|
||||
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);
|
||||
}
|
||||
#else
|
||||
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;
|
||||
return _BitScanForward64(&index, x) ? index : 64;
|
||||
}
|
||||
#endif // __AVX2__
|
||||
#else // compiler
|
||||
#error "bring your own bit counting implementation"
|
||||
#endif
|
||||
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);
|
||||
}
|
||||
|
||||
// no constexpr endian awareness before C++20
|
||||
inline bool is_little_endian()
|
||||
{
|
||||
union {
|
||||
uint32_t u32;
|
||||
uint8_t u8;
|
||||
} u = { 0x01020304 };
|
||||
return u.u8 == 4;
|
||||
}
|
||||
} // namespace json::_bitops
|
||||
#endif // C++20
|
||||
141
3rdparty/include/meojson/parser/packed_bytes.hpp
vendored
Normal file
141
3rdparty/include/meojson/parser/packed_bytes.hpp
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
|
||||
#include "bitops.hpp"
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define __packed_bytes_strong_inline __attribute__((always_inline))
|
||||
#elif defined(_MSC_VER)
|
||||
#define __packed_bytes_strong_inline __forceinline
|
||||
#else
|
||||
#define __packed_bytes_strong_inline inline
|
||||
#endif
|
||||
|
||||
namespace json::_packed_bytes
|
||||
{
|
||||
struct packed_bytes_trait_none
|
||||
{
|
||||
static constexpr bool available = false;
|
||||
};
|
||||
|
||||
template <size_t N>
|
||||
struct packed_bytes
|
||||
{
|
||||
using traits = packed_bytes_trait_none;
|
||||
};
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
namespace json::_packed_bytes
|
||||
{
|
||||
struct packed_bytes_trait_uint64
|
||||
{
|
||||
static constexpr bool available = sizeof(void*) >= 8;
|
||||
static constexpr auto step = 8;
|
||||
using value_type = uint64_t;
|
||||
|
||||
__packed_bytes_strong_inline static value_type load_unaligned(const void* ptr)
|
||||
{
|
||||
value_type result;
|
||||
memcpy((void*)&result, ptr, 8);
|
||||
return result;
|
||||
}
|
||||
|
||||
__packed_bytes_strong_inline static value_type less(value_type x, uint8_t n)
|
||||
{
|
||||
return (((x)-UINT64_C(0x0101010101010101) * (n)) & ~(x)&UINT64_C(0x8080808080808080));
|
||||
}
|
||||
|
||||
__packed_bytes_strong_inline static value_type is_zero_memberwise(value_type v)
|
||||
{
|
||||
return (((v)-UINT64_C(0x0101010101010101)) & ~(v)&UINT64_C(0x8080808080808080));
|
||||
}
|
||||
|
||||
__packed_bytes_strong_inline static bool is_all_zero(value_type v) { return v == UINT64_C(0); }
|
||||
|
||||
__packed_bytes_strong_inline static value_type equal(value_type x, uint8_t n)
|
||||
{
|
||||
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 size_t first_nonzero_byte(value_type x)
|
||||
{
|
||||
if (_bitops::is_little_endian())
|
||||
return _bitops::countr_zero(x) / 8;
|
||||
else
|
||||
return _bitops::countl_zero(x) / 8;
|
||||
}
|
||||
};
|
||||
|
||||
struct packed_bytes_trait_uint32
|
||||
{
|
||||
static constexpr bool available = true;
|
||||
static constexpr auto step = 4;
|
||||
using value_type = uint32_t;
|
||||
|
||||
__packed_bytes_strong_inline static value_type load_unaligned(const void* ptr)
|
||||
{
|
||||
value_type result;
|
||||
memcpy((void*)&result, ptr, 4);
|
||||
return result;
|
||||
}
|
||||
|
||||
__packed_bytes_strong_inline static value_type less(value_type x, uint8_t n)
|
||||
{
|
||||
return (((x) - ~UINT32_C(0) / 255 * (n)) & ~(x) & ~UINT32_C(0) / 255 * 128);
|
||||
}
|
||||
|
||||
__packed_bytes_strong_inline static value_type is_zero_memberwise(value_type v)
|
||||
{
|
||||
return (((v)-UINT32_C(0x01010101)) & ~(v)&UINT32_C(0x80808080));
|
||||
;
|
||||
}
|
||||
|
||||
__packed_bytes_strong_inline static bool is_all_zero(value_type v) { return v == UINT32_C(0); }
|
||||
|
||||
__packed_bytes_strong_inline static value_type equal(value_type x, uint8_t n)
|
||||
{
|
||||
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 size_t first_nonzero_byte(value_type x)
|
||||
{
|
||||
if (_bitops::is_little_endian())
|
||||
return _bitops::countr_zero(x) / 8;
|
||||
else
|
||||
return _bitops::countl_zero(x) / 8;
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct packed_bytes<8>
|
||||
{
|
||||
using traits = packed_bytes_trait_uint64;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct packed_bytes<4>
|
||||
{
|
||||
using traits = packed_bytes_trait_uint32;
|
||||
};
|
||||
|
||||
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>>>>;
|
||||
} // namespace json::_packed_bytes
|
||||
62
3rdparty/include/meojson/parser/packed_bytes_arm.hpp
vendored
Normal file
62
3rdparty/include/meojson/parser/packed_bytes_arm.hpp
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
// current NEON implementation doesn't outperform 64-bit scalar implementation
|
||||
#ifdef MEOJSON_ENABLE_NEON
|
||||
#include "packed_bytes.hpp"
|
||||
#include <arm_neon.h>
|
||||
|
||||
#if defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64)
|
||||
#define __packed_bytes_trait_arm64
|
||||
#endif
|
||||
|
||||
namespace json::_packed_bytes
|
||||
{
|
||||
struct packed_bytes_trait_neon
|
||||
{
|
||||
static constexpr bool available = true;
|
||||
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 less(value_type x, uint8_t n)
|
||||
{
|
||||
auto bcast = vdupq_n_u8(n);
|
||||
auto is_less = vcltq_u8(x, bcast);
|
||||
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, 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 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);
|
||||
return fold32 == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
__packed_bytes_strong_inline static size_t first_nonzero_byte(value_type x)
|
||||
{
|
||||
// https://community.arm.com/arm-community-blogs/b/infrastructure-solutions-blog/posts/porting-x86-vector-bitmask-optimizations-to-arm-neon
|
||||
auto cmp = equal(x, 0);
|
||||
auto res = vshrn_n_u16(cmp, 4);
|
||||
auto mask64 = vget_lane_u64(vreinterpret_u64_u8(res), 0);
|
||||
return _bitops::countr_one(mask64) >> 2;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct packed_bytes<16>
|
||||
{
|
||||
using traits = packed_bytes_trait_neon;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
125
3rdparty/include/meojson/parser/packed_bytes_x86.hpp
vendored
Normal file
125
3rdparty/include/meojson/parser/packed_bytes_x86.hpp
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
#pragma once
|
||||
#include "packed_bytes.hpp"
|
||||
|
||||
#include <emmintrin.h>
|
||||
#if defined(__SSE4_1__) || defined(__AVX2__) || defined(_MSC_VER)
|
||||
// MSVC enables all SSE4.1 intrinsics by default
|
||||
#include <smmintrin.h>
|
||||
#endif
|
||||
|
||||
namespace json::_packed_bytes
|
||||
{
|
||||
struct packed_bytes_trait_sse
|
||||
{
|
||||
static constexpr bool available = true;
|
||||
static constexpr auto step = 16;
|
||||
using value_type = __m128i;
|
||||
|
||||
__packed_bytes_strong_inline static value_type load_unaligned(const void* ptr)
|
||||
{
|
||||
return _mm_loadu_si128(reinterpret_cast<const __m128i*>(ptr));
|
||||
}
|
||||
|
||||
__packed_bytes_strong_inline static value_type less(value_type x, uint8_t n)
|
||||
{
|
||||
auto bcast = _mm_set1_epi8(static_cast<char>(n));
|
||||
auto all1 = _mm_set1_epi8(-1);
|
||||
auto max_with_n = _mm_max_epu8(x, bcast);
|
||||
auto is_greater_or_equal = _mm_cmpeq_epi8(max_with_n, x);
|
||||
auto is_less = _mm_andnot_si128(is_greater_or_equal, all1);
|
||||
return is_less;
|
||||
}
|
||||
|
||||
__packed_bytes_strong_inline static value_type equal(value_type x, uint8_t n)
|
||||
{
|
||||
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 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)
|
||||
{
|
||||
#if defined(__SSE4_1__) || defined(__AVX2__) || defined(_MSC_VER)
|
||||
// SSE4.1 path
|
||||
return !!_mm_testz_si128(x, x);
|
||||
#else
|
||||
// SSE2 path
|
||||
auto cmp = _mm_cmpeq_epi8(x, _mm_set1_epi8(0));
|
||||
auto mask = (uint16_t)_mm_movemask_epi8(cmp);
|
||||
return mask == UINT16_C(0xFFFF);
|
||||
#endif
|
||||
}
|
||||
|
||||
__packed_bytes_strong_inline static size_t first_nonzero_byte(value_type x)
|
||||
{
|
||||
auto cmp = _mm_cmpeq_epi8(x, _mm_set1_epi8(0));
|
||||
auto mask = (uint16_t)_mm_movemask_epi8(cmp);
|
||||
return _bitops::countr_one((uint32_t)mask);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct packed_bytes<16>
|
||||
{
|
||||
using traits = packed_bytes_trait_sse;
|
||||
};
|
||||
}
|
||||
#ifdef __AVX2__
|
||||
#include <immintrin.h>
|
||||
|
||||
namespace json::_packed_bytes
|
||||
{
|
||||
struct packed_bytes_trait_avx2
|
||||
{
|
||||
static constexpr bool available = true;
|
||||
static constexpr auto step = 32;
|
||||
using value_type = __m256i;
|
||||
|
||||
__packed_bytes_strong_inline static value_type load_unaligned(const void* ptr)
|
||||
{
|
||||
return _mm256_loadu_si256(reinterpret_cast<const __m256i*>(ptr));
|
||||
}
|
||||
|
||||
__packed_bytes_strong_inline static value_type less(value_type x, uint8_t n)
|
||||
{
|
||||
auto bcast = _mm256_set1_epi8(static_cast<char>(n));
|
||||
auto all1 = _mm256_set1_epi8(-1);
|
||||
auto max_with_n = _mm256_max_epu8(x, bcast);
|
||||
auto is_greater_or_equal = _mm256_cmpeq_epi8(max_with_n, x);
|
||||
auto is_less = _mm256_andnot_si256(is_greater_or_equal, all1);
|
||||
return is_less;
|
||||
}
|
||||
|
||||
__packed_bytes_strong_inline static value_type equal(value_type x, uint8_t n)
|
||||
{
|
||||
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 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 size_t first_nonzero_byte(value_type x)
|
||||
{
|
||||
auto cmp = _mm256_cmpeq_epi8(x, _mm256_set1_epi8(0));
|
||||
auto mask = (uint32_t)_mm256_movemask_epi8(cmp);
|
||||
// AVX512 alternative: _mm_cmpeq_epi8_mask
|
||||
return _bitops::countr_one(mask);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct packed_bytes<32>
|
||||
{
|
||||
using traits = packed_bytes_trait_avx2;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
627
3rdparty/include/meojson/parser/parser.hpp
vendored
Normal file
627
3rdparty/include/meojson/parser/parser.hpp
vendored
Normal file
@@ -0,0 +1,627 @@
|
||||
#pragma once
|
||||
|
||||
#include <fstream>
|
||||
#include <optional>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
#include "../common/types.hpp"
|
||||
#include "packed_bytes.hpp"
|
||||
|
||||
namespace json
|
||||
{
|
||||
// ****************************
|
||||
// * parser declare *
|
||||
// ****************************
|
||||
|
||||
template <typename string_t = default_string_t, typename parsing_t = void,
|
||||
typename accel_traits = _packed_bytes::packed_bytes_trait_max>
|
||||
class parser
|
||||
{
|
||||
public:
|
||||
using parsing_iter_t = typename parsing_t::const_iterator;
|
||||
|
||||
public:
|
||||
~parser() noexcept = default;
|
||||
|
||||
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) { ; }
|
||||
|
||||
std::optional<basic_value<string_t>> parse();
|
||||
basic_value<string_t> parse_value();
|
||||
|
||||
basic_value<string_t> parse_null();
|
||||
basic_value<string_t> parse_boolean();
|
||||
basic_value<string_t> parse_number();
|
||||
// parse and return a basic_value<string_t> whose type is value_type::string
|
||||
basic_value<string_t> parse_string();
|
||||
basic_value<string_t> parse_array();
|
||||
basic_value<string_t> parse_object();
|
||||
|
||||
// parse and return a string_t
|
||||
std::optional<string_t> parse_stdstring();
|
||||
|
||||
bool skip_string_literal_with_accel();
|
||||
bool skip_whitespace() noexcept;
|
||||
bool skip_digit();
|
||||
|
||||
private:
|
||||
parsing_iter_t _cur;
|
||||
parsing_iter_t _end;
|
||||
};
|
||||
|
||||
// ***************************
|
||||
// * utils declare *
|
||||
// ***************************
|
||||
|
||||
template <typename parsing_t>
|
||||
auto parse(const parsing_t& content);
|
||||
|
||||
template <typename char_t>
|
||||
auto parse(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);
|
||||
|
||||
template <typename ifstream_t = std::ifstream, typename path_t = void>
|
||||
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""_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);
|
||||
|
||||
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>
|
||||
const basic_value<string_t> invalid_value();
|
||||
|
||||
// *************************
|
||||
// * parser impl *
|
||||
// *************************
|
||||
|
||||
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<string_t, parsing_t, accel_traits>(content.cbegin(), content.cend()).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;
|
||||
}
|
||||
|
||||
basic_value<string_t> result_value;
|
||||
switch (*_cur) {
|
||||
case '[':
|
||||
result_value = parse_array();
|
||||
break;
|
||||
case '{':
|
||||
result_value = parse_object();
|
||||
break;
|
||||
default: // A JSON payload should be an basic_object or basic_array
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (!result_value.valid()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// After the parsing is complete, there should be no more content other than
|
||||
// spaces behind
|
||||
if (skip_whitespace()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return result_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':
|
||||
return parse_null();
|
||||
case 't':
|
||||
case 'f':
|
||||
return parse_boolean();
|
||||
case '-':
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
return parse_number();
|
||||
case '"':
|
||||
return parse_string();
|
||||
case '[':
|
||||
return parse_array();
|
||||
case '{':
|
||||
return parse_object();
|
||||
default:
|
||||
return invalid_value<string_t>();
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
++_cur;
|
||||
}
|
||||
else {
|
||||
return invalid_value<string_t>();
|
||||
}
|
||||
}
|
||||
|
||||
return basic_value<string_t>();
|
||||
}
|
||||
|
||||
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':
|
||||
for (const auto& ch : _utils::true_string<string_t>()) {
|
||||
if (_cur != _end && *_cur == ch) {
|
||||
++_cur;
|
||||
}
|
||||
else {
|
||||
return invalid_value<string_t>();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
case 'f':
|
||||
for (const auto& ch : _utils::false_string<string_t>()) {
|
||||
if (_cur != _end && *_cur == ch) {
|
||||
++_cur;
|
||||
}
|
||||
else {
|
||||
return invalid_value<string_t>();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
return invalid_value<string_t>();
|
||||
}
|
||||
}
|
||||
|
||||
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 == '-') {
|
||||
++_cur;
|
||||
}
|
||||
|
||||
// numbers cannot have leading zeroes
|
||||
if (_cur != _end && *_cur == '0' && _cur + 1 != _end && std::isdigit(*(_cur + 1))) {
|
||||
return invalid_value<string_t>();
|
||||
}
|
||||
|
||||
if (!skip_digit()) {
|
||||
return invalid_value<string_t>();
|
||||
}
|
||||
|
||||
if (*_cur == '.') {
|
||||
++_cur;
|
||||
if (!skip_digit()) {
|
||||
return invalid_value<string_t>();
|
||||
}
|
||||
}
|
||||
|
||||
if (*_cur == 'e' || *_cur == 'E') {
|
||||
if (++_cur == _end) {
|
||||
return invalid_value<string_t>();
|
||||
}
|
||||
if (*_cur == '+' || *_cur == '-') {
|
||||
++_cur;
|
||||
}
|
||||
if (!skip_digit()) {
|
||||
return invalid_value<string_t>();
|
||||
}
|
||||
}
|
||||
|
||||
return basic_value<string_t>(basic_value<string_t>::value_type::number, string_t(first, _cur));
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
else {
|
||||
return invalid_value<string_t>();
|
||||
}
|
||||
|
||||
if (!skip_whitespace()) {
|
||||
return invalid_value<string_t>();
|
||||
}
|
||||
else if (*_cur == ']') {
|
||||
++_cur;
|
||||
// empty basic_array
|
||||
return basic_array<string_t>();
|
||||
}
|
||||
|
||||
typename basic_array<string_t>::raw_array result;
|
||||
while (true) {
|
||||
if (!skip_whitespace()) {
|
||||
return invalid_value<string_t>();
|
||||
}
|
||||
|
||||
basic_value<string_t> val = parse_value();
|
||||
|
||||
if (!val.valid() || !skip_whitespace()) {
|
||||
return invalid_value<string_t>();
|
||||
}
|
||||
|
||||
result.emplace_back(std::move(val));
|
||||
|
||||
if (*_cur == ',') {
|
||||
++_cur;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (skip_whitespace() && *_cur == ']') {
|
||||
++_cur;
|
||||
}
|
||||
else {
|
||||
return invalid_value<string_t>();
|
||||
}
|
||||
|
||||
return basic_array<string_t>(std::move(result));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
else {
|
||||
return invalid_value<string_t>();
|
||||
}
|
||||
|
||||
if (!skip_whitespace()) {
|
||||
return invalid_value<string_t>();
|
||||
}
|
||||
else if (*_cur == '}') {
|
||||
++_cur;
|
||||
// empty basic_object
|
||||
return basic_object<string_t>();
|
||||
}
|
||||
|
||||
typename basic_object<string_t>::raw_object result;
|
||||
while (true) {
|
||||
if (!skip_whitespace()) {
|
||||
return invalid_value<string_t>();
|
||||
}
|
||||
|
||||
auto key_opt = parse_stdstring();
|
||||
|
||||
if (key_opt && skip_whitespace() && *_cur == ':') {
|
||||
++_cur;
|
||||
}
|
||||
else {
|
||||
return invalid_value<string_t>();
|
||||
}
|
||||
|
||||
if (!skip_whitespace()) {
|
||||
return invalid_value<string_t>();
|
||||
}
|
||||
|
||||
basic_value<string_t> val = parse_value();
|
||||
|
||||
if (!val.valid() || !skip_whitespace()) {
|
||||
return invalid_value<string_t>();
|
||||
}
|
||||
|
||||
result.emplace(std::move(*key_opt), std::move(val));
|
||||
|
||||
if (*_cur == ',') {
|
||||
++_cur;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (skip_whitespace() && *_cur == '}') {
|
||||
++_cur;
|
||||
}
|
||||
else {
|
||||
return invalid_value<string_t>();
|
||||
}
|
||||
|
||||
return basic_object<string_t>(std::move(result));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
else {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
string_t result;
|
||||
auto no_escape_beg = _cur;
|
||||
|
||||
while (_cur != _end) {
|
||||
if constexpr (sizeof(*_cur) == 1 && accel_traits::available) {
|
||||
if (!skip_string_literal_with_accel()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
switch (*_cur) {
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
return std::nullopt;
|
||||
case '\\': {
|
||||
result += string_t(no_escape_beg, _cur++);
|
||||
if (_cur == _end) {
|
||||
return std::nullopt;
|
||||
}
|
||||
switch (*_cur) {
|
||||
case '"':
|
||||
result.push_back('"');
|
||||
break;
|
||||
case '\\':
|
||||
result.push_back('\\');
|
||||
break;
|
||||
case '/':
|
||||
result.push_back('/');
|
||||
break;
|
||||
case 'b':
|
||||
result.push_back('\b');
|
||||
break;
|
||||
case 'f':
|
||||
result.push_back('\f');
|
||||
break;
|
||||
case 'n':
|
||||
result.push_back('\n');
|
||||
break;
|
||||
case 'r':
|
||||
result.push_back('\r');
|
||||
break;
|
||||
case 't':
|
||||
result.push_back('\t');
|
||||
break;
|
||||
// case 'u':
|
||||
// result.push_back('\u');
|
||||
// break;
|
||||
default:
|
||||
// Illegal backslash escape
|
||||
return std::nullopt;
|
||||
}
|
||||
no_escape_beg = ++_cur;
|
||||
break;
|
||||
}
|
||||
case '"': {
|
||||
result += string_t(no_escape_beg, _cur++);
|
||||
return result;
|
||||
}
|
||||
default:
|
||||
++_cur;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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>('\\')));
|
||||
|
||||
if (accel_traits::is_all_zero(result)) {
|
||||
_cur += accel_traits::step;
|
||||
}
|
||||
else {
|
||||
auto index = accel_traits::first_nonzero_byte(result);
|
||||
_cur += index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return _cur != _end;
|
||||
}
|
||||
|
||||
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) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
++_cur;
|
||||
break;
|
||||
case '\0':
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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)) {
|
||||
++_cur;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (_cur != _end && std::isdigit(*_cur)) {
|
||||
++_cur;
|
||||
}
|
||||
|
||||
if (_cur != _end) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// *************************
|
||||
// * utils impl *
|
||||
// *************************
|
||||
|
||||
template <typename parsing_t>
|
||||
auto parse(const parsing_t& content)
|
||||
{
|
||||
using string_t = std::basic_string<typename parsing_t::value_type>;
|
||||
return parser<string_t, parsing_t>::parse(content);
|
||||
}
|
||||
|
||||
template <typename char_t>
|
||||
auto parse(char_t* content)
|
||||
{
|
||||
return parse(std::basic_string_view<std::decay_t<char_t>> { content });
|
||||
}
|
||||
|
||||
template <typename istream_t, typename _>
|
||||
auto parse(istream_t& ifs, bool check_bom)
|
||||
{
|
||||
using string_t = std::basic_string<typename istream_t::char_type>;
|
||||
|
||||
ifs.seekg(0, std::ios::end);
|
||||
auto file_size = ifs.tellg();
|
||||
|
||||
ifs.seekg(0, std::ios::beg);
|
||||
string_t str(file_size, '\0');
|
||||
|
||||
ifs.read(str.data(), file_size);
|
||||
|
||||
if (check_bom) {
|
||||
using uchar = unsigned char;
|
||||
static constexpr uchar Bom_0 = 0xEF;
|
||||
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) {
|
||||
str.assign(str.begin() + 3, str.end());
|
||||
}
|
||||
}
|
||||
return parse(str);
|
||||
}
|
||||
|
||||
template <typename ifstream_t, typename path_t>
|
||||
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>;
|
||||
using json_t = json::basic_value<string_t>;
|
||||
using return_t = std::optional<json_t>;
|
||||
|
||||
ifstream_t ifs(filepath, std::ios::in);
|
||||
if (!ifs.is_open()) {
|
||||
return return_t(std::nullopt);
|
||||
}
|
||||
auto opt = parse(ifs, check_bom);
|
||||
ifs.close();
|
||||
return opt;
|
||||
}
|
||||
|
||||
namespace literals
|
||||
{
|
||||
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 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 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();
|
||||
}
|
||||
} // 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());
|
||||
}
|
||||
} // namespace json
|
||||
1502
3rdparty/include/meojson/parser5/parser5.hpp
vendored
Normal file
1502
3rdparty/include/meojson/parser5/parser5.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
16
3rdparty/include/meojson/parser5/unicode.h
vendored
Normal file
16
3rdparty/include/meojson/parser5/unicode.h
vendored
Normal file
File diff suppressed because one or more lines are too long
241
3rdparty/include/meojson/reflection/jsonization.hpp
vendored
Normal file
241
3rdparty/include/meojson/reflection/jsonization.hpp
vendored
Normal file
@@ -0,0 +1,241 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include "../common/types.hpp"
|
||||
|
||||
namespace json::_jsonization_helper
|
||||
{
|
||||
struct next_is_optional_t
|
||||
{};
|
||||
struct va_arg_end
|
||||
{};
|
||||
|
||||
struct dumper
|
||||
{
|
||||
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>
|
||||
json::value _to_json(const char*, next_is_optional_t, rest_t&&... rest) const
|
||||
{
|
||||
return _to_json(std::forward<rest_t>(rest)...);
|
||||
}
|
||||
json::value _to_json(va_arg_end) const { return {}; }
|
||||
};
|
||||
|
||||
struct checker
|
||||
{
|
||||
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
|
||||
{
|
||||
auto opt = in.find(key);
|
||||
if (!opt || !opt->is<var_t>()) {
|
||||
error_key = key;
|
||||
return false;
|
||||
}
|
||||
return _check_json(in, error_key, std::forward<rest_t>(rest)...);
|
||||
}
|
||||
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
|
||||
{
|
||||
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
|
||||
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
auto opt = in.find(key);
|
||||
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 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
|
||||
{
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
|
||||
#endif
|
||||
|
||||
namespace json::_private_macro
|
||||
{
|
||||
#define _MEOJSON_STRINGIZE(arg) _MEOJSON_STRINGIZE1(arg)
|
||||
#define _MEOJSON_STRINGIZE1(arg) _MEOJSON_STRINGIZE2(arg)
|
||||
#define _MEOJSON_STRINGIZE2(arg) #arg
|
||||
|
||||
#define _MEOJSON_CONCATENATE(arg1, arg2) _MEOJSON_CONCATENATE1(arg1, arg2)
|
||||
#define _MEOJSON_CONCATENATE1(arg1, arg2) _MEOJSON_CONCATENATE2(arg1, arg2)
|
||||
#define _MEOJSON_CONCATENATE2(arg1, arg2) arg1##arg2
|
||||
|
||||
#define _MEOJSON_EXPAND(x) x
|
||||
|
||||
#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, ...) \
|
||||
N
|
||||
|
||||
#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__))
|
||||
|
||||
#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 \
|
||||
{ \
|
||||
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_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(...) \
|
||||
_MEOJSON_EXPAND(MEO_TOJSON(__VA_ARGS__)) \
|
||||
_MEOJSON_EXPAND(MEO_CHECKJSON(__VA_ARGS__)) \
|
||||
_MEOJSON_EXPAND(MEO_FROMJSON(__VA_ARGS__))
|
||||
|
||||
#define MEO_OPT json::_jsonization_helper::next_is_optional_t {},
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop // -Wgnu-zero-variadic-macro-arguments
|
||||
#endif
|
||||
260
CHANGELOG.md
260
CHANGELOG.md
@@ -1,257 +1,15 @@
|
||||
## v6.2.2
|
||||
|
||||
### Highlights
|
||||
|
||||
随着米诺斯 SS 的到来,我们迎来了一位全新的萨尔贡六星干员,~~那么牛牛的米诺斯大C在哪呢?~~
|
||||
|
||||
#### 日志侧边栏重构
|
||||
|
||||
本次更新我们对主页日志侧边栏进行了整体重构,统一并优化了布局与视觉样式。
|
||||
|
||||
现在你可以在「设置 → 界面设置」中控制【使用卡片样式日志】设置来切换日志样式,控制【日志缩略图最大数量】设置来决定日志侧边栏的缩略图数量上限(这些缩略图都是临时保存在内存里的,**内存较小的用户可能需要调整数量**)
|
||||
|
||||
#### 自动战斗优化
|
||||
|
||||
我们优化了自动战斗功能的作业路径下拉选择栏,现在同一个任务的本地作业将会折叠在一起,大幅度提升了下拉选择栏的可读性。
|
||||
|
||||
另外,本次游戏更新 yj 修改了暂停按钮的位置,我们已经通过热更新修复该问题,本次更新 MAA 也会合并此项修复。
|
||||
|
||||
#### 今日关卡提示优化
|
||||
|
||||
今日关卡提示中的掉落信息现已支持同步显示对应的库存数量,便于在刷图规划时快速判断材料缺口与优先级。
|
||||
|
||||
你可通过「小工具 → 仓库识别」更新库存数量,今日关卡提示中的掉落信息会自动同步更新。
|
||||
|
||||
#### 基建与线索管理优化
|
||||
|
||||
我们在「一键长草 → 基建换班 → 高级设置」里新增了【进行线索交流】【赠送线索】两项独立开关设置,提升基建管理的灵活性。
|
||||
|
||||
我们也优化了一键赠送线索等的逻辑,减少误操作发生的可能性。
|
||||
|
||||
同时,在基建进入设施失败时牛牛将自动保留测试截图,便于后续问题的定位与排查。
|
||||
|
||||
#### 成就系统 DLC
|
||||
|
||||
我们新增了一些成就,覆盖多个场景,等你探索哦~
|
||||
|
||||
----
|
||||
|
||||
#### Log Sidebar Redesign
|
||||
|
||||
In this update, we've completely redesigned the main page log sidebar, unifying and optimizing its layout and visual style.
|
||||
|
||||
You can now switch log styles by controlling the *Use card style log* setting in *Settings → GUI*, and control the *Maximum number of log thumbnails* setting to determine the maximum number of thumbnails in the log sidebar (these thumbnails are temporarily stored in memory, **users with limited memory may need to adjust the number**).
|
||||
|
||||
#### *Copilot* Optimization
|
||||
|
||||
We've optimized the task path dropdown selection bar for the *Copilot*. Local tasks for the same stage will now be collapsed together, significantly improving the readability of the dropdown selection bar.
|
||||
|
||||
Additionally, the game update changed the position of the pause button. We have fixed this issue through a hot update, and this fix has been merged into the MAA update.
|
||||
|
||||
#### *Today's open stages* Hint Optimization
|
||||
|
||||
The drop information in the *Today's open stages* hints now supports synchronous display of the corresponding depot quantity, making it easier to quickly determine material shortages and priorities when planning your stage runs.
|
||||
|
||||
You can update your depot info through *Toolbox → Depot*, and the daily drop information in the *Today's open stages* hints will be automatically updated.
|
||||
|
||||
#### *Base* and Clue Management Optimizations
|
||||
|
||||
We've added two independent toggle settings for *Conduct Clue Exchange* and *Send Clues* in *Farming → Base → Advanced*, improving the flexibility of *Base* management.
|
||||
|
||||
We've also optimized the logic for one-click clue sending, reducing the possibility of accidental operations.
|
||||
|
||||
Additionally, when *Base* entry fails, MAA will automatically save a test screenshot for easier troubleshooting and identification of subsequent issues.
|
||||
|
||||
#### Achievement System DLC
|
||||
|
||||
We've added some achievements covering multiple scenarios, waiting for you to explore!
|
||||
|
||||
----
|
||||
|
||||
以下是详细内容:
|
||||
|
||||
## v6.2.2
|
||||
|
||||
### 新增 | New
|
||||
|
||||
* 只有一个配置时标题栏隐藏配置名 @ABA2396
|
||||
* 检查更新失败时吐司通知 @ABA2396
|
||||
* 新增截图增强模拟器路径的选择窗口 @ABA2396
|
||||
* 自动战斗-自动编队支持技能等级要求 (#15355) @status102
|
||||
* 设置指引中添加使用指引页 @ABA2396
|
||||
|
||||
### 改进 | Improved
|
||||
|
||||
* 调整 ViewModels 目录结构,规范 ViewModels 命名 (#15389) @ABA2396
|
||||
* 优化动画效果 @ABA2396
|
||||
* 优化仓库识别二值化阈值 @ABA2396
|
||||
* 悬浮窗改 static @status102
|
||||
|
||||
### 修复 | Fix
|
||||
|
||||
* 界园指挥避战刷钱增加黑屏等待 @Saratoga-Official
|
||||
* 有猪把成就注释掉了 @ABA2396
|
||||
* 修复特殊路径下执行 adb 命令可能失败的问题 (#15381) (#15382) @sylw114
|
||||
* 修复 TaskDialog 按钮文本赋值时的语法错误及空引用保护 (#15377) @hcl55
|
||||
* 修复牛牛抽卡点击停止之后文字提示不会停止变化 @ABA2396
|
||||
* 仓库数据 parse 失败时返回空数据 @ABA2396
|
||||
* 修复肉鸽快速编队按钮边缘无法点击导致出错 @Saratoga-Official
|
||||
* 修复矿石"杀手"识别 @Saratoga-Official
|
||||
* 肉鸽增加黑屏等待时间 @Saratoga-Official
|
||||
* 悖论模拟-作业列表额外等待 @status102
|
||||
* 修复构建警告 @ABA2396
|
||||
* 收到关卡名识别失败回调时更新卡片 @ABA2396
|
||||
* Fix phantom puppet not deploying @Constrat
|
||||
* Fix AT ClickStage t -> T @Constrat
|
||||
* Add AsstGetImageBgr to wine shim @dantmnf
|
||||
## v5.4.1
|
||||
|
||||
### 文档 | Docs
|
||||
|
||||
* 更新开发指南 @ABA2396
|
||||
* Update cli usage.md with Windows installation note (#15369) @JasonHuang79
|
||||
* 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
|
||||
* 制造站加入苍苔组,避免苍苔与阿罗玛冲突 (#15343) @drway
|
||||
* 地块类型标注 TileType (#15373) @status102
|
||||
* 抽卡任务结束后提示还原为默认 @ABA2396
|
||||
* 一图流上报 id 单独实现 @ABA2396
|
||||
* EN tweak to inventory display @Constrat
|
||||
* AT updates @Constrat
|
||||
* YostarJP AT updates @Manicsteiner
|
||||
* YostarKR AT updates @HX3N
|
||||
* Preload AT + new alter operators regex for EN @Constrat
|
||||
* YostarJP AT preload and ocr edit @Manicsteiner
|
||||
* Update OrundumActivities for EN @Constrat
|
||||
#### YostarEN
|
||||
|
||||
## v6.2.1
|
||||
|
||||
### 新增 | New
|
||||
|
||||
* 公告界面触屏滚动 @ABA2396
|
||||
* 拆分 debug 和 report 文件夹逻辑 @ABA2396
|
||||
|
||||
### 改进 | Improved
|
||||
|
||||
* 自动检测地图是否为多阶段地图, 判断是否需要使用 view[0].x 修正镜头 (#15371) @status102
|
||||
* 优化下拉框逻辑 @ABA2396
|
||||
* 用妖法实现了自动战斗下拉框的失焦和收起按钮 @ABA2396
|
||||
|
||||
### 修复 | Fix
|
||||
|
||||
* 游戏更新后结算黑屏时长大幅增加,导致肉鸽结算失败 @ABA2396
|
||||
* 增加理智战斗后点击到掉落列表的重试次数,避免延长的黑屏时间影响 @ABA2396
|
||||
* 将借助战打 OF-1 的任务结束后最大等待时间翻倍,避免延长的黑屏时间影响 @ABA2396
|
||||
* 肉鸽推荐设置文本 (#15370) @ABA2396 @Saratoga-Official
|
||||
* 自动战斗-悖论模拟 中文路径作业 解析作业失败 @status102
|
||||
* 肉鸽重试时误点进招募界面 @Saratoga-Official
|
||||
* 移除 ExceptionStacktrace.hpp @status102
|
||||
* 收取好友线索延迟 @ABA2396
|
||||
|
||||
### 文档 | Docs
|
||||
|
||||
* 更新 Visual C++ 可再发行程序包链接至 V14 版本 (#15360) @wryx166
|
||||
|
||||
### 其他 | Other
|
||||
|
||||
* 调整战斗结束后的点击位置 @ABA2396
|
||||
* 悖论模拟自动战斗任务翻译 @ABA2396
|
||||
|
||||
## v6.2.0
|
||||
|
||||
### 新增 | New
|
||||
|
||||
* 重构仓库识别结构,支持根据关卡掉落情况自动更新 (#15358) @ABA2396
|
||||
* 成就 DLC 功能 (#15288) @ABA2396
|
||||
* 增强自动战斗文件选择功能,支持多级路径和相对目录 (#15174) @momomochi987 @ABA2396
|
||||
* 允许设置是否启用线索交流与赠送线索 (#15278) @ABA2396
|
||||
* 增加冬时至基建温蒂组并调整温蒂组选人逻辑 (#15294) @drway
|
||||
* 通知渠道添加 Gotify (#15284) @2436238575
|
||||
* 给 Bark 通知添加默认的分类组 (#15244) @Anselyuki
|
||||
* 重构主页日志侧边栏整体布局和样式 (#15211) @MistEO @ABA2396
|
||||
* 支持日志样式切换 @ABA2396
|
||||
* 基建设施缩略图 @ABA2396
|
||||
* 自动战斗日志栏添加日志悬浮窗按钮 @ABA2396
|
||||
* 关卡提示支持显示库存 @ABA2396
|
||||
* 更新库存提示移到 ToolTip @ABA2396
|
||||
* 可以点击 20 次按钮关闭公告弹窗 @ABA2396
|
||||
* 日志允许图片更新时不添加内容 @ABA2396
|
||||
* 限制使用 CPU 推理时的线程占用数,优先保证模拟器运行 @ABA2396
|
||||
* 基建进入设施失败时保留测试截图 @ABA2396
|
||||
* 将自动重载资源独立出来,在 debug 模式下显示勾选框 @ABA2396
|
||||
* 尝试增加 B 服开屏活动跳过 @ABA2396
|
||||
* 检测到自身处于临时路径中时阻止启动 (#14961) @Rbqwow @ABA2396
|
||||
* 企鹅物流上报 ID 不为空时禁止被上报结果赋值 @ABA2396
|
||||
* 新增肉鸽主题推荐配置 tip 并适配多语言 (#15324) @hcl55 @HX3N @Manicsteiner @Constrat @momomochi987 @ABA2396
|
||||
* SideStory 「雅赛努斯复仇记」导航 @SherkeyXD
|
||||
* Disable CoreML for detection and recognition on macOS @MistEO
|
||||
|
||||
### 改进 | Improved
|
||||
|
||||
* 重构自动战斗标签页逻辑,拆分悖论模拟任务 (#15327) @ABA2396 @yali-hzy @status102 @HX3N @Constrat
|
||||
* 刷理智任务指定次数与代理倍率冲突提醒 (#15233) @status102 @HX3N @momomochi987 @Manicsteiner
|
||||
* 优化线索交流、获取好友线索逻辑 @ABA2396
|
||||
* 优化界面显示效果与换行 @ABA2396
|
||||
* 优化缩略图逻辑 @ABA2396
|
||||
* 优化 PropertyDependsOnHelper 实现 @ABA2396
|
||||
* 将 PropertyDependsOnViewModel 改为静态工具类 @ABA2396
|
||||
* 调整缩略图 ToolTip 延迟 @ABA2396
|
||||
* 在禁用时 TooltipBlock 显示特效 (#15260) @yali-hzy @ABA2396
|
||||
* 重命名以符合文件结构 @ABA2396
|
||||
* devcontainer 从 conda 迁移至 mise/uv (#15251) @SherkeyXD
|
||||
* rename Dps to Ops (#15325) @ABA2396
|
||||
|
||||
### 修复 | Fix
|
||||
|
||||
* 界园肉鸽因点击模板边缘导致关卡进不去 @Saratoga-Official
|
||||
* 肉鸽暂停按钮更新 @ABA2396
|
||||
* 20260109 游戏更新导致自动战斗失效 @status102
|
||||
* 同时开启「剿灭模式」和「备选关卡」会导致「企鹅物流汇报 ID」被修改 @ABA2396
|
||||
* 无法通过删除自动战斗输入框内容清除当前作业,无法通过在输入框输入神秘代码直接开始战斗 @ABA2396
|
||||
* 线索数量识别 @ABA2396
|
||||
* 线索板上有线索时无法一键放置线索 @ABA2396
|
||||
* 肉鸽未填写开局干员时借助战强制为 false @ABA2396
|
||||
* 隐秘战线结局识别 @ABA2396
|
||||
* 隐秘战线识别到多余字符时无法进入对应事件 @ABA2396
|
||||
* 给缺失干员检查补上 Unavailable (#15296) @Alan-Charred
|
||||
* 尝试修复基建效率计算中的 out_of_range 异常 @ABA2396
|
||||
* 远程控制截图无法获取最新图像 (#15276) @Hakuin123
|
||||
* Debug 图片保存目录 (#15250) @hguandl
|
||||
* 修复文档站搜索问题 @SherkeyXD
|
||||
* 鬼影迷踪 -> 诡影迷踪 @ABA2396
|
||||
* 撷英调香师 @ABA2396
|
||||
* 避免其他 locale 下,掉落次数误认数字字符 (#15306) @aflyhorse
|
||||
* ai review @ABA2396
|
||||
* Filename too long @Daydreamer114
|
||||
* update DormMini.png for EN (again) @Constrat
|
||||
* fix SA1518 warnings @Constrat
|
||||
* SA1633 warning missing copyright notice @Constrat
|
||||
* waydroid rawbync screencap 2>/dev/null (#15196) @commondservice
|
||||
|
||||
### 文档 | Docs
|
||||
|
||||
* 使用脚本一键安装 maa-cli (#15283) @wangl-cc
|
||||
* 战斗协议 移动镜头 (#15261) @Daydreamer114
|
||||
* 源码链接同步最新行数 @Rbqwow
|
||||
* 中文集成文档统一格式 @ABA2396
|
||||
* update KR documents (#15282) @HX3N
|
||||
* update vsc ext docs for quick ocr (#15298) @neko-para @HX3N @Constrat
|
||||
|
||||
### 其他 | Other
|
||||
|
||||
* 移除地图未修复期间的临时糊屎, 移除未更正的注释 @status102
|
||||
* 添加雪猎基建技能加成 @Saratoga-Official
|
||||
* 调整文件夹判断逻辑 @ABA2396
|
||||
* 调整注释 @ABA2396
|
||||
* 调整 MaxNumberOfLogThumbnails 作用域,调整默认数量 @ABA2396
|
||||
* 微调公告确认按钮位置 @SherkeyXD
|
||||
* 移除多余关卡 @SherkeyXD
|
||||
* 添加挂调试器下使用 GPU 的注释 @ABA2396
|
||||
* add IsDebugVersion to _forcedReloadResource (#15293) @Constrat
|
||||
* port changes from api @SherkeyXD
|
||||
* H16-4, 引航者 #6 TN-1~TN-4 剩余地图 view[1] @status102
|
||||
* YostarKR tweak AS-OpenOcr @HX3N
|
||||
* YostarJP roguelike JieGarden ocr edit @Manicsteiner
|
||||
* YoStarJP SN device ocr (#15310) @cheriu
|
||||
* EN for `FightTimesMayNotExhausted` @Constrat
|
||||
* YoStarEN resolution warning on client switch (#9539) @Constrat @ABA2396
|
||||
|
||||
205
CMakeLists.txt
205
CMakeLists.txt
@@ -1,50 +1,191 @@
|
||||
cmake_minimum_required(VERSION 3.28)
|
||||
cmake_minimum_required(VERSION 3.21)
|
||||
project(MaaAssistantArknights)
|
||||
|
||||
project(MAA)
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build." FORCE)
|
||||
endif ()
|
||||
|
||||
option(BUILD_WPF_GUI "build MaaWpfGui" ${WIN32})
|
||||
option(BUILD_DEBUG_DEMO "build debug demo" OFF)
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
|
||||
|
||||
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}/cmake/utils.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)
|
||||
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(RPATH_LIBRARY_INSTALL_DIR .)
|
||||
set(MaaCore_install_flatten_args RUNTIME DESTINATION . LIBRARY DESTINATION . PUBLIC_HEADER DESTINATION .)
|
||||
endif()
|
||||
|
||||
include(src/MaaUtils/MaaUtils.cmake)
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/modules")
|
||||
include(${PROJECT_SOURCE_DIR}/cmake/config.cmake)
|
||||
include(${PROJECT_SOURCE_DIR}/cmake/utils.cmake)
|
||||
install(TARGETS MaaCore ${MaaCore_install_flatten_args} ${MaaCore_install_extra_args})
|
||||
|
||||
if(APPLE)
|
||||
include(${PROJECT_SOURCE_DIR}/cmake/macos.cmake)
|
||||
if(INSTALL_THIRD_LIBS AND USE_MAADEPS)
|
||||
maadeps_install()
|
||||
endif()
|
||||
|
||||
add_library(HeaderOnlyLibraries INTERFACE)
|
||||
target_include_directories(HeaderOnlyLibraries INTERFACE 3rdparty/include)
|
||||
|
||||
add_subdirectory(src/MaaCore)
|
||||
|
||||
if(BUILD_WPF_GUI)
|
||||
include_external_msproject(MaaWpfGui ${PROJECT_SOURCE_DIR}/src/MaaWpfGui/MaaWpfGui.csproj)
|
||||
|
||||
add_dependencies(MaaWpfGui MaaCore)
|
||||
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
15
MAA.DotSettings
Normal 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
106
MAA.sln
Normal 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
122
MAA.sln.DotSettings
Normal 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
1
MaaDeps
Submodule
Submodule MaaDeps added at 10d51f5832
128
README.md
128
README.md
@@ -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>
|
||||
@@ -21,14 +21,11 @@
|
||||
<img alt="stars" src="https://img.shields.io/github/stars/MaaAssistantArknights/MaaAssistantArknights?style=social">
|
||||
<img alt="GitHub all releases" src="https://img.shields.io/github/downloads/MaaAssistantArknights/MaaAssistantArknights/total?style=social">
|
||||
</div>
|
||||
<div>
|
||||
<a href="https://deepwiki.com/MaaAssistantArknights/MaaAssistantArknights"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki"></a>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<!-- 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
|
||||
|
||||
@@ -36,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://penguin-stats.cn/),[一图流](https://ark.yituliu.cn/)
|
||||
- 智能基建换班,自动计算干员效率,单设施内最优解;同时也支持 [自定义排班](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)
|
||||
- 访问好友、收取信用及购物、领取日常奖励等,一键全日常自动长草
|
||||
@@ -62,60 +55,92 @@ 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)操作,支持 Linux,macOS 和 Windows,可用于自动化脚本或在无图形界面的服务器上使用。请参阅 [CLI 使用指南](https://docs.maa.plus/zh-cn/manual/cli/)
|
||||
MAA 支持命令行界面(CLI)操作,支持 Linux,macOS 和 Windows,可用于自动化脚本或在无图形界面的服务器上使用。请参阅 [CLI 使用指南](https://maa.plus/docs/zh-cn/manual/cli/intro.html)
|
||||
|
||||
## 加入我们
|
||||
|
||||
### 主要关联项目
|
||||
|
||||
**目前项目组非常缺前端大佬,若您有相关经验,欢迎加入我们!**
|
||||
|
||||
- 全新框架:[MaaFramework](https://github.com/MaaXYZ/MaaFramework)
|
||||
- [作业站](https://prts.plus) 前端:[zoot-plus-frontend](https://github.com/ZOOT-Plus/zoot-plus-frontend)
|
||||
- [作业站](https://prts.plus) 后端:[ZootPlusBackend](https://github.com/ZOOT-Plus/ZootPlusBackend)
|
||||
- 全新 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)
|
||||
- 深度学习:[MaaAI](https://github.com/MaaAssistantArknights/MaaAI)
|
||||
|
||||
### 多语言 (i18n)
|
||||
|
||||
MAA 支持多国语言,并使用 Weblate 进行本地化管理。如果您通晓多门语言,欢迎前往 [MAA Weblate](https://weblate.maa-org.net) 帮助我们进行翻译。
|
||||
|
||||
MAA 以中文(简体)为第一语言,翻译词条均以中文(简体)为准。
|
||||
|
||||
[](https://weblate.maa-org.net/engage/maa/)
|
||||
|
||||
### 参与开发
|
||||
|
||||
请参阅 [开发指南](https://docs.maa.plus/zh-cn/develop/development.html)。
|
||||
#### Windows
|
||||
|
||||
### API
|
||||
请参阅 [开始开发](https://maa.plus/docs/zh-cn/develop/development.html)。
|
||||
|
||||
#### Linux | macOS
|
||||
|
||||
请参阅 [Linux 编译教程](https://maa.plus/docs/zh-cn/develop/linux-tutorial.html)。
|
||||
|
||||
#### API
|
||||
|
||||
- [C 接口](include/AsstCaller.h):[集成示例](src/Cpp/main.cpp)
|
||||
- [Python 接口](src/Python/asst/asst.py):[集成示例](src/Python/sample.py)
|
||||
@@ -126,18 +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 修改即可。
|
||||
|
||||
### Issue bot
|
||||
#### 想参与开发,但不太会用 GitHub?
|
||||
|
||||
请参阅 [Issue Bot 使用方法](https://docs.maa.plus/zh-cn/develop/issue-bot-usage.html)
|
||||
[GitHub Pull Request 流程简述](https://maa.plus/docs/zh-cn/develop/development.html#github-pull-request-流程简述)
|
||||
|
||||
#### Issue bot
|
||||
|
||||
请参阅 [Issue Bot 使用方法](https://maa.plus/docs/zh-cn/develop/issue-bot-usage.html)
|
||||
|
||||
## 致谢
|
||||
|
||||
@@ -169,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 越来越好! (\*´▽`)ノノ
|
||||
|
||||
[](https://github.com/MaaAssistantArknights/MaaAssistantArknights/graphs/contributors)
|
||||
[](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 吧!~(网页最上方右上角的小星星),这就是对我们最大的支持了!
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
## 受支持的版本 / Supported Versions
|
||||
|
||||
我们仅对 v6 的最新稳定版提供安全支持,如有安全问题,我们将会尽可能快地发布新的稳定版解决。
|
||||
我们仅对 v4 和 v5 两个大版本的最新稳定版提供安全支持,如有安全问题,我们将会尽可能快地发布新的稳定版解决。
|
||||
|
||||
内测版、公测版仅供测试,我们不会对其提供安全支持。
|
||||
|
||||
We only provide security support for the latest Stable Release versions of v6. If there are security issues, we will release a new stable version as soon as possible to solve them.
|
||||
We only provide security support for the latest Stable Release versions of v4 and v5. If there are security issues, we will release a new stable version as soon as possible to solve them.
|
||||
|
||||
The Nightly Release version and the Beta Release version are for testing only, and we will not provide security support for them.
|
||||
|
||||
|
||||
7
build.cmd
Normal file
7
build.cmd
Normal 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
69
build.ps1
Normal 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
62
build.sh
Normal 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 -- "$@"
|
||||
@@ -1,2 +0,0 @@
|
||||
set(debug_comp_defs "_DEBUG;ASST_DEBUG")
|
||||
add_compile_definitions("$<$<CONFIG:Debug>:${debug_comp_defs}>")
|
||||
@@ -1,81 +1,30 @@
|
||||
if (BUILD_XCFRAMEWORK)
|
||||
set(XCFRAMEWORK_DIR "${CMAKE_BINARY_DIR}/xcframework")
|
||||
file(MAKE_DIRECTORY ${XCFRAMEWORK_DIR})
|
||||
|
||||
# Macro to find a unique library file
|
||||
macro(find_unique_library lib_name glob_pattern output_var)
|
||||
file(GLOB _libs CONFIGURE_DEPENDS "${MAADEPS_DIR}/runtime/${MAADEPS_TRIPLET}/${glob_pattern}")
|
||||
if(_libs)
|
||||
list(LENGTH _libs _cnt)
|
||||
if(_cnt EQUAL 1)
|
||||
list(GET _libs 0 ${output_var})
|
||||
message(STATUS "Found ${lib_name}: ${${output_var}}")
|
||||
else()
|
||||
message(FATAL_ERROR "Ambiguous ${lib_name} dylibs: ${_libs}")
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "${lib_name} library not found in ${MAADEPS_DIR}/runtime/${MAADEPS_TRIPLET}/")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
add_custom_command(OUTPUT ${XCFRAMEWORK_DIR}/MaaCore.xcframework
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -rf "${XCFRAMEWORK_DIR}/MaaCore.xcframework"
|
||||
COMMAND xcodebuild -create-xcframework
|
||||
-library $<TARGET_FILE:MaaCore>
|
||||
-headers ${PROJECT_SOURCE_DIR}/include
|
||||
-output MaaCore.xcframework
|
||||
add_custom_command(OUTPUT MaaCore.xcframework
|
||||
COMMAND rm -rf MaaCore.xcframework
|
||||
COMMAND xcodebuild -create-xcframework -library libMaaCore.dylib -headers ${PROJECT_SOURCE_DIR}/include -output MaaCore.xcframework
|
||||
DEPENDS MaaCore
|
||||
WORKING_DIRECTORY ${XCFRAMEWORK_DIR}
|
||||
COMMENT "Generating MaaCore.xcframework"
|
||||
)
|
||||
|
||||
add_custom_command(OUTPUT ${XCFRAMEWORK_DIR}/MaaUtils.xcframework
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -rf "${XCFRAMEWORK_DIR}/MaaUtils.xcframework"
|
||||
COMMAND xcodebuild -create-xcframework
|
||||
-library $<TARGET_FILE:MaaUtils>
|
||||
-output MaaUtils.xcframework
|
||||
DEPENDS MaaUtils
|
||||
WORKING_DIRECTORY ${XCFRAMEWORK_DIR}
|
||||
COMMENT "Generating MaaUtils.xcframework"
|
||||
)
|
||||
|
||||
find_unique_library("OpenCV" "libopencv_world*.dylib" OPENCV_LIB)
|
||||
add_custom_command(OUTPUT ${XCFRAMEWORK_DIR}/OpenCV.xcframework
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -rf "${XCFRAMEWORK_DIR}/OpenCV.xcframework"
|
||||
COMMAND xcodebuild -create-xcframework
|
||||
-library "${OPENCV_LIB}"
|
||||
-output OpenCV.xcframework
|
||||
WORKING_DIRECTORY ${XCFRAMEWORK_DIR}
|
||||
COMMENT "Generating OpenCV.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.407.dylib" -output OpenCV.xcframework
|
||||
)
|
||||
|
||||
find_unique_library("ONNXRuntime" "libonnxruntime*.dylib" ONNXRUNTIME_LIB)
|
||||
add_custom_command(OUTPUT ${XCFRAMEWORK_DIR}/ONNXRuntime.xcframework
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -rf "${XCFRAMEWORK_DIR}/ONNXRuntime.xcframework"
|
||||
COMMAND xcodebuild -create-xcframework
|
||||
-library "${ONNXRUNTIME_LIB}"
|
||||
-output ONNXRuntime.xcframework
|
||||
WORKING_DIRECTORY ${XCFRAMEWORK_DIR}
|
||||
COMMENT "Generating ONNXRuntime.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.14.1.dylib" -output ONNXRuntime.xcframework
|
||||
)
|
||||
|
||||
add_custom_command(OUTPUT ${XCFRAMEWORK_DIR}/fastdeploy_ppocr.xcframework
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -rf "${XCFRAMEWORK_DIR}/fastdeploy_ppocr.xcframework"
|
||||
COMMAND xcodebuild -create-xcframework
|
||||
-library "${MAADEPS_DIR}/runtime/${MAADEPS_TRIPLET}/libfastdeploy_ppocr.dylib"
|
||||
-output fastdeploy_ppocr.xcframework
|
||||
WORKING_DIRECTORY ${XCFRAMEWORK_DIR}
|
||||
COMMENT "Generating fastdeploy_ppocr.xcframework"
|
||||
add_custom_command(OUTPUT fastdeploy_ppocr.xcframework
|
||||
COMMAND rm -rf fastdeploy_ppocr.xcframework
|
||||
COMMAND xcodebuild -create-xcframework -library "${PROJECT_SOURCE_DIR}/MaaDeps/runtime/${MAADEPS_TRIPLET}/libfastdeploy_ppocr.dylib" -output fastdeploy_ppocr.xcframework
|
||||
)
|
||||
|
||||
add_custom_target(MaaXCFramework ALL
|
||||
DEPENDS
|
||||
MaaCore
|
||||
${XCFRAMEWORK_DIR}/MaaCore.xcframework
|
||||
MaaUtils
|
||||
${XCFRAMEWORK_DIR}/MaaUtils.xcframework
|
||||
${XCFRAMEWORK_DIR}/OpenCV.xcframework
|
||||
${XCFRAMEWORK_DIR}/ONNXRuntime.xcframework
|
||||
${XCFRAMEWORK_DIR}/fastdeploy_ppocr.xcframework
|
||||
DEPENDS MaaCore MaaCore.xcframework OpenCV.xcframework ONNXRuntime.xcframework fastdeploy_ppocr.xcframework
|
||||
)
|
||||
endif (BUILD_XCFRAMEWORK)
|
||||
|
||||
target_compile_options(MaaCore PRIVATE
|
||||
-Wno-deprecated-declarations
|
||||
-Wno-gnu-zero-variadic-macro-arguments)
|
||||
|
||||
54
cmake/opencv.cmake
Normal file
54
cmake/opencv.cmake
Normal 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
44
cmake/thrift-gen.cmake
Normal 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)
|
||||
@@ -1,26 +1,50 @@
|
||||
# 创建资源目录链接的函数
|
||||
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()
|
||||
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})
|
||||
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()
|
||||
endfunction()
|
||||
|
||||
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 (APPLE)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 12.0)
|
||||
get_osx_architecture()
|
||||
endif (APPLE)
|
||||
|
||||
@@ -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: [
|
||||
"//"
|
||||
]
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
**/pnpm-lock.yaml
|
||||
@@ -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: ['**/*.*css'],
|
||||
options: {
|
||||
singleQuote: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.yml', '**/*.yaml'],
|
||||
options: {
|
||||
parser: 'yaml',
|
||||
singleQuote: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.json'],
|
||||
options: {
|
||||
tabWidth: 4,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.md'],
|
||||
options: {
|
||||
embeddedLanguageFormatting: 'off',
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -1,21 +1,8 @@
|
||||
import { defineClientConfig } from 'vuepress/client'
|
||||
|
||||
import { getAsciiArt } from './plugins/asciiArt'
|
||||
|
||||
import AsciiArt from './components/AsciiArt.vue'
|
||||
import ImageGrid from './components/ImageGrid.vue'
|
||||
import Redirect from './components/Redirect.vue'
|
||||
|
||||
import './styles/index.scss'
|
||||
import { defineClientConfig } from "vuepress/client";
|
||||
import ImageGrid from "../components/ImageGrid.vue";
|
||||
|
||||
export default defineClientConfig({
|
||||
enhance: ({ app }) => {
|
||||
app.component('AsciiArt', AsciiArt)
|
||||
app.component('ImageGrid', ImageGrid)
|
||||
app.component('Redirect', Redirect)
|
||||
|
||||
// 输出一个随机的字符画
|
||||
const asciiArtData = getAsciiArt(undefined, 'auto', 'console')
|
||||
console.log('%c' + asciiArtData.text, 'white-space: pre;')
|
||||
app.component("ImageGrid", ImageGrid);
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
<template>
|
||||
<div ref="asciiArtWrapperElement" class="ascii-art-wrapper">
|
||||
<pre ref="asciiArtContentElement" class="ascii-art-content">{{ asciiArtText }}</pre>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onBeforeUnmount } from 'vue'
|
||||
import { getAsciiArt, ThemeType, AsciiArtScope } from '../plugins/asciiArt'
|
||||
|
||||
// -------- Props --------
|
||||
interface AsciiArtProps {
|
||||
name?: string
|
||||
theme?: ThemeType
|
||||
scope?: AsciiArtScope
|
||||
}
|
||||
const props = defineProps<AsciiArtProps>()
|
||||
|
||||
// -------- Refs --------
|
||||
const asciiArtWrapperElement = ref<HTMLElement>()
|
||||
const asciiArtContentElement = ref<HTMLElement>()
|
||||
|
||||
// -------- Data --------
|
||||
let asciiArtNameInUse = props.name
|
||||
const asciiArtText = ref('')
|
||||
|
||||
let layoutObserver: ResizeObserver
|
||||
let themeObserver: MutationObserver
|
||||
|
||||
let isScaleUpLocked = false
|
||||
let lastScaleRatio = 1
|
||||
|
||||
function refreshAsciiArt() {
|
||||
const asciiArtData = getAsciiArt(asciiArtNameInUse, props.theme, props.scope)
|
||||
asciiArtNameInUse = asciiArtData.name
|
||||
asciiArtText.value = asciiArtData.text
|
||||
}
|
||||
|
||||
function scaleAsciiArt() {
|
||||
if (!asciiArtWrapperElement.value || !asciiArtContentElement.value) return
|
||||
|
||||
// 原始高度和宽度(无视scale)
|
||||
const contentWidth = asciiArtContentElement.value.scrollWidth
|
||||
const contentHeight = asciiArtContentElement.value.scrollHeight
|
||||
if (contentWidth === 0 || contentHeight === 0) return
|
||||
|
||||
const targetWidth = asciiArtWrapperElement.value.clientWidth
|
||||
const targetHeight = window.innerHeight
|
||||
|
||||
const scaleRatio = Math.min(targetWidth / contentWidth, targetHeight / contentHeight)
|
||||
// 锁定状态不允许放大
|
||||
if (scaleRatio > lastScaleRatio && isScaleUpLocked) return
|
||||
|
||||
lastScaleRatio = scaleRatio
|
||||
isScaleUpLocked = true
|
||||
|
||||
asciiArtContentElement.value.style.transform = `scale(${scaleRatio})`
|
||||
asciiArtWrapperElement.value.style.height = `${contentHeight * scaleRatio}px`
|
||||
}
|
||||
|
||||
function forceScaleAsciiArt() {
|
||||
isScaleUpLocked = false
|
||||
scaleAsciiArt()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (!asciiArtWrapperElement.value || !asciiArtContentElement.value) return
|
||||
|
||||
layoutObserver = new ResizeObserver(scaleAsciiArt)
|
||||
layoutObserver.observe(asciiArtContentElement.value)
|
||||
layoutObserver.observe(asciiArtWrapperElement.value)
|
||||
|
||||
themeObserver = new MutationObserver(refreshAsciiArt)
|
||||
themeObserver.observe(document.documentElement, { attributes: true, attributeFilter: ['data-theme'] })
|
||||
|
||||
window.addEventListener('resize', forceScaleAsciiArt)
|
||||
|
||||
refreshAsciiArt()
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (layoutObserver) {
|
||||
layoutObserver.disconnect()
|
||||
}
|
||||
if (themeObserver) {
|
||||
themeObserver.disconnect()
|
||||
}
|
||||
window.removeEventListener('resize', forceScaleAsciiArt)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.ascii-art-wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.ascii-art-content {
|
||||
display: block;
|
||||
white-space: pre;
|
||||
margin: 0 auto;
|
||||
transform-origin: top;
|
||||
line-height: 1;
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
}
|
||||
</style>
|
||||
@@ -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>
|
||||
@@ -1,25 +0,0 @@
|
||||
<template />
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted } from 'vue'
|
||||
import { useRouter, useRoute } from 'vuepress/client'
|
||||
|
||||
interface Props {
|
||||
to?: string
|
||||
}
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
function resolvePath(to: string) {
|
||||
const target = new URL(to, 'http://example.com' + route.path) // 使用一个虚拟的基础 URL
|
||||
return target.pathname
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (!props.to) return
|
||||
const targetPath = resolvePath(props.to)
|
||||
router.replace(targetPath)
|
||||
})
|
||||
</script>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user