├── .github ├── update_resource_version.py └── workflows │ └── ci.yml ├── .gitignore ├── .gitmodules ├── .maay ├── control.json ├── repo.json └── resource.json ├── .vscode └── settings.json ├── CHANGELOG.md ├── CMakeLists.txt ├── CMakePresets.json ├── LICENSE ├── README.md ├── assets └── resource │ ├── adb_config.json │ ├── image │ ├── Armada │ │ ├── ApplyForANewCommission.png │ │ ├── ArmadaPageFlag.png │ │ ├── ClaimedContributionRewards.png │ │ ├── CommissionItem.png │ │ ├── CommissionItemBuy.png │ │ ├── CommissionSubmitButton.png │ │ ├── CommissionsPageFlag.png │ │ ├── CommissionsRewardsClaim.png │ │ ├── CommissionsRewardsLastDistribution.png │ │ ├── CommissionsRewardsPageFlag.png │ │ ├── ContributionsPageFlag.png │ │ ├── NotReachContributionProgress.png │ │ ├── ReachContributionProgress.png │ │ └── SubmitCommission.png │ ├── Awards │ │ ├── BPMissionsQuickClaim.png │ │ ├── DailyBPRewardsClaim.png │ │ ├── DailyBPRewardsClaimed.png │ │ ├── DailyBPRewardsPreview.png │ │ └── NoneDailyBPRewards.png │ ├── Combat │ │ ├── StopCombat.png │ │ └── UniversalMirage │ │ │ ├── UniversalMirageCostingTimeSwirlPasses.png │ │ │ ├── UniversalMiragePageFlag.png │ │ │ ├── UniversalMirageStageFightAlone.png │ │ │ ├── UniversalMirageStageFlag.png │ │ │ ├── UniversalMirageStageNoneValkyrja.png │ │ │ ├── UniversalMirageStagePrepare.png │ │ │ └── UniversalMirageStageStart.png │ ├── Dorm │ │ ├── Close.png │ │ ├── CloseCollectAP.png │ │ ├── CollectAP.png │ │ ├── CollectAPButton.png │ │ ├── CollectGold.png │ │ ├── CollectGoldMax.png │ │ ├── Collection_available.png │ │ ├── Collection_forbidden.png │ │ ├── Confirm.png │ │ ├── Confirm_errands.png │ │ ├── ErrandsPageFlag.png │ │ ├── ErrandsRefresh.png │ │ ├── ErrandsUnfold.png │ │ ├── NextErrands.png │ │ ├── QuickDispatch.png │ │ ├── StartErrands.png │ │ ├── StartExpeditions.png │ │ ├── SwitchToFragmentPage.png │ │ ├── SwitchToMaterialPage.png │ │ ├── available.png │ │ └── forbidden.png │ ├── MaterialEvent │ │ ├── LITE.png │ │ ├── MaterialEventFlag.png │ │ └── QuickLITE.png │ ├── Navigation │ │ ├── Armada │ │ │ ├── EnterArmadaContribution.png │ │ │ └── EnterCommissionsPage.png │ │ ├── Attack │ │ │ ├── EnterAttackEventPage.png │ │ │ └── EnterChallengeEventPage.png │ │ ├── AttackEvent │ │ │ └── EnterMaterialExpeditionPage.png │ │ ├── ChallengeEvent │ │ │ └── EnterUniversalMiragePage.png │ │ ├── Commissions │ │ │ └── EnterCommissionsRewardsPage.png │ │ ├── Dorm │ │ │ ├── EnterErrandsPage.png │ │ │ └── EnterExpeditionsPage.png │ │ ├── MaterialExpedition │ │ │ └── EnterMaterialEventPage.png │ │ ├── Missions │ │ │ └── EnterBPMissionsPage.png │ │ ├── Shop │ │ │ ├── EnterActivityShopPage.png │ │ │ └── EnterMirageStorePage.png │ │ ├── Supply │ │ │ └── EnterShopPage.png │ │ └── UniversalMirage │ │ │ ├── EnterBladeGravePage.png │ │ │ ├── EnterGlacialFencesPage.png │ │ │ ├── EnterIlluminatedLandPage.png │ │ │ └── EnterRoaringPalacePage.png │ ├── Shop │ │ ├── DailyShopPageFlag.png │ │ ├── LogisticsTerminalBuyCharacterFragmentByGoldFlag.png │ │ ├── LogisticsTerminalCharacterFragmentFlag.png │ │ ├── LogisticsTerminalPage.png │ │ ├── MirageStore1AsteriteFlag.png │ │ └── SoldOut.png │ ├── StartUp │ │ ├── AbyssSettlement.png │ │ ├── AiPromptFlag_0.png │ │ ├── AiPromptFlag_1.png │ │ ├── CloseAnnouncement.png │ │ ├── CloseVersionAnnouncement.png │ │ ├── CollectDailyLoginReward.png │ │ ├── Confirm.png │ │ ├── Download.png │ │ ├── GameIdentifying.png │ │ ├── GameLoading.png │ │ ├── HomeFlag.png │ │ ├── MiHoYoLogo.png │ │ ├── ObtainedAward.png │ │ └── SuperstringDimensionSettlement.png │ └── Utils │ │ ├── BackButton.png │ │ ├── BackButton_1.png │ │ ├── CancelButton.png │ │ ├── CloseDialogBox.png │ │ ├── HomeButton.png │ │ └── HomeButton_1.png │ ├── model │ └── ocr │ │ ├── README.md │ │ ├── det.onnx │ │ ├── keys.txt │ │ └── rec.onnx │ ├── pipeline │ ├── armada │ │ ├── armada.json │ │ ├── commissions.json │ │ └── contributions.json │ ├── awards.json │ ├── close_bh3.json │ ├── combat │ │ ├── combat.json │ │ ├── universal_mirage.json │ │ └── universal_mirage_combat_generic.json │ ├── dorm │ │ ├── dorm.json │ │ ├── errands.json │ │ └── expeditions.json │ ├── material_event.json │ ├── navigation │ │ ├── armada_navigation.json │ │ ├── attack_event_navigation.json │ │ ├── attack_navigation.json │ │ ├── challenge_event_navigation.json │ │ ├── commissions_navigation.json │ │ ├── dorm_navigation.json │ │ ├── home_navigation.json │ │ ├── material_expedition_navigation.json │ │ ├── missions_navigation.json │ │ ├── shop_navigation.json │ │ ├── supply_navigation.json │ │ └── universal_mirage_navigation.json │ ├── shop.json │ ├── startup.json │ └── utils.json │ └── properties.json ├── cmake ├── assets.cmake ├── config.cmake ├── framework.cmake ├── macos.cmake ├── utils.cmake └── version.cmake ├── docs └── 配置文档.md ├── source └── cli │ ├── .clang-format │ ├── CMakeLists.txt │ ├── Config │ ├── Config.cpp │ ├── Config.h │ ├── ConfigMgr.cpp │ ├── ConfigMgr.h │ ├── ControlConfig.cpp │ ├── ControlConfig.h │ ├── DeviceConfig.cpp │ ├── DeviceConfig.h │ ├── TasksConfig.cpp │ └── TasksConfig.h │ ├── CustomAction │ ├── CombatAction.cpp │ ├── CombatAction.h │ ├── CustomAction.cpp │ ├── CustomAction.h │ ├── CustomActionRegistrar.cpp │ ├── CustomActionRegistrar.h │ ├── CustomActionRegistry.h │ ├── RandomPointGenerator.cpp │ └── RandomPointGenerator.h │ ├── CustomRecognizer │ ├── CombatRecognizer.cpp │ ├── CombatRecognizer.h │ ├── CustomRecognizer.cpp │ ├── CustomRecognizer.h │ ├── CustomRecognizerRegistrar.cpp │ ├── CustomRecognizerRegistrar.h │ └── CustomRecognizerRegistry.h │ ├── control.cpp │ ├── control.h │ ├── device.cpp │ ├── device.h │ ├── main.cpp │ ├── main.h │ ├── meojson │ ├── .clang-format │ ├── bitops.hpp │ ├── json.hpp │ ├── json5.hpp │ ├── packed_bytes.hpp │ ├── packed_bytes_arm.hpp │ └── packed_bytes_x86.hpp │ ├── tasks.cpp │ └── tasks.h └── tools ├── ChangelogGenerator ├── .gitignore ├── changelog_generator.py └── start.bat ├── CombatGenerator ├── .gitignore ├── README.md ├── combat.schema.json ├── data │ ├── input.json │ └── output.json ├── pdm.lock ├── pyproject.toml ├── src │ └── combatgenerator │ │ └── __init__.py └── tests │ ├── __init__.py │ ├── data │ ├── combat_to_json.json │ └── json_to_combat.json │ └── test.py └── CropRoi ├── .gitignore ├── README.md ├── dst └── .gitkeep ├── main.py ├── pdm.lock ├── pyproject.toml ├── requirements.txt ├── src └── .gitkeep └── start.bat /.github/update_resource_version.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import json 3 | 4 | if len(sys.argv) < 3: 5 | print("Usage: python update_resource_version.py ") 6 | exit(1) 7 | 8 | properties_file = sys.argv[1] 9 | version = sys.argv[2] 10 | 11 | with open(properties_file, "r") as f: 12 | data = json.load(f) 13 | 14 | data["version"] = version 15 | 16 | with open(properties_file, "w") as f: 17 | json.dump(data, f, indent=4) 18 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: build cli 2 | 3 | permissions: 4 | contents: write 5 | 6 | on: 7 | push: 8 | tags: 9 | - 'v*' 10 | branches: 11 | - '**' 12 | paths: 13 | - '.github/workflows/ci.yml' 14 | - 'source/cli/**' 15 | - 'assets/**' 16 | - 'cmake/**' 17 | - 'CMakelists.txt' 18 | - 'CMakePresets.json' 19 | pull_request: 20 | branches: 21 | - '**' 22 | paths: 23 | - '.github/workflows/ci.yml' 24 | - 'source/cli/**' 25 | - 'assets/**' 26 | - 'cmake/**' 27 | - 'CMakelists.txt' 28 | - 'CMakePresets.json' 29 | workflow_dispatch: 30 | 31 | jobs: 32 | meta: 33 | runs-on: ubuntu-latest 34 | steps: 35 | - uses: actions/checkout@v3 36 | with: 37 | fetch-depth: 0 38 | - id: set_tag 39 | run: | 40 | is_release=${{ startsWith(github.ref, 'refs/tags/v') }} 41 | tag=$(git describe --tags --match "v*" ${{ github.ref }} || true) 42 | if [[ $tag != v* ]]; then 43 | tag=$(curl -sX GET "https://api.github.com/repos/MaaAssistantArknights/MaaFramework/releases/latest" --header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' | awk '/tag_name/{print $4}' FS='["]') 44 | if [[ $tag != v* ]]; then 45 | tag="v0.0.0" 46 | fi 47 | tag=$(date "+$tag-%y%m%d-$(git rev-parse --short HEAD)") 48 | fi 49 | if ! $($is_release) ; then 50 | prefix=${tag%-*-*} 51 | suffix=${tag#$prefix-} 52 | tag="$prefix-ci.$suffix" 53 | fi 54 | 55 | echo tag=$tag | tee -a $GITHUB_OUTPUT 56 | echo is_release=$is_release | tee -a $GITHUB_OUTPUT 57 | 58 | - if: ${{ startsWith(github.ref, 'refs/tags/v') }} 59 | run: | 60 | this_tag=${{ steps.set_tag.outputs.tag }} 61 | last_tag=$(git describe --tags --match "v*" --abbrev=0 --exclude='${{ steps.set_tag.outputs.tag }}') 62 | echo >> CHANGELOG.md 63 | echo "**Full Changelog**: [$last_tag -> $this_tag](https://github.com/MaaAssistantArknights/MAABH3/compare/${last_tag}...${this_tag})" >> CHANGELOG.md 64 | 65 | - uses: actions/upload-artifact@v4 66 | if: ${{ startsWith(github.ref, 'refs/tags/v') }} 67 | with: 68 | name: changelog 69 | path: CHANGELOG.md 70 | outputs: 71 | tag: ${{ steps.set_tag.outputs.tag }} 72 | is_release: ${{ steps.set_tag.outputs.is_release }} 73 | 74 | windows: 75 | needs: meta 76 | runs-on: windows-latest 77 | strategy: 78 | matrix: 79 | arch: [aarch64, x86_64] 80 | fail-fast: false 81 | 82 | steps: 83 | - uses: actions/checkout@v3 84 | with: 85 | submodules: true 86 | 87 | - name: Update resource version 88 | run: | 89 | python3 .github/update_resource_version.py assets/resource/properties.json ${{ needs.meta.outputs.tag }} 90 | 91 | - name: Download MaaFramework 92 | uses: robinraju/release-downloader@v1.11 93 | with: 94 | repository: MaaAssistantArknights/MaaFramework 95 | tag: "v1.8.9" 96 | fileName: "MAA-win-${{ matrix.arch }}*" 97 | out-file-path: "deps" 98 | extract: true 99 | 100 | - name: Build MAABH3 101 | run: | 102 | cmake --preset "${{ matrix.arch == 'x86_64' && 'MSVC 2022' || 'MSVC 2022 ARM' }}" -DMAABH3_HASH_VERSION='${{ needs.meta.outputs.tag }}' 103 | 104 | cmake --build build --config Release -j 16 105 | 106 | - name: Install 107 | shell: bash 108 | run: | 109 | cmake --install build --prefix install 110 | 111 | - uses: actions/upload-artifact@v4 112 | with: 113 | name: MAABH3-win-${{ matrix.arch }} 114 | path: "install" 115 | 116 | ubuntu: 117 | needs: meta 118 | runs-on: ubuntu-latest 119 | container: archlinux:base-devel 120 | strategy: 121 | matrix: 122 | arch: [aarch64, x86_64] 123 | fail-fast: false 124 | 125 | steps: 126 | # maybe should explicitly update some pkg instead of all? 127 | - name: Update system 128 | run: | 129 | pacman -Syu --noconfirm 130 | 131 | - name: Install dep 132 | run: | 133 | pacman -Sy 134 | pacman -S --noconfirm cmake python ccache ninja git 135 | 136 | # https://github.com/MaaAssistantArknights/MaaFramework/actions/runs/5643408179/job/15285186255 137 | - uses: actions/checkout@v3 138 | with: 139 | submodules: true 140 | 141 | - name: Install cross compile toolchains 142 | if: ${{ matrix.arch != 'x86_64' }} 143 | run: | 144 | pacman -Sy 145 | pacman -S --noconfirm aarch64-linux-gnu-gcc 146 | 147 | - name: Setup ccache 148 | uses: Chocobo1/setup-ccache-action@v1 149 | with: 150 | remove_stale_cache: false 151 | 152 | - name: Update resource version 153 | run: | 154 | python3 .github/update_resource_version.py assets/resource/properties.json ${{ needs.meta.outputs.tag }} 155 | 156 | - name: Download MaaFramework 157 | uses: robinraju/release-downloader@v1.11 158 | with: 159 | repository: MaaAssistantArknights/MaaFramework 160 | tag: "v1.8.9" 161 | fileName: "MAA-linux-${{ matrix.arch }}*" 162 | out-file-path: "deps" 163 | extract: true 164 | 165 | - name: Build MAABH3 166 | env: 167 | CC: ${{ matrix.arch == 'x86_64' && 'ccache gcc' || 'ccache aarch64-linux-gnu-gcc' }} 168 | CXX: ${{ matrix.arch == 'x86_64' && 'ccache g++' || 'ccache aarch64-linux-gnu-g++' }} 169 | run: | 170 | cmake --preset 'NinjaMulti' \ 171 | -DMAABH3_HASH_VERSION='${{ needs.meta.outputs.tag }}' 172 | 173 | cmake --build build --config Release -j 16 174 | 175 | - name: Install 176 | shell: bash 177 | run: | 178 | cmake --install build --prefix install 179 | 180 | - uses: actions/upload-artifact@v4 181 | with: 182 | name: MAABH3-linux-${{ matrix.arch }} 183 | path: "install" 184 | 185 | macos: 186 | needs: meta 187 | runs-on: macos-latest 188 | strategy: 189 | matrix: 190 | arch: [aarch64] 191 | fail-fast: false 192 | 193 | steps: 194 | - uses: actions/checkout@v3 195 | with: 196 | submodules: true 197 | 198 | - name: Install dep 199 | run: | 200 | brew install cmake python ninja 201 | # ccache? 202 | 203 | - name: Install compiler 204 | run: | 205 | brew install llvm 206 | # 16 207 | 208 | - name: Update resource version 209 | run: | 210 | python3 .github/update_resource_version.py assets/resource/properties.json ${{ needs.meta.outputs.tag }} 211 | 212 | - name: Download MaaFramework 213 | uses: robinraju/release-downloader@v1.11 214 | with: 215 | repository: MaaAssistantArknights/MaaFramework 216 | tag: "v1.8.9" 217 | fileName: "MAA-macos-${{ matrix.arch }}*" 218 | out-file-path: "deps" 219 | extract: true 220 | 221 | - name: Build MAABH3 222 | env: 223 | CC: "/opt/homebrew/opt/llvm/bin/clang" 224 | CXX: "/opt/homebrew/opt/llvm/bin/clang++" 225 | LDFLAGS: "-L/opt/homebrew/opt/llvm/lib" 226 | CPPFLAGS: "-I/opt/homebrew/opt/llvm/include" 227 | run: | 228 | cmake --preset 'NinjaMulti' \ 229 | -DARCH='${{ matrix.arch == 'x86_64' && 'x64' || 'arm64' }}' \ 230 | -DMAABH3_HASH_VERSION='${{ needs.meta.outputs.tag }}' 231 | 232 | cmake --build build --config Release -j 16 233 | 234 | - name: Install 235 | shell: bash 236 | run: | 237 | cmake --install build --prefix install 238 | 239 | - uses: actions/upload-artifact@v4 240 | with: 241 | name: MAABH3-macos-${{ matrix.arch }} 242 | path: "install" 243 | 244 | release: 245 | if: ${{ needs.meta.outputs.is_release == 'true' }} 246 | needs: [meta, windows, ubuntu, macos] 247 | runs-on: ubuntu-latest 248 | steps: 249 | - uses: actions/download-artifact@v4 250 | with: 251 | path: assets 252 | - run: | 253 | mv -vf assets/changelog/* . 254 | rm -rf assets/changelog 255 | cd assets 256 | for f in *; do 257 | (cd $f && zip -r ../$f-${{ needs.meta.outputs.tag }}.zip .) 258 | done 259 | - uses: softprops/action-gh-release@v1 260 | with: 261 | body_path: CHANGELOG.md 262 | files: assets/* 263 | tag_name: ${{ needs.meta.outputs.tag }} -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/.gitmodules -------------------------------------------------------------------------------- /.maay/control.json: -------------------------------------------------------------------------------- 1 | { 2 | "option": { 3 | "expeditions": { 4 | "name": "远征类型", 5 | "type": "select_string", 6 | "default": "material", 7 | "case": [ 8 | { 9 | "name": "碎片", 10 | "value": "fragment", 11 | "provide": { 12 | "Sub_SwitchToFragmentPage": { 13 | "enabled": true 14 | } 15 | } 16 | }, 17 | { 18 | "name": "材料", 19 | "value": "material", 20 | "provide": { 21 | "Sub_SwitchToFragmentPage": { 22 | "enabled": false 23 | } 24 | } 25 | } 26 | ] 27 | }, 28 | "server": { 29 | "name": "服务器", 30 | "type": "select_string", 31 | "default": "official", 32 | "case": [ 33 | { 34 | "name": "官服", 35 | "value": "official", 36 | "provide": { 37 | "Sub_StartBH3": { 38 | "package": "com.miHoYo.enterprise.NGHSoD/com.miHoYo.overridenativeactivity.OverrideNativeActivity" 39 | }, 40 | "RestartBH3": { 41 | "package": "com.miHoYo.enterprise.NGHSoD" 42 | }, 43 | "CloseBH3": { 44 | "package": "com.miHoYo.enterprise.NGHSoD" 45 | } 46 | } 47 | }, 48 | { 49 | "name": "B服", 50 | "value": "bilibili", 51 | "provide": { 52 | "Sub_StartBH3": { 53 | "package": "com.miHoYo.bh3.bilibili/com.miHoYo.overridenativeactivity.OverrideNativeActivity" 54 | }, 55 | "RestartBH3": { 56 | "package": "com.miHoYo.bh3.bilibili" 57 | }, 58 | "CloseBH3": { 59 | "package": "com.miHoYo.bh3.bilibili" 60 | } 61 | } 62 | }, 63 | { 64 | "name": "Vivo服", 65 | "value": "vivo", 66 | "provide": { 67 | "Sub_StartBH3": { 68 | "package": "com.miHoYo.bh3.vivo/com.miHoYo.overridenativeactivity.OverrideNativeActivity" 69 | }, 70 | "RestartBH3": { 71 | "package": "com.miHoYo.bh3.vivo" 72 | }, 73 | "CloseBH3": { 74 | "package": "com.miHoYo.bh3.vivo" 75 | } 76 | } 77 | } 78 | ] 79 | } 80 | }, 81 | "global": { 82 | "option": ["server"] 83 | }, 84 | "entry": [ 85 | { 86 | "name": "家园", 87 | "task": "Dorm", 88 | "option": ["expeditions"] 89 | }, 90 | { 91 | "name": "材料远征", 92 | "task": "MaterialEvent" 93 | }, 94 | { 95 | "name": "舰团", 96 | "task": "Armada" 97 | }, 98 | { 99 | "name": "商店", 100 | "task": "Shop" 101 | }, 102 | { 103 | "name": "领取奖励", 104 | "task": "Awards" 105 | } 106 | ] 107 | } 108 | -------------------------------------------------------------------------------- /.maay/repo.json: -------------------------------------------------------------------------------- 1 | { 2 | "resource": { 3 | "default": "assets/resource" 4 | } 5 | } -------------------------------------------------------------------------------- /.maay/resource.json: -------------------------------------------------------------------------------- 1 | { 2 | "resource": { 3 | "default": { 4 | "name": "默认", 5 | "path": "@default" 6 | } 7 | }, 8 | "app": { 9 | "start": "com.miHoYo.enterprise.NGHSoD/com.miHoYo.overridenativeactivity.OverrideNativeActivity", 10 | "stop": "com.miHoYo.enterprise.NGHSoD", 11 | "orientation": "landscape", 12 | "size": { 13 | "short": 720 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "json.schemas": [ 3 | { 4 | "fileMatch": [ 5 | "/assets/resource/**/*.json", 6 | "/install/resource/**/*.json" 7 | ], 8 | "url": "/deps/tools/pipeline.schema.json" 9 | } 10 | ], 11 | "[json]": { 12 | "editor.formatOnSave": true, 13 | "editor.insertSpaces": true, 14 | "editor.tabSize": 4, 15 | "editor.indentSize": "tabSize" 16 | }, 17 | "files.associations": { 18 | "algorithm": "cpp", 19 | "array": "cpp", 20 | "atomic": "cpp", 21 | "bit": "cpp", 22 | "cctype": "cpp", 23 | "charconv": "cpp", 24 | "chrono": "cpp", 25 | "clocale": "cpp", 26 | "cmath": "cpp", 27 | "compare": "cpp", 28 | "concepts": "cpp", 29 | "cstddef": "cpp", 30 | "cstdint": "cpp", 31 | "cstdio": "cpp", 32 | "cstdlib": "cpp", 33 | "cstring": "cpp", 34 | "ctime": "cpp", 35 | "cwchar": "cpp", 36 | "deque": "cpp", 37 | "exception": "cpp", 38 | "filesystem": "cpp", 39 | "format": "cpp", 40 | "forward_list": "cpp", 41 | "fstream": "cpp", 42 | "functional": "cpp", 43 | "initializer_list": "cpp", 44 | "iomanip": "cpp", 45 | "ios": "cpp", 46 | "iosfwd": "cpp", 47 | "iostream": "cpp", 48 | "istream": "cpp", 49 | "iterator": "cpp", 50 | "limits": "cpp", 51 | "list": "cpp", 52 | "locale": "cpp", 53 | "map": "cpp", 54 | "memory": "cpp", 55 | "mutex": "cpp", 56 | "new": "cpp", 57 | "optional": "cpp", 58 | "ostream": "cpp", 59 | "random": "cpp", 60 | "ranges": "cpp", 61 | "ratio": "cpp", 62 | "regex": "cpp", 63 | "span": "cpp", 64 | "sstream": "cpp", 65 | "stack": "cpp", 66 | "stdexcept": "cpp", 67 | "stop_token": "cpp", 68 | "streambuf": "cpp", 69 | "string": "cpp", 70 | "system_error": "cpp", 71 | "thread": "cpp", 72 | "tuple": "cpp", 73 | "type_traits": "cpp", 74 | "typeinfo": "cpp", 75 | "unordered_map": "cpp", 76 | "unordered_set": "cpp", 77 | "utility": "cpp", 78 | "variant": "cpp", 79 | "vector": "cpp", 80 | "xfacet": "cpp", 81 | "xhash": "cpp", 82 | "xiosbase": "cpp", 83 | "xlocale": "cpp", 84 | "xlocbuf": "cpp", 85 | "xlocinfo": "cpp", 86 | "xlocmes": "cpp", 87 | "xlocmon": "cpp", 88 | "xlocnum": "cpp", 89 | "xloctime": "cpp", 90 | "xmemory": "cpp", 91 | "xstring": "cpp", 92 | "xtr1common": "cpp", 93 | "xtree": "cpp", 94 | "xutility": "cpp" 95 | } 96 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## v0.7.0 2 | 3 | ### 新增 4 | 5 | - cli 一些命令 @dongwlin 6 | - 多配置 @dongwlin 7 | 8 | ### 修复 9 | 10 | - 修复虚境万象异常 @dongwlin 11 | - 修复参数错误时仍然继续执行的问题 @dongwlin 12 | - 修复材料远征收家园体力时模板不存在的问题 @dongwlin 13 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.21) 2 | project(MAABH3) 3 | 4 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 5 | set(Boost_NO_WARN_NEW_VERSIONS 1) 6 | 7 | include(${PROJECT_SOURCE_DIR}/cmake/config.cmake) # Basic compile & link configuration 8 | include(${PROJECT_SOURCE_DIR}/cmake/assets.cmake) 9 | include(${PROJECT_SOURCE_DIR}/cmake/utils.cmake) 10 | include(${PROJECT_SOURCE_DIR}/cmake/version.cmake) 11 | include(${PROJECT_SOURCE_DIR}/cmake/framework.cmake) 12 | 13 | # if(USE_MAADEPS) 14 | # include(${PROJECT_SOURCE_DIR}/MaaDeps/maadeps.cmake) 15 | # endif() 16 | # find_package(OpenCV REQUIRED COMPONENTS core imgproc imgcodecs videoio) 17 | # find_package(Boost REQUIRED COMPONENTS system url) 18 | 19 | add_subdirectory(source/cli) 20 | -------------------------------------------------------------------------------- /CMakePresets.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 5, 3 | "cmakeMinimumRequired": { 4 | "major": 3, 5 | "minor": 21, 6 | "patch": 0 7 | }, 8 | "configurePresets": [ 9 | { 10 | "name": "NinjaMulti", 11 | "displayName": "Ninja MultiConfig", 12 | "description": "Ninja MultiConfig", 13 | "generator": "Ninja Multi-Config", 14 | "binaryDir": "${sourceDir}/build" 15 | }, 16 | { 17 | "name": "MSVC 2022", 18 | "displayName": "MSVC 2022", 19 | "description": "MSVC 2022", 20 | "generator": "Visual Studio 17 2022", 21 | "binaryDir": "${sourceDir}/build", 22 | "condition": { 23 | "type": "equals", 24 | "lhs": "${hostSystemName}", 25 | "rhs": "Windows" 26 | } 27 | }, 28 | { 29 | "name": "MSVC 2022 ARM", 30 | "displayName": "MSVC 2022 ARM", 31 | "description": "MSVC 2022 ARM", 32 | "generator": "Visual Studio 17 2022", 33 | "binaryDir": "${sourceDir}/build", 34 | "condition": { 35 | "type": "equals", 36 | "lhs": "${hostSystemName}", 37 | "rhs": "Windows" 38 | }, 39 | "architecture": { 40 | "strategy": "set", 41 | "value": "ARM64" 42 | } 43 | } 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | # MAABH3 5 | 6 | 基于MAA全新架构的 蹦蹦蹦 小助手 7 | 8 | 图像技术 + 模拟控制,解放双手! 9 | 10 | 由 [MaaFramework](https://github.com/MaaXYZ/MaaFramework) 强力驱动! 11 | 12 |
13 | 14 | ## How to use 15 | 16 | > 1. [下载](https://github.com/MaaXYZ/MAABH3/releases) 对应平台的压缩包 17 | > 2. 将压缩包解压到没有中文的目录下 18 | 19 | ### 基本说明 20 | 21 | 1. 请根据 [模拟器支持情况](https://maa.plus/docs/zh-cn/manual/device/windows.html),进行对应的操作。 22 | 2. 修改模拟器分辨率为 `16:9` 比例,最低 `1280 * 720`,更高不限。 23 | 24 | ### 直接使用 25 | 26 | > 以 Windows 用户为主,其他系统请照葫芦画瓢。 27 | 28 | 1. 首次使用,双击打开 `MAABH3_CLI.exe` 或 通过 CMD 执行 `MAABH3_CLI.exe` 29 | 2. 连接设备设置 30 | 3. 选择服务器 31 | 4. 输入需要执行的任务序号 32 | 33 | - 以空格分隔,例如 `1 2 3 4 5` 和 `2 3 1 4 5`,序号的顺序代表着执行顺序 34 | - 序号可重复,例如 `5 1 2 3 4 5` 35 | 36 | 5. 开始使用吧! 37 | 38 | - 后续使用无需再次选择客户端和输入需要执行的任务 39 | - 后续使用除非需要连接的设备的配置不存在,否则无需再次进行连接设备设置 40 | 41 | ### 作为MAA结束后脚本使用 42 | 43 | > 以 Windows 用户为主,其他系统请照葫芦画瓢。 44 | 45 | 1. 先按照 [直接使用](#直接使用) 进行操作 46 | 2. 在MAA目录下新建一个文本文件,在其中填入以下内容 47 | 48 | ```bat 49 | @echo off 50 | cd D:/Software/MAABH3 51 | MAABH3_CLI.exe 52 | ``` 53 | 54 | - 注意:`D:/Software/MAABH3` 请替换成你自己的 MAABH3 目录 55 | 56 | 3. 将文本文件重命名为 `finish.bat` 57 | 58 | - 如果重命名后没有弹出修改扩展名的二次确认对话框,且文件图标没有变化,请自行搜索“Windows如何显示文件扩展名”。 59 | 60 | 4. 在MAA `设置`-`连接设置`-`结束后脚本` 中填入 `finish.bat` 61 | 5. 开始使用吧! 62 | 63 | ## Task 64 | 65 | | 任务 | 说明 | 66 | | ---- | ---- | 67 | | Dorm | 家园;自动收家园金币、体力、打工和远征 | 68 | | MaterialEvent | 材料远征;自动一键减负 | 69 | | Armada | 舰团;自动提交委托回收和领取舰团贡献奖励 | 70 | | Shop | 商店;用金币购买后勤终端的角色碎片和用1星石购买虚境商店的时序通行证 | 71 | | Awards | 奖励;领取每日奖励 | 72 | | UniversalMirage | 万象虚境;自动打第二层 | 73 | 74 | - 目前启动游戏仅支持官服、Bilibili服和Vivo服 75 | - 其他渠道服虽不支持启动,但可手动启动游戏后正常使用 76 | - 若需要适配启动其他渠道服,欢迎提 `issues` 或 `pr` 77 | - 家园远征可能会清空当前体力和家园体力罐内体力,总量受远征派遣体力限制 78 | - 如果任务列表中同时包含 MaterialEvent 和 Dorm,先完成 MaterialEvent是一个更好的选择。这样做有助于确保有足够的体力来完成所有任务 79 | - 使用材料减负需要先三星通关一次对应关卡,有多个关卡的模块(如曜日材料)则会自动进行已完成挑战的最高一级关卡 80 | - 万象虚境需要先选好上场女武神 81 | 82 | ## Config 83 | 84 | `./config/control` 目录下放置 control 相关配置 85 | 86 | `./config/device` 目录下放置 device 相关配置 87 | 88 | `./config/tasks` 目录下放置 tasks 相关配置 89 | 90 | 详细见 [配置文档](./docs/配置文档.md) 91 | 92 | ## How to build 93 | 94 | **如果你要编译源码才看这节,否则直接 [下载](https://github.com/MaaXYZ/MAABH3/releases) 即可** 95 | 96 | 欢迎大佬们来带带~ 97 | 98 | 1. 下载 MaaFramework 的 [Release 包](https://github.com/MaaXYZ/MaaFramework/releases),解压到 `deps` 文件夹中 99 | 2. 配置 cmake 100 | 101 | - Windows 102 | 103 | ```bash 104 | cmake --preset "MSVC 2022" 105 | ``` 106 | 107 | - Linux / macOS 108 | 109 | ```bash 110 | cmake --preset "NinjaMulti" 111 | ``` 112 | 113 | 3. 使用 cmake 构建工程 114 | 115 | ```bash 116 | cmake --build build --config Release 117 | cmake --install build --prefix install 118 | ``` 119 | 120 | 生成的二进制及相关资源文件在 `install` 目录下 121 | 122 | ## 开发相关 123 | 124 | - `tools/CropRoi` 可以用来裁剪图片和获取 ROI 125 | - Pipeline 协议请参考 [MaaFramework 的文档](https://github.com/MaaXYZ/MaaFramework/blob/main/docs/zh_cn/3.1-%E4%BB%BB%E5%8A%A1%E6%B5%81%E6%B0%B4%E7%BA%BF%E5%8D%8F%E8%AE%AE.md) 126 | 127 | ## Join us 128 | 129 | QQ 群:566868495 130 | 131 | ## 其他 132 | 133 | - 芝士[MAA1999](https://github.com/MaaXYZ/MAA1999),基于MAA全新架构的 亿韭韭韭 小助手。 134 | 135 | ## Todo 136 | 137 | - [x] 启动 138 | - [x] 签到 139 | 140 | - [x] 家园 141 | - [x] 家园金币和体力 142 | - [x] 家园打工 143 | - [x] 家园远征 144 | 145 | - [x] 材料远征一键减负 146 | 147 | - [x] 舰团 148 | - [x] 委托回收 149 | - [x] 舰团贡献 150 | 151 | - [ ] 商店 152 | - [x] 后勤终端金币碎片 153 | - [x] 虚境商店1星石时序通行证 154 | - [ ] 吼姆秘宝 155 | 156 | - [ ] 万象虚境 157 | - [x] 第二层 158 | - [ ] 第五层 159 | 160 | - [ ] 奖励 161 | - [x] 每日奖励 162 | - [ ] 邮件 163 | 164 | - [ ] 杂项 165 | - [ ] 每周分享 166 | 167 | - [ ] 肉鸽(乐土) 168 | -------------------------------------------------------------------------------- /assets/resource/adb_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "prebuilt": { 3 | "minicap": { 4 | "arch": [ 5 | "x86", 6 | "armeabi-v7a", 7 | "armeabi" 8 | ], 9 | "sdk": [ 10 | 31, 11 | 29, 12 | 28, 13 | 27, 14 | 26, 15 | 25, 16 | 24, 17 | 23, 18 | 22, 19 | 21, 20 | 19, 21 | 18, 22 | 17, 23 | 16, 24 | 15, 25 | 14 26 | ] 27 | }, 28 | "minitouch": { 29 | "arch": [ 30 | "x86_64", 31 | "x86", 32 | "arm64-v8a", 33 | "armeabi-v7a", 34 | "armeabi" 35 | ] 36 | }, 37 | "maatouch": { 38 | "package": "com.shxyke.MaaTouch.App" 39 | } 40 | }, 41 | "command": { 42 | "Devices": [ 43 | "{ADB}", 44 | "devices" 45 | ], 46 | "Connect": [ 47 | "{ADB}", 48 | "connect", 49 | "{ADB_SERIAL}" 50 | ], 51 | "KillServer": [ 52 | "{ADB}", 53 | "kill-server" 54 | ], 55 | "UUID": [ 56 | "{ADB}", 57 | "-s", 58 | "{ADB_SERIAL}", 59 | "shell", 60 | "settings get secure android_id" 61 | ], 62 | "Resolution": [ 63 | "{ADB}", 64 | "-s", 65 | "{ADB_SERIAL}", 66 | "shell", 67 | "dumpsys window displays | grep -o -E cur=+[^\\ ]+ | grep -o -E [0-9]+" 68 | ], 69 | "StartApp": [ 70 | "{ADB}", 71 | "-s", 72 | "{ADB_SERIAL}", 73 | "shell", 74 | "am start -n {INTENT}" 75 | ], 76 | "StopApp": [ 77 | "{ADB}", 78 | "-s", 79 | "{ADB_SERIAL}", 80 | "shell", 81 | "am force-stop {INTENT}" 82 | ], 83 | "Click": [ 84 | "{ADB}", 85 | "-s", 86 | "{ADB_SERIAL}", 87 | "shell", 88 | "input tap {X} {Y}" 89 | ], 90 | "Swipe": [ 91 | "{ADB}", 92 | "-s", 93 | "{ADB_SERIAL}", 94 | "shell", 95 | "input swipe {X1} {Y1} {X2} {Y2} {DURATION}" 96 | ], 97 | "PressKey": [ 98 | "{ADB}", 99 | "-s", 100 | "{ADB_SERIAL}", 101 | "shell", 102 | "input keyevent {KEY}" 103 | ], 104 | "ForwardSocket": [ 105 | "{ADB}", 106 | "-s", 107 | "{ADB_SERIAL}", 108 | "forward", 109 | "tcp:{FOWARD_PORT}", 110 | "localabstract:{LOCAL_SOCKET}" 111 | ], 112 | "NetcatAddress": [ 113 | "{ADB}", 114 | "-s", 115 | "{ADB_SERIAL}", 116 | "shell", 117 | "cat /proc/net/arp | grep : " 118 | ], 119 | "ScreencapRawByNetcat": [ 120 | "{ADB}", 121 | "-s", 122 | "{ADB_SERIAL}", 123 | "exec-out", 124 | "screencap | nc -w 3 {NETCAT_ADDRESS} {NETCAT_PORT}" 125 | ], 126 | "ScreencapRawWithGzip": [ 127 | "{ADB}", 128 | "-s", 129 | "{ADB_SERIAL}", 130 | "exec-out", 131 | "screencap | gzip -1" 132 | ], 133 | "ScreencapEncode": [ 134 | "{ADB}", 135 | "-s", 136 | "{ADB_SERIAL}", 137 | "exec-out", 138 | "screencap -p" 139 | ], 140 | "ScreencapEncodeToFile": [ 141 | "{ADB}", 142 | "-s", 143 | "{ADB_SERIAL}", 144 | "shell", 145 | "screencap -p > \"/data/local/tmp/{TEMP_FILE}\"" 146 | ], 147 | "PullFile": [ 148 | "{ADB}", 149 | "-s", 150 | "{ADB_SERIAL}", 151 | "pull", 152 | "/data/local/tmp/{TEMP_FILE}", 153 | "{DST_PATH}" 154 | ], 155 | "Abilist": [ 156 | "{ADB}", 157 | "-s", 158 | "{ADB_SERIAL}", 159 | "shell", 160 | "getprop ro.product.cpu.abilist | tr -d '\n\r'" 161 | ], 162 | "SDK": [ 163 | "{ADB}", 164 | "-s", 165 | "{ADB_SERIAL}", 166 | "shell", 167 | "getprop ro.build.version.sdk | tr -d '\n\r'" 168 | ], 169 | "Orientation": [ 170 | "{ADB}", 171 | "-s", 172 | "{ADB_SERIAL}", 173 | "shell", 174 | "dumpsys input | grep SurfaceOrientation | grep -m 1 -o -E [0-9]" 175 | ], 176 | "PushBin": [ 177 | "{ADB}", 178 | "-s", 179 | "{ADB_SERIAL}", 180 | "push", 181 | "{BIN_PATH}", 182 | "/data/local/tmp/{BIN_WORKING_FILE}" 183 | ], 184 | "ChmodBin": [ 185 | "{ADB}", 186 | "-s", 187 | "{ADB_SERIAL}", 188 | "shell", 189 | "chmod 700 \"/data/local/tmp/{BIN_WORKING_FILE}\"" 190 | ], 191 | "InvokeBin": [ 192 | "{ADB}", 193 | "-s", 194 | "{ADB_SERIAL}", 195 | "exec-out", 196 | "export LD_LIBRARY_PATH=/data/local/tmp/; \"/data/local/tmp/{BIN_WORKING_FILE}\" {BIN_EXTRA_PARAMS}" 197 | ], 198 | "InvokeApp": [ 199 | "{ADB}", 200 | "-s", 201 | "{ADB_SERIAL}", 202 | "shell", 203 | "export CLASSPATH=\"/data/local/tmp/{APP_WORKING_FILE}\"; app_process /data/local/tmp {PACKAGE_NAME}" 204 | ] 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /assets/resource/image/Armada/ApplyForANewCommission.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Armada/ApplyForANewCommission.png -------------------------------------------------------------------------------- /assets/resource/image/Armada/ArmadaPageFlag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Armada/ArmadaPageFlag.png -------------------------------------------------------------------------------- /assets/resource/image/Armada/ClaimedContributionRewards.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Armada/ClaimedContributionRewards.png -------------------------------------------------------------------------------- /assets/resource/image/Armada/CommissionItem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Armada/CommissionItem.png -------------------------------------------------------------------------------- /assets/resource/image/Armada/CommissionItemBuy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Armada/CommissionItemBuy.png -------------------------------------------------------------------------------- /assets/resource/image/Armada/CommissionSubmitButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Armada/CommissionSubmitButton.png -------------------------------------------------------------------------------- /assets/resource/image/Armada/CommissionsPageFlag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Armada/CommissionsPageFlag.png -------------------------------------------------------------------------------- /assets/resource/image/Armada/CommissionsRewardsClaim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Armada/CommissionsRewardsClaim.png -------------------------------------------------------------------------------- /assets/resource/image/Armada/CommissionsRewardsLastDistribution.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Armada/CommissionsRewardsLastDistribution.png -------------------------------------------------------------------------------- /assets/resource/image/Armada/CommissionsRewardsPageFlag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Armada/CommissionsRewardsPageFlag.png -------------------------------------------------------------------------------- /assets/resource/image/Armada/ContributionsPageFlag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Armada/ContributionsPageFlag.png -------------------------------------------------------------------------------- /assets/resource/image/Armada/NotReachContributionProgress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Armada/NotReachContributionProgress.png -------------------------------------------------------------------------------- /assets/resource/image/Armada/ReachContributionProgress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Armada/ReachContributionProgress.png -------------------------------------------------------------------------------- /assets/resource/image/Armada/SubmitCommission.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Armada/SubmitCommission.png -------------------------------------------------------------------------------- /assets/resource/image/Awards/BPMissionsQuickClaim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Awards/BPMissionsQuickClaim.png -------------------------------------------------------------------------------- /assets/resource/image/Awards/DailyBPRewardsClaim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Awards/DailyBPRewardsClaim.png -------------------------------------------------------------------------------- /assets/resource/image/Awards/DailyBPRewardsClaimed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Awards/DailyBPRewardsClaimed.png -------------------------------------------------------------------------------- /assets/resource/image/Awards/DailyBPRewardsPreview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Awards/DailyBPRewardsPreview.png -------------------------------------------------------------------------------- /assets/resource/image/Awards/NoneDailyBPRewards.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Awards/NoneDailyBPRewards.png -------------------------------------------------------------------------------- /assets/resource/image/Combat/StopCombat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Combat/StopCombat.png -------------------------------------------------------------------------------- /assets/resource/image/Combat/UniversalMirage/UniversalMirageCostingTimeSwirlPasses.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Combat/UniversalMirage/UniversalMirageCostingTimeSwirlPasses.png -------------------------------------------------------------------------------- /assets/resource/image/Combat/UniversalMirage/UniversalMiragePageFlag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Combat/UniversalMirage/UniversalMiragePageFlag.png -------------------------------------------------------------------------------- /assets/resource/image/Combat/UniversalMirage/UniversalMirageStageFightAlone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Combat/UniversalMirage/UniversalMirageStageFightAlone.png -------------------------------------------------------------------------------- /assets/resource/image/Combat/UniversalMirage/UniversalMirageStageFlag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Combat/UniversalMirage/UniversalMirageStageFlag.png -------------------------------------------------------------------------------- /assets/resource/image/Combat/UniversalMirage/UniversalMirageStageNoneValkyrja.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Combat/UniversalMirage/UniversalMirageStageNoneValkyrja.png -------------------------------------------------------------------------------- /assets/resource/image/Combat/UniversalMirage/UniversalMirageStagePrepare.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Combat/UniversalMirage/UniversalMirageStagePrepare.png -------------------------------------------------------------------------------- /assets/resource/image/Combat/UniversalMirage/UniversalMirageStageStart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Combat/UniversalMirage/UniversalMirageStageStart.png -------------------------------------------------------------------------------- /assets/resource/image/Dorm/Close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Dorm/Close.png -------------------------------------------------------------------------------- /assets/resource/image/Dorm/CloseCollectAP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Dorm/CloseCollectAP.png -------------------------------------------------------------------------------- /assets/resource/image/Dorm/CollectAP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Dorm/CollectAP.png -------------------------------------------------------------------------------- /assets/resource/image/Dorm/CollectAPButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Dorm/CollectAPButton.png -------------------------------------------------------------------------------- /assets/resource/image/Dorm/CollectGold.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Dorm/CollectGold.png -------------------------------------------------------------------------------- /assets/resource/image/Dorm/CollectGoldMax.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Dorm/CollectGoldMax.png -------------------------------------------------------------------------------- /assets/resource/image/Dorm/Collection_available.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Dorm/Collection_available.png -------------------------------------------------------------------------------- /assets/resource/image/Dorm/Collection_forbidden.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Dorm/Collection_forbidden.png -------------------------------------------------------------------------------- /assets/resource/image/Dorm/Confirm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Dorm/Confirm.png -------------------------------------------------------------------------------- /assets/resource/image/Dorm/Confirm_errands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Dorm/Confirm_errands.png -------------------------------------------------------------------------------- /assets/resource/image/Dorm/ErrandsPageFlag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Dorm/ErrandsPageFlag.png -------------------------------------------------------------------------------- /assets/resource/image/Dorm/ErrandsRefresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Dorm/ErrandsRefresh.png -------------------------------------------------------------------------------- /assets/resource/image/Dorm/ErrandsUnfold.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Dorm/ErrandsUnfold.png -------------------------------------------------------------------------------- /assets/resource/image/Dorm/NextErrands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Dorm/NextErrands.png -------------------------------------------------------------------------------- /assets/resource/image/Dorm/QuickDispatch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Dorm/QuickDispatch.png -------------------------------------------------------------------------------- /assets/resource/image/Dorm/StartErrands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Dorm/StartErrands.png -------------------------------------------------------------------------------- /assets/resource/image/Dorm/StartExpeditions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Dorm/StartExpeditions.png -------------------------------------------------------------------------------- /assets/resource/image/Dorm/SwitchToFragmentPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Dorm/SwitchToFragmentPage.png -------------------------------------------------------------------------------- /assets/resource/image/Dorm/SwitchToMaterialPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Dorm/SwitchToMaterialPage.png -------------------------------------------------------------------------------- /assets/resource/image/Dorm/available.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Dorm/available.png -------------------------------------------------------------------------------- /assets/resource/image/Dorm/forbidden.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Dorm/forbidden.png -------------------------------------------------------------------------------- /assets/resource/image/MaterialEvent/LITE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/MaterialEvent/LITE.png -------------------------------------------------------------------------------- /assets/resource/image/MaterialEvent/MaterialEventFlag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/MaterialEvent/MaterialEventFlag.png -------------------------------------------------------------------------------- /assets/resource/image/MaterialEvent/QuickLITE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/MaterialEvent/QuickLITE.png -------------------------------------------------------------------------------- /assets/resource/image/Navigation/Armada/EnterArmadaContribution.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Navigation/Armada/EnterArmadaContribution.png -------------------------------------------------------------------------------- /assets/resource/image/Navigation/Armada/EnterCommissionsPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Navigation/Armada/EnterCommissionsPage.png -------------------------------------------------------------------------------- /assets/resource/image/Navigation/Attack/EnterAttackEventPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Navigation/Attack/EnterAttackEventPage.png -------------------------------------------------------------------------------- /assets/resource/image/Navigation/Attack/EnterChallengeEventPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Navigation/Attack/EnterChallengeEventPage.png -------------------------------------------------------------------------------- /assets/resource/image/Navigation/AttackEvent/EnterMaterialExpeditionPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Navigation/AttackEvent/EnterMaterialExpeditionPage.png -------------------------------------------------------------------------------- /assets/resource/image/Navigation/ChallengeEvent/EnterUniversalMiragePage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Navigation/ChallengeEvent/EnterUniversalMiragePage.png -------------------------------------------------------------------------------- /assets/resource/image/Navigation/Commissions/EnterCommissionsRewardsPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Navigation/Commissions/EnterCommissionsRewardsPage.png -------------------------------------------------------------------------------- /assets/resource/image/Navigation/Dorm/EnterErrandsPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Navigation/Dorm/EnterErrandsPage.png -------------------------------------------------------------------------------- /assets/resource/image/Navigation/Dorm/EnterExpeditionsPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Navigation/Dorm/EnterExpeditionsPage.png -------------------------------------------------------------------------------- /assets/resource/image/Navigation/MaterialExpedition/EnterMaterialEventPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Navigation/MaterialExpedition/EnterMaterialEventPage.png -------------------------------------------------------------------------------- /assets/resource/image/Navigation/Missions/EnterBPMissionsPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Navigation/Missions/EnterBPMissionsPage.png -------------------------------------------------------------------------------- /assets/resource/image/Navigation/Shop/EnterActivityShopPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Navigation/Shop/EnterActivityShopPage.png -------------------------------------------------------------------------------- /assets/resource/image/Navigation/Shop/EnterMirageStorePage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Navigation/Shop/EnterMirageStorePage.png -------------------------------------------------------------------------------- /assets/resource/image/Navigation/Supply/EnterShopPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Navigation/Supply/EnterShopPage.png -------------------------------------------------------------------------------- /assets/resource/image/Navigation/UniversalMirage/EnterBladeGravePage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Navigation/UniversalMirage/EnterBladeGravePage.png -------------------------------------------------------------------------------- /assets/resource/image/Navigation/UniversalMirage/EnterGlacialFencesPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Navigation/UniversalMirage/EnterGlacialFencesPage.png -------------------------------------------------------------------------------- /assets/resource/image/Navigation/UniversalMirage/EnterIlluminatedLandPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Navigation/UniversalMirage/EnterIlluminatedLandPage.png -------------------------------------------------------------------------------- /assets/resource/image/Navigation/UniversalMirage/EnterRoaringPalacePage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Navigation/UniversalMirage/EnterRoaringPalacePage.png -------------------------------------------------------------------------------- /assets/resource/image/Shop/DailyShopPageFlag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Shop/DailyShopPageFlag.png -------------------------------------------------------------------------------- /assets/resource/image/Shop/LogisticsTerminalBuyCharacterFragmentByGoldFlag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Shop/LogisticsTerminalBuyCharacterFragmentByGoldFlag.png -------------------------------------------------------------------------------- /assets/resource/image/Shop/LogisticsTerminalCharacterFragmentFlag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Shop/LogisticsTerminalCharacterFragmentFlag.png -------------------------------------------------------------------------------- /assets/resource/image/Shop/LogisticsTerminalPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Shop/LogisticsTerminalPage.png -------------------------------------------------------------------------------- /assets/resource/image/Shop/MirageStore1AsteriteFlag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Shop/MirageStore1AsteriteFlag.png -------------------------------------------------------------------------------- /assets/resource/image/Shop/SoldOut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Shop/SoldOut.png -------------------------------------------------------------------------------- /assets/resource/image/StartUp/AbyssSettlement.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/StartUp/AbyssSettlement.png -------------------------------------------------------------------------------- /assets/resource/image/StartUp/AiPromptFlag_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/StartUp/AiPromptFlag_0.png -------------------------------------------------------------------------------- /assets/resource/image/StartUp/AiPromptFlag_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/StartUp/AiPromptFlag_1.png -------------------------------------------------------------------------------- /assets/resource/image/StartUp/CloseAnnouncement.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/StartUp/CloseAnnouncement.png -------------------------------------------------------------------------------- /assets/resource/image/StartUp/CloseVersionAnnouncement.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/StartUp/CloseVersionAnnouncement.png -------------------------------------------------------------------------------- /assets/resource/image/StartUp/CollectDailyLoginReward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/StartUp/CollectDailyLoginReward.png -------------------------------------------------------------------------------- /assets/resource/image/StartUp/Confirm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/StartUp/Confirm.png -------------------------------------------------------------------------------- /assets/resource/image/StartUp/Download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/StartUp/Download.png -------------------------------------------------------------------------------- /assets/resource/image/StartUp/GameIdentifying.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/StartUp/GameIdentifying.png -------------------------------------------------------------------------------- /assets/resource/image/StartUp/GameLoading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/StartUp/GameLoading.png -------------------------------------------------------------------------------- /assets/resource/image/StartUp/HomeFlag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/StartUp/HomeFlag.png -------------------------------------------------------------------------------- /assets/resource/image/StartUp/MiHoYoLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/StartUp/MiHoYoLogo.png -------------------------------------------------------------------------------- /assets/resource/image/StartUp/ObtainedAward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/StartUp/ObtainedAward.png -------------------------------------------------------------------------------- /assets/resource/image/StartUp/SuperstringDimensionSettlement.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/StartUp/SuperstringDimensionSettlement.png -------------------------------------------------------------------------------- /assets/resource/image/Utils/BackButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Utils/BackButton.png -------------------------------------------------------------------------------- /assets/resource/image/Utils/BackButton_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Utils/BackButton_1.png -------------------------------------------------------------------------------- /assets/resource/image/Utils/CancelButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Utils/CancelButton.png -------------------------------------------------------------------------------- /assets/resource/image/Utils/CloseDialogBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Utils/CloseDialogBox.png -------------------------------------------------------------------------------- /assets/resource/image/Utils/HomeButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Utils/HomeButton.png -------------------------------------------------------------------------------- /assets/resource/image/Utils/HomeButton_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/image/Utils/HomeButton_1.png -------------------------------------------------------------------------------- /assets/resource/model/ocr/README.md: -------------------------------------------------------------------------------- 1 | # PaddleOCR model 2 | 3 | 2023/09/29 4 | 5 | from 6 | 7 | ## det model 8 | 9 | ch_PP-OCRv4_det 10 | 【最新】原始超轻量模型,支持中英文、多语种文本检测 11 | 12 | 13 | 14 | ## rec model 15 | 16 | ch_PP-OCRv4_rec 17 | 【最新】超轻量模型,支持中英文、数字识别 18 | 19 | 20 | 21 | ## rec label 22 | 23 | 24 | -------------------------------------------------------------------------------- /assets/resource/model/ocr/det.onnx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/model/ocr/det.onnx -------------------------------------------------------------------------------- /assets/resource/model/ocr/rec.onnx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/assets/resource/model/ocr/rec.onnx -------------------------------------------------------------------------------- /assets/resource/pipeline/armada/armada.json: -------------------------------------------------------------------------------- 1 | { 2 | "Armada": { 3 | "next": [ 4 | "ArmadaPageFlag", 5 | "Sub_AiPromptFlag", 6 | "Sub_CancelDownload", 7 | "Sub_EnterArmadaPage", 8 | "Sub_StartUp" 9 | ] 10 | }, 11 | "ArmadaPageFlag": { 12 | "recognition": "TemplateMatch", 13 | "template": "Armada/ArmadaPageFlag.png", 14 | "roi": [ 15 | 0, 16 | 599, 17 | 168, 18 | 121 19 | ], 20 | "next": [ 21 | "Commissions", 22 | "Contributions", 23 | "Stop" 24 | ] 25 | } 26 | } -------------------------------------------------------------------------------- /assets/resource/pipeline/armada/commissions.json: -------------------------------------------------------------------------------- 1 | { 2 | "Commissions": { 3 | "next": [ 4 | "CommissionsPageFlag", 5 | "Sub_EnterCommissionsPage", 6 | "Sub_EnterArmadaPage", 7 | "Sub_BackButton" 8 | ] 9 | }, 10 | "CommissionsPageFlag": { 11 | "recognition": "TemplateMatch", 12 | "template": "Armada/CommissionsPageFlag.png", 13 | "roi": [ 14 | 0, 15 | 62, 16 | 129, 17 | 127 18 | ], 19 | "next": [ 20 | "ApplyForANewCommission", 21 | "AcceptNewCommission", 22 | "CommissionItem", 23 | "CommissionItemBuy", 24 | "CommissionSubmitButton", 25 | "CommissionNoneSubmitButton" 26 | ] 27 | }, 28 | "ApplyForANewCommission": { 29 | "recognition": "TemplateMatch", 30 | "template": "Armada/ApplyForANewCommission.png", 31 | "threshold": 0.9, 32 | "roi": [ 33 | 37, 34 | 577, 35 | 239, 36 | 141 37 | ], 38 | "action": "Click", 39 | "next": [ 40 | "ApplyForANewCommission", 41 | "AcceptNewCommission", 42 | "CommissionItem", 43 | "CommissionItemBuy", 44 | "CommissionSubmitButton" 45 | ] 46 | }, 47 | "AcceptNewCommission": { 48 | "recognition": "OCR", 49 | "expected": [ 50 | "接受" 51 | ], 52 | "roi": [ 53 | 1018, 54 | 154, 55 | 211, 56 | 560 57 | ], 58 | "action": "Click", 59 | "next": [ 60 | "AcceptNewCommission", 61 | "CommissionItem", 62 | "CommissionItemBuy", 63 | "CommissionSubmitButton" 64 | ] 65 | }, 66 | "CommissionItem": { 67 | "recognition": "TemplateMatch", 68 | "green_mask": true, 69 | "template": "Armada/CommissionItem.png", 70 | "roi": [ 71 | 7, 72 | 112, 73 | 248, 74 | 248 75 | ], 76 | "action": "Click", 77 | "post_wait_freezes": 200, 78 | "next": [ 79 | "CommissionItemBuy", 80 | "CommissionSubmitButton", 81 | "CommissionItem" 82 | ] 83 | }, 84 | "CommissionItemBuy": { 85 | "recognition": "TemplateMatch", 86 | "template": "Armada/CommissionItemBuy.png", 87 | "roi": [ 88 | 872, 89 | 494, 90 | 167, 91 | 145 92 | ], 93 | "action": "Click", 94 | "post_wait_freezes": 200, 95 | "next": [ 96 | "CommissionSubmitButton", 97 | "SubmitCommission" 98 | ] 99 | }, 100 | "CommissionSubmitButton": { 101 | "recognition": "TemplateMatch", 102 | "template": "Armada/CommissionSubmitButton.png", 103 | "threshold": 0.94, 104 | "roi": [ 105 | 860, 106 | 579, 107 | 171, 108 | 141 109 | ], 110 | "action": "Click", 111 | "next": [ 112 | "CommissionSubmitButton", 113 | "SubmitCommission" 114 | ] 115 | }, 116 | "CommissionNoneSubmitButton": { 117 | "inverse": true, 118 | "recognition": "TemplateMatch", 119 | "template": "Armada/CommissionSubmitButton.png", 120 | "threshold": 0.94, 121 | "roi": [ 122 | 860, 123 | 579, 124 | 171, 125 | 141 126 | ], 127 | "next": [ 128 | "CommissionsRewardsPageFlag", 129 | "Sub_EnterCommissionsRewardsPage" 130 | ] 131 | }, 132 | "CommossionLimit": { 133 | "recognition": "OCR", 134 | "expected": [ 135 | "回收委托次数已经耗尽" 136 | ], 137 | "roi": [ 138 | 361, 139 | 287, 140 | 539, 141 | 142 142 | ], 143 | "action": "Click", 144 | "post_wait_freezes": 200, 145 | "next": [ 146 | "CommissionsRewardsPageFlag", 147 | "Sub_EnterCommissionsRewardsPage" 148 | ] 149 | }, 150 | "SubmitCommission": { 151 | "recognition": "TemplateMatch", 152 | "template": "Armada/SubmitCommission.png", 153 | "roi": [ 154 | 696, 155 | 492, 156 | 230, 157 | 141 158 | ], 159 | "action": "Click", 160 | "next": [ 161 | "CommossionLimit", 162 | "SubmitCommission", 163 | "Sub_CloseDialogBox", 164 | "CommissionItem", 165 | "CommissionItemBuy", 166 | "CommissionSubmitButton", 167 | "CommissionNoneSubmitButton" 168 | ] 169 | }, 170 | "CommissionsRewardsPageFlag": { 171 | "recognition": "TemplateMatch", 172 | "template": "Armada/CommissionsRewardsPageFlag.png", 173 | "roi": [ 174 | 0, 175 | 60, 176 | 131, 177 | 131 178 | ], 179 | "next": [ 180 | "CommissionsRewardsClaim", 181 | "Sub_CloseDialogBox", 182 | "CommissionsRewardsLastDistribution" 183 | ] 184 | }, 185 | "CommissionsRewardsClaim": { 186 | "recognition": "TemplateMatch", 187 | "template": "Armada/CommissionsRewardsClaim.png", 188 | "roi": [ 189 | 828, 190 | 580, 191 | 168, 192 | 137 193 | ], 194 | "action": "Click", 195 | "post_wait_freezes": 200, 196 | "next": [ 197 | "Sub_CloseDialogBox", 198 | "CommissionsRewardsLastDistribution" 199 | ] 200 | }, 201 | "CommissionsRewardsLastDistribution": { 202 | "recognition": "TemplateMatch", 203 | "template": "Armada/CommissionsRewardsLastDistribution.png", 204 | "roi": [ 205 | 778, 206 | 579, 207 | 268, 208 | 137 209 | ], 210 | "next": [ 211 | "BackToArmadaPage" 212 | ] 213 | }, 214 | "BackToArmadaPage": { 215 | "recognition": "TemplateMatch", 216 | "template": "Utils/BackButton.png", 217 | "roi": [ 218 | 0, 219 | 0, 220 | 180, 221 | 133 222 | ], 223 | "action": "Click", 224 | "post_wait_freezes": { 225 | "time": 200, 226 | "target": [ 227 | 0, 228 | 600, 229 | 300, 230 | 110 231 | ] 232 | }, 233 | "next": [ 234 | "Contributions", 235 | "Stop" 236 | ] 237 | } 238 | } -------------------------------------------------------------------------------- /assets/resource/pipeline/awards.json: -------------------------------------------------------------------------------- 1 | { 2 | "Awards": { 3 | "next": [ 4 | "MissionsPageFlag", 5 | "Sub_AiPromptFlag", 6 | "Sub_CancelDownload", 7 | "Sub_EnterMissionsPage", 8 | "Sub_StartUp" 9 | ] 10 | }, 11 | "MissionsPageFlag": { 12 | "recognition": "OCR", 13 | "expected": "作战任务", 14 | "roi": [ 15 | 0, 16 | 60, 17 | 210, 18 | 575 19 | ], 20 | "post_wait_freezes": 200, 21 | "next": [ 22 | "Sub_EnterBPMissionsPage", 23 | "BPMissionsQuickClaim", 24 | "NoneDailyBPRewards", 25 | "DailyBPRewards_100", 26 | "DailyBPRewards_200", 27 | "DailyBPRewards_300", 28 | "DailyBPRewards_450", 29 | "DailyBPRewards_600" 30 | ] 31 | }, 32 | "BPMissionsQuickClaim": { 33 | "recognition": "TemplateMatch", 34 | "template": "Awards/BPMissionsQuickClaim.png", 35 | "threshold": 0.85, 36 | "roi": [ 37 | 1055, 38 | 53, 39 | 225, 40 | 135 41 | ], 42 | "action": "Click", 43 | "next": [ 44 | "Sub_CloseDialogBox", 45 | "BPMissionsQuickClaim", 46 | "NoneDailyBPRewards", 47 | "DailyBPRewards_100", 48 | "DailyBPRewards_200", 49 | "DailyBPRewards_300", 50 | "DailyBPRewards_450", 51 | "DailyBPRewards_600" 52 | ] 53 | }, 54 | "DailyBPRewards_100": { 55 | "recognition": "TemplateMatch", 56 | "template": "Awards/DailyBPRewardsClaimed.png", 57 | "inverse": true, 58 | "roi": [ 59 | 485, 60 | 637, 61 | 52, 62 | 67 63 | ], 64 | "action": "Click", 65 | "target": [ 66 | 485, 67 | 637, 68 | 52, 69 | 67 70 | ], 71 | "next": [ 72 | "DailyBPRewardsClaim_100", 73 | "DailyBPRewardsPreview", 74 | "Sub_CloseDialogBox", 75 | "Sub_BackButton", 76 | "HomeFlag" 77 | ] 78 | }, 79 | "DailyBPRewardsClaim_100": { 80 | "recognition": "TemplateMatch", 81 | "template": "Awards/DailyBPRewardsClaim.png", 82 | "roi": [ 83 | 485, 84 | 637, 85 | 52, 86 | 67 87 | ], 88 | "next": [ 89 | "DailyBPRewardsPreview", 90 | "DailyBPRewards_100", 91 | "Sub_CloseDialogBox", 92 | "Sub_BackButton", 93 | "HomeFlag" 94 | ] 95 | }, 96 | "DailyBPRewards_200": { 97 | "recognition": "TemplateMatch", 98 | "template": "Awards/DailyBPRewardsClaimed.png", 99 | "inverse": true, 100 | "roi": [ 101 | 660, 102 | 636, 103 | 57, 104 | 69 105 | ], 106 | "action": "Click", 107 | "target": [ 108 | 660, 109 | 636, 110 | 57, 111 | 69 112 | ], 113 | "next": [ 114 | "DailyBPRewardsClaim_200", 115 | "DailyBPRewardsPreview", 116 | "Sub_CloseDialogBox", 117 | "Sub_BackButton", 118 | "HomeFlag" 119 | ] 120 | }, 121 | "DailyBPRewardsClaim_200": { 122 | "recognition": "TemplateMatch", 123 | "template": "Awards/DailyBPRewardsClaim.png", 124 | "roi": [ 125 | 660, 126 | 636, 127 | 57, 128 | 69 129 | ], 130 | "next": [ 131 | "DailyBPRewardsPreview", 132 | "DailyBPRewards_200", 133 | "Sub_CloseDialogBox", 134 | "Sub_BackButton", 135 | "HomeFlag" 136 | ] 137 | }, 138 | "DailyBPRewards_300": { 139 | "recognition": "TemplateMatch", 140 | "template": "Awards/DailyBPRewardsClaimed.png", 141 | "inverse": true, 142 | "roi": [ 143 | 837, 144 | 637, 145 | 54, 146 | 69 147 | ], 148 | "action": "Click", 149 | "target": [ 150 | 837, 151 | 637, 152 | 54, 153 | 69 154 | ], 155 | "next": [ 156 | "DailyBPRewardsClaim_300", 157 | "DailyBPRewardsPreview", 158 | "Sub_CloseDialogBox", 159 | "Sub_BackButton", 160 | "HomeFlag" 161 | ] 162 | }, 163 | "DailyBPRewardsClaim_300": { 164 | "recognition": "TemplateMatch", 165 | "template": "Awards/DailyBPRewardsClaim.png", 166 | "roi": [ 167 | 837, 168 | 637, 169 | 54, 170 | 69 171 | ], 172 | "next": [ 173 | "DailyBPRewardsPreview", 174 | "DailyBPRewards_300", 175 | "Sub_CloseDialogBox", 176 | "Sub_BackButton", 177 | "HomeFlag" 178 | ] 179 | }, 180 | "DailyBPRewards_450": { 181 | "recognition": "TemplateMatch", 182 | "template": "Awards/DailyBPRewardsClaimed.png", 183 | "inverse": true, 184 | "roi": [ 185 | 1013, 186 | 636, 187 | 53, 188 | 67 189 | ], 190 | "action": "Click", 191 | "target": [ 192 | 1013, 193 | 636, 194 | 53, 195 | 67 196 | ], 197 | "next": [ 198 | "DailyBPRewardsClaim_450", 199 | "DailyBPRewardsPreview", 200 | "Sub_CloseDialogBox", 201 | "Sub_BackButton", 202 | "HomeFlag" 203 | ] 204 | }, 205 | "DailyBPRewardsClaim_450": { 206 | "recognition": "TemplateMatch", 207 | "template": "Awards/DailyBPRewardsClaim.png", 208 | "roi": [ 209 | 1013, 210 | 636, 211 | 53, 212 | 67 213 | ], 214 | "next": [ 215 | "DailyBPRewardsPreview", 216 | "DailyBPRewards_450", 217 | "Sub_CloseDialogBox", 218 | "Sub_BackButton", 219 | "HomeFlag" 220 | ] 221 | }, 222 | "DailyBPRewards_600": { 223 | "recognition": "TemplateMatch", 224 | "template": "Awards/DailyBPRewardsClaimed.png", 225 | "inverse": true, 226 | "roi": [ 227 | 1187, 228 | 636, 229 | 55, 230 | 66 231 | ], 232 | "action": "Click", 233 | "target": [ 234 | 1187, 235 | 636, 236 | 55, 237 | 66 238 | ], 239 | "next": [ 240 | "DailyBPRewardsClaim_600", 241 | "DailyBPRewardsPreview", 242 | "Sub_CloseDialogBox", 243 | "Sub_BackButton", 244 | "HomeFlag" 245 | ] 246 | }, 247 | "DailyBPRewardsClaim_600": { 248 | "recognition": "TemplateMatch", 249 | "template": "Awards/DailyBPRewardsClaim.png", 250 | "roi": [ 251 | 1187, 252 | 636, 253 | 55, 254 | 66 255 | ], 256 | "next": [ 257 | "DailyBPRewardsPreview", 258 | "DailyBPRewards_600", 259 | "Sub_CloseDialogBox", 260 | "Sub_BackButton", 261 | "HomeFlag" 262 | ] 263 | }, 264 | "DailyBPRewardsPreview": { 265 | "recognition": "TemplateMatch", 266 | "template": "Awards/DailyBPRewardsPreview.png", 267 | "roi": [ 268 | 442, 269 | 94, 270 | 398, 271 | 143 272 | ], 273 | "next": [ 274 | "Sub_CloseDialogBox", 275 | "Sub_BackButton", 276 | "HomeFlag" 277 | ] 278 | }, 279 | "NoneDailyBPRewards": { 280 | "recognition": "TemplateMatch", 281 | "template": "Awards/NoneDailyBPRewards.png", 282 | "roi": [ 283 | 439, 284 | 597, 285 | 585, 286 | 123 287 | ], 288 | "next": [ 289 | "Sub_BackButton", 290 | "HomeFlag" 291 | ] 292 | } 293 | } -------------------------------------------------------------------------------- /assets/resource/pipeline/close_bh3.json: -------------------------------------------------------------------------------- 1 | { 2 | "CloseBH3": { 3 | "action": "StopApp" 4 | } 5 | } -------------------------------------------------------------------------------- /assets/resource/pipeline/combat/combat.json: -------------------------------------------------------------------------------- 1 | { 2 | "Combating": {} 3 | } -------------------------------------------------------------------------------- /assets/resource/pipeline/dorm/dorm.json: -------------------------------------------------------------------------------- 1 | { 2 | "Dorm": { 3 | "next": [ 4 | "Sub_ConfirmDormUpdate", 5 | "DormPageFlag", 6 | "Sub_AiPromptFlag", 7 | "Sub_CancelDownload", 8 | "Sub_EnterDormPage", 9 | "Sub_StartUp" 10 | ] 11 | }, 12 | "DormPageFlag": { 13 | "recognition": "OCR", 14 | "expected": "家园小队", 15 | "roi": [ 16 | 28, 17 | 589, 18 | 208, 19 | 131 20 | ], 21 | "next": [ 22 | "Sub_ConfirmDormUpdate", 23 | "CollectGold", 24 | "CollectAP", 25 | "Errands", 26 | "Expeditions", 27 | "Stop" 28 | ] 29 | }, 30 | "CollectGold": { 31 | "recognition": "TemplateMatch", 32 | "template": [ 33 | "Dorm/CollectGold.png", 34 | "Dorm/CollectGoldMax.png" 35 | ], 36 | "roi": [ 37 | 286, 38 | 69, 39 | 141, 40 | 146 41 | ], 42 | "action": "Click", 43 | "next": [ 44 | "CollectGold", 45 | "CollectAP", 46 | "Errands", 47 | "Expeditions", 48 | "Stop" 49 | ] 50 | }, 51 | "CollectAP": { 52 | "recognition": "TemplateMatch", 53 | "template": "Dorm/CollectAP.png", 54 | "roi": [ 55 | 124, 56 | 68, 57 | 146, 58 | 155 59 | ], 60 | "action": "Click", 61 | "next": [ 62 | "CollectAP", 63 | "CollectAPButton" 64 | ] 65 | }, 66 | "CollectAPButton": { 67 | "recognition": "TemplateMatch", 68 | "template": "Dorm/CollectAPButton.png", 69 | "roi": [ 70 | 650, 71 | 496, 72 | 215, 73 | 130 74 | ], 75 | "action": "Click", 76 | "next": [ 77 | "APMax", 78 | "CollectAPButton", 79 | "Errands", 80 | "Expeditions", 81 | "Stop" 82 | ] 83 | }, 84 | "APMax": { 85 | "recognition": "OCR", 86 | "expected": "已经达到体力上限", 87 | "roi": [ 88 | 461, 89 | 289, 90 | 359, 91 | 138 92 | ], 93 | "next": [ 94 | "CloseCollectAP" 95 | ] 96 | }, 97 | "CloseCollectAP": { 98 | "recognition": "TemplateMatch", 99 | "template": "Dorm/CloseCollectAP.png", 100 | "roi": [ 101 | 1017, 102 | 58, 103 | 137, 104 | 138 105 | ], 106 | "action": "Click", 107 | "next": [ 108 | "CloseCollectAP", 109 | "Errands", 110 | "Expeditions", 111 | "Stop" 112 | ] 113 | }, 114 | "Sub_ConfirmDormUpdate": { 115 | "is_sub": true, 116 | "recognition": "TemplateMatch", 117 | "template": "StartUp/Confirm.png", 118 | "roi": [ 119 | 554, 120 | 518, 121 | 173, 122 | 136 123 | ], 124 | "action": "Click" 125 | } 126 | } -------------------------------------------------------------------------------- /assets/resource/pipeline/dorm/errands.json: -------------------------------------------------------------------------------- 1 | { 2 | "Errands": { 3 | "next": [ 4 | "ErrandsPageFlag", 5 | "Sub_EnterErrandsPage", 6 | "Sub_EnterDormPage", 7 | "Sub_BackButton" 8 | ] 9 | }, 10 | "ErrandsPageFlag": { 11 | "recognition": "TemplateMatch", 12 | "template": "Dorm/ErrandsPageFlag.png", 13 | "roi": [ 14 | 0, 15 | 17, 16 | 278, 17 | 250 18 | ], 19 | "next": [ 20 | "ErrandsUnfold", 21 | "Rewards_claim1", 22 | "Rewards_claim2" 23 | ] 24 | }, 25 | "ErrandsUnfold": { 26 | "recognition": "OCR", 27 | "expected": [ 28 | "一键打工" 29 | ], 30 | "roi": [ 31 | 878, 32 | 612, 33 | 247, 34 | 108 35 | ], 36 | "action": "Click", 37 | "next": [ 38 | "ErrandsUnfold", 39 | "One_click1" 40 | ] 41 | }, 42 | "One_click1": { 43 | "recognition": "TemplateMatch", 44 | "template": "Dorm/available.png", 45 | "roi": [ 46 | 611, 47 | 545, 48 | 417, 49 | 153 50 | ], 51 | "action": "Click", 52 | "next": [ 53 | "Rewards_claim", 54 | "One_click2", 55 | "One_click1" 56 | ] 57 | }, 58 | "One_click2": { 59 | "recognition": "TemplateMatch", 60 | "template": "Dorm/forbidden.png", 61 | "roi": [ 62 | 609, 63 | 547, 64 | 417, 65 | 145 66 | ], 67 | "next": [ 68 | "Close", 69 | "One_click2", 70 | "One_click1", 71 | "Close" 72 | ] 73 | }, 74 | "Close": { 75 | "recognition": "TemplateMatch", 76 | "template": "Dorm/Close.png", 77 | "roi": [ 78 | 1059, 79 | 3, 80 | 137, 81 | 133 82 | ], 83 | "action": "Click", 84 | "next": [ 85 | "Close", 86 | "Rewards_claim1", 87 | "Rewards_claim2" 88 | ] 89 | }, 90 | "Rewards_claim1": { 91 | "recognition": "TemplateMatch", 92 | "template": "Dorm/Collection_available.png", 93 | "roi": [ 94 | 1051, 95 | 610, 96 | 229, 97 | 110 98 | ], 99 | "action": "Click", 100 | "next": [ 101 | "Rewards_claim1", 102 | "ErrandsCompleted", 103 | "Rewards_claim2" 104 | ] 105 | }, 106 | "Rewards_claim2": { 107 | "recognition": "TemplateMatch", 108 | "template": "Dorm/Collection_forbidden.png", 109 | "roi": [ 110 | 1053, 111 | 611, 112 | 227, 113 | 109 114 | ], 115 | "next": [ 116 | "Expeditions", 117 | "Rewards_claim1", 118 | "Rewards_claim2", 119 | "Stop" 120 | ] 121 | }, 122 | "ErrandsCompleted": { 123 | "recognition": "TemplateMatch", 124 | "template": "Dorm/Confirm_errands.png", 125 | "roi": [ 126 | 447, 127 | 470, 128 | 384, 129 | 150 130 | ], 131 | "action": "Click", 132 | "next": [ 133 | "ErrandsCompleted", 134 | "Expeditions", 135 | "Stop" 136 | ] 137 | } 138 | } -------------------------------------------------------------------------------- /assets/resource/pipeline/material_event.json: -------------------------------------------------------------------------------- 1 | { 2 | "MaterialEvent": { 3 | "next": [ 4 | "MaterialEventFlag", 5 | "Sub_AiPromptFlag", 6 | "Sub_CancelDownload", 7 | "Sub_EnterMaterialExpeditionPage", 8 | "Sub_EnterAttackEventPage", 9 | "Sub_EnterAttackPage", 10 | "Sub_BackButton", 11 | "Sub_StartUp" 12 | ] 13 | }, 14 | "MaterialEventFlag": { 15 | "recognition": "TemplateMatch", 16 | "template": "MaterialEvent/MaterialEventFlag.png", 17 | "roi": [ 18 | 525, 19 | 40, 20 | 229, 21 | 141 22 | ], 23 | "next": [ 24 | "QuickLITE", 25 | "Sub_EnterMaterialEventPage", 26 | "NoneQuickLITE" 27 | ] 28 | }, 29 | "QuickLITE": { 30 | "recognition": "TemplateMatch", 31 | "template": "MaterialEvent/QuickLITE.png", 32 | "roi": [ 33 | 1037, 34 | 598, 35 | 243, 36 | 122 37 | ], 38 | "action": "Click", 39 | "post_wait_freezes": 200, 40 | "next": [ 41 | "LITE", 42 | "MaterialEventNoneLevelsToLITE", 43 | "QuickLITE" 44 | ] 45 | }, 46 | "NoneQuickLITE": { 47 | "recognition": "TemplateMatch", 48 | "template": "MaterialEvent/QuickLITE.png", 49 | "roi": [ 50 | 1037, 51 | 598, 52 | 243, 53 | 122 54 | ], 55 | "inverse": true, 56 | "next": [ 57 | "Sub_HomeButton", 58 | "HomeFlag" 59 | ] 60 | }, 61 | "LITE": { 62 | "recognition": "TemplateMatch", 63 | "template": "MaterialEvent/LITE.png", 64 | "roi": [ 65 | 558, 66 | 462, 67 | 162, 68 | 135 69 | ], 70 | "action": "Click", 71 | "next": [ 72 | "LITE", 73 | "MaterialEventNotEnoughAP", 74 | "Sub_CloseDialogBox", 75 | "Sub_HomeButton", 76 | "HomeFlag" 77 | ] 78 | }, 79 | "MaterialEventNotEnoughAP": { 80 | "recognition": "OCR", 81 | "expected": [ 82 | "没有足够体力" 83 | ], 84 | "roi": [ 85 | 488, 86 | 285, 87 | 302, 88 | 145 89 | ], 90 | "action": "Click", 91 | "post_wait_freezes": 200, 92 | "next": [ 93 | "MaterialEventNotEnoughAPToGetStoredAP", 94 | "Sub_CloseDialogBox", 95 | "Sub_HomeButton", 96 | "HomeFlag" 97 | ] 98 | }, 99 | "MaterialEventNotEnoughAPToGetStoredAP": { 100 | "recognition": "TemplateMatch", 101 | "template": "Dorm/CollectAPButton.png", 102 | "roi": [ 103 | 647, 104 | 492, 105 | 221, 106 | 137 107 | ], 108 | "action": "Click", 109 | "next": [ 110 | "QuickLITE", 111 | "Sub_CloseDialogBox", 112 | "Sub_HomeButton", 113 | "HomeFlag" 114 | ] 115 | }, 116 | "MaterialEventNoneLevelsToLITE": { 117 | "recognition": "OCR", 118 | "expected": "没有可减负的关卡", 119 | "roi": [ 120 | 457, 121 | 283, 122 | 364, 123 | 148 124 | ], 125 | "action": "Click", 126 | "next": [ 127 | "Sub_HomeButton", 128 | "HomeFlag" 129 | ] 130 | } 131 | } -------------------------------------------------------------------------------- /assets/resource/pipeline/navigation/armada_navigation.json: -------------------------------------------------------------------------------- 1 | { 2 | "Sub_EnterCommissionsPage": { 3 | "is_sub": true, 4 | "recognition": "TemplateMatch", 5 | "template": "Navigation/Armada/EnterCommissionsPage.png", 6 | "roi": [ 7 | 390, 8 | 583, 9 | 215, 10 | 137 11 | ], 12 | "action": "Click" 13 | }, 14 | "Sub_EnterContributionsPage": { 15 | "is_sub": true, 16 | "recognition": "TemplateMatch", 17 | "template": "Navigation/Armada/EnterArmadaContribution.png", 18 | "roi": [ 19 | 832, 20 | 586, 21 | 212, 22 | 133 23 | ], 24 | "action": "Click", 25 | "post_wait_freezes": { 26 | "time": 200, 27 | "target": [ 28 | 0, 29 | 0, 30 | 420, 31 | 330 32 | ] 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /assets/resource/pipeline/navigation/attack_event_navigation.json: -------------------------------------------------------------------------------- 1 | { 2 | "Sub_EnterMaterialExpeditionPage": { 3 | "is_sub": true, 4 | "recognition": "TemplateMatch", 5 | "template": "Navigation/AttackEvent/EnterMaterialExpeditionPage.png", 6 | "roi": [ 7 | 452, 8 | 574, 9 | 196, 10 | 130 11 | ], 12 | "action": "Click", 13 | "post_delay": 1500 14 | } 15 | } -------------------------------------------------------------------------------- /assets/resource/pipeline/navigation/attack_navigation.json: -------------------------------------------------------------------------------- 1 | { 2 | "Sub_EnterAttackEventPage": { 3 | "is_sub": true, 4 | "recognition": "TemplateMatch", 5 | "template": "Navigation/Attack/EnterAttackEventPage.png", 6 | "roi": [ 7 | 472, 8 | 33, 9 | 159, 10 | 135 11 | ], 12 | "action": "Click", 13 | "post_delay": 1500 14 | }, 15 | "Sub_EnterChallengeEventPage": { 16 | "is_sub": true, 17 | "recognition": "TemplateMatch", 18 | "template": "Navigation/Attack/EnterChallengeEventPage.png", 19 | "roi": [ 20 | 647, 21 | 34, 22 | 162, 23 | 134 24 | ], 25 | "action": "Click", 26 | "post_delay": 1500 27 | } 28 | } -------------------------------------------------------------------------------- /assets/resource/pipeline/navigation/challenge_event_navigation.json: -------------------------------------------------------------------------------- 1 | { 2 | "Sub_EnterUniversalMiragePage": { 3 | "is_sub": true, 4 | "recognition": "TemplateMatch", 5 | "template": "Navigation/ChallengeEvent/EnterUniversalMiragePage.png", 6 | "roi": [ 7 | 511, 8 | 541, 9 | 195, 10 | 132 11 | ], 12 | "action": "Click" 13 | } 14 | } -------------------------------------------------------------------------------- /assets/resource/pipeline/navigation/commissions_navigation.json: -------------------------------------------------------------------------------- 1 | { 2 | "Sub_EnterCommissionsRewardsPage": { 3 | "is_sub": true, 4 | "recognition": "TemplateMatch", 5 | "template": "Navigation/Commissions/EnterCommissionsRewardsPage.png", 6 | "roi": [ 7 | 1095, 8 | 161, 9 | 185, 10 | 137 11 | ], 12 | "action": "Click" 13 | } 14 | } -------------------------------------------------------------------------------- /assets/resource/pipeline/navigation/dorm_navigation.json: -------------------------------------------------------------------------------- 1 | { 2 | "Sub_EnterErrandsPage": { 3 | "is_sub": true, 4 | "recognition": "TemplateMatch", 5 | "template": "Navigation/Dorm/EnterErrandsPage.png", 6 | "roi": [ 7 | 905, 8 | 595, 9 | 160, 10 | 125 11 | ], 12 | "action": "Click" 13 | }, 14 | "Sub_EnterExpeditionsPage": { 15 | "is_sub": true, 16 | "recognition": "TemplateMatch", 17 | "template": "Navigation/Dorm/EnterExpeditionsPage.png", 18 | "roi": [ 19 | 743, 20 | 596, 21 | 161, 22 | 124 23 | ], 24 | "action": "Click" 25 | } 26 | } -------------------------------------------------------------------------------- /assets/resource/pipeline/navigation/home_navigation.json: -------------------------------------------------------------------------------- 1 | { 2 | "Sub_EnterAttackPage": { 3 | "is_sub": true, 4 | "recognition": "OCR", 5 | "expected": "出击", 6 | "roi": [ 7 | 1082, 8 | 282, 9 | 192, 10 | 150 11 | ], 12 | "action": "Click", 13 | "post_delay": 1500 14 | }, 15 | "Sub_EnterSupplyPage": { 16 | "is_sub": true, 17 | "recognition": "OCR", 18 | "expected": "补给", 19 | "roi": [ 20 | 1085, 21 | 510, 22 | 147, 23 | 126 24 | ], 25 | "action": "Click", 26 | "post_delay": 1500 27 | }, 28 | "Sub_EnterArmadaPage": { 29 | "is_sub": true, 30 | "recognition": "OCR", 31 | "expected": [ 32 | "舰团" 33 | ], 34 | "roi": [ 35 | 868, 36 | 611, 37 | 141, 38 | 109 39 | ], 40 | "action": "Click", 41 | "post_delay": 1500 42 | }, 43 | "Sub_EnterDormPage": { 44 | "is_sub": true, 45 | "recognition": "OCR", 46 | "expected": [ 47 | "家园" 48 | ], 49 | "roi": [ 50 | 1118, 51 | 659, 52 | 47, 53 | 30 54 | ], 55 | "action": "Click", 56 | "post_delay": 1500 57 | }, 58 | "Sub_EnterMissionsPage": { 59 | "is_sub": true, 60 | "recognition": "OCR", 61 | "expected": [ 62 | "任务" 63 | ], 64 | "roi": [ 65 | 48, 66 | 61, 67 | 142, 68 | 122 69 | ], 70 | "action": "Click", 71 | "target_offset": [ 72 | -67, 73 | 7, 74 | 14, 75 | 14 76 | ], 77 | "post_delay": 1500 78 | } 79 | } -------------------------------------------------------------------------------- /assets/resource/pipeline/navigation/material_expedition_navigation.json: -------------------------------------------------------------------------------- 1 | { 2 | "Sub_EnterMaterialEventPage": { 3 | "is_sub": true, 4 | "recognition": "TemplateMatch", 5 | "template": "Navigation/MaterialExpedition/EnterMaterialEventPage.png", 6 | "roi": [ 7 | 0, 8 | 162, 9 | 137, 10 | 216 11 | ], 12 | "action": "Click" 13 | } 14 | } -------------------------------------------------------------------------------- /assets/resource/pipeline/navigation/missions_navigation.json: -------------------------------------------------------------------------------- 1 | { 2 | "Sub_EnterBPMissionsPage": { 3 | "is_sub": true, 4 | "recognition": "TemplateMatch", 5 | "template": "Navigation/Missions/EnterBPMissionsPage.png", 6 | "roi": [ 7 | 35, 8 | 64, 9 | 213, 10 | 143 11 | ], 12 | "action": "Click" 13 | } 14 | } -------------------------------------------------------------------------------- /assets/resource/pipeline/navigation/shop_navigation.json: -------------------------------------------------------------------------------- 1 | { 2 | "Sub_EnterActivityShopPage": { 3 | "is_sub": true, 4 | "recognition": "TemplateMatch", 5 | "template": "Navigation/Shop/EnterActivityShopPage.png", 6 | "roi": [ 7 | 61, 8 | 509, 9 | 203, 10 | 133 11 | ], 12 | "action": "Click" 13 | }, 14 | "Sub_EnterMirageStorePage": { 15 | "is_sub": true, 16 | "recognition": "TemplateMatch", 17 | "template": "Navigation/Shop/EnterMirageStorePage.png", 18 | "roi": [ 19 | 62, 20 | 440, 21 | 201, 22 | 130 23 | ], 24 | "action": "Click" 25 | } 26 | } -------------------------------------------------------------------------------- /assets/resource/pipeline/navigation/supply_navigation.json: -------------------------------------------------------------------------------- 1 | { 2 | "Sub_EnterShopPage": { 3 | "is_sub": true, 4 | "recognition": "TemplateMatch", 5 | "template": "Navigation/Supply/EnterShopPage.png", 6 | "roi": [ 7 | 157, 8 | 484, 9 | 213, 10 | 135 11 | ], 12 | "action": "Click", 13 | "post_wait_freezes": { 14 | "time": 200, 15 | "target": "Sub_EnterShopPage" 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /assets/resource/pipeline/navigation/universal_mirage_navigation.json: -------------------------------------------------------------------------------- 1 | { 2 | "Sub_EnterGlacialFencesPage": { 3 | "enabled": false, 4 | "is_sub": true, 5 | "recognition": "TemplateMatch", 6 | "template": "Navigation/UniversalMirage/EnterGlacialFencesPage.png", 7 | "roi": [ 8 | 76, 9 | 428, 10 | 235, 11 | 140 12 | ], 13 | "action": "Click" 14 | }, 15 | "Sub_EnterIlluminatedLandPage": { 16 | "enabled": false, 17 | "is_sub": true, 18 | "recognition": "TemplateMatch", 19 | "template": "Navigation/UniversalMirage/EnterIlluminatedLandPage.png", 20 | "roi": [ 21 | 371, 22 | 428, 23 | 240, 24 | 140 25 | ], 26 | "action": "Click" 27 | }, 28 | "Sub_EnterRoaringPalacePage": { 29 | "enabled": false, 30 | "is_sub": true, 31 | "recognition": "TemplateMatch", 32 | "template": "Navigation/UniversalMirage/EnterRoaringPalacePage.png", 33 | "roi": [ 34 | 668, 35 | 428, 36 | 241, 37 | 140 38 | ], 39 | "action": "Click" 40 | }, 41 | "Sub_EnterBladeGravePage": { 42 | "enabled": false, 43 | "is_sub": true, 44 | "recognition": "TemplateMatch", 45 | "template": "Navigation/UniversalMirage/EnterBladeGravePage.png", 46 | "roi": [ 47 | 966, 48 | 427, 49 | 242, 50 | 142 51 | ], 52 | "action": "Click" 53 | } 54 | } -------------------------------------------------------------------------------- /assets/resource/pipeline/shop.json: -------------------------------------------------------------------------------- 1 | { 2 | "Shop": { 3 | "next": [ 4 | "DailyShopPageFlag", 5 | "Sub_AiPromptFlag", 6 | "Sub_CancelDownload", 7 | "Sub_EnterShopPage", 8 | "Sub_EnterSupplyPage", 9 | "Sub_StartUp" 10 | ] 11 | }, 12 | "DailyShopPageFlag": { 13 | "recognition": "TemplateMatch", 14 | "template": "Shop/DailyShopPageFlag.png", 15 | "roi": [ 16 | 63, 17 | 53, 18 | 201, 19 | 138 20 | ], 21 | "next": [ 22 | "LogisticsTerminalBuyCharacterFragmentByGold", 23 | "MirageStoreBuyTimeSwirlPassesBy1Asterite", 24 | "Sub_CloseDialogBox" 25 | ] 26 | }, 27 | "LogisticsTerminalBuyCharacterFragmentByGold": { 28 | "recognition": "TemplateMatch", 29 | "template": "Shop/LogisticsTerminalPage.png", 30 | "roi": [ 31 | 61, 32 | 131, 33 | 204, 34 | 134 35 | ], 36 | "next": [ 37 | "LogisticsTerminalCharacterFragmentFlag", 38 | "LogisticsTerminalNotCharacterFragmentFlag" 39 | ] 40 | }, 41 | "LogisticsTerminalCharacterFragmentFlag": { 42 | "recognition": "TemplateMatch", 43 | "template": "Shop/LogisticsTerminalCharacterFragmentFlag.png", 44 | "roi": [ 45 | 232, 46 | 138, 47 | 139, 48 | 140 49 | ], 50 | "next": [ 51 | "LogisticsTerminalBuyCharacterFragmentByGoldFlag", 52 | "LogisticsTerminalNotBuyCharacterFragmentByGoldFlag" 53 | ] 54 | }, 55 | "LogisticsTerminalNotCharacterFragmentFlag": { 56 | "recognition": "TemplateMatch", 57 | "inverse": true, 58 | "template": "Shop/LogisticsTerminalCharacterFragmentFlag.png", 59 | "roi": [ 60 | 232, 61 | 138, 62 | 139, 63 | 140 64 | ], 65 | "next": [ 66 | "MirageStoreBuyTimeSwirlPassesBy1Asterite", 67 | "Stop" 68 | ] 69 | }, 70 | "LogisticsTerminalBuyCharacterFragmentByGoldFlag": { 71 | "recognition": "TemplateMatch", 72 | "template": "Shop/LogisticsTerminalBuyCharacterFragmentByGoldFlag.png", 73 | "roi": [ 74 | 246, 75 | 373, 76 | 133, 77 | 136 78 | ], 79 | "action": "Click", 80 | "next": [ 81 | "LogisticsTerminalCharacterFragmentFlag", 82 | "LogisticsTerminalBuyCharacterFragmentByGoldDo" 83 | ] 84 | }, 85 | "LogisticsTerminalNotBuyCharacterFragmentByGoldFlag": { 86 | "recognition": "TemplateMatch", 87 | "inverse": true, 88 | "template": "Shop/LogisticsTerminalBuyCharacterFragmentByGoldFlag.png", 89 | "roi": [ 90 | 246, 91 | 373, 92 | 133, 93 | 136 94 | ], 95 | "action": "Click", 96 | "next": [ 97 | "MirageStoreBuyTimeSwirlPassesBy1Asterite", 98 | "Stop" 99 | ] 100 | }, 101 | "LogisticsTerminalBuyCharacterFragmentByGoldDo": { 102 | "recognition": "TemplateMatch", 103 | "template": "Shop/LogisticsTerminalBuyCharacterFragmentByGoldFlag.png", 104 | "roi": [ 105 | 757, 106 | 496, 107 | 135, 108 | 140 109 | ], 110 | "action": "Click", 111 | "next": [ 112 | "LogisticsTerminalBuyCharacterFragmentByGoldSuccess", 113 | "LogisticsTerminalBuyCharacterFragmentByGoldDone", 114 | "LogisticsTerminalBuyCharacterFragmentByGoldDo" 115 | ] 116 | }, 117 | "LogisticsTerminalBuyCharacterFragmentByGoldSuccess": { 118 | "recognition": "OCR", 119 | "expected": "您已购买成功", 120 | "roi": [ 121 | 490, 122 | 288, 123 | 302, 124 | 140 125 | ], 126 | "action": "Click", 127 | "next": [ 128 | "MirageStoreBuyTimeSwirlPassesBy1Asterite", 129 | "Stop" 130 | ] 131 | }, 132 | "LogisticsTerminalBuyCharacterFragmentByGoldDone": { 133 | "recognition": "TemplateMatch", 134 | "template": "Shop/SoldOut.png", 135 | "roi": [ 136 | 262, 137 | 372, 138 | 179, 139 | 135 140 | ], 141 | "next": [ 142 | "MirageStoreBuyTimeSwirlPassesBy1Asterite", 143 | "Stop" 144 | ] 145 | }, 146 | "MirageStoreBuyTimeSwirlPassesBy1Asterite": { 147 | "recognition": "TemplateMatch", 148 | "template": "Shop/LogisticsTerminalPage.png", 149 | "next": [ 150 | "MirageStore1AsteriteFlag", 151 | "Sub_EnterMirageStorePage", 152 | "Sub_EnterActivityShopPage", 153 | "Stop" 154 | ] 155 | }, 156 | "MirageStore1AsteriteFlag": { 157 | "recognition": "TemplateMatch", 158 | "template": "Shop/MirageStore1AsteriteFlag.png", 159 | "roi": [ 160 | 273, 161 | 371, 162 | 172, 163 | 142 164 | ], 165 | "action": "Click", 166 | "next": [ 167 | "MirageStoreBuyTimeSwirlPassesBy1AsteriteDo", 168 | "MirageStore1AsteriteFlag" 169 | ] 170 | }, 171 | "MirageStoreBuyTimeSwirlPassesBy1AsteriteDo": { 172 | "recognition": "TemplateMatch", 173 | "template": "Shop/MirageStore1AsteriteFlag.png", 174 | "roi": [ 175 | 781, 176 | 495, 177 | 161, 178 | 145 179 | ], 180 | "action": "Click", 181 | "next": [ 182 | "MirageStoreBuyTimeSwirlPassesBy1AsteriteSuccess", 183 | "MirageStoreBuyTimeSwirlPassesBy1AsteriteDone", 184 | "MirageStoreBuyTimeSwirlPassesBy1AsteriteDo" 185 | ] 186 | }, 187 | "MirageStoreBuyTimeSwirlPassesBy1AsteriteSuccess": { 188 | "recognition": "OCR", 189 | "expected": "您已购买成功", 190 | "roi": [ 191 | 490, 192 | 288, 193 | 302, 194 | 140 195 | ], 196 | "action": "Click", 197 | "next": [ 198 | "Stop" 199 | ] 200 | }, 201 | "MirageStoreBuyTimeSwirlPassesBy1AsteriteDone": { 202 | "recognition": "TemplateMatch", 203 | "template": "Shop/SoldOut.png", 204 | "roi": [ 205 | 262, 206 | 372, 207 | 179, 208 | 135 209 | ], 210 | "next": [ 211 | "Stop" 212 | ] 213 | } 214 | } -------------------------------------------------------------------------------- /assets/resource/pipeline/utils.json: -------------------------------------------------------------------------------- 1 | { 2 | "Sub_BackButton": { 3 | "is_sub": true, 4 | "recognition": "TemplateMatch", 5 | "template": [ 6 | "Utils/BackButton.png", 7 | "Utils/BackButton_1.png" 8 | ], 9 | "roi": [ 10 | [ 11 | 0, 12 | 0, 13 | 180, 14 | 133 15 | ], 16 | [ 17 | 60, 18 | 0, 19 | 124, 20 | 132 21 | ] 22 | ], 23 | "action": "Click" 24 | }, 25 | "Sub_BackText": { 26 | "is_sub": true, 27 | "recognition": "OCR", 28 | "expected": [ 29 | "返回" 30 | ], 31 | "roi": [ 32 | 0, 33 | 0, 34 | 220, 35 | 160 36 | ], 37 | "action": "Click" 38 | }, 39 | "Sub_HomeButton": { 40 | "is_sub": true, 41 | "recognition": "TemplateMatch", 42 | "template": [ 43 | "Utils/HomeButton.png", 44 | "Utils/HomeButton_1.png" 45 | ], 46 | "roi": [ 47 | [ 48 | 126, 49 | 0, 50 | 212, 51 | 134 52 | ], 53 | [ 54 | 136, 55 | 0, 56 | 133, 57 | 132 58 | ] 59 | ], 60 | "action": "Click" 61 | }, 62 | "Sub_CancelButton": { 63 | "is_sub": true, 64 | "recognition": "TemplateMatch", 65 | "template": "Utils/CancelButton.png", 66 | "roi": [ 67 | 422, 68 | 351, 69 | 164, 70 | 139 71 | ], 72 | "action": "Click" 73 | }, 74 | "Sub_CloseDialogBox": { 75 | "is_sub": true, 76 | "recognition": "TemplateMatch", 77 | "template": "Utils/CloseDialogBox.png", 78 | "roi": [ 79 | 640, 80 | 0, 81 | 640, 82 | 720 83 | ], 84 | "action": "Click" 85 | }, 86 | "Sub_CancelDownload": { 87 | "is_sub": true, 88 | "recognition": "OCR", 89 | "expected": [ 90 | "即将下载" 91 | ], 92 | "roi": [ 93 | 298, 94 | 232, 95 | 669, 96 | 143 97 | ], 98 | "next": [ 99 | "Sub_CancelButton", 100 | "Stop" 101 | ] 102 | }, 103 | "Stop": {} 104 | } -------------------------------------------------------------------------------- /assets/resource/properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "is_base": true 3 | } -------------------------------------------------------------------------------- /cmake/assets.cmake: -------------------------------------------------------------------------------- 1 | set(maa_assets_target ${CMAKE_BINARY_DIR}) 2 | 3 | add_custom_command(OUTPUT ${maa_assets_target}/resource 4 | COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/assets/resource ${maa_assets_target}/resource 5 | ) 6 | add_custom_target(AssetsResource ALL DEPENDS ${maa_assets_target}/resource) 7 | set_property(TARGET AssetsResource APPEND PROPERTY ADDITIONAL_CLEAN_FILES ${maa_assets_target}/resource) 8 | set_target_properties(AssetsResource PROPERTIES FOLDER Assets) 9 | install(DIRECTORY ${PROJECT_SOURCE_DIR}/assets/resource DESTINATION .) -------------------------------------------------------------------------------- /cmake/config.cmake: -------------------------------------------------------------------------------- 1 | set(debug_comp_defs "_DEBUG;MAA_DEBUG") 2 | add_compile_definitions("$<$:${debug_comp_defs}>") 3 | 4 | set(rel_debug_comp_defs "MAA_DEBUG") 5 | 6 | if (MSVC) 7 | add_compile_options("/utf-8") 8 | add_compile_options("/MP") 9 | add_compile_options("/W4;/WX;/Gy;/permissive-;/sdl") 10 | add_compile_options("/wd4127") # conditional expression is constant 11 | add_compile_options("/wd4251") # export dll with templates 12 | 13 | set(rel_debug_comp_options "/Od") 14 | 15 | set(release_link_options "/OPT:REF;/OPT:ICF") 16 | add_link_options("$<$:${release_link_options}>") 17 | 18 | set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") 19 | else () 20 | add_compile_options("-Wall;-Werror;-Wextra;-Wpedantic;-Wno-missing-field-initializers") 21 | if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13) 22 | add_compile_options("-Wno-restrict") 23 | endif() 24 | 25 | set(rel_debug_comp_options "-O0") 26 | endif () 27 | 28 | if (APPLE) 29 | set(CMAKE_INSTALL_RPATH "@loader_path;@executable_path") 30 | add_compile_options("-Wno-deprecated-declarations") # supress tmpnam 31 | if ("${ARCH}" STREQUAL "arm64") 32 | add_compile_options("-arch;arm64") 33 | add_link_options("-arch;arm64") 34 | endif () 35 | elseif (UNIX) 36 | set(CMAKE_INSTALL_RPATH "$ORIGIN") 37 | endif () 38 | 39 | set(CMAKE_CXX_STANDARD 20) 40 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 41 | 42 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) 43 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) 44 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) 45 | -------------------------------------------------------------------------------- /cmake/framework.cmake: -------------------------------------------------------------------------------- 1 | install(DIRECTORY "${CMAKE_SOURCE_DIR}/deps/bin/" DESTINATION .) 2 | install(DIRECTORY "${CMAKE_SOURCE_DIR}/deps/share/MaaAgentBinary" DESTINATION .) 3 | -------------------------------------------------------------------------------- /cmake/macos.cmake: -------------------------------------------------------------------------------- 1 | if (BUILD_XCFRAMEWORK) 2 | add_custom_command(OUTPUT MaaFramework.xcframework 3 | COMMAND rm -rf MaaFramework.xcframework 4 | COMMAND xcodebuild -create-xcframework -library libMaaFramework.dylib -headers ${PROJECT_SOURCE_DIR}/include -output MaaFramework.xcframework 5 | DEPENDS MaaFramework 6 | ) 7 | 8 | add_custom_command(OUTPUT OpenCV.xcframework 9 | COMMAND rm -rf OpenCV.xcframework 10 | COMMAND xcodebuild -create-xcframework -library "${PROJECT_SOURCE_DIR}/MaaDeps/runtime/${MAADEPS_TRIPLET}/libopencv_world4.407.dylib" -output OpenCV.xcframework 11 | ) 12 | 13 | add_custom_target(MaaXCFramework ALL 14 | DEPENDS MaaFramework MaaFramework.xcframework OpenCV.xcframework 15 | ) 16 | endif (BUILD_XCFRAMEWORK) 17 | 18 | target_compile_options(MaaFramework PRIVATE 19 | -Wno-deprecated-declarations 20 | -Wno-gnu-zero-variadic-macro-arguments) 21 | -------------------------------------------------------------------------------- /cmake/utils.cmake: -------------------------------------------------------------------------------- 1 | function(download_and_decompress url filename sha256_checksum decompress_dir) 2 | if(EXISTS ${filename}) 3 | file(SHA256 ${filename} CHECKSUM_VARIABLE) 4 | endif() 5 | if(NOT EXISTS ${filename} OR NOT CHECKSUM_VARIABLE STREQUAL sha256_checksum) 6 | message("Downloading file from ${url} to ${filename} ...") 7 | file(DOWNLOAD ${url} "${filename}.tmp" SHOW_PROGRESS EXPECTED_HASH SHA256=${sha256_checksum}) 8 | file(RENAME "${filename}.tmp" ${filename}) 9 | endif() 10 | if(NOT EXISTS ${decompress_dir}) 11 | file(MAKE_DIRECTORY ${decompress_dir}) 12 | endif() 13 | message("Decompress file ${filename} ...") 14 | execute_process(COMMAND ${CMAKE_COMMAND} -E tar -xf ${filename} WORKING_DIRECTORY ${decompress_dir}) 15 | endfunction() 16 | 17 | function(get_osx_architecture) 18 | if (CMAKE_OSX_ARCHITECTURES STREQUAL "arm64") 19 | set(CURRENT_OSX_ARCH "arm64" PARENT_SCOPE) 20 | elseif(CMAKE_OSX_ARCHITECTURES STREQUAL "x86_64") 21 | set(CURRENT_OSX_ARCH "x86_64" PARENT_SCOPE) 22 | else() 23 | set(CURRENT_OSX_ARCH ${CMAKE_HOST_SYSTEM_PROCESSOR} PARENT_SCOPE) 24 | endif() 25 | endfunction() 26 | 27 | if (APPLE) 28 | set(CMAKE_OSX_DEPLOYMENT_TARGET 12.0) 29 | get_osx_architecture() 30 | endif (APPLE) 31 | -------------------------------------------------------------------------------- /cmake/version.cmake: -------------------------------------------------------------------------------- 1 | # define MAABH3_HASH_VERSION from git 2 | set(MAABH3_HASH_VERSION "DEBUG_VERSION" CACHE STRING "maabh3 version") 3 | if (MAABH3_HASH_VERSION STREQUAL "DEBUG_VERSION") 4 | find_package(Git) 5 | endif () 6 | if (MAABH3_HASH_VERSION STREQUAL "DEBUG_VERSION" AND GIT_FOUND) 7 | execute_process( 8 | COMMAND "${GIT_EXECUTABLE}" rev-parse HEAD 9 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 10 | RESULT_VARIABLE result 11 | OUTPUT_VARIABLE output 12 | ERROR_VARIABLE err 13 | OUTPUT_STRIP_TRAILING_WHITESPACE 14 | ) 15 | if (result EQUAL 0) 16 | set(MAABH3_HASH_VERSION "${output}") 17 | else () 18 | message(WARNING "git rev-parse returning ${result}, output:\n${err}") 19 | endif () 20 | endif () 21 | message(STATUS "MAABH3_HASH_VERSION=${MAABH3_HASH_VERSION}") 22 | add_compile_definitions(MAABH3_VERSION="${MAABH3_HASH_VERSION}") 23 | -------------------------------------------------------------------------------- /docs/配置文档.md: -------------------------------------------------------------------------------- 1 | # Config 2 | 3 | ## 配置文件目录结构 4 | 5 | > 默认情况下 6 | 7 | ``` 8 | config 9 | ├─control 10 | | └─default.json 11 | ├─device 12 | | └─default.json 13 | ├─tasks 14 | | └─default.json 15 | └─maa_toolkit.json 16 | ``` 17 | 18 | `./config/control` 目录下放置 [control](#control) 相关配置 19 | 20 | `./config/device` 目录下放置 [device](#device) 相关配置 21 | 22 | `./config/tasks` 目录下放置 [tasks](#tasks) 相关配置 23 | 24 | `maa_toolkit.json` 用于管理 maa_toolkit 相关配置 25 | 26 | ## control 27 | 28 | `./config/control/default.json` 为成功初始化后生成的 `control` 默认配置文件 29 | 30 | ## device 31 | 32 | > CLI成功配置目标连接设备后,会生成一个名为 `default.json` 的 device 默认配置文件。你可以在 `./config/control` 目录下找到此文件。该配置文件用于定义默认连接的设备。请注意,根据系统的要求和需求,你可能需要修改此文件以适应特定的配置。 33 | 34 | `./config/device/default.json` 内容一般如下 35 | 36 | ```json 37 | { 38 | "adb": "D:/MuMuPlayer-12.0/shell/adb.exe", 39 | "device_SN": "127.0.0.1:16384", 40 | "device_name": "MuMuPlayer12" 41 | } 42 | ``` 43 | 44 | ### device 配置属性 45 | 46 | | 属性名 | 类型 | 描述 | 47 | | ---- | ---- | ---- | 48 | | device_name | string | 设备名称 | 49 | | device_SN | string | 设备序列号(serial number) | 50 | | adb | srting | adb路径 | 51 | 52 | ## tasks 53 | 54 | `./config/tasks/default.json` 为成功初始化后生成的 `tasks` 默认配置文件 -------------------------------------------------------------------------------- /source/cli/.clang-format: -------------------------------------------------------------------------------- 1 | Language: Json 2 | ColumnLimit: 1000 3 | IndentWidth: 4 4 | --- 5 | Language: Cpp 6 | AccessModifierOffset: -4 7 | AlignAfterOpenBracket: Align 8 | AlignArrayOfStructures: None 9 | AlignConsecutiveMacros: None 10 | AlignConsecutiveAssignments: None 11 | AlignConsecutiveBitFields: None 12 | AlignConsecutiveDeclarations: None 13 | AlignEscapedNewlines: Left 14 | AlignOperands: Align 15 | AlignTrailingComments: true 16 | AllowAllArgumentsOnNextLine: true 17 | AllowAllParametersOfDeclarationOnNextLine: true 18 | AllowShortEnumsOnASingleLine: false 19 | AllowShortBlocksOnASingleLine: Empty 20 | AllowShortCaseLabelsOnASingleLine: false 21 | AllowShortFunctionsOnASingleLine: Inline 22 | AllowShortLambdasOnASingleLine: All 23 | AllowShortIfStatementsOnASingleLine: WithoutElse 24 | AllowShortLoopsOnASingleLine: false 25 | AlwaysBreakAfterDefinitionReturnType: None 26 | AlwaysBreakAfterReturnType: None 27 | AlwaysBreakBeforeMultilineStrings: false 28 | AlwaysBreakTemplateDeclarations: true 29 | AttributeMacros: 30 | - __capability 31 | BinPackArguments: true 32 | BinPackParameters: true 33 | BraceWrapping: 34 | AfterCaseLabel: false 35 | AfterClass: true 36 | AfterControlStatement: Never 37 | AfterEnum: true 38 | AfterFunction: true 39 | AfterNamespace: true 40 | AfterObjCDeclaration: true 41 | AfterStruct: true 42 | AfterUnion: false 43 | AfterExternBlock: true 44 | BeforeCatch: true 45 | BeforeElse: true 46 | BeforeLambdaBody: false 47 | BeforeWhile: false 48 | IndentBraces: false 49 | SplitEmptyFunction: false 50 | SplitEmptyRecord: false 51 | SplitEmptyNamespace: false 52 | BreakBeforeBinaryOperators: None 53 | BreakBeforeConceptDeclarations: true 54 | BreakBeforeBraces: Custom 55 | BreakBeforeInheritanceComma: false 56 | BreakInheritanceList: BeforeColon 57 | BreakBeforeTernaryOperators: true 58 | BreakConstructorInitializersBeforeComma: false 59 | BreakConstructorInitializers: BeforeColon 60 | BreakAfterJavaFieldAnnotations: false 61 | BreakStringLiterals: true 62 | ColumnLimit: 120 63 | CommentPragmas: '^ IWYU pragma:' 64 | QualifierAlignment: Leave 65 | CompactNamespaces: false 66 | ConstructorInitializerIndentWidth: 4 67 | ContinuationIndentWidth: 4 68 | Cpp11BracedListStyle: false 69 | DeriveLineEnding: true 70 | DerivePointerAlignment: false 71 | DisableFormat: false 72 | EmptyLineAfterAccessModifier: Never 73 | EmptyLineBeforeAccessModifier: LogicalBlock 74 | ExperimentalAutoDetectBinPacking: false 75 | PackConstructorInitializers: BinPack 76 | BasedOnStyle: '' 77 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 78 | AllowAllConstructorInitializersOnNextLine: true 79 | FixNamespaceComments: true 80 | ForEachMacros: 81 | - foreach 82 | - Q_FOREACH 83 | - BOOST_FOREACH 84 | IfMacros: 85 | - KJ_IF_MAYBE 86 | IncludeBlocks: Preserve 87 | IncludeCategories: 88 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/' 89 | Priority: 2 90 | SortPriority: 0 91 | CaseSensitive: false 92 | - Regex: '^(<|"(gtest|gmock|isl|json)/)' 93 | Priority: 3 94 | SortPriority: 0 95 | CaseSensitive: false 96 | - Regex: '.*' 97 | Priority: 1 98 | SortPriority: 0 99 | CaseSensitive: false 100 | IncludeIsMainRegex: '(Test)?$' 101 | IncludeIsMainSourceRegex: '' 102 | IndentAccessModifiers: false 103 | IndentCaseLabels: false 104 | IndentCaseBlocks: false 105 | IndentGotoLabels: true 106 | IndentPPDirectives: None 107 | IndentExternBlock: AfterExternBlock 108 | IndentRequiresClause: false 109 | IndentWidth: 4 110 | IndentWrappedFunctionNames: false 111 | InsertTrailingCommas: None 112 | JavaScriptQuotes: Leave 113 | JavaScriptWrapImports: true 114 | KeepEmptyLinesAtTheStartOfBlocks: true 115 | LambdaBodyIndentation: Signature 116 | MacroBlockBegin: '' 117 | MacroBlockEnd: '' 118 | MaxEmptyLinesToKeep: 1 119 | NamespaceIndentation: Inner 120 | ObjCBinPackProtocolList: Auto 121 | ObjCBlockIndentWidth: 2 122 | ObjCBreakBeforeNestedBlockParam: true 123 | ObjCSpaceAfterProperty: false 124 | ObjCSpaceBeforeProtocolList: true 125 | PenaltyBreakAssignment: 2 126 | PenaltyBreakBeforeFirstCallParameter: 19 127 | PenaltyBreakComment: 300 128 | PenaltyBreakFirstLessLess: 120 129 | PenaltyBreakOpenParenthesis: 0 130 | PenaltyBreakString: 1000 131 | PenaltyBreakTemplateDeclaration: 10 132 | PenaltyExcessCharacter: 1000000 133 | PenaltyReturnTypeOnItsOwnLine: 1000 134 | PenaltyIndentedWhitespace: 0 135 | PointerAlignment: Left 136 | PPIndentWidth: -1 137 | ReferenceAlignment: Pointer 138 | ReflowComments: true 139 | RemoveBracesLLVM: false 140 | RequiresClausePosition: OwnLine 141 | SeparateDefinitionBlocks: Leave 142 | ShortNamespaceLines: 50 143 | SortIncludes: CaseSensitive 144 | SortJavaStaticImport: Before 145 | SortUsingDeclarations: true 146 | SpaceAfterCStyleCast: false 147 | SpaceAfterLogicalNot: false 148 | SpaceAfterTemplateKeyword: true 149 | SpaceBeforeAssignmentOperators: true 150 | SpaceBeforeCaseColon: false 151 | SpaceBeforeCpp11BracedList: true 152 | SpaceBeforeCtorInitializerColon: true 153 | SpaceBeforeInheritanceColon: true 154 | SpaceBeforeParens: ControlStatements 155 | SpaceBeforeParensOptions: 156 | AfterControlStatements: true 157 | AfterForeachMacros: true 158 | AfterFunctionDefinitionName: false 159 | AfterFunctionDeclarationName: false 160 | AfterIfMacros: true 161 | AfterOverloadedOperator: false 162 | AfterRequiresInClause: true 163 | AfterRequiresInExpression: true 164 | BeforeNonEmptyParentheses: false 165 | SpaceAroundPointerQualifiers: Default 166 | SpaceBeforeRangeBasedForLoopColon: true 167 | SpaceInEmptyBlock: false 168 | SpaceInEmptyParentheses: false 169 | SpacesBeforeTrailingComments: 1 170 | SpacesInAngles: Never 171 | SpacesInConditionalStatement: false 172 | SpacesInContainerLiterals: true 173 | SpacesInCStyleCastParentheses: false 174 | SpacesInLineCommentPrefix: 175 | Minimum: 1 176 | Maximum: -1 177 | SpacesInParentheses: false 178 | SpacesInSquareBrackets: false 179 | SpaceBeforeSquareBrackets: false 180 | BitFieldColonSpacing: Both 181 | Standard: c++20 182 | StatementAttributeLikeMacros: 183 | - Q_EMIT 184 | StatementMacros: 185 | - Q_UNUSED 186 | - QT_REQUIRE_VERSION 187 | TabWidth: 4 188 | UseCRLF: false 189 | UseTab: Never 190 | WhitespaceSensitiveMacros: 191 | - STRINGIZE 192 | - PP_STRINGIZE 193 | - BOOST_PP_STRINGIZE 194 | - NS_SWIFT_NAME 195 | - CF_SWIFT_NAME 196 | -------------------------------------------------------------------------------- /source/cli/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${CMAKE_SOURCE_DIR}/deps/include) 2 | if (WIN32) 3 | link_directories(${CMAKE_SOURCE_DIR}/deps/lib) 4 | else () 5 | link_directories(${CMAKE_SOURCE_DIR}/deps/bin) 6 | endif () 7 | 8 | set(CMAKE_BUILD_TYPE "Release") 9 | set(CMAKE_CONFIGURATION_TYPES "Release") 10 | 11 | add_executable(MAABH3_CLI 12 | main.cpp 13 | control.cpp 14 | device.cpp 15 | tasks.cpp 16 | CustomAction/CustomAction.cpp 17 | CustomAction/CustomActionRegistrar.cpp 18 | CustomAction/CombatAction.cpp 19 | CustomAction/RandomPointGenerator.cpp 20 | CustomRecognizer/CustomRecognizer.cpp 21 | CustomRecognizer/CustomRecognizerRegistrar.cpp 22 | CustomRecognizer/CombatRecognizer.cpp 23 | Config/Config.cpp 24 | Config/ControlConfig.cpp 25 | Config/DeviceConfig.cpp 26 | Config/TasksConfig.cpp 27 | Config/ConfigMgr.cpp 28 | ) 29 | target_link_libraries(MAABH3_CLI PRIVATE MaaFramework MaaToolkit) 30 | 31 | add_dependencies(MAABH3_CLI AssetsResource) 32 | 33 | install(TARGETS MAABH3_CLI RUNTIME DESTINATION .) 34 | -------------------------------------------------------------------------------- /source/cli/Config/Config.cpp: -------------------------------------------------------------------------------- 1 | #include "Config.h" 2 | 3 | Config::Config() 4 | { 5 | if (!_target.ends_with(".json")) { 6 | _target += ".json"; 7 | } 8 | } 9 | 10 | bool Config::exists() 11 | { 12 | return std::filesystem::exists(_target_path); 13 | } 14 | 15 | bool Config::load() 16 | { 17 | auto config_opt = json::open(_target_path); 18 | if (!config_opt) { 19 | std::cerr << "Failed to open config file: " << _target_path << std::endl; 20 | return false; 21 | } 22 | 23 | auto& config = *config_opt; 24 | if (!config.is_object()) { 25 | std::cerr << "Json is not an object: " << config << std::endl; 26 | return false; 27 | } 28 | 29 | if (!parse(config)) { 30 | std::cerr << "Failed to parse control: " << config << std::endl; 31 | return false; 32 | } 33 | 34 | return true; 35 | } 36 | 37 | bool Config::save(const json::value& root) 38 | { 39 | std::filesystem::create_directories(_target_path.parent_path()); 40 | std::ofstream ofs(_target_path, std::ios::out); 41 | if (!ofs.is_open()) { 42 | std::cerr << "Failed to open config file: " << _target_path << std::endl; 43 | return false; 44 | } 45 | ofs << root; 46 | ofs.close(); 47 | return true; 48 | } 49 | 50 | bool Config::dump() 51 | { 52 | return save(to_json()); 53 | } 54 | 55 | void Config::set_target(std::string target) 56 | { 57 | _target = target; 58 | if (!_target.ends_with(".json")) { 59 | _target += ".json"; 60 | } 61 | build_target_path(); 62 | } -------------------------------------------------------------------------------- /source/cli/Config/Config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "../meojson/json.hpp" 8 | 9 | class Config 10 | { 11 | public: 12 | Config(); 13 | virtual ~Config() = default; 14 | 15 | public: 16 | virtual bool exists(); 17 | virtual bool parse(const json::value& config_json) = 0; 18 | virtual bool load(); 19 | virtual json::value to_json() = 0; 20 | virtual bool save(const json::value& root); 21 | bool dump(); 22 | 23 | public: 24 | virtual void set_target(const std::string target); 25 | 26 | private: 27 | virtual void build_target_path() = 0; 28 | 29 | protected: 30 | std::string _target = "default"; 31 | std::filesystem::path _target_path = "."; 32 | }; -------------------------------------------------------------------------------- /source/cli/Config/ConfigMgr.cpp: -------------------------------------------------------------------------------- 1 | #include "ConfigMgr.h" 2 | 3 | ConfigMgr& ConfigMgr::get_instance() 4 | { 5 | static ConfigMgr instance; 6 | return instance; 7 | } 8 | 9 | bool ConfigMgr::init() 10 | { 11 | if (!_control.load()) { 12 | std::cerr << "Failed to load control config" << std::endl; 13 | return false; 14 | } 15 | if (!_device.load()) { 16 | std::cerr << "Failed to load device config" << std::endl; 17 | return false; 18 | } 19 | if (!_tasks.load()) { 20 | std::cerr << "Failed to load tasks config" << std::endl; 21 | return false; 22 | } 23 | return true; 24 | } 25 | 26 | bool ConfigMgr::set_config_target(ConfigOption option, std::string target) 27 | { 28 | switch (option) { 29 | case ConfigOption_Control: 30 | _control.set_target(target); 31 | break; 32 | case ConfigOption_Device: 33 | _device.set_target(target); 34 | break; 35 | case ConfigOption_Tasks: 36 | _tasks.set_target(target); 37 | break; 38 | default: 39 | return false; 40 | } 41 | return true; 42 | } 43 | 44 | ControlConfig& ConfigMgr::get_control_config() 45 | { 46 | return _control; 47 | } 48 | 49 | DeviceConfig& ConfigMgr::get_device_config() 50 | { 51 | return _device; 52 | } 53 | 54 | TasksConfig& ConfigMgr::get_tasks_config() 55 | { 56 | return _tasks; 57 | } 58 | -------------------------------------------------------------------------------- /source/cli/Config/ConfigMgr.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "ControlConfig.h" 6 | #include "DeviceConfig.h" 7 | #include "TasksConfig.h" 8 | 9 | enum ConfigOption 10 | { 11 | ConfigOption_Control = 0, 12 | ConfigOption_Device = 1, 13 | ConfigOption_Tasks = 2 14 | }; 15 | 16 | class ConfigMgr 17 | { 18 | public: 19 | static ConfigMgr& get_instance(); 20 | 21 | public: 22 | bool init(); 23 | bool set_config_target(ConfigOption option, std::string target); 24 | 25 | public: 26 | ControlConfig& get_control_config(); 27 | DeviceConfig& get_device_config(); 28 | TasksConfig& get_tasks_config(); 29 | 30 | private: 31 | ConfigMgr() = default; 32 | ~ConfigMgr() = default; 33 | 34 | private: 35 | ControlConfig _control; 36 | DeviceConfig _device; 37 | TasksConfig _tasks; 38 | }; -------------------------------------------------------------------------------- /source/cli/Config/ControlConfig.cpp: -------------------------------------------------------------------------------- 1 | #include "ControlConfig.h" 2 | 3 | ControlConfig::ControlConfig() 4 | { 5 | build_target_path(); 6 | } 7 | 8 | bool ControlConfig::parse(const json::value& config_opt) 9 | { 10 | _config_server = config_opt.get("server", _config_server); 11 | _config_screencap = config_opt.get("screencap", _config_screencap); 12 | _config_touch = config_opt.get("touch", _config_touch); 13 | 14 | return true; 15 | } 16 | 17 | json::value ControlConfig::to_json() 18 | { 19 | json::value root; 20 | root = { { "server", _config_server }, { "screencap", _config_screencap }, { "touch", _config_touch } }; 21 | return root; 22 | } 23 | 24 | void ControlConfig::set_config_server(int server) 25 | { 26 | _config_server = server; 27 | } 28 | 29 | void ControlConfig::set_config_screencap(int screencap) 30 | { 31 | _config_screencap = screencap; 32 | } 33 | 34 | void ControlConfig::set_config_touch(int touch) 35 | { 36 | _config_touch = touch; 37 | } 38 | 39 | int ControlConfig::get_config_server() 40 | { 41 | return _config_server; 42 | } 43 | 44 | int ControlConfig::get_config_screencap() 45 | { 46 | return _config_screencap; 47 | } 48 | 49 | int ControlConfig::get_config_touch() 50 | { 51 | return _config_touch; 52 | } 53 | 54 | void ControlConfig::build_target_path() 55 | { 56 | _target_path = config_dir / _target; 57 | } 58 | -------------------------------------------------------------------------------- /source/cli/Config/ControlConfig.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Config.h" 6 | 7 | class ControlConfig : public Config 8 | { 9 | public: 10 | ControlConfig(); 11 | virtual ~ControlConfig() = default; 12 | 13 | public: 14 | inline static const std::filesystem::path local_dir = "."; 15 | inline static const std::filesystem::path config_dir = local_dir / "config" / "control"; 16 | 17 | public: 18 | bool parse(const json::value& config_json) override; 19 | json::value to_json() override; 20 | 21 | public: 22 | void set_config_server(int server); 23 | void set_config_screencap(int screencap); 24 | void set_config_touch(int touch); 25 | 26 | public: 27 | int get_config_server(); 28 | int get_config_screencap(); 29 | int get_config_touch(); 30 | 31 | private: 32 | void build_target_path() override; 33 | 34 | private: 35 | int _config_server = 1; 36 | int _config_screencap = 3; 37 | int _config_touch = 3; 38 | }; -------------------------------------------------------------------------------- /source/cli/Config/DeviceConfig.cpp: -------------------------------------------------------------------------------- 1 | #include "DeviceConfig.h" 2 | 3 | DeviceConfig::DeviceConfig() 4 | { 5 | build_target_path(); 6 | } 7 | 8 | bool DeviceConfig::parse(const json::value& config_opt) 9 | { 10 | _config_adb = config_opt.get("adb", _config_adb); 11 | _config_device_name = config_opt.get("device_name", _config_device_name); 12 | _config_device_SN = config_opt.get("device_SN", _config_device_SN); 13 | 14 | return true; 15 | } 16 | 17 | json::value DeviceConfig::to_json() 18 | { 19 | json::value root = { { "device_name", _config_device_name }, 20 | { "device_SN", _config_device_SN }, 21 | { "adb", _config_adb } }; 22 | 23 | return root; 24 | } 25 | 26 | void DeviceConfig::set_config_device_name(std::string name) 27 | { 28 | _config_device_name = name; 29 | } 30 | 31 | void DeviceConfig::set_config_device_SN(std::string SN) 32 | { 33 | _config_device_SN = SN; 34 | } 35 | 36 | void DeviceConfig::set_config_adb(std::string adb) 37 | { 38 | _config_adb = adb; 39 | } 40 | 41 | std::string DeviceConfig::get_config_device_name() 42 | { 43 | return _config_device_name; 44 | } 45 | 46 | std::string DeviceConfig::get_config_device_SN() 47 | { 48 | return _config_device_SN; 49 | } 50 | 51 | std::string DeviceConfig::get_config_adb() 52 | { 53 | return _config_adb; 54 | } 55 | 56 | void DeviceConfig::build_target_path() 57 | { 58 | _target_path = config_dir / _target; 59 | } 60 | -------------------------------------------------------------------------------- /source/cli/Config/DeviceConfig.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Config.h" 6 | 7 | class DeviceConfig : public Config 8 | { 9 | public: 10 | DeviceConfig(); 11 | virtual ~DeviceConfig() = default; 12 | 13 | public: 14 | inline static const std::filesystem::path local_dir = "."; 15 | inline static const std::filesystem::path config_dir = local_dir / "config" / "device"; 16 | 17 | public: 18 | bool parse(const json::value& config_opt) override; 19 | json::value to_json() override; 20 | 21 | public: 22 | void set_config_device_name(std::string name); 23 | void set_config_device_SN(std::string SN); 24 | void set_config_adb(std::string adb); 25 | 26 | public: 27 | std::string get_config_device_name(); 28 | std::string get_config_device_SN(); 29 | std::string get_config_adb(); 30 | 31 | private: 32 | void build_target_path() override; 33 | 34 | private: 35 | std::string _config_device_name; 36 | std::string _config_device_SN; 37 | std::string _config_adb; 38 | }; -------------------------------------------------------------------------------- /source/cli/Config/TasksConfig.cpp: -------------------------------------------------------------------------------- 1 | #include "TasksConfig.h" 2 | 3 | TasksConfig::TasksConfig() 4 | { 5 | build_target_path(); 6 | } 7 | 8 | bool TasksConfig::parse(const json::value& config_opt) 9 | { 10 | _config_tasklist.clear(); 11 | auto arr = config_opt.as_array(); 12 | for (auto& el : arr) { 13 | Task task; 14 | task.name = el.get("name", ""); 15 | task.status = el.get("status", true); 16 | if (!task.status) { 17 | continue; 18 | } 19 | task.param = el.get("param", json::object()); 20 | task.type = el.get("type", ""); 21 | _config_tasklist.emplace_back(std::move(task)); 22 | } 23 | 24 | return true; 25 | } 26 | 27 | bool TasksConfig::load() 28 | { 29 | auto config_opt = json::open(_target_path); 30 | if (!config_opt) { 31 | std::cerr << "Failed to open config file: " << _target_path << std::endl; 32 | return false; 33 | } 34 | 35 | auto& config = *config_opt; 36 | if (!config.is_array()) { 37 | std::cerr << "Json is not an array: " << config << std::endl; 38 | return false; 39 | } 40 | 41 | if (!parse(config)) { 42 | std::cerr << "Failed to parse control: " << config << std::endl; 43 | return false; 44 | } 45 | 46 | return true; 47 | } 48 | 49 | json::value TasksConfig::to_json() 50 | { 51 | json::value root = json::array(); 52 | for (auto& task : _config_tasklist) { 53 | json::object obj = { 54 | { "name", task.name }, { "status", task.status }, { "param", task.param }, { "type", task.type } 55 | }; 56 | root.emplace(obj); 57 | } 58 | 59 | return root; 60 | } 61 | 62 | void TasksConfig::set_config_tasklist(std::vector tasklist) 63 | { 64 | _config_tasklist = tasklist; 65 | } 66 | 67 | std::vector TasksConfig::get_config_tasklist() 68 | { 69 | return _config_tasklist; 70 | } 71 | 72 | void TasksConfig::build_target_path() 73 | { 74 | _target_path = config_dir / _target; 75 | } 76 | -------------------------------------------------------------------------------- /source/cli/Config/TasksConfig.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Config.h" 6 | 7 | struct Task 8 | { 9 | std::string name; 10 | bool status = true; 11 | std::string type; 12 | json::value param = json::object(); 13 | }; 14 | 15 | class TasksConfig : public Config 16 | { 17 | public: 18 | TasksConfig(); 19 | virtual ~TasksConfig() = default; 20 | 21 | public: 22 | inline static const std::filesystem::path local_dir = "."; 23 | inline static const std::filesystem::path config_dir = local_dir / "config" / "tasks"; 24 | 25 | public: 26 | bool parse(const json::value& config_opt) override; 27 | bool load() override; 28 | json::value to_json() override; 29 | 30 | public: 31 | void set_config_tasklist(std::vector tasklist); 32 | 33 | public: 34 | std::vector get_config_tasklist(); 35 | 36 | private: 37 | void build_target_path() override; 38 | 39 | private: 40 | std::vector _config_tasklist; 41 | }; -------------------------------------------------------------------------------- /source/cli/CustomAction/CombatAction.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "MaaFramework/Task/MaaSyncContext.h" 8 | 9 | #include "RandomPointGenerator.h" 10 | 11 | void combat_move(MaaSyncContextHandle sync_context, MaaStringView custom_action_param, int32_t target_x, 12 | int32_t target_y, int32_t target_w, int32_t target_h); 13 | 14 | MaaBool combat_move_forward(MaaSyncContextHandle sync_context, MaaStringView task_name, 15 | MaaStringView custom_action_param, MaaRectHandle cur_box, MaaStringView cur_rec_detail, 16 | MaaTransparentArg arg); 17 | MaaBool combat_move_backward(MaaSyncContextHandle sync_context, MaaStringView task_name, 18 | MaaStringView custom_action_param, MaaRectHandle cur_box, MaaStringView cur_rec_detail, 19 | MaaTransparentArg arg); 20 | MaaBool combat_move_left(MaaSyncContextHandle sync_context, MaaStringView task_name, MaaStringView custom_action_param, 21 | MaaRectHandle cur_box, MaaStringView cur_rec_detail, MaaTransparentArg arg); 22 | MaaBool combat_move_right(MaaSyncContextHandle sync_context, MaaStringView task_name, MaaStringView custom_action_param, 23 | MaaRectHandle cur_box, MaaStringView cur_rec_detail, MaaTransparentArg arg); 24 | MaaBool combat_move_left_forward(MaaSyncContextHandle sync_context, MaaStringView task_name, 25 | MaaStringView custom_action_param, MaaRectHandle cur_box, MaaStringView cur_rec_detail, 26 | MaaTransparentArg arg); 27 | MaaBool combat_move_right_forward(MaaSyncContextHandle sync_context, MaaStringView task_name, 28 | MaaStringView custom_action_param, MaaRectHandle cur_box, 29 | MaaStringView cur_rec_detail, MaaTransparentArg arg); 30 | MaaBool combat_move_left_backward(MaaSyncContextHandle sync_context, MaaStringView task_name, 31 | MaaStringView custom_action_param, MaaRectHandle cur_box, 32 | MaaStringView cur_rec_detail, MaaTransparentArg arg); 33 | MaaBool combat_move_right_backward(MaaSyncContextHandle sync_context, MaaStringView task_name, 34 | MaaStringView custom_action_param, MaaRectHandle cur_box, 35 | MaaStringView cur_rec_detail, MaaTransparentArg arg); 36 | 37 | MaaBool combat_basic_ATK(MaaSyncContextHandle sync_context, MaaStringView task_name, MaaStringView custom_action_param, 38 | MaaRectHandle cur_box, MaaStringView cur_rec_detail, MaaTransparentArg arg); 39 | MaaBool combat_basic_ATK_charge(MaaSyncContextHandle sync_context, MaaStringView task_name, 40 | MaaStringView custom_action_param, MaaRectHandle cur_box, MaaStringView cur_rec_detail, 41 | MaaTransparentArg arg); 42 | MaaBool combat_evade(MaaSyncContextHandle sync_context, MaaStringView task_name, MaaStringView custom_action_param, 43 | MaaRectHandle cur_box, MaaStringView cur_rec_detail, MaaTransparentArg arg); 44 | MaaBool combat_ultimate(MaaSyncContextHandle sync_context, MaaStringView task_name, MaaStringView custom_action_param, 45 | MaaRectHandle cur_box, MaaStringView cur_rec_detail, MaaTransparentArg arg); 46 | MaaBool combat_ultimate_charge(MaaSyncContextHandle sync_context, MaaStringView task_name, 47 | MaaStringView custom_action_param, MaaRectHandle cur_box, MaaStringView cur_rec_detail, 48 | MaaTransparentArg arg); 49 | MaaBool combat_weapon_skill(MaaSyncContextHandle sync_context, MaaStringView task_name, 50 | MaaStringView custom_action_param, MaaRectHandle cur_box, MaaStringView cur_rec_detail, 51 | MaaTransparentArg arg); 52 | MaaBool combat_ELF_skill(MaaSyncContextHandle sync_context, MaaStringView task_name, MaaStringView custom_action_param, 53 | MaaRectHandle cur_box, MaaStringView cur_rec_detail, MaaTransparentArg arg); 54 | MaaBool combat_extra_skill(MaaSyncContextHandle sync_context, MaaStringView task_name, 55 | MaaStringView custom_action_param, MaaRectHandle cur_box, MaaStringView cur_rec_detail, 56 | MaaTransparentArg arg); 57 | MaaBool combat_QTE1(MaaSyncContextHandle sync_context, MaaStringView task_name, MaaStringView custom_action_param, 58 | MaaRectHandle cur_box, MaaStringView cur_rec_detail, MaaTransparentArg arg); 59 | MaaBool combat_QTE2(MaaSyncContextHandle sync_context, MaaStringView task_name, MaaStringView custom_action_param, 60 | MaaRectHandle cur_box, MaaStringView cur_rec_detail, MaaTransparentArg arg); -------------------------------------------------------------------------------- /source/cli/CustomAction/CustomAction.cpp: -------------------------------------------------------------------------------- 1 | #include "CustomAction.h" 2 | 3 | CustomAction::CustomAction(const std::string& action_name, 4 | MaaBool (*action_run)(MaaSyncContextHandle sync_context, MaaStringView task_name, 5 | MaaStringView custom_action_param, MaaRectHandle cur_box, 6 | MaaStringView cur_rec_detail, MaaTransparentArg arg)) 7 | : _name(action_name) 8 | { 9 | _custom_action.run = action_run; 10 | } 11 | 12 | CustomAction::CustomAction(const std::string& action_name, 13 | MaaBool (*action_run)(MaaSyncContextHandle sync_context, MaaStringView task_name, 14 | MaaStringView custom_action_param, MaaRectHandle cur_box, 15 | MaaStringView cur_rec_detail, MaaTransparentArg arg), 16 | void (*action_stop)(MaaTransparentArg arg)) 17 | : _name(action_name) 18 | { 19 | _custom_action.run = action_run; 20 | _custom_action.stop = action_stop; 21 | } 22 | 23 | std::string CustomAction::get_name() const 24 | { 25 | return _name; 26 | } 27 | 28 | MaaCustomActionAPI CustomAction::get_custom_action() const 29 | { 30 | return _custom_action; 31 | } -------------------------------------------------------------------------------- /source/cli/CustomAction/CustomAction.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "MaaFramework/Task/MaaCustomAction.h" 6 | 7 | class CustomAction 8 | { 9 | public: 10 | CustomAction(const std::string& action_name, 11 | MaaBool (*action_run)(MaaSyncContextHandle sync_context, MaaStringView task_name, 12 | MaaStringView custom_action_param, MaaRectHandle cur_box, 13 | MaaStringView cur_rec_detail, MaaTransparentArg arg)); 14 | CustomAction(const std::string& action_name, 15 | MaaBool (*action_run)(MaaSyncContextHandle sync_context, MaaStringView task_name, 16 | MaaStringView custom_action_param, MaaRectHandle cur_box, 17 | MaaStringView cur_rec_detail, MaaTransparentArg arg), 18 | void (*action_stop)(MaaTransparentArg arg)); 19 | ~CustomAction() = default; 20 | 21 | public: 22 | std::string get_name() const; 23 | MaaCustomActionAPI get_custom_action() const; 24 | 25 | private: 26 | std::string _name; 27 | MaaCustomActionAPI _custom_action; 28 | }; -------------------------------------------------------------------------------- /source/cli/CustomAction/CustomActionRegistrar.cpp: -------------------------------------------------------------------------------- 1 | #include "CustomActionRegistrar.h" 2 | 3 | void CustomActionRegistrar::add_action(const std::string& name, 4 | MaaBool (*action_run)(MaaSyncContextHandle sync_context, MaaStringView task_name, 5 | MaaStringView custom_action_param, MaaRectHandle cur_box, 6 | MaaStringView cur_rec_detail, MaaTransparentArg arg)) 7 | { 8 | _actions.emplace_back(name, action_run); 9 | } 10 | 11 | void CustomActionRegistrar::add_action(const std::string& name, 12 | MaaBool (*action_run)(MaaSyncContextHandle sync_context, MaaStringView task_name, 13 | MaaStringView custom_action_param, MaaRectHandle cur_box, 14 | MaaStringView cur_rec_detail, MaaTransparentArg arg), 15 | void (*action_stop)(MaaTransparentArg arg)) 16 | { 17 | _actions.emplace_back(name, action_run, action_stop); 18 | } 19 | 20 | void CustomActionRegistrar::register_actions(MaaInstanceHandle maa_handle) 21 | { 22 | for (const auto& action : _actions) { 23 | std::shared_ptr custom_action = 24 | std::make_shared(action.get_custom_action()); 25 | _custom_actions.push_back(custom_action); 26 | MaaRegisterCustomAction(maa_handle, action.get_name().c_str(), custom_action.get(), nullptr); 27 | } 28 | } -------------------------------------------------------------------------------- /source/cli/CustomAction/CustomActionRegistrar.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "CustomAction.h" 8 | #include "MaaFramework/Instance/MaaInstance.h" 9 | #include "MaaFramework/Task/MaaCustomAction.h" 10 | 11 | class CustomActionRegistrar 12 | { 13 | public: 14 | CustomActionRegistrar() = default; 15 | ~CustomActionRegistrar() = default; 16 | 17 | public: 18 | void add_action(const std::string& name, 19 | MaaBool (*action_run)(MaaSyncContextHandle sync_context, MaaStringView task_name, 20 | MaaStringView custom_action_param, MaaRectHandle cur_box, 21 | MaaStringView cur_rec_detail, MaaTransparentArg arg)); 22 | void add_action(const std::string& name, 23 | MaaBool (*action_run)(MaaSyncContextHandle sync_context, MaaStringView task_name, 24 | MaaStringView custom_action_param, MaaRectHandle cur_box, 25 | MaaStringView cur_rec_detail, MaaTransparentArg arg), 26 | void (*action_stop)(MaaTransparentArg arg)); 27 | void register_actions(MaaInstanceHandle maa_handle); 28 | 29 | private: 30 | std::vector _actions; 31 | std::vector> _custom_actions; 32 | }; -------------------------------------------------------------------------------- /source/cli/CustomAction/CustomActionRegistry.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CombatAction.h" 4 | #include "CustomActionRegistrar.h" 5 | 6 | void custom_action_init(CustomActionRegistrar& registrar) 7 | { 8 | registrar.add_action("Forward", combat_move_forward); 9 | registrar.add_action("Backward", combat_move_backward); 10 | registrar.add_action("Left", combat_move_left); 11 | registrar.add_action("Right", combat_move_right); 12 | registrar.add_action("LeftForward", combat_move_left_forward); 13 | registrar.add_action("RightForward", combat_move_right_forward); 14 | registrar.add_action("LeftBackward", combat_move_left_backward); 15 | registrar.add_action("RightBackward", combat_move_right_backward); 16 | registrar.add_action("BasicATK", combat_basic_ATK); 17 | registrar.add_action("BasicATKCharge", combat_basic_ATK_charge); 18 | registrar.add_action("Evade", combat_evade); 19 | registrar.add_action("Ultimate", combat_ultimate); 20 | registrar.add_action("UltimateCharge", combat_ultimate_charge); 21 | registrar.add_action("WeaponSkill", combat_weapon_skill); 22 | registrar.add_action("ELFSkill", combat_ELF_skill); 23 | registrar.add_action("ExtraSkill", combat_extra_skill); 24 | registrar.add_action("QTE1", combat_QTE1); 25 | registrar.add_action("QTE2", combat_QTE2); 26 | } 27 | 28 | void register_custom_action(MaaInstanceHandle maa_handle, CustomActionRegistrar& registerar) 29 | { 30 | custom_action_init(registerar); 31 | registerar.register_actions(maa_handle); 32 | } -------------------------------------------------------------------------------- /source/cli/CustomAction/RandomPointGenerator.cpp: -------------------------------------------------------------------------------- 1 | #include "RandomPointGenerator.h" 2 | 3 | RandomPointGenerator::RandomPointGenerator() : rng_(std::random_device{}()) {} 4 | 5 | void RandomPointGenerator::generate_point(int32_t x, int32_t y, int32_t w, int32_t h, int32_t& rx, int32_t& ry) 6 | { 7 | std::uniform_int_distribution uni_x(x, x + w); 8 | std::uniform_int_distribution uni_y(y, y + h); 9 | rx = uni_x(rng_); 10 | ry = uni_y(rng_); 11 | } -------------------------------------------------------------------------------- /source/cli/CustomAction/RandomPointGenerator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class RandomPointGenerator 6 | { 7 | public: 8 | RandomPointGenerator(); 9 | ~RandomPointGenerator() = default; 10 | 11 | public: 12 | void generate_point(int32_t x, int32_t y, int32_t w, int32_t h, int32_t& rx, int32_t& ry); 13 | 14 | private: 15 | std::mt19937 rng_; 16 | }; -------------------------------------------------------------------------------- /source/cli/CustomRecognizer/CombatRecognizer.cpp: -------------------------------------------------------------------------------- 1 | #include "CombatRecognizer.h" 2 | 3 | MaaBool combat_combating(MaaSyncContextHandle sync_context, const MaaImageBufferHandle image, 4 | [[maybe_unused]] MaaStringView task_name, 5 | [[maybe_unused]] MaaStringView custom_recognition_param, 6 | [[maybe_unused]] MaaTransparentArg recognizer_arg, MaaRectHandle out_box, 7 | MaaStringBufferHandle detail_buff) 8 | { 9 | json::object combating { { "recognition", "TemplateMatch" }, 10 | { "template", "Combat/StopCombat.png" }, 11 | { "roi", json::array { 0, 0, 136, 140 } } }; 12 | json::value diff_task { { "Combating", combating } }; 13 | json::value task_param { { "diff_task", diff_task } }; 14 | std::string task_param_str = task_param.to_string(); 15 | 16 | MaaBool result = 17 | MaaSyncContextRunRecognition(sync_context, image, "Combating", task_param_str.c_str(), out_box, detail_buff); 18 | return result; 19 | } -------------------------------------------------------------------------------- /source/cli/CustomRecognizer/CombatRecognizer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "MaaFramework/Task/MaaSyncContext.h" 6 | #include "MaaFramework/Utility/MaaBuffer.h" 7 | #include "../meojson/json.hpp" 8 | 9 | MaaBool combat_combating(MaaSyncContextHandle sync_context, const MaaImageBufferHandle image, MaaStringView task_name, 10 | MaaStringView custom_recognition_param, MaaTransparentArg recognizer_arg, MaaRectHandle out_box, 11 | MaaStringBufferHandle detail_buff); -------------------------------------------------------------------------------- /source/cli/CustomRecognizer/CustomRecognizer.cpp: -------------------------------------------------------------------------------- 1 | #include "CustomRecognizer.h" 2 | 3 | CustomRecognizer::CustomRecognizer( 4 | const std::string& recognizer_name, 5 | MaaBool (*recognizer_analyze)(MaaSyncContextHandle sync_context, const MaaImageBufferHandle image, 6 | MaaStringView task_name, MaaStringView custom_recognition_param, 7 | MaaTransparentArg recognizer_arg, MaaRectHandle out_box, 8 | MaaStringBufferHandle detail_buff)) 9 | : _name(recognizer_name) 10 | { 11 | _custom_recognizer.analyze = recognizer_analyze; 12 | } 13 | 14 | std::string CustomRecognizer::get_name() const 15 | { 16 | return _name; 17 | } 18 | 19 | MaaCustomRecognizerAPI CustomRecognizer::get_custom_recognizer() const 20 | { 21 | return _custom_recognizer; 22 | } -------------------------------------------------------------------------------- /source/cli/CustomRecognizer/CustomRecognizer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "MaaFramework/Task/MaaCustomRecognizer.h" 6 | 7 | class CustomRecognizer 8 | { 9 | public: 10 | CustomRecognizer(const std::string& recognizer_name, 11 | MaaBool (*recognizer_analyze)(MaaSyncContextHandle sync_context, const MaaImageBufferHandle image, 12 | MaaStringView task_name, MaaStringView custom_recognition_param, 13 | MaaTransparentArg recognizer_arg, MaaRectHandle out_box, 14 | MaaStringBufferHandle detail_buff)); 15 | ~CustomRecognizer() = default; 16 | 17 | public: 18 | std::string get_name() const; 19 | MaaCustomRecognizerAPI get_custom_recognizer() const; 20 | 21 | private: 22 | std::string _name; 23 | MaaCustomRecognizerAPI _custom_recognizer; 24 | }; -------------------------------------------------------------------------------- /source/cli/CustomRecognizer/CustomRecognizerRegistrar.cpp: -------------------------------------------------------------------------------- 1 | #include "CustomRecognizerRegistrar.h" 2 | 3 | void CustomRecognizerRegistrar::add_recognizer( 4 | const std::string& name, 5 | MaaBool (*recognizer_analyze)(MaaSyncContextHandle sync_context, const MaaImageBufferHandle image, 6 | MaaStringView task_name, MaaStringView custom_recognition_param, 7 | MaaTransparentArg recognizer_arg, MaaRectHandle out_box, 8 | MaaStringBufferHandle detail_buff)) 9 | { 10 | _recognizers.emplace_back(name, recognizer_analyze); 11 | } 12 | 13 | void CustomRecognizerRegistrar::register_recognizers(MaaInstanceHandle maa_handle) 14 | { 15 | for (const auto& recognizer : _recognizers) { 16 | std::shared_ptr custom_recognizer = 17 | std::make_shared(recognizer.get_custom_recognizer()); 18 | _custom_recognizers.push_back(custom_recognizer); 19 | MaaRegisterCustomRecognizer(maa_handle, recognizer.get_name().c_str(), custom_recognizer.get(), nullptr); 20 | } 21 | } -------------------------------------------------------------------------------- /source/cli/CustomRecognizer/CustomRecognizerRegistrar.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "CustomRecognizer.h" 8 | #include "MaaFramework/Instance/MaaInstance.h" 9 | #include "MaaFramework/Task/MaaCustomRecognizer.h" 10 | 11 | class CustomRecognizerRegistrar 12 | { 13 | public: 14 | CustomRecognizerRegistrar() = default; 15 | ~CustomRecognizerRegistrar() = default; 16 | 17 | public: 18 | void add_recognizer(const std::string& name, 19 | MaaBool (*recognizer_analyze)(MaaSyncContextHandle sync_context, 20 | const MaaImageBufferHandle image, MaaStringView task_name, 21 | MaaStringView custom_recognition_param, 22 | MaaTransparentArg recognizer_arg, MaaRectHandle out_box, 23 | MaaStringBufferHandle detail_buff)); 24 | void register_recognizers(MaaInstanceHandle maa_handle); 25 | 26 | private: 27 | std::vector _recognizers; 28 | std::vector> _custom_recognizers; 29 | }; -------------------------------------------------------------------------------- /source/cli/CustomRecognizer/CustomRecognizerRegistry.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CustomRecognizerRegistrar.h" 4 | 5 | #include "CombatRecognizer.h" 6 | 7 | void custom_recognizer_init(CustomRecognizerRegistrar& registrar) 8 | { 9 | registrar.add_recognizer("Combating", combat_combating); 10 | } 11 | 12 | void register_custom_recognizer(MaaInstanceHandle maa_handle, CustomRecognizerRegistrar& registerar) 13 | { 14 | custom_recognizer_init(registerar); 15 | registerar.register_recognizers(maa_handle); 16 | } -------------------------------------------------------------------------------- /source/cli/control.cpp: -------------------------------------------------------------------------------- 1 | #include "control.h" 2 | 3 | bool default_control_init(ControlConfig& control) 4 | { 5 | int server = 0; 6 | if (!select_server(server)) { 7 | return false; 8 | } 9 | control.set_config_server(server); 10 | return true; 11 | } 12 | 13 | bool select_server(int& server) 14 | { 15 | std::cout << std::endl 16 | << "Please select server number: " << std::endl 17 | << std::endl 18 | << " 1. Official(CN)\n" 19 | " 2. Bilibili\n" 20 | " 3. Vivo\n" 21 | << std::endl 22 | << "Please enter the server number: " << std::endl; 23 | 24 | std::cin >> server; 25 | 26 | if (server < 1 || server > 3) { 27 | std::cout << "Unknown server number: " << server << std::endl; 28 | return false; 29 | } 30 | 31 | return true; 32 | } 33 | 34 | bool app_package_and_activity(int server_type, std::string& package, std::string& activity) 35 | { 36 | switch (server_type) { 37 | case 1: 38 | // "1. Official(CN)\n" 39 | package = "com.miHoYo.enterprise.NGHSoD"; 40 | activity = "com.miHoYo.enterprise.NGHSoD/com.miHoYo.overridenativeactivity.OverrideNativeActivity"; 41 | break; 42 | case 2: 43 | // "2. Bilibili\n" 44 | package = "com.miHoYo.bh3.bilibili"; 45 | activity = "com.miHoYo.bh3.bilibili/com.miHoYo.overridenativeactivity.OverrideNativeActivity"; 46 | break; 47 | case 3: 48 | // "2. Vivo\n" 49 | package = "com.miHoYo.bh3.vivo"; 50 | activity = "com.miHoYo.bh3.vivo/com.miHoYo.overridenativeactivity.OverrideNativeActivity"; 51 | break; 52 | default: 53 | return false; 54 | } 55 | 56 | return true; 57 | } -------------------------------------------------------------------------------- /source/cli/control.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Config/ControlConfig.h" 4 | 5 | bool default_control_init(ControlConfig& control); 6 | 7 | bool select_server(int& server); 8 | 9 | bool app_package_and_activity(int client_type, std::string& package, std::string& activity); -------------------------------------------------------------------------------- /source/cli/device.cpp: -------------------------------------------------------------------------------- 1 | #include "device.h" 2 | 3 | bool default_device_init(DeviceConfig& device) 4 | { 5 | std::string name, SN, adb; 6 | if (!select_device(name, SN, adb)) { 7 | return false; 8 | } 9 | device.set_config_device_name(name); 10 | device.set_config_device_SN(SN); 11 | device.set_config_adb(adb); 12 | return true; 13 | } 14 | 15 | MaaSize scanning_devices() 16 | { 17 | std::cout << "Scanning for Devices..." << std::endl; 18 | MaaToolkitPostFindDevice(); 19 | auto device_size = MaaToolkitWaitForFindDeviceToComplete(); 20 | if (device_size == 0) { 21 | std::cout << "No Devices Found" << std::endl; 22 | return 0; 23 | } 24 | std::cout << "Scanning Finished" << std::endl; 25 | return device_size; 26 | } 27 | 28 | bool select_device(std::string& name, std::string& SN, std::string& adb) 29 | { 30 | auto device_size = scanning_devices(); 31 | if (!device_size) { 32 | if (!manually_enter_device_info(name, SN, adb)) { 33 | return false; 34 | } 35 | return true; 36 | } 37 | MaaSize number = 0; 38 | if (!select_device_number(device_size, number)) { 39 | return false; 40 | } 41 | if (!number) { 42 | if (!manually_enter_device_info(name, SN, adb)) { 43 | return false; 44 | } 45 | return true; 46 | } 47 | MaaSize device_index = number - 1; 48 | name = MaaToolkitGetDeviceName(device_index); 49 | SN = MaaToolkitGetDeviceAdbSerial(device_index); 50 | adb = MaaToolkitGetDeviceAdbPath(device_index); 51 | return true; 52 | } 53 | 54 | bool select_device_number(const MaaSize& device_size, MaaSize& number) 55 | { 56 | std::cout << std::endl << "Please select a device:" << std::endl << std::endl; 57 | std::cout << " 0. Manual" << std::endl; 58 | print_device_list(device_size); 59 | std::cout << std::endl << "Please enter option number:" << std::endl; 60 | 61 | std::cin >> number; 62 | std::cin.ignore(); 63 | 64 | if (number > device_size) { 65 | std::cout << std::endl << "Unknown option number: " << number << std::endl; 66 | return false; 67 | } 68 | 69 | return true; 70 | } 71 | 72 | void print_device_list(const MaaSize& device_size) 73 | { 74 | for (MaaSize i = 0; i < device_size; i++) { 75 | std::cout << " " << i + 1 << ". " << MaaToolkitGetDeviceName(i) << " (" << MaaToolkitGetDeviceAdbSerial(i) 76 | << ")\n"; 77 | } 78 | } 79 | 80 | bool manually_enter_device_info(std::string& name, std::string& SN, std::string& adb) 81 | { 82 | if (!manually_enter_device_name(name)) { 83 | return false; 84 | } 85 | if (!manually_enter_device_SN(SN)) { 86 | return false; 87 | } 88 | if (!manually_enter_device_adb(adb)) { 89 | return false; 90 | } 91 | return true; 92 | } 93 | 94 | bool manually_enter_device_name(std::string& name) 95 | { 96 | std::cout << std::endl << "Please enter device name: " << std::endl; 97 | std::getline(std::cin, name); 98 | if (name.empty()) { 99 | return false; 100 | } 101 | return true; 102 | } 103 | 104 | bool manually_enter_device_SN(std::string& SN) 105 | { 106 | std::cout << std::endl << "Please enter device serial number: " << std::endl; 107 | std::getline(std::cin, SN); 108 | if (SN.empty()) { 109 | return false; 110 | } 111 | return true; 112 | } 113 | 114 | bool manually_enter_device_adb(std::string& adb) 115 | { 116 | std::cout << std::endl << "Please enter adb path: " << std::endl; 117 | std::getline(std::cin, adb); 118 | if (adb.empty()) { 119 | return false; 120 | } 121 | return true; 122 | } -------------------------------------------------------------------------------- /source/cli/device.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "Config/DeviceConfig.h" 7 | 8 | bool default_device_init(DeviceConfig& device); 9 | 10 | MaaSize scanning_devices(); 11 | 12 | bool select_device(std::string& name, std::string& SN, std::string& adb); 13 | 14 | bool select_device_number(const MaaSize& device_size, MaaSize& number); 15 | 16 | void print_device_list(const MaaSize& device_size); 17 | 18 | bool manually_enter_device_info(std::string& name, std::string& SN, std::string& adb); 19 | 20 | bool manually_enter_device_name(std::string& name); 21 | 22 | bool manually_enter_device_SN(std::string& SN); 23 | 24 | bool manually_enter_device_adb(std::string& adb); -------------------------------------------------------------------------------- /source/cli/main.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include "Config/ConfigMgr.h" 13 | 14 | #include "CustomAction/CustomActionRegistry.h" 15 | #include "CustomRecognizer/CustomRecognizerRegistry.h" 16 | 17 | #include "control.h" 18 | #include "device.h" 19 | #include "tasks.h" 20 | 21 | bool parse_param(int argc, char** argv, std::unordered_map& options, 22 | std::unordered_map& flags); 23 | 24 | void print_help(); 25 | 26 | void print_version(); 27 | 28 | std::string get_default_adb_config(); 29 | 30 | void mpause(); -------------------------------------------------------------------------------- /source/cli/meojson/.clang-format: -------------------------------------------------------------------------------- 1 | Language: Json 2 | ColumnLimit: 1000 3 | IndentWidth: 4 4 | --- 5 | Language: Cpp 6 | AccessModifierOffset: -4 7 | AlignAfterOpenBracket: Align 8 | AlignArrayOfStructures: None 9 | AlignConsecutiveMacros: None 10 | AlignConsecutiveAssignments: None 11 | AlignConsecutiveBitFields: None 12 | AlignConsecutiveDeclarations: None 13 | AlignEscapedNewlines: Left 14 | AlignOperands: Align 15 | AlignTrailingComments: true 16 | AllowAllArgumentsOnNextLine: true 17 | AllowAllParametersOfDeclarationOnNextLine: true 18 | AllowShortEnumsOnASingleLine: false 19 | AllowShortBlocksOnASingleLine: Empty 20 | AllowShortCaseLabelsOnASingleLine: false 21 | AllowShortFunctionsOnASingleLine: Inline 22 | AllowShortLambdasOnASingleLine: All 23 | AllowShortIfStatementsOnASingleLine: WithoutElse 24 | AllowShortLoopsOnASingleLine: false 25 | AlwaysBreakAfterDefinitionReturnType: None 26 | AlwaysBreakAfterReturnType: None 27 | AlwaysBreakBeforeMultilineStrings: false 28 | AlwaysBreakTemplateDeclarations: true 29 | AttributeMacros: 30 | - __capability 31 | BinPackArguments: true 32 | BinPackParameters: true 33 | BraceWrapping: 34 | AfterCaseLabel: false 35 | AfterClass: true 36 | AfterControlStatement: Never 37 | AfterEnum: true 38 | AfterFunction: true 39 | AfterNamespace: true 40 | AfterObjCDeclaration: true 41 | AfterStruct: true 42 | AfterUnion: false 43 | AfterExternBlock: true 44 | BeforeCatch: true 45 | BeforeElse: true 46 | BeforeLambdaBody: false 47 | BeforeWhile: false 48 | IndentBraces: false 49 | SplitEmptyFunction: false 50 | SplitEmptyRecord: false 51 | SplitEmptyNamespace: false 52 | BreakBeforeBinaryOperators: None 53 | BreakBeforeConceptDeclarations: true 54 | BreakBeforeBraces: Custom 55 | BreakBeforeInheritanceComma: false 56 | BreakInheritanceList: BeforeColon 57 | BreakBeforeTernaryOperators: true 58 | BreakConstructorInitializersBeforeComma: false 59 | BreakConstructorInitializers: BeforeColon 60 | BreakAfterJavaFieldAnnotations: false 61 | BreakStringLiterals: true 62 | ColumnLimit: 120 63 | CommentPragmas: '^ IWYU pragma:' 64 | QualifierAlignment: Leave 65 | CompactNamespaces: false 66 | ConstructorInitializerIndentWidth: 4 67 | ContinuationIndentWidth: 4 68 | Cpp11BracedListStyle: false 69 | DeriveLineEnding: true 70 | DerivePointerAlignment: false 71 | DisableFormat: false 72 | EmptyLineAfterAccessModifier: Never 73 | EmptyLineBeforeAccessModifier: LogicalBlock 74 | ExperimentalAutoDetectBinPacking: false 75 | PackConstructorInitializers: BinPack 76 | BasedOnStyle: '' 77 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 78 | AllowAllConstructorInitializersOnNextLine: true 79 | FixNamespaceComments: true 80 | ForEachMacros: 81 | - foreach 82 | - Q_FOREACH 83 | - BOOST_FOREACH 84 | IfMacros: 85 | - KJ_IF_MAYBE 86 | IncludeBlocks: Preserve 87 | IncludeCategories: 88 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/' 89 | Priority: 2 90 | SortPriority: 0 91 | CaseSensitive: false 92 | - Regex: '^(<|"(gtest|gmock|isl|json)/)' 93 | Priority: 3 94 | SortPriority: 0 95 | CaseSensitive: false 96 | - Regex: '.*' 97 | Priority: 1 98 | SortPriority: 0 99 | CaseSensitive: false 100 | IncludeIsMainRegex: '(Test)?$' 101 | IncludeIsMainSourceRegex: '' 102 | IndentAccessModifiers: false 103 | IndentCaseLabels: false 104 | IndentCaseBlocks: false 105 | IndentGotoLabels: true 106 | IndentPPDirectives: None 107 | IndentExternBlock: AfterExternBlock 108 | IndentRequiresClause: false 109 | IndentWidth: 4 110 | IndentWrappedFunctionNames: false 111 | InsertTrailingCommas: None 112 | JavaScriptQuotes: Leave 113 | JavaScriptWrapImports: true 114 | KeepEmptyLinesAtTheStartOfBlocks: true 115 | LambdaBodyIndentation: Signature 116 | MacroBlockBegin: '' 117 | MacroBlockEnd: '' 118 | MaxEmptyLinesToKeep: 1 119 | NamespaceIndentation: Inner 120 | ObjCBinPackProtocolList: Auto 121 | ObjCBlockIndentWidth: 2 122 | ObjCBreakBeforeNestedBlockParam: true 123 | ObjCSpaceAfterProperty: false 124 | ObjCSpaceBeforeProtocolList: true 125 | PenaltyBreakAssignment: 2 126 | PenaltyBreakBeforeFirstCallParameter: 19 127 | PenaltyBreakComment: 300 128 | PenaltyBreakFirstLessLess: 120 129 | PenaltyBreakOpenParenthesis: 0 130 | PenaltyBreakString: 1000 131 | PenaltyBreakTemplateDeclaration: 10 132 | PenaltyExcessCharacter: 1000000 133 | PenaltyReturnTypeOnItsOwnLine: 1000 134 | PenaltyIndentedWhitespace: 0 135 | PointerAlignment: Left 136 | PPIndentWidth: -1 137 | ReferenceAlignment: Pointer 138 | ReflowComments: true 139 | RemoveBracesLLVM: false 140 | RequiresClausePosition: OwnLine 141 | SeparateDefinitionBlocks: Leave 142 | ShortNamespaceLines: 50 143 | SortIncludes: CaseSensitive 144 | SortJavaStaticImport: Before 145 | SortUsingDeclarations: true 146 | SpaceAfterCStyleCast: false 147 | SpaceAfterLogicalNot: false 148 | SpaceAfterTemplateKeyword: true 149 | SpaceBeforeAssignmentOperators: true 150 | SpaceBeforeCaseColon: false 151 | SpaceBeforeCpp11BracedList: true 152 | SpaceBeforeCtorInitializerColon: true 153 | SpaceBeforeInheritanceColon: true 154 | SpaceBeforeParens: ControlStatements 155 | SpaceBeforeParensOptions: 156 | AfterControlStatements: true 157 | AfterForeachMacros: true 158 | AfterFunctionDefinitionName: false 159 | AfterFunctionDeclarationName: false 160 | AfterIfMacros: true 161 | AfterOverloadedOperator: false 162 | AfterRequiresInClause: true 163 | AfterRequiresInExpression: true 164 | BeforeNonEmptyParentheses: false 165 | SpaceAroundPointerQualifiers: Default 166 | SpaceBeforeRangeBasedForLoopColon: true 167 | SpaceInEmptyBlock: false 168 | SpaceInEmptyParentheses: false 169 | SpacesBeforeTrailingComments: 1 170 | SpacesInAngles: Never 171 | SpacesInConditionalStatement: false 172 | SpacesInContainerLiterals: true 173 | SpacesInCStyleCastParentheses: false 174 | SpacesInLineCommentPrefix: 175 | Minimum: 1 176 | Maximum: -1 177 | SpacesInParentheses: false 178 | SpacesInSquareBrackets: false 179 | SpaceBeforeSquareBrackets: false 180 | BitFieldColonSpacing: Both 181 | Standard: c++20 182 | StatementAttributeLikeMacros: 183 | - Q_EMIT 184 | StatementMacros: 185 | - Q_UNUSED 186 | - QT_REQUIRE_VERSION 187 | TabWidth: 4 188 | UseCRLF: false 189 | UseTab: Never 190 | WhitespaceSensitiveMacros: 191 | - STRINGIZE 192 | - PP_STRINGIZE 193 | - BOOST_PP_STRINGIZE 194 | - NS_SWIFT_NAME 195 | - CF_SWIFT_NAME 196 | -------------------------------------------------------------------------------- /source/cli/meojson/bitops.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if __cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) 4 | #include 5 | namespace json::__bitops { 6 | using std::countl_one; 7 | using std::countr_one; 8 | using std::countl_zero; 9 | using std::countr_zero; 10 | inline constexpr bool is_little_endian() { 11 | return std::endian::native == std::endian::little; 12 | } 13 | } 14 | #else 15 | #include 16 | namespace json::__bitops { 17 | #if defined(__GNUC__) || defined(__clang__) 18 | inline constexpr int countl_zero(uint32_t x) { 19 | if constexpr (sizeof(uint32_t) == sizeof(unsigned int)) 20 | return x == 0 ? 32 : __builtin_clz(x); 21 | if constexpr (sizeof(uint32_t) == sizeof(unsigned long)) 22 | return x == 0 ? 32 : __builtin_clzl(x); 23 | return x == 0 ? 32 : __builtin_clzll(x); 24 | } 25 | inline constexpr int countr_zero(uint32_t x) { 26 | if constexpr (sizeof(uint32_t) == sizeof(unsigned int)) 27 | return x == 0 ? 32 : __builtin_ctz(x); 28 | if constexpr (sizeof(uint32_t) == sizeof(unsigned long)) 29 | return x == 0 ? 32 : __builtin_ctzl(x); 30 | return x == 0 ? 32 : __builtin_ctzll(x); 31 | } 32 | inline constexpr int countl_zero(uint64_t x) { 33 | return x == 0 ? 64 : __builtin_clzll(x); 34 | } 35 | inline constexpr int countr_zero(uint64_t x) { 36 | return x == 0 ? 64 : __builtin_ctzll(x); 37 | } 38 | #elif defined(_MSC_VER) 39 | #ifdef __AVX2__ 40 | // lzcnt intrinsics is not constexpr 41 | inline int countl_zero(uint32_t x) { 42 | return __lzcnt(x); 43 | } 44 | inline int countr_zero(uint32_t x) { 45 | return _tzcnt_u32(x); 46 | } 47 | inline int countl_zero(uint64_t x) { 48 | return (int)__lzcnt64(x); 49 | } 50 | inline int countr_zero(uint64_t x) { 51 | return (int)_tzcnt_u64(x); 52 | } 53 | #else 54 | inline constexpr int countl_zero(uint32_t x) { 55 | unsigned long index = 0; 56 | return _BitScanReverse(&index, x) ? 31 - index : 32; 57 | } 58 | inline constexpr int countr_zero(uint32_t x) { 59 | unsigned long index = 0; 60 | return _BitScanForward(&index, x) ? index : 32; 61 | } 62 | inline constexpr int countl_zero(uint64_t x) { 63 | unsigned long index = 0; 64 | return _BitScanReverse64(&index, x) ? 63 - index : 64; 65 | } 66 | inline constexpr int countr_zero(uint64_t x) { 67 | unsigned long index = 0; 68 | return _BitScanForward64(&index, x) ? index : 64; 69 | } 70 | #endif // __AVX2__ 71 | #else // compiler 72 | #error "bring your own bit counting implementation" 73 | #endif 74 | inline int countl_one(uint32_t x) { return countl_zero(~x); } 75 | inline int countr_one(uint32_t x) { return countr_zero(~x); } 76 | inline int countl_one(uint64_t x) { return countl_zero(~x); } 77 | inline int countr_one(uint64_t x) { return countr_zero(~x); } 78 | 79 | // no constexpr endian awareness before C++20 80 | inline bool is_little_endian() { 81 | union { 82 | uint32_t u32; 83 | uint8_t u8; 84 | } u = { 0x01020304 }; 85 | return u.u8 == 4; 86 | } 87 | } 88 | #endif // C++20 89 | -------------------------------------------------------------------------------- /source/cli/meojson/packed_bytes.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include "bitops.hpp" 6 | 7 | #if defined(__GNUC__) || defined(__clang__) 8 | #define __packed_bytes_strong_inline __attribute__((always_inline)) 9 | #elif defined(_MSC_VER) 10 | #define __packed_bytes_strong_inline __forceinline 11 | #else 12 | #define __packed_bytes_strong_inline inline 13 | #endif 14 | 15 | struct packed_bytes_trait_none { 16 | static constexpr bool available = false; 17 | }; 18 | 19 | template 20 | struct packed_bytes { 21 | using traits = packed_bytes_trait_none; 22 | }; 23 | 24 | #if defined(__SSE2__) || defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP) 25 | #include "packed_bytes_x86.hpp" 26 | #elif defined(__ARM_NEON) || defined(_M_ARM) || defined(_M_ARM64) 27 | #include "packed_bytes_arm.hpp" 28 | #endif 29 | 30 | struct packed_bytes_trait_uint64 { 31 | static constexpr bool available = sizeof(void*) >= 8; 32 | static constexpr auto step = 8; 33 | using value_type = std::enable_if_t= 8, uint64_t>; 34 | 35 | __packed_bytes_strong_inline static value_type load_unaligned(const void *ptr) { 36 | value_type result; 37 | memcpy((void*)&result, ptr, 8); 38 | return result; 39 | } 40 | 41 | __packed_bytes_strong_inline static value_type less(value_type x, uint8_t n) { 42 | return (((x) - UINT64_C(0x0101010101010101) * (n)) & ~(x) & UINT64_C(0x8080808080808080)); 43 | } 44 | 45 | __packed_bytes_strong_inline static value_type is_zero_memberwise(value_type v) { 46 | return (((v) - UINT64_C(0x0101010101010101)) & ~(v) & UINT64_C(0x8080808080808080)); 47 | } 48 | 49 | __packed_bytes_strong_inline static bool is_all_zero(value_type v) 50 | { 51 | return v == UINT64_C(0); 52 | } 53 | 54 | __packed_bytes_strong_inline static value_type equal(value_type x, uint8_t n) { 55 | return is_zero_memberwise((x) ^ (UINT64_C(0x0101010101010101) * (n))); 56 | } 57 | 58 | __packed_bytes_strong_inline static value_type bitwise_or(value_type a, value_type b) { 59 | return a | b; 60 | } 61 | 62 | __packed_bytes_strong_inline static size_t first_nonzero_byte(value_type x) { 63 | if (json::__bitops::is_little_endian()) 64 | return json::__bitops::countr_zero(x) / 8; 65 | else 66 | return json::__bitops::countl_zero(x) / 8; 67 | } 68 | }; 69 | 70 | struct packed_bytes_trait_uint32 { 71 | static constexpr bool available = true; 72 | static constexpr auto step = 4; 73 | using value_type = uint32_t; 74 | 75 | __packed_bytes_strong_inline static value_type load_unaligned(const void *ptr) { 76 | value_type result; 77 | memcpy((void*)&result, ptr, 4); 78 | return result; 79 | } 80 | 81 | __packed_bytes_strong_inline static value_type less(value_type x, uint8_t n) { 82 | return (((x) - ~UINT32_C(0) / 255 * (n)) & ~(x) & ~UINT32_C(0) / 255 * 128); 83 | } 84 | 85 | __packed_bytes_strong_inline static value_type is_zero_memberwise(value_type v) { 86 | return (((v) - UINT32_C(0x01010101)) & ~(v) & UINT32_C(0x80808080));; 87 | } 88 | 89 | __packed_bytes_strong_inline static bool is_all_zero(value_type v) { 90 | return v == UINT32_C(0); 91 | } 92 | 93 | __packed_bytes_strong_inline static value_type equal(value_type x, uint8_t n) { 94 | return is_zero_memberwise((x) ^ (~UINT32_C(0) / 255 * (n))); 95 | } 96 | 97 | __packed_bytes_strong_inline static value_type bitwise_or(value_type a, value_type b) { 98 | return a | b; 99 | } 100 | 101 | __packed_bytes_strong_inline static size_t first_nonzero_byte(value_type x) { 102 | if (json::__bitops::is_little_endian()) 103 | return json::__bitops::countr_zero(x) / 8; 104 | else 105 | return json::__bitops::countl_zero(x) / 8; 106 | } 107 | }; 108 | template <> 109 | struct packed_bytes<8> { 110 | using traits = std::enable_if_t; 111 | }; 112 | 113 | template <> 114 | struct packed_bytes<4> { 115 | using traits = packed_bytes_trait_uint32; 116 | }; 117 | 118 | template 119 | using packed_bytes_trait = typename packed_bytes::traits; 120 | 121 | using packed_bytes_trait_max = std::conditional_t::available, packed_bytes_trait<32>, 122 | std::conditional_t::available, packed_bytes_trait<16>, 123 | std::conditional_t::available, packed_bytes_trait<8>, 124 | packed_bytes_trait<4> 125 | >>>; 126 | 127 | -------------------------------------------------------------------------------- /source/cli/meojson/packed_bytes_arm.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // current NEON implementation doesn't outperform 64-bit scalar implementation 4 | #ifdef MEOJSON_ENABLE_NEON 5 | #include "packed_bytes.hpp" 6 | #include 7 | 8 | #if defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64) 9 | #define __packed_bytes_trait_arm64 10 | #endif 11 | 12 | struct packed_bytes_trait_neon { 13 | static constexpr bool available = true; 14 | static constexpr auto step = 16; 15 | using value_type = uint8x16_t; 16 | 17 | __packed_bytes_strong_inline static value_type load_unaligned(const void *ptr) { 18 | return vld1q_u8((uint8_t*)ptr); 19 | } 20 | 21 | __packed_bytes_strong_inline static value_type less(value_type x, uint8_t n) { 22 | auto bcast = vdupq_n_u8(n); 23 | auto is_less = vcltq_u8(x, bcast); 24 | return is_less; 25 | } 26 | 27 | __packed_bytes_strong_inline static value_type equal(value_type x, uint8_t n) { 28 | return vceqq_u8(x, vdupq_n_u8(n)); 29 | } 30 | 31 | __packed_bytes_strong_inline static value_type equal(value_type x, value_type y) { 32 | return vceqq_u8(x, y); 33 | } 34 | 35 | __packed_bytes_strong_inline static value_type bitwise_or(value_type a, value_type b) { 36 | return vorrq_u8(a, b); 37 | } 38 | 39 | __packed_bytes_strong_inline static bool is_all_zero(value_type x) { 40 | #ifdef __packed_bytes_trait_arm64 41 | return vmaxvq_u8(x) == 0; 42 | #else 43 | auto fold64 = vorr_u64(vget_high_u64(vreinterpretq_u8_u64(x), 0), vget_low_u64(vreinterpretq_u8_u64(x), 1)); 44 | auto fold32 = vget_lane_u32(vreinterpret_u64_u32(fold64), 0) | vget_lane_u32(vreinterpret_u64_u32(fold64), 1); 45 | return fold32 == 0; 46 | #endif 47 | } 48 | 49 | __packed_bytes_strong_inline static size_t first_nonzero_byte(value_type x) { 50 | // https://community.arm.com/arm-community-blogs/b/infrastructure-solutions-blog/posts/porting-x86-vector-bitmask-optimizations-to-arm-neon 51 | auto cmp = equal(x, 0); 52 | auto res = vshrn_n_u16(cmp, 4); 53 | auto mask64 = vget_lane_u64(vreinterpret_u64_u8(res), 0); 54 | return json::__bitops::countr_one(mask64) >> 2; 55 | } 56 | }; 57 | 58 | template <> 59 | struct packed_bytes<16> { 60 | using traits = packed_bytes_trait_neon; 61 | }; 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /source/cli/meojson/packed_bytes_x86.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "packed_bytes.hpp" 3 | 4 | #include 5 | #if defined(__SSE4_1__) || defined(__AVX2__) || defined(_MSC_VER) 6 | // MSVC enables all SSE4.1 intrinsics by default 7 | #include 8 | #endif 9 | 10 | struct packed_bytes_trait_sse { 11 | static constexpr bool available = true; 12 | static constexpr auto step = 16; 13 | using value_type = __m128i; 14 | 15 | __packed_bytes_strong_inline static value_type load_unaligned(const void *ptr) { 16 | return _mm_loadu_si128(reinterpret_cast(ptr)); 17 | } 18 | 19 | __packed_bytes_strong_inline static value_type less(value_type x, uint8_t n) { 20 | auto bcast = _mm_set1_epi8(static_cast(n)); 21 | auto all1 = _mm_set1_epi8(-1); 22 | auto max_with_n = _mm_max_epu8(x, bcast); 23 | auto is_greater_or_equal = _mm_cmpeq_epi8(max_with_n, x); 24 | auto is_less = _mm_andnot_si128(is_greater_or_equal, all1); 25 | return is_less; 26 | } 27 | 28 | __packed_bytes_strong_inline static value_type equal(value_type x, uint8_t n) { 29 | return _mm_cmpeq_epi8(x, _mm_set1_epi8(static_cast(n))); 30 | } 31 | 32 | __packed_bytes_strong_inline static value_type equal(value_type x, value_type y) { 33 | return _mm_cmpeq_epi8(x, y); 34 | } 35 | 36 | __packed_bytes_strong_inline static value_type bitwise_or(value_type a, value_type b) { 37 | return _mm_or_si128(a, b); 38 | } 39 | 40 | __packed_bytes_strong_inline static bool is_all_zero(value_type x) { 41 | #if defined(__SSE4_1__) || defined(__AVX2__) || defined(_MSC_VER) 42 | // SSE4.1 path 43 | return !!_mm_testz_si128(x, x); 44 | #else 45 | // SSE2 path 46 | auto cmp = _mm_cmpeq_epi8(x, _mm_set1_epi8(0)); 47 | auto mask = (uint16_t)_mm_movemask_epi8(cmp); 48 | return mask == UINT16_C(0xFFFF); 49 | #endif 50 | } 51 | 52 | __packed_bytes_strong_inline static size_t first_nonzero_byte(value_type x) { 53 | auto cmp = _mm_cmpeq_epi8(x, _mm_set1_epi8(0)); 54 | auto mask = (uint16_t)_mm_movemask_epi8(cmp); 55 | return json::__bitops::countr_one((uint32_t)mask); 56 | } 57 | }; 58 | 59 | template <> 60 | struct packed_bytes<16> { 61 | using traits = packed_bytes_trait_sse; 62 | }; 63 | 64 | 65 | #ifdef __AVX2__ 66 | #include 67 | 68 | struct packed_bytes_trait_avx2 69 | { 70 | static constexpr bool available = true; 71 | static constexpr auto step = 32; 72 | using value_type = __m256i; 73 | 74 | __packed_bytes_strong_inline static value_type load_unaligned(const void* ptr) 75 | { 76 | return _mm256_loadu_si256(reinterpret_cast(ptr)); 77 | } 78 | 79 | __packed_bytes_strong_inline static value_type less(value_type x, uint8_t n) 80 | { 81 | auto bcast = _mm256_set1_epi8(static_cast(n)); 82 | auto all1 = _mm256_set1_epi8(-1); 83 | auto max_with_n = _mm256_max_epu8(x, bcast); 84 | auto is_greater_or_equal = _mm256_cmpeq_epi8(max_with_n, x); 85 | auto is_less = _mm256_andnot_si256(is_greater_or_equal, all1); 86 | return is_less; 87 | } 88 | 89 | __packed_bytes_strong_inline static value_type equal(value_type x, uint8_t n) 90 | { 91 | return _mm256_cmpeq_epi8(x, _mm256_set1_epi8(static_cast(n))); 92 | } 93 | 94 | __packed_bytes_strong_inline static value_type equal(value_type x, value_type y) 95 | { 96 | return _mm256_cmpeq_epi8(x, y); 97 | } 98 | 99 | __packed_bytes_strong_inline static value_type bitwise_or(value_type a, value_type b) 100 | { 101 | return _mm256_or_si256(a, b); 102 | } 103 | 104 | __packed_bytes_strong_inline static bool is_all_zero(value_type x) 105 | { 106 | return (bool)_mm256_testz_si256(x, x); 107 | } 108 | 109 | __packed_bytes_strong_inline static size_t first_nonzero_byte(value_type x) 110 | { 111 | auto cmp = _mm256_cmpeq_epi8(x, _mm256_set1_epi8(0)); 112 | auto mask = (uint32_t)_mm256_movemask_epi8(cmp); 113 | // AVX512 alternative: _mm_cmpeq_epi8_mask 114 | return json::__bitops::countr_one(mask); 115 | } 116 | }; 117 | 118 | template <> 119 | struct packed_bytes<32> { 120 | using traits = packed_bytes_trait_avx2; 121 | }; 122 | 123 | #endif 124 | -------------------------------------------------------------------------------- /source/cli/tasks.cpp: -------------------------------------------------------------------------------- 1 | #include "tasks.h" 2 | 3 | bool default_tasks_init(TasksConfig& tasks) 4 | { 5 | std::vector tasklist; 6 | if (!select_tasks(tasklist)) { 7 | return false; 8 | } 9 | tasks.set_config_tasklist(tasklist); 10 | return true; 11 | } 12 | 13 | bool select_tasks(std::vector& tasklist) 14 | { 15 | std::cout << std::endl 16 | << "Please select tasks: " << std::endl 17 | << std::endl 18 | << " 1. Dorm\n" 19 | " 2. MaterialEvent\n" 20 | " 3. Armada\n" 21 | " 4. Shop\n" 22 | " 5. Awards\n" 23 | " 6. UniversalMirage\n" 24 | << std::endl 25 | << "Please enter the task numbers to be executed: " << std::endl; 26 | std::vector task_ids; 27 | std::string line; 28 | 29 | if (std::cin.rdbuf()->in_avail() > 0) { 30 | std::cin.ignore(std::numeric_limits::max(), '\n'); 31 | } 32 | std::getline(std::cin, line); 33 | 34 | std::istringstream iss(line); 35 | int task_id; 36 | while (iss >> task_id) { 37 | task_ids.emplace_back(task_id); 38 | } 39 | 40 | int index = 1; 41 | for (auto id : task_ids) { 42 | Task task_obj; 43 | task_obj.name = "MyTask" + std::to_string(index++); 44 | 45 | switch (id) { 46 | case 1: 47 | task_obj.type = "Dorm"; 48 | task_obj.param = dorm_param(); 49 | break; 50 | case 2: 51 | task_obj.type = "MaterialEvent"; 52 | break; 53 | case 3: 54 | task_obj.type = "Armada"; 55 | break; 56 | case 4: 57 | task_obj.type = "Shop"; 58 | break; 59 | case 5: 60 | task_obj.type = "Awards"; 61 | break; 62 | case 6: 63 | task_obj.type = "UniversalMirage"; 64 | task_obj.param = universal_mirage_param(); 65 | break; 66 | 67 | default: 68 | std::cout << "Unknown task: " << id << std::endl; 69 | return false; 70 | } 71 | tasklist.emplace_back(std::move(task_obj)); 72 | } 73 | Task close_game_task; 74 | close_game_task.name = "CloseGame"; 75 | close_game_task.status = false; 76 | close_game_task.param = close_game_param(); 77 | close_game_task.type = "CloseBH3"; 78 | 79 | tasklist.emplace_back(std::move(close_game_task)); 80 | 81 | return true; 82 | } 83 | 84 | json::value dorm_param() 85 | { 86 | json::value param; 87 | auto& diff = param["diff_task"]; 88 | auto& doc = diff["Sub_SwitchToFragmentPage"]["doc"]; 89 | auto& enabled = diff["Sub_SwitchToFragmentPage"]["enabled"]; 90 | 91 | doc = "切换刷最近碎片;默认false,刷最近材料"; 92 | enabled = false; 93 | 94 | return param; 95 | } 96 | 97 | json::value universal_mirage_param() 98 | { 99 | json::value param; 100 | auto& diff = param["diff_task"]; 101 | auto& costing_time_swirl_passes_doc = diff["UniversalMirageCostingTimeSwirlPasses"]["doc"]; 102 | auto& costing_time_swirl_passes_enabled = diff["UniversalMirageCostingTimeSwirlPasses"]["enabled"]; 103 | auto& glacial_fences_doc = diff["Sub_EnterGlacialFencesPage"]["doc"]; 104 | auto& glacial_fences_enabled = diff["Sub_EnterGlacialFencesPage"]["enabled"]; 105 | auto& illuminated_land_doc = diff["Sub_EnterIlluminatedLandPage"]["doc"]; 106 | auto& illuminated_land_enabled = diff["Sub_EnterIlluminatedLandPage"]["enabled"]; 107 | auto& roaring_palace_doc = diff["Sub_EnterRoaringPalacePage"]["doc"]; 108 | auto& roaring_palace_enabled = diff["Sub_EnterRoaringPalacePage"]["enabled"]; 109 | auto& blade_grave_doc = diff["Sub_EnterBladeGravePage"]["doc"]; 110 | auto& blade_grave_enabled = diff["Sub_EnterBladeGravePage"]["enabled"]; 111 | auto& stage_f2_doc = diff["UniversalMirageStageF2"]["doc"]; 112 | auto& stage_f2_enabled = diff["UniversalMirageStageF2"]["enabled"]; 113 | 114 | costing_time_swirl_passes_doc = "花费时序通行证;默认false"; 115 | costing_time_swirl_passes_enabled = false; 116 | glacial_fences_doc = "幽寒之槛"; 117 | glacial_fences_enabled = true; 118 | illuminated_land_doc = "煌然之地"; 119 | illuminated_land_enabled = false; 120 | roaring_palace_doc = "轰鸣之殿"; 121 | roaring_palace_enabled = false; 122 | blade_grave_doc = "千刃之冢"; 123 | blade_grave_enabled = false; 124 | stage_f2_doc = "第二层"; 125 | stage_f2_enabled = true; 126 | 127 | return param; 128 | } 129 | 130 | json::value close_game_param() 131 | { 132 | json::value param; 133 | auto& diff = param["diff_task"]; 134 | auto& close_bh3 = diff["CloseBH3"]["enabled"]; 135 | auto& close_bh3_doc = diff["CloseBH3"]["doc"]; 136 | 137 | close_bh3 = false; 138 | close_bh3_doc = "关闭崩坏3;默认false"; 139 | 140 | return param; 141 | } 142 | 143 | std::string TaskStatus(MaaStatus status) 144 | { 145 | std::string task_status; 146 | switch (status) { 147 | case MaaStatus_Invalid: 148 | task_status = "Invalid"; 149 | break; 150 | case MaaStatus_Pending: 151 | task_status = "Pending"; 152 | break; 153 | case MaaStatus_Running: 154 | task_status = "Running"; 155 | break; 156 | case MaaStatus_Success: 157 | task_status = "Success"; 158 | break; 159 | case MaaStatus_Failed: 160 | task_status = "Failed"; 161 | break; 162 | default: 163 | task_status = "Unknown"; 164 | } 165 | return task_status; 166 | } -------------------------------------------------------------------------------- /source/cli/tasks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "meojson/json.hpp" 4 | #include 5 | 6 | #include "Config/TasksConfig.h" 7 | 8 | bool default_tasks_init(TasksConfig& tasks); 9 | 10 | bool select_tasks(std::vector& tasklist); 11 | 12 | json::value dorm_param(); 13 | 14 | json::value universal_mirage_param(); 15 | 16 | json::value close_game_param(); 17 | 18 | std::string TaskStatus(MaaStatus status); -------------------------------------------------------------------------------- /tools/ChangelogGenerator/.gitignore: -------------------------------------------------------------------------------- 1 | contributors.json 2 | -------------------------------------------------------------------------------- /tools/ChangelogGenerator/start.bat: -------------------------------------------------------------------------------- 1 | python changelog_generator.py 2 | pause -------------------------------------------------------------------------------- /tools/CombatGenerator/.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # pdm 105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 106 | #pdm.lock 107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 108 | # in version control. 109 | # https://pdm.fming.dev/#use-with-ide 110 | .pdm.toml 111 | .pdm-python 112 | .pdm-build/ 113 | 114 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 115 | __pypackages__/ 116 | 117 | # Celery stuff 118 | celerybeat-schedule 119 | celerybeat.pid 120 | 121 | # SageMath parsed files 122 | *.sage.py 123 | 124 | # Environments 125 | .env 126 | .venv/ 127 | env/ 128 | venv/ 129 | ENV/ 130 | env.bak/ 131 | venv.bak/ 132 | 133 | # Spyder project settings 134 | .spyderproject 135 | .spyproject 136 | 137 | # Rope project settings 138 | .ropeproject 139 | 140 | # mkdocs documentation 141 | /site 142 | 143 | # mypy 144 | .mypy_cache/ 145 | .dmypy.json 146 | dmypy.json 147 | 148 | # Pyre type checker 149 | .pyre/ 150 | 151 | # pytype static type analyzer 152 | .pytype/ 153 | 154 | # Cython debug symbols 155 | cython_debug/ 156 | 157 | # PyCharm 158 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 159 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 160 | # and can be added to the global gitignore or merged into this file. For a more nuclear 161 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 162 | #.idea/ 163 | .vscode/ 164 | -------------------------------------------------------------------------------- /tools/CombatGenerator/README.md: -------------------------------------------------------------------------------- 1 | # CombatGenerator 2 | 3 | ## 环境 4 | 5 | 需要 `python` 环境 6 | 7 | ## 依赖 8 | 9 | ### ⚠️在.tools/CombatGenerator目录下执行所有命令 10 | 11 | (如果已经安装过pipx和pdm可以跳过直接使用pdm install) 12 | 13 | ```shell 14 | python -m pip install pipx 15 | pipx ensurepath 16 | ``` 17 | 18 | 重启终端 19 | 20 | ```shell 21 | pipx install pdm 22 | pdm install 23 | ``` 24 | 25 | ## 使用 26 | 27 | 输入文件需预先保存到 `.tools/CombatGenerator/data/` 路径下, 28 | 产物如果没有使用可选参数将会使用默认值保存在 `.tools/CombatGenerator/data/output.json` 路径下 29 | 30 | 打开cmd, 执行以下命令 31 | 32 | ```shell 33 | .venv\Scripts\Activate.ps1 34 | cd src/combatgenerator 35 | pdm run python __init__.py 36 | ``` 37 | 38 | ## 可选参数 39 | 40 | ### 反序列器 将生成的combatJson反序列化为输入的结构体 41 | 42 | -r 43 | 44 | ### 传入路径 45 | 46 | -i path/to/yourfile.json(绝对路径) 47 | 48 | ### 输出路径 49 | 50 | -o path/to/yourfile.json(绝对路径) 51 | 52 | ### e.g. 53 | 54 | 例如我想使用反序列器,传入路径为F:/1.json, 输出路径为F:/2.json 55 | 56 | pdm run python __init__.py -r -i F:/1.json -o F:/2.json 57 | 58 | ## input说明 59 | 60 | `"BasicATK": [ 61 | 0, 62 | 30 63 | ]`中[0, 30]表示`pre_delay=0`, `post_delay=30`。 64 | 若不填则根据下表填入默认值 65 | 66 | | Action | Pre Delay | Post Delay | 67 | |----------------|-----------|------------| 68 | | Forward | 0 | 50 | 69 | | Backward | 0 | 50 | 70 | | Left | 0 | 50 | 71 | | Right | 0 | 50 | 72 | | LeftForward | 0 | 50 | 73 | | LeftBackward | 0 | 50 | 74 | | RightForward | 0 | 50 | 75 | | RightBackward | 0 | 50 | 76 | | BasicATK | 0 | 200 | 77 | | BasicATKCharge | 0 | 100 | 78 | | Evade | 0 | 150 | 79 | | Ultimate | 0 | 150 | 80 | | UltimateCharge | 0 | 100 | 81 | | WeaponSkill | 0 | 150 | 82 | | ELFSkill | 0 | 150 | 83 | | ExtraSkill | 0 | 100 | 84 | | QTE1 | 0 | 200 | 85 | | QTE2 | 0 | 200 | 86 | 87 | { 88 | "mode": "[关卡类型]", 89 | "role": "[女武神名称]", 90 | "version": "[版本]", 91 | "combat": [ 92 | "[Combat Action]", 93 | {"[Combat Action]": ["[pre delay]","[post delay]"]}, 94 | "..." 95 | ] 96 | } 97 | 98 | `prefix`: [mode]Combat[role] 99 | 100 | { 101 | "UniversalMirageCombatElysianPreheat": { 102 | "recognition": "Custom", 103 | "custom_recognizer": "Combating", 104 | "action": "Custom", 105 | "pre_delay": 1000, 106 | "post_delay": 1000, 107 | "next": [ 108 | "UniversalMirageCombatElysianFinish", 109 | "UniversalMirageCombatElysian_001" 110 | ], 111 | "custom_action": "BasicATK" 112 | }, 113 | "UniversalMirageCombatElysian_001": { 114 | "recognition": "Custom", 115 | "custom_recognizer": "Combating", 116 | "action": "Custom", 117 | "pre_delay": 0, 118 | "post_delay": 30, 119 | "next": [ 120 | "UniversalMirageCombatElysianFinish", 121 | "UniversalMirageCombatElysian_002" 122 | ], 123 | "custom_action": "BasicATK" 124 | }, 125 | "..." 126 | } 127 | 128 | ### 首项无论是什么延迟均为[1000, 1000] 129 | 130 | 具体样本可以去data下看 131 | 132 | -------------------------------------------------------------------------------- /tools/CombatGenerator/combat.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft-07/schema", 3 | "type": "object", 4 | "properties": { 5 | "$schema": { 6 | "type": "string", 7 | "$ref": "#/definitions/path_url" 8 | }, 9 | "mode": { 10 | "description": "模式", 11 | "type": "string", 12 | "default": "" 13 | }, 14 | "role": { 15 | "description": "角色", 16 | "type": "string", 17 | "default": "" 18 | }, 19 | "version": { 20 | "description": "版本", 21 | "type": "string", 22 | "default": "v0.1.0" 23 | }, 24 | "combat": { 25 | "description": "战斗", 26 | "$ref": "#/definitions/combat_list" 27 | } 28 | }, 29 | "required": ["mode", "role", "version", "combat"], 30 | "additionalProperties": false, 31 | "definitions": { 32 | "path_url": { 33 | "oneOf": [ 34 | { 35 | "type": "string", 36 | "pattern": "^\\.\\./.*$" 37 | }, 38 | { 39 | "type": "string", 40 | "pattern": "^/.*$" 41 | }, 42 | { 43 | "type": "string", 44 | "format": "uri" 45 | } 46 | ] 47 | }, 48 | "combat": { 49 | "type": "string", 50 | "enum": [ 51 | "Forward", 52 | "Backward", 53 | "Left", 54 | "Right", 55 | "LeftForward", 56 | "LeftBackward", 57 | "RightForward", 58 | "RightBackward", 59 | "BasicATK", 60 | "BasicATKCharge", 61 | "Evade", 62 | "Ultimate", 63 | "UltimateCharge", 64 | "WeaponSkill", 65 | "ELFSkill", 66 | "ExtraSkill", 67 | "QTE1", 68 | "QTE2" 69 | ], 70 | "default": "BasicATK" 71 | }, 72 | "combat_delay": { 73 | "type": "array", 74 | "items": { 75 | "type": "integer", 76 | "minimum": 0 77 | }, 78 | "minItems": 2, 79 | "maxItems": 2 80 | }, 81 | "combat_obj": { 82 | "type": "object", 83 | "properties": { 84 | "Forward": { 85 | "$ref": "#/definitions/combat_delay", 86 | "default": [0, 50] 87 | }, 88 | "Backward": { 89 | "$ref": "#/definitions/combat_delay", 90 | "default": [0, 50] 91 | }, 92 | "Left": { 93 | "$ref": "#/definitions/combat_delay", 94 | "default": [0, 50] 95 | }, 96 | "Right": { 97 | "$ref": "#/definitions/combat_delay", 98 | "default": [0, 50] 99 | }, 100 | "LeftForward": { 101 | "$ref": "#/definitions/combat_delay", 102 | "default": [0, 50] 103 | }, 104 | "LeftBackward": { 105 | "$ref": "#/definitions/combat_delay", 106 | "default": [0, 50] 107 | }, 108 | "RightForward": { 109 | "$ref": "#/definitions/combat_delay", 110 | "default": [0, 50] 111 | }, 112 | "RightBackward": { 113 | "$ref": "#/definitions/combat_delay", 114 | "default": [0, 50] 115 | }, 116 | "BasicATK": { 117 | "$ref": "#/definitions/combat_delay", 118 | "default": [0, 200] 119 | }, 120 | "BasicATKCharge": { 121 | "$ref": "#/definitions/combat_delay", 122 | "default": [0, 100] 123 | }, 124 | "Evade": { 125 | "$ref": "#/definitions/combat_delay", 126 | "default": [0, 150] 127 | }, 128 | "Ultimate": { 129 | "$ref": "#/definitions/combat_delay", 130 | "default": [0, 150] 131 | }, 132 | "UltimateCharge": { 133 | "$ref": "#/definitions/combat_delay", 134 | "default": [0, 100] 135 | }, 136 | "WeaponSkill": { 137 | "$ref": "#/definitions/combat_delay", 138 | "default": [0, 150] 139 | }, 140 | "ELFSkill": { 141 | "$ref": "#/definitions/combat_delay", 142 | "default": [0, 150] 143 | }, 144 | "ExtraSkill": { 145 | "$ref": "#/definitions/combat_delay", 146 | "default": [0, 100] 147 | }, 148 | "QTE1": { 149 | "$ref": "#/definitions/combat_delay", 150 | "default": [0, 200] 151 | }, 152 | "QTE2": { 153 | "$ref": "#/definitions/combat_delay", 154 | "default": [0, 200] 155 | } 156 | } 157 | }, 158 | "combat_list": { 159 | "type": "array", 160 | "items": { 161 | "anyOf": [ 162 | { 163 | "$ref": "#/definitions/combat" 164 | }, 165 | { 166 | "$ref": "#/definitions/combat_obj" 167 | } 168 | ] 169 | } 170 | } 171 | } 172 | } -------------------------------------------------------------------------------- /tools/CombatGenerator/data/input.json: -------------------------------------------------------------------------------- 1 | { 2 | "mode": "UniversalMirage", 3 | "role": "Elysian", 4 | "version": "debug", 5 | "combat": [ 6 | "BasicATK", 7 | { 8 | "BasicATK": [ 9 | 0, 10 | 30 11 | ] 12 | }, 13 | "ExtraSkill", 14 | { 15 | "ExtraSkill": [ 16 | 30, 17 | 0 18 | ] 19 | }, 20 | "Forward" 21 | ] 22 | } -------------------------------------------------------------------------------- /tools/CombatGenerator/data/output.json: -------------------------------------------------------------------------------- 1 | { 2 | "UniversalMirageCombatElysianPreheat": { 3 | "recognition": "Custom", 4 | "custom_recognizer": "Combating", 5 | "action": "Custom", 6 | "pre_delay": 1000, 7 | "post_delay": 1000, 8 | "next": [ 9 | "UniversalMirageCombatElysianFinish", 10 | "UniversalMirageCombatElysian_001" 11 | ], 12 | "custom_action": "BasicATK" 13 | }, 14 | "UniversalMirageCombatElysian_001": { 15 | "recognition": "Custom", 16 | "custom_recognizer": "Combating", 17 | "action": "Custom", 18 | "pre_delay": 0, 19 | "post_delay": 30, 20 | "next": [ 21 | "UniversalMirageCombatElysianFinish", 22 | "UniversalMirageCombatElysian_002" 23 | ], 24 | "custom_action": "BasicATK" 25 | }, 26 | "UniversalMirageCombatElysian_002": { 27 | "recognition": "Custom", 28 | "custom_recognizer": "Combating", 29 | "action": "Custom", 30 | "pre_delay": 0, 31 | "post_delay": 100, 32 | "next": [ 33 | "UniversalMirageCombatElysianFinish", 34 | "UniversalMirageCombatElysian_003" 35 | ], 36 | "custom_action": "ExtraSkill" 37 | }, 38 | "UniversalMirageCombatElysian_003": { 39 | "recognition": "Custom", 40 | "custom_recognizer": "Combating", 41 | "action": "Custom", 42 | "pre_delay": 30, 43 | "post_delay": 0, 44 | "next": [ 45 | "UniversalMirageCombatElysianFinish", 46 | "UniversalMirageCombatElysian_004" 47 | ], 48 | "custom_action": "ExtraSkill" 49 | }, 50 | "UniversalMirageCombatElysian_004": { 51 | "recognition": "Custom", 52 | "custom_recognizer": "Combating", 53 | "action": "Custom", 54 | "pre_delay": 0, 55 | "post_delay": 50, 56 | "next": [ 57 | "UniversalMirageCombatFinish" 58 | ], 59 | "custom_action": "Forward" 60 | } 61 | } -------------------------------------------------------------------------------- /tools/CombatGenerator/pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "CombatGenerator" 3 | version = "0.1.0" 4 | description = "" 5 | authors = [ 6 | {name = "BalconyJH", email = "balconyjh@gmail.com"}, 7 | ] 8 | dependencies = [ 9 | "pydantic>=2.4.2", 10 | "rich>=13.6.0", 11 | "coverage>=7.3.2", 12 | ] 13 | requires-python = ">=3.9" 14 | readme = "README.md" 15 | license = {text = "AGPL-3.0"} 16 | 17 | [build-system] 18 | requires = ["pdm-backend"] 19 | build-backend = "pdm.backend" 20 | -------------------------------------------------------------------------------- /tools/CombatGenerator/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/tools/CombatGenerator/tests/__init__.py -------------------------------------------------------------------------------- /tools/CombatGenerator/tests/data/combat_to_json.json: -------------------------------------------------------------------------------- 1 | { 2 | "mode": "UniversalMirage", 3 | "role": "Elysian", 4 | "version": "debug", 5 | "combat": [ 6 | "BasicATK", 7 | { 8 | "BasicATK": [ 9 | 0, 10 | 30 11 | ] 12 | }, 13 | "ExtraSkill", 14 | { 15 | "ExtraSkill": [ 16 | 30, 17 | 0 18 | ] 19 | }, 20 | "Forward" 21 | ] 22 | } -------------------------------------------------------------------------------- /tools/CombatGenerator/tests/data/json_to_combat.json: -------------------------------------------------------------------------------- 1 | { 2 | "UniversalMirageCombatElysianPreheat": { 3 | "recognition": "Custom", 4 | "custom_recognizer": "Combating", 5 | "action": "Custom", 6 | "pre_delay": 1000, 7 | "post_delay": 1000, 8 | "next": [ 9 | "UniversalMirageCombatElysianFinish", 10 | "UniversalMirageCombatElysian_001" 11 | ], 12 | "custom_action": "BasicATK" 13 | }, 14 | "UniversalMirageCombatElysian_001": { 15 | "recognition": "Custom", 16 | "custom_recognizer": "Combating", 17 | "action": "Custom", 18 | "pre_delay": 0, 19 | "post_delay": 30, 20 | "next": [ 21 | "UniversalMirageCombatElysianFinish", 22 | "UniversalMirageCombatElysian_002" 23 | ], 24 | "custom_action": "BasicATK" 25 | }, 26 | "UniversalMirageCombatElysian_002": { 27 | "recognition": "Custom", 28 | "custom_recognizer": "Combating", 29 | "action": "Custom", 30 | "pre_delay": 0, 31 | "post_delay": 100, 32 | "next": [ 33 | "UniversalMirageCombatElysianFinish", 34 | "UniversalMirageCombatElysian_003" 35 | ], 36 | "custom_action": "ExtraSkill" 37 | }, 38 | "UniversalMirageCombatElysian_003": { 39 | "recognition": "Custom", 40 | "custom_recognizer": "Combating", 41 | "action": "Custom", 42 | "pre_delay": 30, 43 | "post_delay": 0, 44 | "next": [ 45 | "UniversalMirageCombatElysianFinish", 46 | "UniversalMirageCombatElysian_004" 47 | ], 48 | "custom_action": "ExtraSkill" 49 | }, 50 | "UniversalMirageCombatElysian_004": { 51 | "recognition": "Custom", 52 | "custom_recognizer": "Combating", 53 | "action": "Custom", 54 | "pre_delay": 0, 55 | "post_delay": 50, 56 | "next": [ 57 | "UniversalMirageCombatFinish" 58 | ], 59 | "custom_action": "Forward" 60 | } 61 | } -------------------------------------------------------------------------------- /tools/CombatGenerator/tests/test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from pathlib import Path 3 | 4 | from combatgenerator import ( 5 | default_delay, 6 | generate_from_combat, 7 | load_file, 8 | Combat, 9 | action_list, 10 | json_template, 11 | reverse_to_combat, 12 | ) 13 | 14 | 15 | class TestCombatMethods(unittest.TestCase): 16 | @classmethod 17 | def setUpClass(cls): 18 | cls.combat_to_json = Path(__file__).parent / "data" / "combat_to_json.json" 19 | cls.json_to_combat = Path(__file__).parent / "data" / "json_to_combat.json" 20 | 21 | def test_file_load(self): 22 | """测试 load_file 函数是否返回正确的文件内容。""" 23 | data = load_file(self.combat_to_json) 24 | self.assertIsNotNone(data) 25 | 26 | data = load_file(self.json_to_combat) 27 | self.assertIsNotNone(data) 28 | 29 | def test_default_delay(self): 30 | """测试 default_delay 函数是否返回正确的预延迟和后延迟。""" 31 | for test_case in action_list: 32 | with self.subTest(test_case=test_case): 33 | action = default_delay(str(test_case["action"])) 34 | self.assertEqual(action.pre_delay, test_case["pre_delay"]) 35 | self.assertEqual(action.post_delay, test_case["post_delay"]) 36 | 37 | def test_generate_json_from_combat(self): 38 | """测试 generate_json_from_combat 函数是否返回正确的 JSON 结构。""" 39 | data = Combat.model_validate(load_file(self.combat_to_json)) 40 | generated_json = generate_from_combat( 41 | data.combat, data.mode, data.role, json_template 42 | ) 43 | self.assertIsNotNone(generated_json) 44 | 45 | # 检查 "UniversalMirageCombatGenericPreheat" 步骤 46 | self.assertIn(f"{data.mode}Combat{data.role}Preheat", generated_json) 47 | self.assertEqual( 48 | generated_json[f"{data.mode}Combat{data.role}Preheat"]["pre_delay"], 1000 49 | ) 50 | self.assertEqual( 51 | generated_json[f"{data.mode}Combat{data.role}Preheat"]["post_delay"], 1000 52 | ) 53 | 54 | # 检查 "next" 字段和下一个步骤的键是否匹配 55 | keys = list(generated_json.keys()) 56 | for i in range(len(keys) - 1): # 跳过最后一个元素 57 | current_key = keys[i] 58 | next_key = keys[i + 1] 59 | self.assertIn(next_key, generated_json[current_key]["next"]) 60 | 61 | # 检查最后一个步骤的 "next" 字段应该只包含 "UniversalMirageCombatFinish" 62 | self.assertEqual(generated_json[keys[-1]]["next"], [f"{data.mode}CombatFinish"]) 63 | 64 | def test_reverse_json_to_combat(self): 65 | json_cache = load_file(self.json_to_combat) 66 | combat_cache = load_file(self.combat_to_json) 67 | actual_output = reverse_to_combat(json_cache).model_dump() 68 | 69 | self.assertEqual(actual_output["mode"], combat_cache["mode"]) 70 | self.assertEqual(actual_output["role"], combat_cache["role"]) 71 | self.assertEqual(actual_output["version"], combat_cache["version"]) 72 | self.assertListEqual(actual_output["combat"], combat_cache["combat"]) 73 | 74 | 75 | if __name__ == "__main__": 76 | unittest.main() 77 | -------------------------------------------------------------------------------- /tools/CropRoi/.gitignore: -------------------------------------------------------------------------------- 1 | ### Python template 2 | # Byte-compiled / optimized / DLL files 3 | __pycache__/ 4 | *.py[cod] 5 | *$py.class 6 | 7 | # C extensions 8 | *.so 9 | 10 | # Distribution / packaging 11 | .Python 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | cover/ 54 | 55 | # Translations 56 | *.mo 57 | *.pot 58 | 59 | # Django stuff: 60 | *.log 61 | local_settings.py 62 | db.sqlite3 63 | db.sqlite3-journal 64 | 65 | # Flask stuff: 66 | instance/ 67 | .webassets-cache 68 | 69 | # Scrapy stuff: 70 | .scrapy 71 | 72 | # Sphinx documentation 73 | docs/_build/ 74 | 75 | # PyBuilder 76 | .pybuilder/ 77 | target/ 78 | 79 | # Jupyter Notebook 80 | .ipynb_checkpoints 81 | 82 | # IPython 83 | profile_default/ 84 | ipython_config.py 85 | 86 | # pyenv 87 | # For a library or package, you might want to ignore these files since the code is 88 | # intended to run in multiple environments; otherwise, check them in: 89 | # .python-version 90 | 91 | # pipenv 92 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 93 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 94 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 95 | # install all needed dependencies. 96 | #Pipfile.lock 97 | 98 | # poetry 99 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 100 | # This is especially recommended for binary packages to ensure reproducibility, and is more 101 | # commonly ignored for libraries. 102 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 103 | #poetry.lock 104 | 105 | # pdm 106 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 107 | #pdm.lock 108 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 109 | # in version control. 110 | # https://pdm.fming.dev/#use-with-ide 111 | .pdm.toml 112 | .pdm-python 113 | 114 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 115 | __pypackages__/ 116 | 117 | # Celery stuff 118 | celerybeat-schedule 119 | celerybeat.pid 120 | 121 | # SageMath parsed files 122 | *.sage.py 123 | 124 | # Environments 125 | .env 126 | .venv 127 | env/ 128 | venv/ 129 | ENV/ 130 | env.bak/ 131 | venv.bak/ 132 | 133 | # Spyder project settings 134 | .spyderproject 135 | .spyproject 136 | 137 | # Rope project settings 138 | .ropeproject 139 | 140 | # mkdocs documentation 141 | /site 142 | 143 | # mypy 144 | .mypy_cache/ 145 | .dmypy.json 146 | dmypy.json 147 | 148 | # Pyre type checker 149 | .pyre/ 150 | 151 | # pytype static type analyzer 152 | .pytype/ 153 | 154 | # Cython debug symbols 155 | cython_debug/ 156 | 157 | # PyCharm 158 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 159 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 160 | # and can be added to the global gitignore or merged into this file. For a more nuclear 161 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 162 | #.idea/ 163 | 164 | -------------------------------------------------------------------------------- /tools/CropRoi/README.md: -------------------------------------------------------------------------------- 1 | # 截图工具 2 | 3 | ## 环境 4 | 5 | 需要 `python` 环境 6 | 7 | ## 依赖 8 | 9 | 在./tools/CropRoi下执行以下命令 10 | 11 | (如果已经安装过pipx和pdm可以跳过直接使用pdm install) 12 | 13 | ```shell 14 | python -m pip install pipx 15 | pipx ensurepath 16 | ``` 17 | 18 | 重启终端 19 | 20 | ```shell 21 | pipx install pdm 22 | pdm install 23 | ``` 24 | 25 | ## 使用 26 | 27 | 截图需预先保存到 `./src/` 路径下, 产物将会保存在 `./dst/` 路径下 28 | 29 | 打开cmd, 执行以下命令 30 | 31 | ```shell 32 | .venv\Scripts\Activate.ps1 33 | pdm run python main.py 34 | ``` 35 | 36 | 在弹出窗口中使用鼠标左键画框, `s` 键保存, `q` 键退出 37 | -------------------------------------------------------------------------------- /tools/CropRoi/dst/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/tools/CropRoi/dst/.gitkeep -------------------------------------------------------------------------------- /tools/CropRoi/main.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import os 3 | from typing import List, Tuple 4 | 5 | print( 6 | "Usage:\n" 7 | "Put the 16:9 images under ./src, and run this script, it will be auto converted to 720p.\n" 8 | "Drag mouse to select ROI, press 'S' to save, press 'Q' to quit.\n" 9 | "The cropped images will be saved in ./dst\n" 10 | ) 11 | 12 | # 初始化参考点列表和布尔值标志:是否正在执行裁剪 13 | refPt: List[Tuple[int, int]] = [] 14 | cropping = False 15 | 16 | 17 | # 点击并裁剪ROI区域 18 | # -events 鼠标事件(如按下鼠标左键,释放鼠标左键,鼠标移动等) 19 | # -x x坐标 20 | # -y y坐标 21 | # -flages params 其他参数 22 | def click_and_crop(event: int, x: int, y: int, *args) -> None: 23 | # 获取全局变量的引用 24 | 25 | global refPt, cropping 26 | 27 | # 如果鼠标左被单击,记录(x,y)坐标并显示裁剪正在进行 28 | if event == cv2.EVENT_LBUTTONDOWN: 29 | refPt = [(x, y)] 30 | cropping = True 31 | # 检测鼠标是否移动 32 | elif event == cv2.EVENT_MOUSEMOVE: 33 | if cropping: 34 | # 创建图像副本以绘制动态矩形 35 | draw = image.copy() 36 | cv2.rectangle(draw, refPt[0], (x, y), (0, 255, 0), 2) 37 | cv2.imshow("image", draw) 38 | # 检测鼠标左键是否释放 39 | elif event == cv2.EVENT_LBUTTONUP: 40 | # 记录结束(x,y)坐标,并显示裁剪结束 41 | refPt.append((x, y)) 42 | cropping = False 43 | 44 | draw = image.copy() 45 | cv2.rectangle(draw, refPt[0], refPt[1], (0, 255, 0), 2) 46 | cv2.imshow("image", draw) 47 | 48 | 49 | std_width: int = 1280 50 | std_height: int = 720 51 | std_ratio = std_width / std_height 52 | 53 | cv2.namedWindow("image") 54 | cv2.setMouseCallback("image", click_and_crop) 55 | 56 | for filename in os.listdir("./src"): 57 | if not (filename.endswith(".png") or filename.endswith(".jpg")): 58 | continue 59 | 60 | print("src:", filename) 61 | image = cv2.imread(f"./src/{filename}") 62 | 63 | cur_ratio = image.shape[1] / image.shape[0] 64 | 65 | if cur_ratio >= std_ratio: 66 | dsize_width = int(cur_ratio * std_height) 67 | dsize_height = std_height 68 | else: 69 | dsize_width = std_width 70 | dsize_height = int(std_width / cur_ratio) 71 | 72 | dsize = (dsize_width, dsize_height) 73 | image = cv2.resize(image, dsize, interpolation=cv2.INTER_AREA) 74 | 75 | while True: 76 | cv2.imshow("image", image) 77 | key = cv2.waitKey(0) & 0xFF 78 | if key == ord("s"): 79 | break 80 | elif key == ord("q"): 81 | exit() 82 | 83 | # 如果参考点列表里有俩个点,则裁剪区域并展示 84 | if len(refPt) == 2: 85 | pt1, pt2 = sorted(refPt) 86 | 87 | left, top = pt1 88 | right, bottom = pt2 89 | 90 | roi = image[top:bottom, left:right] 91 | 92 | horizontal_expansion = 100 93 | vertical_expansion = 100 94 | 95 | # 计算扩展后的左上角坐标,并确保不超出图像边界 96 | filename_x = max(0, left - horizontal_expansion // 2) 97 | filename_y = max(0, top - vertical_expansion // 2) 98 | 99 | # 计算扩展后的宽度和高度,并进行边界检查 100 | filename_w = min( 101 | dsize_width - filename_x, (right - left) + horizontal_expansion 102 | ) 103 | filename_h = min(dsize_height - filename_y, (bottom - top) + vertical_expansion) 104 | 105 | dst_filename: str = ( 106 | f"{filename}_{filename_x},{filename_y},{filename_w},{filename_h}.png" 107 | ) 108 | print("dst:", dst_filename) 109 | 110 | print( 111 | f"original roi: {left}, {top}, {right - left}, {bottom - top}, \n" 112 | f"amplified roi: {filename_x}, {filename_y}, {filename_w}, {filename_h}\n\n" 113 | ) 114 | 115 | cv2.imwrite(f"./dst/{dst_filename}", roi) 116 | 117 | refPt: List[Tuple[int, int]] = [] 118 | cropping = False 119 | 120 | # 关闭所有打开的窗口 121 | cv2.destroyAllWindows() 122 | -------------------------------------------------------------------------------- /tools/CropRoi/pdm.lock: -------------------------------------------------------------------------------- 1 | # This file is @generated by PDM. 2 | # It is not intended for manual editing. 3 | 4 | [metadata] 5 | groups = ["default"] 6 | strategy = ["cross_platform"] 7 | lock_version = "4.4" 8 | content_hash = "sha256:c8ef58caa94bb224e56b87703c59a64edc481e38be9413403097d225ff9caccb" 9 | 10 | [[package]] 11 | name = "numpy" 12 | version = "1.26.2" 13 | requires_python = ">=3.9" 14 | summary = "Fundamental package for array computing in Python" 15 | files = [ 16 | {file = "numpy-1.26.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b96e7b9c624ef3ae2ae0e04fa9b460f6b9f17ad8b4bec6d7756510f1f6c0c841"}, 17 | {file = "numpy-1.26.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:aa18428111fb9a591d7a9cc1b48150097ba6a7e8299fb56bdf574df650e7d1f1"}, 18 | {file = "numpy-1.26.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:06fa1ed84aa60ea6ef9f91ba57b5ed963c3729534e6e54055fc151fad0423f0a"}, 19 | {file = "numpy-1.26.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96ca5482c3dbdd051bcd1fce8034603d6ebfc125a7bd59f55b40d8f5d246832b"}, 20 | {file = "numpy-1.26.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:854ab91a2906ef29dc3925a064fcd365c7b4da743f84b123002f6139bcb3f8a7"}, 21 | {file = "numpy-1.26.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f43740ab089277d403aa07567be138fc2a89d4d9892d113b76153e0e412409f8"}, 22 | {file = "numpy-1.26.2-cp311-cp311-win32.whl", hash = "sha256:a2bbc29fcb1771cd7b7425f98b05307776a6baf43035d3b80c4b0f29e9545186"}, 23 | {file = "numpy-1.26.2-cp311-cp311-win_amd64.whl", hash = "sha256:2b3fca8a5b00184828d12b073af4d0fc5fdd94b1632c2477526f6bd7842d700d"}, 24 | {file = "numpy-1.26.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a4cd6ed4a339c21f1d1b0fdf13426cb3b284555c27ac2f156dfdaaa7e16bfab0"}, 25 | {file = "numpy-1.26.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5d5244aabd6ed7f312268b9247be47343a654ebea52a60f002dc70c769048e75"}, 26 | {file = "numpy-1.26.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a3cdb4d9c70e6b8c0814239ead47da00934666f668426fc6e94cce869e13fd7"}, 27 | {file = "numpy-1.26.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa317b2325f7aa0a9471663e6093c210cb2ae9c0ad824732b307d2c51983d5b6"}, 28 | {file = "numpy-1.26.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:174a8880739c16c925799c018f3f55b8130c1f7c8e75ab0a6fa9d41cab092fd6"}, 29 | {file = "numpy-1.26.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f79b231bf5c16b1f39c7f4875e1ded36abee1591e98742b05d8a0fb55d8a3eec"}, 30 | {file = "numpy-1.26.2-cp312-cp312-win32.whl", hash = "sha256:4a06263321dfd3598cacb252f51e521a8cb4b6df471bb12a7ee5cbab20ea9167"}, 31 | {file = "numpy-1.26.2-cp312-cp312-win_amd64.whl", hash = "sha256:b04f5dc6b3efdaab541f7857351aac359e6ae3c126e2edb376929bd3b7f92d7e"}, 32 | {file = "numpy-1.26.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1cc3d5029a30fb5f06704ad6b23b35e11309491c999838c31f124fee32107c79"}, 33 | {file = "numpy-1.26.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94cc3c222bb9fb5a12e334d0479b97bb2df446fbe622b470928f5284ffca3f8d"}, 34 | {file = "numpy-1.26.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fe6b44fb8fcdf7eda4ef4461b97b3f63c466b27ab151bec2366db8b197387841"}, 35 | {file = "numpy-1.26.2.tar.gz", hash = "sha256:f65738447676ab5777f11e6bbbdb8ce11b785e105f690bc45966574816b6d3ea"}, 36 | ] 37 | 38 | [[package]] 39 | name = "opencv-python" 40 | version = "4.8.1.78" 41 | requires_python = ">=3.6" 42 | summary = "Wrapper package for OpenCV python bindings." 43 | dependencies = [ 44 | "numpy>=1.17.0; python_version >= \"3.7\"", 45 | "numpy>=1.17.3; python_version >= \"3.8\"", 46 | "numpy>=1.19.3; python_version >= \"3.6\" and platform_system == \"Linux\" and platform_machine == \"aarch64\"", 47 | "numpy>=1.19.3; python_version >= \"3.9\"", 48 | "numpy>=1.21.2; python_version >= \"3.10\"", 49 | "numpy>=1.21.4; python_version >= \"3.10\" and platform_system == \"Darwin\"", 50 | "numpy>=1.23.5; python_version >= \"3.11\"", 51 | ] 52 | files = [ 53 | {file = "opencv-python-4.8.1.78.tar.gz", hash = "sha256:cc7adbbcd1112877a39274106cb2752e04984bc01a031162952e97450d6117f6"}, 54 | {file = "opencv_python-4.8.1.78-cp37-abi3-macosx_10_16_x86_64.whl", hash = "sha256:91d5f6f5209dc2635d496f6b8ca6573ecdad051a09e6b5de4c399b8e673c60da"}, 55 | {file = "opencv_python-4.8.1.78-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:bc31f47e05447da8b3089faa0a07ffe80e114c91ce0b171e6424f9badbd1c5cd"}, 56 | {file = "opencv_python-4.8.1.78-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9814beca408d3a0eca1bae7e3e5be68b07c17ecceb392b94170881216e09b319"}, 57 | {file = "opencv_python-4.8.1.78-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4c406bdb41eb21ea51b4e90dfbc989c002786c3f601c236a99c59a54670a394"}, 58 | {file = "opencv_python-4.8.1.78-cp37-abi3-win32.whl", hash = "sha256:a7aac3900fbacf55b551e7b53626c3dad4c71ce85643645c43e91fcb19045e47"}, 59 | {file = "opencv_python-4.8.1.78-cp37-abi3-win_amd64.whl", hash = "sha256:b983197f97cfa6fcb74e1da1802c7497a6f94ed561aba6980f1f33123f904956"}, 60 | ] 61 | -------------------------------------------------------------------------------- /tools/CropRoi/pyproject.toml: -------------------------------------------------------------------------------- 1 | 2 | [project] 3 | # PEP 621 project metadata 4 | # See https://www.python.org/dev/peps/pep-0621/ 5 | dependencies = [ 6 | "opencv-python>=4.5.3", 7 | ] 8 | requires-python = ">=3.11" 9 | 10 | [build-system] 11 | requires = ["pdm-backend"] 12 | build-backend = "pdm.backend" -------------------------------------------------------------------------------- /tools/CropRoi/requirements.txt: -------------------------------------------------------------------------------- 1 | # This file is @generated by PDM. 2 | # Please do not edit it manually. 3 | 4 | numpy==1.26.2 5 | opencv-python==4.8.1.78 6 | -------------------------------------------------------------------------------- /tools/CropRoi/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaaXYZ/MAABH3/d7f1b23871c8cf548e86e4e7bfe1b73dafea27c2/tools/CropRoi/src/.gitkeep -------------------------------------------------------------------------------- /tools/CropRoi/start.bat: -------------------------------------------------------------------------------- 1 | python main.py 2 | pause --------------------------------------------------------------------------------