├── .github ├── ISSUE_TEMPLATE │ └── bug_report.yml ├── images │ ├── BlockStatus.png │ ├── BridgeLinkedInfo.png │ ├── BuildHealthBar.png │ ├── ConstructorBlockInfo.png │ ├── EnemyIndicator.png │ ├── OverdriveZone.png │ ├── PayloadHint.png │ ├── PlayerRange.png │ ├── SpawnerInfo.png │ ├── TurretAlert.png │ ├── UnitAlert.png │ ├── UnitBuildInfo.png │ ├── UnitInfoBar.png │ └── ui │ │ ├── BetterCoreItemsDisplay.png │ │ ├── BetterHoverInfoTable.png │ │ ├── ChatTable.png │ │ ├── MinerToolsSetting-UI.png │ │ ├── PowerInfo.png │ │ └── TeamInfo.png └── workflows │ ├── autoReleaseUpload.yml │ ├── commitTest.yml │ └── syncBundle.yml ├── .gitignore ├── LICENSE ├── README.md ├── annotation ├── build.gradle └── src │ └── main │ └── java │ └── MinerTools │ └── annotation │ ├── Annotations.java │ └── MProcessor.java ├── assets ├── bundles │ ├── bundle.properties │ └── bundle_zh_CN.properties ├── shaders │ └── rangeZone.frag └── sprites │ └── ui │ └── gradient.png ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── mod.hjson ├── settings.gradle ├── src └── MinerTools │ ├── MinerTools.java │ ├── MinerVars.java │ ├── ModUpdater.java │ ├── ai │ ├── BaseAI.java │ ├── PlayerAI.java │ └── types │ │ ├── PlayerFollowAI.java │ │ └── PlayerMinerAI.java │ ├── content │ ├── MContents.java │ └── override │ │ ├── MBars.java │ │ ├── MStats.java │ │ └── stats │ │ ├── StatOverrider.java │ │ └── unit │ │ └── MineTierOverrider.java │ ├── game │ ├── ConveyorUpdater.java │ ├── MobileObserverMode.java │ └── PowerInfo.java │ ├── graphics │ ├── MDrawf.java │ ├── MLayer.java │ ├── MRenderer.java │ ├── MShaders.java │ ├── draw │ │ ├── BuildDrawer.java │ │ ├── Drawer.java │ │ ├── PlayerDrawer.java │ │ ├── UnitDrawer.java │ │ ├── build │ │ │ ├── BuildHealthBar.java │ │ │ ├── BuildStatus.java │ │ │ ├── ConstructBlockInfo.java │ │ │ ├── OverdriveZone.java │ │ │ ├── TurretAlert.java │ │ │ ├── TurretAmmoDisplay.java │ │ │ ├── UnitAssemblerInfo.java │ │ │ ├── UnitBuildInfo.java │ │ │ └── select │ │ │ │ ├── BridgeLinkedList.java │ │ │ │ └── BuildSelect.java │ │ ├── player │ │ │ ├── PayloadDropHint.java │ │ │ └── PlayerRange.java │ │ └── unit │ │ │ ├── EnemyIndicator.java │ │ │ ├── UnitAlert.java │ │ │ └── UnitInfoBar.java │ └── provider │ │ ├── BuildProvider.java │ │ ├── CameraProvider.java │ │ ├── DrawerProvider.java │ │ ├── PlayerProvider.java │ │ ├── SelectProvider.java │ │ └── UnitProvider.java │ ├── input │ └── ModBinding.java │ ├── interfaces │ ├── Displayable.java │ ├── OverrideUI.java │ └── TableBuilder.java │ ├── modules │ ├── AbstractModule.java │ ├── Module.java │ ├── Modules.java │ ├── SettingModule.java │ └── SpawnerInfo │ │ ├── DestroyBuildings.java │ │ ├── SpawnCounter.java │ │ ├── SpawnerGroup.java │ │ ├── SpawnerInfo.java │ │ ├── SpawnerRange.java │ │ ├── SpawnerTables.java │ │ └── SpawnerViewer.java │ ├── ui │ ├── BorderColorImage.java │ ├── MStyles.java │ ├── MUI.java │ ├── override │ │ ├── BetterInfoTable.java │ │ └── CoreItemsDisplay.java │ ├── settings │ │ ├── BaseSetting.java │ │ ├── CategorySetting.java │ │ ├── MSettingTable.java │ │ ├── MSettingsDialog.java │ │ └── MSettingsMenu.java │ └── tables │ │ ├── DraggableTable.java │ │ ├── MembersTable.java │ │ ├── floats │ │ ├── ChatTable.java │ │ ├── FloatManager.java │ │ ├── FloatTable.java │ │ ├── MainTable.java │ │ ├── ScriptButtons.java │ │ ├── TemporaryFloatTable.java │ │ └── ToolsFloatTable.java │ │ └── members │ │ ├── AITable.java │ │ ├── PlayerList.java │ │ ├── SchematicList.java │ │ ├── TeamChanger.java │ │ └── TeamsInfo.java │ └── utils │ ├── CameraUtils.java │ └── GameUtils.java └── tools ├── build.gradle └── src └── main └── java ├── bundle └── SyncBundle.java └── utils ├── BaiduTranslator.java └── MD5.java /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug report 2 | description: The type of device you were playing on 3 | labels: [ "bug" ] 4 | 5 | body: 6 | - type: dropdown 7 | id: platform 8 | attributes: 9 | label: Platforms 10 | description: On what platforms do you know the bug happens? 11 | multiple: false 12 | options: 13 | - Android 14 | - iOS 15 | - Mac 16 | - Windows 17 | - Linux 18 | validations: 19 | required: true 20 | - type: input 21 | id: build 22 | attributes: 23 | label: Build 24 | description: The build number under the title in the main menu. 25 | placeholder: LATEST IS NOT A VERSION, I NEED THE EXACT BUILD NUMBER OF YOUR GAME. 26 | validations: 27 | required: true 28 | - type: textarea 29 | id: issue 30 | attributes: 31 | label: Issue 32 | description: Explain your issue in detail. 33 | validations: 34 | required: true 35 | - type: textarea 36 | id: reproduction 37 | attributes: 38 | label: Steps to reproduce 39 | description: How you happened across the issue, and what exactly you did to make the bug happen. 40 | validations: 41 | required: true 42 | - type: textarea 43 | id: mods 44 | attributes: 45 | label: Mods used 46 | description: The mod repositories or zip files that are related to the issue, if applicable. 47 | validations: 48 | required: false 49 | - type: textarea 50 | id: save-file 51 | attributes: 52 | label: Save file 53 | description: The (zipped) save file you were playing on when the bug happened. If this happened in the campaign, specify the sector, and attach the file you get from Settings -> Game Data -> Export Data. For custom games, attach the .msav file exported from the save dialog, zipped. 54 | placeholder: THIS IS REQUIRED FOR ANY ISSUE HAPPENING IN-GAME OR IN MULTIPLAYER, REGARDLESS OF WHETHER YOU THINK IT HAPPENS EVERYWHERE. DO NOT OMIT THIS LINE UNLESS YOU ARE SURE THAT THE ISSUE DOES NOT HAPPEN IN-GAME. IF YOU DO NOT HAVE A SAVE, DON'T WASTE TIME OPENING THIS ISSUE. 55 | validations: 56 | required: false 57 | - type: textarea 58 | id: logs 59 | attributes: 60 | label: (Crash) logs 61 | description: Either crash reports from the crash folder, or the file you get when you go into Settings -> Game Data -> Export Crash logs. 62 | placeholder: REQUIRED if you are reporting a crash. 63 | validations: 64 | required: false 65 | - type: checkboxes 66 | id: agreement 67 | attributes: 68 | label: Submission 69 | description: Check the boxes to confirm that you have read the lines below. 70 | options: 71 | - label: I have updated to the latest release (https://github.com/MinRi2/MinerTools/releases) to make sure my issue has not been fixed. 72 | required: true 73 | - label: I have searched the closed and open issues to make sure that this problem has not already been reported. 74 | required: true 75 | - label: I am not using Custom Client, and have made sure the bug is not caused by mods I have installed. 76 | required: true -------------------------------------------------------------------------------- /.github/images/BlockStatus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MinRi2/MinerTools/8ab2fe090cf24f0a5c8eaa0dcbea01f0a5447dd8/.github/images/BlockStatus.png -------------------------------------------------------------------------------- /.github/images/BridgeLinkedInfo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MinRi2/MinerTools/8ab2fe090cf24f0a5c8eaa0dcbea01f0a5447dd8/.github/images/BridgeLinkedInfo.png -------------------------------------------------------------------------------- /.github/images/BuildHealthBar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MinRi2/MinerTools/8ab2fe090cf24f0a5c8eaa0dcbea01f0a5447dd8/.github/images/BuildHealthBar.png -------------------------------------------------------------------------------- /.github/images/ConstructorBlockInfo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MinRi2/MinerTools/8ab2fe090cf24f0a5c8eaa0dcbea01f0a5447dd8/.github/images/ConstructorBlockInfo.png -------------------------------------------------------------------------------- /.github/images/EnemyIndicator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MinRi2/MinerTools/8ab2fe090cf24f0a5c8eaa0dcbea01f0a5447dd8/.github/images/EnemyIndicator.png -------------------------------------------------------------------------------- /.github/images/OverdriveZone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MinRi2/MinerTools/8ab2fe090cf24f0a5c8eaa0dcbea01f0a5447dd8/.github/images/OverdriveZone.png -------------------------------------------------------------------------------- /.github/images/PayloadHint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MinRi2/MinerTools/8ab2fe090cf24f0a5c8eaa0dcbea01f0a5447dd8/.github/images/PayloadHint.png -------------------------------------------------------------------------------- /.github/images/PlayerRange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MinRi2/MinerTools/8ab2fe090cf24f0a5c8eaa0dcbea01f0a5447dd8/.github/images/PlayerRange.png -------------------------------------------------------------------------------- /.github/images/SpawnerInfo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MinRi2/MinerTools/8ab2fe090cf24f0a5c8eaa0dcbea01f0a5447dd8/.github/images/SpawnerInfo.png -------------------------------------------------------------------------------- /.github/images/TurretAlert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MinRi2/MinerTools/8ab2fe090cf24f0a5c8eaa0dcbea01f0a5447dd8/.github/images/TurretAlert.png -------------------------------------------------------------------------------- /.github/images/UnitAlert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MinRi2/MinerTools/8ab2fe090cf24f0a5c8eaa0dcbea01f0a5447dd8/.github/images/UnitAlert.png -------------------------------------------------------------------------------- /.github/images/UnitBuildInfo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MinRi2/MinerTools/8ab2fe090cf24f0a5c8eaa0dcbea01f0a5447dd8/.github/images/UnitBuildInfo.png -------------------------------------------------------------------------------- /.github/images/UnitInfoBar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MinRi2/MinerTools/8ab2fe090cf24f0a5c8eaa0dcbea01f0a5447dd8/.github/images/UnitInfoBar.png -------------------------------------------------------------------------------- /.github/images/ui/BetterCoreItemsDisplay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MinRi2/MinerTools/8ab2fe090cf24f0a5c8eaa0dcbea01f0a5447dd8/.github/images/ui/BetterCoreItemsDisplay.png -------------------------------------------------------------------------------- /.github/images/ui/BetterHoverInfoTable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MinRi2/MinerTools/8ab2fe090cf24f0a5c8eaa0dcbea01f0a5447dd8/.github/images/ui/BetterHoverInfoTable.png -------------------------------------------------------------------------------- /.github/images/ui/ChatTable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MinRi2/MinerTools/8ab2fe090cf24f0a5c8eaa0dcbea01f0a5447dd8/.github/images/ui/ChatTable.png -------------------------------------------------------------------------------- /.github/images/ui/MinerToolsSetting-UI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MinRi2/MinerTools/8ab2fe090cf24f0a5c8eaa0dcbea01f0a5447dd8/.github/images/ui/MinerToolsSetting-UI.png -------------------------------------------------------------------------------- /.github/images/ui/PowerInfo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MinRi2/MinerTools/8ab2fe090cf24f0a5c8eaa0dcbea01f0a5447dd8/.github/images/ui/PowerInfo.png -------------------------------------------------------------------------------- /.github/images/ui/TeamInfo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MinRi2/MinerTools/8ab2fe090cf24f0a5c8eaa0dcbea01f0a5447dd8/.github/images/ui/TeamInfo.png -------------------------------------------------------------------------------- /.github/workflows/autoReleaseUpload.yml: -------------------------------------------------------------------------------- 1 | name: autoReleaseUpload 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' 7 | 8 | jobs: 9 | buildJar: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: Set up PATH 15 | run: | 16 | echo "${ANDROID_HOME}/build-tools/34.0.0" >> $GITHUB_PATH 17 | - name: Set env 18 | run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV 19 | - name: Set up JDK 17 20 | uses: actions/setup-java@v1 21 | with: 22 | java-version: 17 23 | - name: Build mod jar 24 | run: | 25 | ./gradlew deploy 26 | 27 | - name: Upload 28 | uses: svenstaro/upload-release-action@2.9.0 29 | with: 30 | repo_token: ${{ secrets.TOKEN }} 31 | file: build/libs/* 32 | asset_name: ${{ github.event.repository.name }}.jar-$tag 33 | tag: ${{ github.ref }} 34 | -------------------------------------------------------------------------------- /.github/workflows/commitTest.yml: -------------------------------------------------------------------------------- 1 | name: Build Mod 2 | 3 | on: [ push, pull_request ] 4 | 5 | jobs: 6 | buildJar: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Set up PATH 12 | run: | 13 | echo "${ANDROID_HOME}/build-tools/34.0.0" >> $GITHUB_PATH 14 | - name: Set up JDK 17 15 | uses: actions/setup-java@v1 16 | with: 17 | java-version: 17 18 | 19 | - name: Build mod jar 20 | run: ./gradlew deploy 21 | - name: Upload built jar file 22 | uses: actions/upload-artifact@v2 23 | with: 24 | name: ${{ github.event.repository.name }} 25 | path: build/libs/${{ github.event.repository.name }}.jar -------------------------------------------------------------------------------- /.github/workflows/syncBundle.yml: -------------------------------------------------------------------------------- 1 | name: Build Mod 2 | 3 | on: [ workflow_dispatch ] 4 | 5 | jobs: 6 | buildJar: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - name: Setup Gradle 11 | uses: gradle/gradle-build-action@v2 12 | - name: Sync bundles 13 | env: 14 | BAIDU_APP_ID: ${ { secrets.BAIDU_APP_ID } } 15 | BAIDU_KEY: ${ { secrets.BAIDU_KEY } } 16 | run: | 17 | ./gradlew syncBundle 18 | echo "Git status:" 19 | echo $(git status --porcelain) 20 | if [ -n "$(git status --porcelain)" ]; then 21 | git config --global user.name "Github Actions" 22 | git add ./assets/bundles/* 23 | git commit -m "Automatic bundle update" 24 | git push 25 | fi -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | logs/ 2 | /core/assets/mindustry-saves/ 3 | /core/assets/mindustry-maps/ 4 | /core/assets/bundles/output/ 5 | /core/assets/.gifimages/ 6 | /deploy/ 7 | /desktop/packr-out/ 8 | /desktop/packr-export/ 9 | /desktop/mindustry-saves/ 10 | /desktop/mindustry-maps/ 11 | /desktop/gifexport/ 12 | /core/lib/ 13 | /ios/assets/ 14 | /core/assets-raw/sprites/generated/ 15 | /core/assets-raw/sprites_out/ 16 | /annotations/build/ 17 | /annotations/out/ 18 | /net/build/ 19 | /tools/build/ 20 | /tests/build/ 21 | /server/build/ 22 | /test_files/ 23 | /annotations/build/ 24 | /desktop-sdl/build/ 25 | desktop-sdl/build/ 26 | /android/assets/mindustry-maps/ 27 | /android/assets/mindustry-saves/ 28 | /core/assets/gifexport/ 29 | /core/assets/version.properties 30 | /core/assets/locales 31 | /ios/src/io/anuke/mindustry/gen/ 32 | /core/src/io/anuke/mindustry/gen/ 33 | ios/robovm.properties 34 | packr-out/ 35 | config/ 36 | *.gif 37 | *.bat 38 | 39 | version.properties 40 | 41 | .attach_* 42 | ## Java 43 | 44 | *.class 45 | *.war 46 | *.ear 47 | hs_err_pid* 48 | crash-report-* 49 | 50 | ## Robovm 51 | /ios/robovm-build/ 52 | 53 | ## GWT 54 | /html/war/ 55 | /html/gwt-unitCache/ 56 | .apt_generated/ 57 | .gwt/ 58 | gwt-unitCache/ 59 | www-test/ 60 | .gwt-tmp/ 61 | 62 | ## Android Studio and Intellij and Android in general 63 | /android/libs/armeabi/ 64 | /android/libs/armeabi-v7a/ 65 | /android/libs/arm64-v8a/ 66 | /android/libs/x86/ 67 | /android/libs/x86_64/ 68 | /android/gen/ 69 | .idea/ 70 | *.ipr 71 | *.iws 72 | *.iml 73 | /android/out/ 74 | com_crashlytics_export_strings.xml 75 | 76 | ## Eclipse 77 | 78 | .classpath 79 | .project 80 | .metadata/ 81 | /android/bin/ 82 | /core/bin/ 83 | /desktop/bin/ 84 | /html/bin/ 85 | /ios/bin/ 86 | /ios-moe/bin/ 87 | *.tmp 88 | *.bak 89 | *.swp 90 | *~.nib 91 | .settings/ 92 | .loadpath 93 | .externalToolBuilders/ 94 | *.launch 95 | 96 | ## NetBeans 97 | 98 | /nbproject/private/ 99 | /android/nbproject/private/ 100 | /core/nbproject/private/ 101 | /desktop/nbproject/private/ 102 | /html/nbproject/private/ 103 | /ios/nbproject/private/ 104 | /ios-moe/nbproject/private/ 105 | 106 | /build/ 107 | /android/build/ 108 | /core/build/ 109 | /desktop/build/ 110 | /html/build/ 111 | /ios/build/ 112 | /ios-moe/build/ 113 | 114 | /nbbuild/ 115 | /android/nbbuild/ 116 | /core/nbbuild/ 117 | /desktop/nbbuild/ 118 | /html/nbbuild/ 119 | /ios/nbbuild/ 120 | /ios-moe/nbbuild/ 121 | 122 | /dist/ 123 | /android/dist/ 124 | /core/dist/ 125 | /desktop/dist/ 126 | /html/dist/ 127 | /ios/dist/ 128 | /ios-moe/dist/ 129 | 130 | /nbdist/ 131 | /android/nbdist/ 132 | /core/nbdist/ 133 | /desktop/nbdist/ 134 | /html/nbdist/ 135 | /ios/nbdist/ 136 | /ios-moe/nbdist/ 137 | 138 | nbactions.xml 139 | nb-configuration.xml 140 | 141 | ## Gradle 142 | 143 | /local.properties 144 | .gradle/ 145 | gradle-app.setting 146 | /build/ 147 | /android/build/ 148 | /core/build/ 149 | /desktop/build/ 150 | /html/build/ 151 | /ios/build/ 152 | /ios-moe/build/ 153 | 154 | ## OS Specific 155 | .DS_Store 156 | Thumbs.db 157 | android/libs/ 158 | 159 | ## Annotation Processor 160 | /annotation/build 161 | 162 | null/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Mod功能区 2 | =========================== 3 | 4 | 说明的上次更新时间:2024/02/09,仅供参考,具体功能看最新版 5 | 6 | # UI 7 | 8 | ## 工具箱 9 | 10 | * 队伍信息 11 | * 队伍玩家数量(Tooltip显示基础队伍规则) 12 | * 队伍单位显示 13 | * 队伍全局电量 14 | 15 | ![TeamInfo](.github/images/ui/TeamInfo.png) ![PowerInfo](.github/images/ui/PowerInfo.png) 16 | 17 | * 玩家列表 18 | * 所有玩家的名字 19 | * 可锁定玩家视角(锁定的玩家控制炮塔时,会自动调整视角) 20 | * 可切换到玩家视角 21 | * 可一键投票踢出玩家 22 | 23 | * 玩家AI 24 | * 挖矿AI 25 | * 跟随AI 26 | 27 | 3. 聊天记录 28 | * 查询历史聊天记录 29 | * 可以复制聊天记录(电脑:Ctrl+单击) 30 | 31 | ![ChatTable](.github/images/ui/ChatTable.png) 32 | 33 | 4. 更好的**核心资源显示** 34 | * 单位数量显示 35 | * 物品每秒变化量显示 36 | * 玩家预建消耗显示 37 | * 可自定义的ui列数 38 | 39 | ![BetterCoreItemsDisplay](.github/images/ui/BetterCoreItemsDisplay.png) 40 | 41 | 5. 更好的**信息面板** 42 | * **单位,建筑,地板信息一起显示!** 43 | * 单位 44 | * 武器冷却状态 45 | * 建筑 46 | * 物品详情 47 | * 地板 48 | * 显示更详尽 49 | 50 | ![BetterHoverInfoTable](.github/images/ui/BetterHoverInfoTable.png) 51 | 52 | --- 53 | 54 | ## 画面 55 | 56 | * 建筑 57 | * 选中 58 | * 异队选中信息 59 | 60 | ![BlockStatus](.github/images/BlockStatus.png) 61 | 62 | * 桥带连接详情 63 | 64 | ![BridgeLinkedInfo](.github/images/BridgeLinkedInfo.png) 65 | 66 | * 建筑血条 67 | * 异队方块状态 68 | 69 | ![BuildHealthBar](.github/images/BuildHealthBar.png) 70 | 71 | * 构造方块耗材信息 72 | 73 | ![ConstructorBlockInfo](.github/images/ConstructorBlockInfo.png) 74 | 75 | * 附近炮塔警戒 76 | * 物品炮塔子弹类型显示 77 | 78 | ![TurretAlert](.github/images/TurretAlert.png) 79 | 80 | * 单位工厂进度条 81 | 82 | ![UnitBuildInfo](.github/images/UnitBuildInfo.png) 83 | 84 | * 显示超速区域 85 | 86 | ![OverdriveZone](.github/images/OverdriveZone.png) 87 | 88 | * 单位 89 | * 单位指示器(核心危险警告) 90 | 91 | ![EnemyIndicator](.github/images/EnemyIndicator.png) 92 | 93 | * 附近单位警戒 94 | 95 | ![UnitAlert](.github/images/UnitAlert.png) 96 | 97 | * 单位信息条 98 | * 血条 99 | * 立场回复条 100 | * 单位状态条 101 | * 荷载条 102 | 103 | ![UnitInfoBar](.github/images/UnitInfoBar.png) 104 | 105 | * 玩家 106 | * 荷载拾放提示 107 | 108 | ![PayloadHint](.github/images/PayloadHint.png) 109 | 110 | * 玩家范围显示 111 | 112 | ![PlayerRange](.github/images/PlayerRange.png) 113 | 114 | --- 115 | 116 | ## 其他小功能 117 | 118 | * 物品桥带可拿取物品 119 | * 更多方块信息条 120 | * 血条: 血量显示更详细 121 | * 进度条: 进度显示更详细 122 | * 出怪点显示 123 | ![SpawnerInfo](.github/images/SpawnerInfo.png) 124 | 125 | ## 更多功能 ... 126 | 127 | ![Settings](.github/images/ui/MinerToolsSetting-UI.png) 128 | 129 | --- 130 | 131 | Mod 90%的功能支持游戏内开关 132 | 133 | 试试[MI2-Utilities](https://github.com/BlackDeluxeCat/MI2-Utilities-Java/)! -------------------------------------------------------------------------------- /annotation/build.gradle: -------------------------------------------------------------------------------- 1 | project(":annotation"){ 2 | apply plugin: "java-library" 3 | 4 | 5 | tasks.withType(JavaCompile){ 6 | options.compilerArgs.addAll(['--release', '16']) 7 | } 8 | 9 | repositories{ 10 | mavenCentral() 11 | maven{ url "https://raw.githubusercontent.com/Zelaux/MindustryRepo/master/repository" } 12 | maven{ url 'https://www.jitpack.io' } 13 | } 14 | 15 | dependencies{ 16 | compileOnly "com.github.Anuken.Arc:arc-core:$mindustryVersion" 17 | compileOnly 'com.google.auto.service:auto-service:1.0-rc2' 18 | 19 | annotationProcessor 'com.google.auto.service:auto-service:1.0-rc2' 20 | } 21 | } -------------------------------------------------------------------------------- /annotation/src/main/java/MinerTools/annotation/Annotations.java: -------------------------------------------------------------------------------- 1 | package MinerTools.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | public class Annotations{ 6 | 7 | /** 8 | * 将枚举类转化为获取设置数值的对象 9 | */ 10 | @Target(ElementType.TYPE) 11 | @Retention(RetentionPolicy.SOURCE) 12 | public @interface SettingData{ 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /annotation/src/main/java/MinerTools/annotation/MProcessor.java: -------------------------------------------------------------------------------- 1 | package MinerTools.annotation; 2 | 3 | import javax.annotation.processing.*; 4 | import javax.lang.model.*; 5 | import javax.lang.model.element.*; 6 | import java.util.*; 7 | 8 | //@AutoService(Processor.class) 9 | public class MProcessor implements Processor{ 10 | @Override 11 | public Set getSupportedOptions(){ 12 | return null; 13 | } 14 | 15 | @Override 16 | public Set getSupportedAnnotationTypes(){ 17 | return null; 18 | } 19 | 20 | @Override 21 | public SourceVersion getSupportedSourceVersion(){ 22 | return null; 23 | } 24 | 25 | @Override 26 | public void init(ProcessingEnvironment processingEnv){ 27 | 28 | } 29 | 30 | @Override 31 | public boolean process(Set annotations, RoundEnvironment roundEnv){ 32 | return false; 33 | } 34 | 35 | @Override 36 | public Iterable getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText){ 37 | return null; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /assets/bundles/bundle.properties: -------------------------------------------------------------------------------- 1 | # Updater 2 | miner-tools.updater.name = [red]⚠[white]MinerTools has new version! 3 | miner-tools.updater.info = Your version: [red]{0}, [white]New version: [green]{1} 4 | miner-tools.updater.load = Update now 5 | # Buttons' tooltip 6 | miner-tools.buttons.tooltips.updateConveyor = Update conveyor 7 | miner-tools.buttons.tooltips.stopBuilding = Stop building 8 | miner-tools.buttons.tooltips.observerMode = Observer Mode 9 | miner-tools.buttons.tooltips.wayzerObserver = ObserverMode(Wayzer plugin) 10 | miner-tools.buttons.tooltips.quickVoteGameOver = Vote game over 11 | # FloatTable Hint 12 | miner-tools.floats.reshow-hint = This can reshow in setting 13 | miner-tools.floats.main = MinerTools 14 | # FloatTables' name 15 | miner-tools.floats.chat = Chat 16 | miner-tools.floats.scriptButtons = ScriptButtons 17 | miner-tools.floats.tools = ToolsBox 18 | miner-tools.settings = MinerTools settings 19 | miner-tools.setting.modules.name = Modules 20 | miner-tools.setting.graphics.name = Graphics 21 | miner-tools.setting.ui.name = UI 22 | # Modules Setting 23 | miner-tools.setting.spawnerViewer.preview.name = Spawner Preview 24 | miner-tools.setting.spawnerViewer.alwaysShow.name = Always Draw Spawner's Position 25 | # Graphics Setting 26 | ## Unit 27 | miner-tools.setting.enemyUnitIndicator.name = Enemy Unit Indicator 28 | miner-tools.setting.enemyUnitIndicatorRadius.name = Enemy Unit Indicator Radius 29 | miner-tools.setting.unitAlert.name = Unit Alert 30 | miner-tools.setting.unitAlertRadius.name = Unit Alert Radius 31 | miner-tools.setting.unitInfoBar.name = Unit Info Bar 32 | ## Build 33 | miner-tools.setting.turretAlert.name = Turret Alert 34 | miner-tools.setting.turretAlertRadius.name = Turret Alert Radius 35 | miner-tools.setting.itemTurretAmmoShow.name = ItemTurretAmmoShow 36 | miner-tools.setting.overdriveZone.name = Overdrive Zone 37 | miner-tools.setting.buildStatus.name = Build Status 38 | miner-tools.setting.buildHealthBar.name = Build HealthBar 39 | miner-tools.setting.constructBuildInfo.name = ConstructBuild Info 40 | miner-tools.setting.unitBuildInfo.name = UnitBuild ProBar 41 | ## Select 42 | miner-tools.setting.buildSelectInfo.name = Build Select Info 43 | miner-tools.setting.itemBridgeLinksShow.name = ItemBridge Links Show 44 | ## Player 45 | miner-tools.setting.payloadDropHint.name = Payload Drop Hint 46 | miner-tools.setting.playerRange.name = Player Range 47 | # UI Setting 48 | miner-tools.setting.floats.chat.shown.name = ChatTable Shown 49 | miner-tools.setting.floats.tools.shown.name = Show tools float table 50 | miner-tools.setting.floats.scriptButtons.shown.name = Show script buttons table 51 | miner-tools.setting.overrideCoreItemsDisplay.name = Override CoreItemsDisplay(MinerTools) 52 | miner-tools.setting.showPlanInfo.name = PlanInfoTable Shown 53 | miner-tools.setting.showColumns.name = Show Columns 54 | miner-tools.setting.overrideInfoTable.name = Override HoverInfoTable(MinerTools) 55 | miner-tools.setting.hover-locked.name = Locked HoverInfo 56 | # Modules Setting Categories' name 57 | miner-tools.setting.category.modules.spawnerInfo.name = SpawnerInfo 58 | miner-tools.setting.category.modules.spawnerInfo.spawnerTables.name = SpawnerTables 59 | miner-tools.setting.category.modules.spawnerInfo.destroyBuildings.name = DestroyBuildings 60 | miner-tools.setting.category.modules.spawnerInfo.spawnerRange.name = SpawnerRange 61 | miner-tools.setting.category.modules.spawnerInfo.spawnerViewer.name = SpawnerPreview 62 | # UI Setting Categories' name 63 | miner-tools.setting.category.ui.chat.name = ChatTable 64 | miner-tools.setting.category.ui.tools.name = Tools 65 | miner-tools.setting.category.ui.scriptButtons.name = Script buttons 66 | miner-tools.setting.category.ui.overrideCoreItemsDisplay.name = CoreItemsDisplay 67 | miner-tools.setting.category.ui.overrideInfoTable.name = HoverInfoTable 68 | miner-tools.setting.updateHeat.name = Item Flow Update Heat 69 | miner-tools.setting.meanSize.name = Item Flow Mean Size 70 | # Graphics Setting Categories' name 71 | miner-tools.setting.category.graphics.unit.name = Unit 72 | miner-tools.setting.category.graphics.build.name = Building 73 | miner-tools.setting.category.graphics.build.info.name = Building Info 74 | miner-tools.setting.category.graphics.select.name = Select 75 | miner-tools.setting.category.graphics.player.name = Player 76 | # Settings' Describe 77 | miner-tools.setting.unitAlert.describe = Show the unit's range that within player 78 | miner-tools.setting.turretAlert.describe = Show the turret's range that within player 79 | miner-tools.setting.overdriveZone.describe = Show the overdrive's range 80 | miner-tools.setting.constructBuildInfo.describe = Show the requirements of constructBuild 81 | miner-tools.setting.buildStatus.describe = Show build status even if different team 82 | miner-tools.setting.buildSelectInfo.describe = Show select info even if different team 83 | miner-tools.operator.show-hint = Click on the blank space to exit 84 | miner-tools.power-info = {0} Power Info 85 | # Stats 86 | stat.itemMineSpeed = Item Mine Speed 87 | # KeyBind Category 88 | category.MinerTools.name = MinerTools 89 | confirmvoteob = Are you sure you want to vote-observe "{0}[white]"? 90 | confirmvotegameover = Are you suer you want to vote-gameover? 91 | expand = expand 92 | retract = retract 93 | column = Column 94 | enabled = [green]Enable 95 | disabled = [red]Disabled 96 | nextWave = Next Wave 97 | totalUnits = Total Units 98 | totalHealth = Total Health 99 | totalShield = Total Shield 100 | translation-test = Translation test health range [yellow] M 101 | -------------------------------------------------------------------------------- /assets/bundles/bundle_zh_CN.properties: -------------------------------------------------------------------------------- 1 | # ModUpdater 2 | miner-tools.updater.name = [red]⚠[white]MinerTools有新版本可以更新! 3 | miner-tools.updater.info = 您的版本: [red]{0}, [white]最新版本: [green]{1} 4 | miner-tools.updater.load = 现在更新 5 | 6 | # Buttons' tooltip 7 | miner-tools.buttons.tooltips.updateConveyor = 升级传送带 8 | miner-tools.buttons.tooltips.stopBuilding = 暂停建造 9 | miner-tools.buttons.tooltips.observerMode = 观察者模式(静止不动) 10 | miner-tools.buttons.tooltips.wayzerObserver = 观察者模式(Wayzer) 11 | miner-tools.buttons.tooltips.quickVoteGameOver = 投降 12 | 13 | # FloatTable Hint 14 | miner-tools.floats.reshow-hint = 可以在设置中重新打开 15 | 16 | # FloatTables' name 17 | miner-tools.floats.main = MinerTools 18 | miner-tools.floats.chat = 聊天 19 | miner-tools.floats.scriptButtons = 实用按钮 20 | miner-tools.floats.tools = 工具箱 21 | 22 | miner-tools.settings = MinerTools设置 23 | 24 | # SettingTable's name 25 | miner-tools.setting.modules.name = 模块 26 | miner-tools.setting.graphics.name = 图像 27 | miner-tools.setting.ui.name = UI 28 | 29 | # Modules Setting 30 | miner-tools.setting.spawnerViewer.preview.name = 出怪点预览 31 | miner-tools.setting.spawnerViewer.alwaysShow.name = 出怪点位置显示 32 | 33 | # Graphics Setting 34 | ## Unit 35 | miner-tools.setting.enemyUnitIndicator.name = 敌军单位指示器 36 | miner-tools.setting.enemyUnitIndicatorRadius.name = 敌军单位指示器范围 37 | miner-tools.setting.unitAlert.name = 单位警戒 38 | miner-tools.setting.unitAlertRadius.name = 单位警戒范围 39 | miner-tools.setting.unitInfoBar.name = 单位信息条 40 | 41 | ## Build 42 | miner-tools.setting.turretAlert.name = 炮塔警戒 43 | miner-tools.setting.turretAlertRadius.name = 炮塔警戒范围 44 | miner-tools.setting.itemTurretAmmoShow.name = 显示物品炮塔的子弹类型 45 | miner-tools.setting.overdriveZone.name = 超速区域 46 | miner-tools.setting.buildStatus.name = 显示方块状态 47 | miner-tools.setting.buildHealthBar.name = 建筑血条 48 | miner-tools.setting.constructBuildInfo.name = 显示构造方块信息 49 | miner-tools.setting.unitBuildInfo.name = 单位工厂进度条 50 | 51 | ## Select 52 | miner-tools.setting.buildSelectInfo.name = 显示选择信息 53 | miner-tools.setting.itemBridgeLinksShow.name = 显示桥带连接 54 | 55 | ## Player 56 | miner-tools.setting.payloadDropHint.name = 荷载拾放提示 57 | miner-tools.setting.playerRange.name = 玩家范围 58 | 59 | # UI Setting 60 | miner-tools.setting.floats.chat.shown.name = 显示聊天浮窗 61 | miner-tools.setting.floats.tools.shown.name = 显示工具箱浮窗 62 | miner-tools.setting.floats.scriptButtons.shown.name = 显示实用按钮浮窗 63 | 64 | miner-tools.setting.overrideCoreItemsDisplay.name = 覆盖原版核心资源显示[yellow][M] 65 | miner-tools.setting.showPlanInfo.name = 显示预建消耗 66 | miner-tools.setting.showColumns.name = 显示物品列数 67 | 68 | miner-tools.setting.overrideInfoTable.name = 覆盖原版HoverInfoTable[yellow][M] 69 | miner-tools.setting.hover-locked.name = 锁定HoverInfo 70 | 71 | # Modules Setting Categories' name 72 | miner-tools.setting.category.modules.spawnerInfo.name = 出怪点显示 73 | miner-tools.setting.category.modules.spawnerInfo.spawnerTables.name = 出怪面板显示 74 | miner-tools.setting.category.modules.spawnerInfo.destroyBuildings.name = 摧毁建筑显示 75 | miner-tools.setting.category.modules.spawnerInfo.spawnerRange.name = 出怪点范围显示 76 | miner-tools.setting.category.modules.spawnerInfo.spawnerViewer.name = 出怪点预览 77 | 78 | # UI Setting Categories' name 79 | miner-tools.setting.category.ui.chat.name = 聊天 80 | miner-tools.setting.category.ui.tools.name = 工具箱 81 | miner-tools.setting.category.ui.scriptButtons.name = 实用按钮 82 | miner-tools.setting.category.ui.overrideCoreItemsDisplay.name = 核心资源显示 83 | miner-tools.setting.category.ui.overrideInfoTable.name = HoverInfoTable 84 | miner-tools.setting.updateHeat.name = 物品流动计算速度 85 | miner-tools.setting.meanSize.name = 物品流动采样数量 86 | 87 | # Graphics Setting Categories' name 88 | miner-tools.setting.category.graphics.unit.name = 单位 89 | 90 | miner-tools.setting.category.graphics.build.name = 建筑 91 | miner-tools.setting.category.graphics.build.info.name = 建筑信息 92 | 93 | miner-tools.setting.category.graphics.select.name = 选择 94 | 95 | miner-tools.setting.category.graphics.player.name = 玩家 96 | 97 | # Settings' Description 98 | miner-tools.setting.unitAlert.describe = 显示靠近玩家的单位的范围 99 | miner-tools.setting.turretAlert.describe = 显示靠近玩家的炮塔的范围 100 | miner-tools.setting.overdriveZone.describe = 显示超速范围 101 | miner-tools.setting.constructBuildInfo.describe = 显示建造中方块的资源需求信息 102 | miner-tools.setting.buildStatus.describe = 异队也能显示方块状态 103 | miner-tools.setting.buildSelectInfo.describe = 异队也能显示选中信息 104 | 105 | # ElementOperator 106 | miner-tools.operator.show-hint = 点击空白处可退出 107 | 108 | #TeamsInfo 109 | miner-tools.power-info = {0} 电力详情 110 | 111 | # Stats 112 | stat.itemMineSpeed = 挖矿速度 113 | 114 | # KeyBind Category 115 | category.MinerTools.name = MinerTools 116 | 117 | confirmvoteob = 确定投票使玩家“{0}[white]”ob? 118 | confirmvotegameover = 确定投降? 119 | 120 | expand = 展开 121 | retract = 收起 122 | 123 | column = 列 124 | 125 | enabled = [green]开启 126 | disabled = [red]关闭 127 | 128 | nextWave = 下一波 129 | totalUnits = 总单位 130 | totalHealth = 总血量 131 | totalShield = 总护盾 132 | 133 | translation-test = 翻译测试 血量 范围[yellow]M -------------------------------------------------------------------------------- /assets/shaders/rangeZone.frag: -------------------------------------------------------------------------------- 1 | #define HIGHP 2 | 3 | #define alpha 0.3 4 | #define width 2.0 5 | uniform sampler2D u_texture; 6 | uniform vec2 u_texsize; 7 | uniform vec2 u_invsize; 8 | uniform float u_time; 9 | uniform float u_dp; 10 | uniform vec2 u_offset; 11 | 12 | varying vec2 v_texCoords; 13 | 14 | /** From shields.frag */ 15 | void main(){ 16 | vec2 T = v_texCoords.xy; 17 | vec2 coords = (T * u_texsize) + u_offset; 18 | 19 | T += vec2(sin(coords.y / 4.0 + u_time / 50.0), cos(coords.x / 4.0 + u_time / 50.0)) / u_texsize; 20 | 21 | vec4 color = texture2D(u_texture, T); 22 | vec2 v = u_invsize; 23 | 24 | vec4 maxed = max(max(max(texture2D(u_texture, T + vec2(0, width) * v), texture2D(u_texture, T + vec2(0, -width) * v)), texture2D(u_texture, T + vec2(width, 0) * v)), texture2D(u_texture, T + vec2(-width, 0) * v)); 25 | 26 | if(texture2D(u_texture, T).a < 0.5 && maxed.a > 0.5){ 27 | gl_FragColor = vec4(maxed.rgb, maxed.a * 100.0); 28 | }else{ 29 | if(color.a > 0.0){ 30 | color.a = alpha * step(sin(coords.x / u_dp + coords.y / u_dp + u_time / 10.0), 0.9); 31 | } 32 | 33 | gl_FragColor = color; 34 | } 35 | } -------------------------------------------------------------------------------- /assets/sprites/ui/gradient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MinRi2/MinerTools/8ab2fe090cf24f0a5c8eaa0dcbea01f0a5447dd8/assets/sprites/ui/gradient.png -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "java" 2 | 3 | group = 'com.github.MinRi2' 4 | 5 | sourceSets.main.java.srcDirs = ["src"] 6 | 7 | java{ 8 | targetCompatibility = 8 9 | sourceCompatibility = 16 10 | } 11 | 12 | ext{ 13 | //the build number that this mod is made for 14 | mindustryVersion = 'v146' 15 | mindustryXVersion = 'ca40f700fb' 16 | minModCoreVersion = 'ccf5144901' 17 | uncVersion = '3397fc68eb' 18 | 19 | //windows sucks 20 | isWindows = System.getProperty("os.name").toLowerCase().contains("windows") 21 | sdkRoot = System.getenv("ANDROID_HOME") ?: System.getenv("ANDROID_SDK_ROOT") ?: "D:/Sdk" 22 | 23 | modDir = "${System.getenv("APPDATA")}\\Mindustry\\mods" 24 | } 25 | 26 | allprojects{ 27 | tasks.withType(JavaCompile){ 28 | options.compilerArgs.addAll(['--release', '8']) 29 | options.encoding('UTF-8') 30 | } 31 | } 32 | 33 | repositories{ 34 | mavenCentral() 35 | mavenLocal() 36 | maven{ url 'https://www.jitpack.io' } 37 | } 38 | 39 | dependencies{ 40 | annotationProcessor project(':annotation') 41 | annotationProcessor "com.github.EB-wilson.UniverseCore:annotations:$uncVersion" // 使用Unc注解处理器替代jabel 42 | 43 | compileOnly project(":annotation") 44 | compileOnly "com.github.anuken.arc:arc-core:$mindustryVersion" 45 | compileOnly "com.github.TinyLake.MindustryX:core:$mindustryXVersion" 46 | implementation "com.github.MinRi2:MinModCore:$minModCoreVersion" 47 | } 48 | 49 | //force arc version 50 | configurations.all{ 51 | resolutionStrategy.eachDependency{ details -> 52 | if(details.requested.group == 'com.github.Anuken.Arc'){ 53 | details.useVersion "$mindustryVersion" 54 | } 55 | } 56 | } 57 | 58 | task jarAndroid{ 59 | dependsOn "jar" 60 | 61 | doLast{ 62 | if(!sdkRoot || !new File(sdkRoot).exists()) throw new GradleException("No valid Android SDK found. Ensure that ANDROID_HOME is set to your Android SDK directory.") 63 | 64 | def platformRoot = new File("$sdkRoot/platforms/").listFiles().sort().reverse().find{ f -> new File(f, "android.jar").exists() } 65 | 66 | if(!platformRoot) throw new GradleException("No android.jar found. Ensure that you have an Android platform installed.") 67 | 68 | //collect dependencies needed for desugaring 69 | def dependencies = (configurations.compileClasspath.asList() + configurations.runtimeClasspath.asList() + [new File(platformRoot, "android.jar")]).collect{ "--classpath $it.path" }.join(" ") 70 | 71 | def d8 = isWindows ? "d8.bat" : "d8" 72 | 73 | //dex and desugar files - this requires d8 in your PATH 74 | "$d8 $dependencies --min-api 14 --output ${project.archivesBaseName}Android.jar ${project.archivesBaseName}Desktop.jar" 75 | .execute(null, new File("$buildDir/libs")).waitForProcessOutput(System.out, System.err) 76 | } 77 | } 78 | 79 | jar{ 80 | archiveFileName = "${base.archivesBaseName}Desktop.jar" 81 | 82 | from{ 83 | configurations.runtimeClasspath.collect{ it.isDirectory() ? it : zipTree(it) } 84 | } 85 | 86 | from(rootDir){ 87 | include "mod.hjson" 88 | } 89 | 90 | from("assets/"){ 91 | include "**" 92 | } 93 | } 94 | 95 | task deploy(type: Jar){ 96 | dependsOn jarAndroid 97 | dependsOn jar 98 | archiveFileName = "${base.archivesBaseName}.jar" 99 | 100 | from{ [zipTree("$buildDir/libs/${project.archivesBaseName}Desktop.jar"), zipTree("$buildDir/libs/${project.archivesBaseName}Android.jar")] } 101 | 102 | doLast{ 103 | delete{ 104 | delete "$buildDir/libs/${project.archivesBaseName}Desktop.jar" 105 | delete "$buildDir/libs/${project.archivesBaseName}Android.jar" 106 | } 107 | } 108 | } 109 | 110 | task compileAndCopy{ 111 | dependsOn jar 112 | 113 | doLast{ 114 | copy{ 115 | from "$buildDir/libs/" 116 | into "$modDir/" 117 | include "${project.archivesBaseName}Desktop.jar" 118 | } 119 | } 120 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs = --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \ 2 | --add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED \ 3 | --add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED \ 4 | --add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED \ 5 | --add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED \ 6 | --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED \ 7 | --add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED \ 8 | --add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED \ 9 | --add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED \ 10 | --add-exports=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED \ 11 | --add-exports=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED \ 12 | --add-exports=java.base/sun.reflect.annotation=ALL-UNNAMED -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MinRi2/MinerTools/8ab2fe090cf24f0a5c8eaa0dcbea01f0a5447dd8/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /mod.hjson: -------------------------------------------------------------------------------- 1 | #the mod name as displayed in-game 2 | displayName: "MinerTools" 3 | 4 | #the internal name of your mod 5 | name: "miner-tools" 6 | 7 | #your name 8 | author: "MinRi2" 9 | 10 | #the fully qualified main class of the mod 11 | main: "MinerTools.MinerTools" 12 | 13 | #the mod description as seen in the mod dialog 14 | description: " 15 | # 功能 16 | 17 | --- 18 | 19 | ## UI 20 | 1. [yellow]MinerToolsTable[white]: 21 | * 队伍信息: 22 | * 队伍玩家数量(Tooltip显示基础队伍规则) 23 | * 队伍单位显示 24 | * 队伍全局电量(Tooltip显示详细电量情况) 25 | * 一些有用的按钮: 26 | * 暂停建造([red]仅手机[white]) 27 | * 自动升级传送带 28 | * 重建方块 29 | * 快捷投降 30 | * 换队/跳波器 31 | * 玩家列表: 32 | * 所有玩家的名字 33 | * 可锁定玩家视角(锁定的玩家控制炮塔时,会自动调整视角) 34 | * 可切换到玩家视角 35 | * 可一键投票踢出玩家 36 | * 快捷蓝图 37 | * 玩家AI: 38 | * 挖矿AI 39 | * 跟随AI 40 | 41 | 2. [yellow]聊天记录[white]: 42 | * 查询历史聊天记录 43 | * 可以复制聊天记录(电脑:Ctrl+单击) 44 | 45 | 3. [yellow]更好的[red]核心资源显示[white]: 46 | * 单位数量显示 47 | * 物品每秒变化量显示 48 | * 玩家预建消耗显示 49 | * 可自定义的ui列数 50 | 51 | 4. [yellow]更好的[red]信息面板[white]: 52 | * 单位,建筑,地板信息一起显示! 53 | * 单位: 54 | * 武器冷却状态 55 | * 建筑: 56 | * 物品详情 57 | * 地板: 58 | * 显示更详尽 59 | 60 | --- 61 | 62 | ## 画面 63 | * 建筑: 64 | * 选中: 65 | * 异队选中信息 66 | * 桥带连接详情 67 | * 建筑血条 68 | * 异队方块状态 69 | * 构造方块耗材信息 70 | * 附近炮塔警戒 71 | * 物品炮塔子弹类型显示 72 | * 单位工厂进度条 73 | 74 | * 单位: 75 | * 单位指示器(核心危险警告) 76 | * 附近单位警戒 77 | 78 | * 单位信息条: 79 | * 血条 80 | * 立场回复条 81 | * 单位状态条 82 | * 荷载条 83 | 84 | * 玩家: 85 | * 荷载拾放提示 86 | * 玩家范围显示 87 | 88 | --- 89 | 90 | ## 其他小功能 91 | * 进入游戏后,显示被ban的单位或方块 92 | * UIScale的step修改 93 | * 物品桥带可拿取物品 94 | * 更多方块信息条: 95 | * 血条: 血量显示更详细 96 | * 进度条: 进度显示更详细 97 | 98 | --- 99 | 100 | # 其他 101 | Mod的90%功均可在设置中打开或关闭!" 102 | 103 | #the mod version 104 | version: 2.1.3 105 | 106 | hidden: true 107 | 108 | #the minimum game build required to run this mod 109 | minGameVersion: 136.1 110 | 111 | #this is a java mod 112 | java: true 113 | 114 | repo: "MinRi2/MinerTools" 115 | 116 | #dependencies: ["min-mod-core"] 117 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | if(JavaVersion.current().ordinal() < JavaVersion.VERSION_17.ordinal()) 2 | throw new IllegalStateException("this project require minium JDK version is 17, current: " + JavaVersion.current()) 3 | 4 | rootProject.name = "MinerTools" 5 | include 'annotation' 6 | include 'tools' -------------------------------------------------------------------------------- /src/MinerTools/MinerTools.java: -------------------------------------------------------------------------------- 1 | package MinerTools; 2 | 3 | import MinerTools.ai.*; 4 | import MinerTools.content.*; 5 | import MinerTools.content.override.*; 6 | import MinerTools.graphics.*; 7 | import MinerTools.modules.*; 8 | import arc.*; 9 | import arc.input.*; 10 | import mindustry.game.EventType.*; 11 | import mindustry.mod.*; 12 | 13 | import static MinerTools.MinerVars.desktop; 14 | import static MinerTools.game.ConveyorUpdater.*; 15 | import static MinerTools.input.ModBinding.updateConveyor; 16 | import static MinerTools.utils.GameUtils.tryPanToController; 17 | import static arc.Core.input; 18 | import static mindustry.Vars.mobile; 19 | 20 | public class MinerTools extends Mod{ 21 | public MinerTools(){ 22 | // mobile = true; // Only for debug 23 | Events.on(ContentInitEvent.class, e -> MContents.init()); 24 | 25 | Events.on(ClientLoadEvent.class, e -> Core.app.post(() -> { 26 | new ModUpdater(MinerVars.modName).checkUpdate(); 27 | 28 | MinerVars.init(); 29 | 30 | MStats.init(); 31 | 32 | Modules.init(); 33 | 34 | MRenderer.init(); 35 | 36 | Modules.load(); 37 | })); 38 | 39 | Events.run(Trigger.update, this::update); 40 | } 41 | 42 | public void update(){ 43 | if((desktop && input.keyDown(updateConveyor)) || (mobile && enable)){ 44 | tryUpdateConveyor(); 45 | } 46 | 47 | if(desktop && input.alt() && input.keyTap(KeyCode.mouseLeft)){ 48 | tryPanToController(); 49 | } 50 | 51 | if(MinerVars.ui != null){ 52 | MinerVars.ui.update(); 53 | } 54 | 55 | BaseAI.updateController(); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/MinerTools/MinerVars.java: -------------------------------------------------------------------------------- 1 | package MinerTools; 2 | 3 | import MinRi2.ModCore.io.*; 4 | import MinerTools.input.*; 5 | import MinerTools.ui.*; 6 | import arc.KeyBinds.*; 7 | import arc.files.*; 8 | import arc.util.*; 9 | import mindustry.*; 10 | 11 | import static arc.Core.*; 12 | import static mindustry.Vars.*; 13 | 14 | public class MinerVars{ 15 | public static final String modName = "miner-tools"; 16 | public static final String modSymbol = "[yellow][M]"; 17 | public static final float worldFontScl = Vars.tilesize / 36f; 18 | 19 | public static MinModSettings settings; 20 | public static MUI ui; 21 | 22 | public static boolean desktop; 23 | 24 | public static void init(){ 25 | settings = MinModSettings.registerSettings(modName); 26 | migrateOldSettings(); 27 | 28 | ui = new MUI(); 29 | 30 | desktop = app.isDesktop(); 31 | 32 | // update controls 33 | if(desktop){ 34 | initBindings(); 35 | } 36 | 37 | ui.init(); 38 | 39 | betterSchemeSize(); 40 | } 41 | 42 | public static void betterSchemeSize(){ 43 | maxSchematicSize = 128; 44 | } 45 | 46 | public static void initBindings(){ 47 | KeyBind[] bindings = Reflect.get(keybinds, "definitions"); 48 | KeyBind[] modBindings = ModBinding.values(); 49 | 50 | KeyBind[] newBindings = new KeyBind[bindings.length + modBindings.length]; 51 | System.arraycopy(bindings, 0, newBindings, 0, bindings.length); 52 | System.arraycopy(modBindings, 0, newBindings, bindings.length, modBindings.length); 53 | 54 | keybinds.setDefaults(newBindings); 55 | Reflect.invoke(keybinds, "load"); 56 | Reflect.invoke(Vars.ui.controls, "setup"); 57 | } 58 | 59 | private static void migrateOldSettings(){ 60 | Fi old = modDirectory.child("MinerTools").child("settings"); 61 | 62 | if(old.exists()){ 63 | old.copyTo(settings.settingsFi); 64 | settings.load(); 65 | settings.save(); 66 | modDirectory.child("MinerTools").deleteDirectory(); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/MinerTools/ModUpdater.java: -------------------------------------------------------------------------------- 1 | package MinerTools; 2 | 3 | import arc.*; 4 | import arc.util.*; 5 | import arc.util.serialization.*; 6 | import mindustry.*; 7 | import mindustry.mod.Mods.*; 8 | import mindustry.ui.dialogs.*; 9 | 10 | public class ModUpdater{ 11 | private final VersionChecker checker; 12 | private final LoadedMod mod; 13 | private final String repo; 14 | 15 | public ModUpdater(String modName){ 16 | this(modName, VersionChecker.defaultChecker); 17 | } 18 | 19 | public ModUpdater(String modName, VersionChecker checker){ 20 | this.mod = Vars.mods.locateMod(modName); 21 | if(this.mod == null){ 22 | throw new RuntimeException("Mod '" + modName + "' doesn't exit. Please check your modName parameter."); 23 | } 24 | 25 | repo = this.mod.getRepo(); 26 | if(repo == null){ 27 | throw new RuntimeException("Mod '" + modName + "' doesn't have repo."); 28 | } 29 | 30 | this.checker = checker; 31 | } 32 | 33 | public void checkUpdate(){ 34 | String modVersion = mod.meta.version; 35 | 36 | Http.get(Vars.ghApi + "/repos/" + repo + "/releases/latest", res -> { 37 | var json = Jval.read(res.getResultAsString()); 38 | String latestVersion = json.getString("tag_name").substring(1); 39 | 40 | Core.app.post(() -> { 41 | if(!checker.check(modVersion, latestVersion)){ 42 | confirmUpdate(latestVersion); 43 | } 44 | }); 45 | }, e -> { 46 | // Log.err(e); 47 | }); 48 | } 49 | 50 | private void confirmUpdate(String version){ 51 | Vars.ui.showCustomConfirm("@updater.name", 52 | Core.bundle.format("@updater.info", mod.meta.version, version), 53 | "@updater.load", "@ok", () -> { 54 | Reflect.invoke(ModsDialog.class, Vars.ui.mods, "githubImportJavaMod", new Object[]{repo, null}, String.class, String.class); 55 | }, () -> { 56 | }); 57 | } 58 | 59 | public interface VersionChecker{ 60 | VersionChecker defaultChecker = (currentVersion, latestVersion) -> { 61 | String[] current = currentVersion.split("\\."); 62 | String[] latest = currentVersion.split("\\."); 63 | 64 | if(current.length != latest.length){ 65 | return false; 66 | } 67 | 68 | for(int i = 0; i < current.length; i++){ 69 | int currentPart; 70 | int latestPart; 71 | 72 | try{ 73 | currentPart = Integer.parseInt(current[i]); 74 | latestPart = Integer.parseInt(latest[i]); 75 | }catch(Exception e){ 76 | Log.err("'@' or '@' cannot format into number", current[i], latest[i]); 77 | return false; 78 | } 79 | 80 | if(currentPart >= latestPart){ 81 | continue; 82 | } 83 | 84 | return false; 85 | } 86 | 87 | return true; 88 | }; 89 | 90 | boolean check(String currentVersion, String latestVersion); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/MinerTools/ai/BaseAI.java: -------------------------------------------------------------------------------- 1 | package MinerTools.ai; 2 | 3 | import mindustry.*; 4 | import mindustry.entities.units.*; 5 | import mindustry.input.*; 6 | 7 | public class BaseAI extends AIController{ 8 | public static BaseAI controller; 9 | 10 | public void requireUpdate(){ 11 | controller = this; 12 | } 13 | 14 | protected void update(){ 15 | if(Vars.control.input instanceof MobileInput input){ 16 | input.movement.setZero(); 17 | } 18 | } 19 | 20 | public static void resetController(){ 21 | controller = null; 22 | } 23 | 24 | public static void updateController(){ 25 | if(controller != null){ 26 | controller.update(); 27 | 28 | if(controller.unit() != null){ 29 | controller.updateUnit(); 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/MinerTools/ai/PlayerAI.java: -------------------------------------------------------------------------------- 1 | package MinerTools.ai; 2 | 3 | import MinerTools.interfaces.*; 4 | import arc.scene.style.*; 5 | import arc.scene.ui.layout.*; 6 | 7 | import static mindustry.Vars.player; 8 | 9 | public class PlayerAI extends BaseAI implements Displayable{ 10 | /** 用于{@link MinerTools.ui.tables.members.AITable} 标识AI种类, 不用时可为null */ 11 | public Drawable icon; 12 | 13 | public PlayerAI(Drawable icon){ 14 | this.icon = icon; 15 | } 16 | 17 | /* Needn't update weapons */ 18 | @Override 19 | public void updateWeapons(){} 20 | 21 | /* Needn't update target */ 22 | @Override 23 | public void updateTargeting(){} 24 | 25 | protected void update(){ 26 | super.update(); 27 | 28 | if(unit == null || unit != player.unit()){ 29 | unit(player.unit()); 30 | } 31 | } 32 | 33 | @Override 34 | public void display(Table table){} 35 | } 36 | -------------------------------------------------------------------------------- /src/MinerTools/ai/types/PlayerFollowAI.java: -------------------------------------------------------------------------------- 1 | package MinerTools.ai.types; 2 | 3 | import MinerTools.ai.*; 4 | import MinerTools.ui.*; 5 | import arc.scene.style.*; 6 | import arc.scene.ui.*; 7 | import arc.scene.ui.layout.*; 8 | import mindustry.*; 9 | import mindustry.content.*; 10 | import mindustry.gen.*; 11 | import mindustry.ui.*; 12 | 13 | public class PlayerFollowAI extends PlayerAI{ 14 | /* display */ 15 | private final Table playerSelect; 16 | private final ScrollPane pane; 17 | private int lastPlayerSize; 18 | private Player follow; 19 | 20 | public PlayerFollowAI(){ 21 | super(new TextureRegionDrawable(UnitTypes.oct.uiIcon)); 22 | 23 | pane = new ScrollPane(playerSelect = new Table(), Styles.noBarPane); 24 | 25 | MUI.panes.add(pane); 26 | 27 | setupPlayersTable(); 28 | } 29 | 30 | @Override 31 | protected void update(){ 32 | super.update(); 33 | 34 | if(follow != null && follow.unit().isNull()){ 35 | follow = null; 36 | } 37 | } 38 | 39 | @Override 40 | public void updateMovement(){ 41 | if(follow == null) return; 42 | 43 | if(!Vars.player.within(follow, follow.unit().hitSize() + 10 * Vars.tilesize)){ 44 | moveTo(follow, follow.unit().hitSize() + 10 * Vars.tilesize, 20f); 45 | }else{ 46 | if(unit.mineTile != null){ 47 | circle(unit.mineTile, unit.type.mineRange / 2f, 0.5f); 48 | }else{ 49 | circle(follow, follow.unit().hitSize() + 10 * Vars.tilesize, 0.5f); 50 | } 51 | } 52 | 53 | if(follow.unit().isBuilding()){ 54 | Vars.player.unit().plans().clear(); 55 | Vars.player.unit().plans().addFirst(follow.unit().plans.first()); 56 | } 57 | 58 | if(follow.unit().mining()){ 59 | Vars.player.unit().mineTile(follow.unit().mineTile()); 60 | } 61 | } 62 | 63 | @Override 64 | public void display(Table table){ 65 | table.add(pane).maxHeight(Vars.iconXLarge * 5).growX().get(); 66 | } 67 | 68 | private void setupPlayersTable(){ 69 | playerSelect.update(() -> { 70 | if(lastPlayerSize != Groups.player.size()){ 71 | lastPlayerSize = Groups.player.size(); 72 | rebuildPlayersTable(); 73 | } 74 | }); 75 | } 76 | 77 | private void rebuildPlayersTable(){ 78 | playerSelect.clear(); 79 | 80 | int index = 0; 81 | for(Player player : Groups.player){ 82 | if(player.team() != Vars.player.team()) continue; 83 | 84 | playerSelect.image().update(i -> i.setColor(player.team().color)).growY(); 85 | 86 | playerSelect.button(b -> { 87 | b.table(Tex.pane, i -> i.image(player::icon).size(Vars.iconXLarge).grow()).left(); 88 | b.labelWrap(player.coloredName()).padLeft(5f).growX(); 89 | }, MStyles.clearToggleAccentb, () -> resetFollow(player)).growX().minWidth(225f).checked(b -> follow == player); 90 | 91 | if(++index % 2 == 0) playerSelect.row(); 92 | } 93 | } 94 | 95 | private void resetFollow(Player player){ 96 | if(follow == player){ 97 | follow = null; 98 | }else{ 99 | follow = player; 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/MinerTools/ai/types/PlayerMinerAI.java: -------------------------------------------------------------------------------- 1 | package MinerTools.ai.types; 2 | 3 | import MinerTools.ai.*; 4 | import arc.*; 5 | import arc.graphics.*; 6 | import arc.scene.style.*; 7 | import arc.scene.ui.Button.*; 8 | import arc.scene.ui.layout.*; 9 | import arc.struct.*; 10 | import mindustry.content.*; 11 | import mindustry.game.*; 12 | import mindustry.gen.*; 13 | import mindustry.type.*; 14 | import mindustry.world.*; 15 | 16 | import static MinerTools.content.MContents.allOres; 17 | import static mindustry.Vars.*; 18 | 19 | public class PlayerMinerAI extends PlayerAI{ 20 | private final Seq mineOres = Seq.with(Items.copper, Items.lead); 21 | 22 | public Item targetItem; 23 | public Tile ore; 24 | public boolean mining; 25 | 26 | public PlayerMinerAI(){ 27 | super(new TextureRegionDrawable(UnitTypes.mono.uiIcon)); 28 | 29 | /* 适配ContentLoader */ 30 | Events.on(EventType.ContentInitEvent.class, e -> { 31 | for(int i = 0; i < mineOres.size; i++){ 32 | mineOres.set(i, content.item(i)); 33 | } 34 | }); 35 | } 36 | 37 | @Override 38 | public void updateMovement(){ 39 | Building core = unit.closestCore(); 40 | 41 | if(!(unit.canMine()) || core == null){ 42 | return; 43 | } 44 | 45 | if(unit.mineTile != null && !unit.mineTile.within(unit, unit.type.mineRange)){ 46 | unit.mineTile(null); 47 | } 48 | 49 | if(mining){ 50 | if(timer.get(timerTarget2, 60 * 4) || targetItem == null){ 51 | targetItem = mineOres.min(i -> indexer.hasOre(i) && unit.canMine(i), i -> core.items.get(i)); 52 | } 53 | 54 | //core full of the target item, do nothing 55 | if(targetItem != null && core.acceptStack(targetItem, 1, unit) == 0){ 56 | Call.dropItem(player.angleTo(player.x, player.y)); 57 | unit.mineTile = null; 58 | return; 59 | } 60 | 61 | //if inventory is full, drop it off. 62 | if(unit.stack.amount >= unit.type.itemCapacity || (targetItem != null && !unit.acceptsItem(targetItem))){ 63 | mining = false; 64 | }else{ 65 | if(timer.get(timerTarget3, 60) && targetItem != null){ 66 | ore = indexer.findClosestOre(unit, targetItem); 67 | } 68 | 69 | if(ore != null){ 70 | moveTo(ore, unit.type.mineRange / 2f, 20f); 71 | 72 | if(ore.block() == Blocks.air && unit.within(ore, unit.type.mineRange)){ 73 | unit.mineTile = ore; 74 | } 75 | 76 | if(ore.block() != Blocks.air){ 77 | mining = false; 78 | } 79 | } 80 | } 81 | }else{ 82 | unit.mineTile = null; 83 | 84 | if(unit.stack.amount == 0){ 85 | mining = true; 86 | return; 87 | } 88 | 89 | if(unit.within(core, unit.type.range)){ 90 | if(core.acceptStack(unit.stack.item, unit.stack.amount, unit) > 0){ 91 | Call.transferItemTo(unit, unit.stack.item, unit.stack.amount, unit.x, unit.y, core); 92 | } 93 | 94 | Call.dropItem(player.angleTo(player.x, player.y)); 95 | mining = true; 96 | } 97 | 98 | circle(core, unit.type.range / 1.8f); 99 | } 100 | } 101 | 102 | @Override 103 | public void display(Table table){ 104 | ButtonStyle none = new ButtonStyle(); 105 | 106 | table.table(oreSetting -> { 107 | oreSetting.add("Ore Setting: "); 108 | for(Item ore : allOres){ 109 | oreSetting.button(b -> { 110 | b.image(ore.uiIcon).update(i -> i.setColor(mineOres.contains(ore) ? Color.white : Color.gray)); 111 | }, none, () -> { 112 | if(!mineOres.contains(ore)){ 113 | mineOres.add(ore); 114 | mineOres.sort(o -> o.id); 115 | }else{ 116 | mineOres.remove(ore); 117 | } 118 | }).fill().get(); 119 | } 120 | }).right(); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/MinerTools/content/MContents.java: -------------------------------------------------------------------------------- 1 | package MinerTools.content; 2 | 3 | import MinerTools.content.override.*; 4 | import arc.struct.*; 5 | import mindustry.type.*; 6 | import mindustry.world.*; 7 | import mindustry.world.blocks.distribution.*; 8 | 9 | import static mindustry.Vars.content; 10 | 11 | public class MContents{ 12 | public static Seq allOres = new Seq<>(); 13 | 14 | public static void init(){ 15 | initBlocks(); 16 | initUnits(); 17 | } 18 | 19 | private static void initBlocks(){ 20 | allOres.clear(); 21 | 22 | for(Block block : content.blocks()){ 23 | if(block.itemDrop != null && !allOres.contains(block.itemDrop)){ 24 | allOres.add(block.itemDrop); 25 | } 26 | 27 | if(block instanceof ItemBridge){ 28 | block.allowConfigInventory = true; 29 | } 30 | 31 | MBars.override(block); 32 | } 33 | 34 | allOres.sort(item -> item.id); 35 | } 36 | 37 | private static void initUnits(){ 38 | // for(UnitType type : content.units()){ 39 | // } 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/MinerTools/content/override/MBars.java: -------------------------------------------------------------------------------- 1 | package MinerTools.content.override; 2 | 3 | import arc.*; 4 | import arc.func.*; 5 | import arc.graphics.*; 6 | import arc.util.*; 7 | import mindustry.core.*; 8 | import mindustry.gen.*; 9 | import mindustry.graphics.*; 10 | import mindustry.type.*; 11 | import mindustry.ui.*; 12 | import mindustry.world.*; 13 | import mindustry.world.blocks.heat.*; 14 | import mindustry.world.blocks.heat.HeatProducer.*; 15 | import mindustry.world.blocks.power.*; 16 | import mindustry.world.blocks.power.NuclearReactor.*; 17 | import mindustry.world.blocks.production.*; 18 | import mindustry.world.blocks.units.*; 19 | import mindustry.world.blocks.units.Reconstructor.*; 20 | import mindustry.world.blocks.units.UnitFactory.*; 21 | import mindustry.world.consumers.*; 22 | 23 | public class MBars{ 24 | 25 | public static void override(Block block){ 26 | block.addBar("health", e -> new Bar( 27 | () -> String.format("%.1f", e.health) + "/" + e.maxHealth + "(" + (int)(100 * e.healthf()) + "%" + ")", 28 | () -> Pal.health, e::healthf).blink(Color.white)); 29 | 30 | if(block.hasLiquids){ 31 | addLiquidBars(block); 32 | 33 | if(block instanceof GenericCrafter crafter && crafter.outputLiquids != null){ 34 | crafter.removeBar("liquid"); 35 | 36 | for(var stack : crafter.outputLiquids){ 37 | addLiquidBar(crafter, stack.liquid); 38 | } 39 | } 40 | } 41 | 42 | if(block instanceof UnitFactory factory){ 43 | block.addBar("progress", (UnitFactoryBuild e) -> new Bar( 44 | () -> { 45 | float ticks = e.currentPlan == -1 ? 0 : (1 - e.fraction()) * factory.plans.get(e.currentPlan).time / e.timeScale(); 46 | return Core.bundle.get("bar.progress") + ":" + UI.formatTime(ticks) + "(" + (int)(100 * e.fraction()) + "%" + ")"; 47 | }, 48 | () -> Pal.ammo, e::fraction)); 49 | } 50 | 51 | if(block instanceof Reconstructor reconstructor){ 52 | block.addBar("progress", (ReconstructorBuild e) -> new Bar( 53 | () -> Core.bundle.get("bar.progress") + ":" + UI.formatTime((1 - e.fraction()) * reconstructor.constructTime / e.timeScale()) + "(" + (int)(100 * e.fraction()) + "%" + ")", 54 | () -> Pal.ammo, e::fraction)); 55 | } 56 | 57 | if(block instanceof HeatProducer producer){ 58 | producer.addBar("heat", (HeatProducerBuild e) -> new Bar( 59 | () -> Core.bundle.format("bar.heatamount", (int)e.heat), 60 | () -> Pal.lightOrange, () -> e.heat / producer.heatOutput) 61 | ); 62 | } 63 | 64 | if(block instanceof NuclearReactor reactor){ 65 | reactor.addBar("heat", (NuclearReactorBuild e) -> new Bar( 66 | () -> Core.bundle.format("bar.heatamount", Strings.autoFixed(e.heat, 2)), 67 | () -> Pal.lightOrange, () -> e.heat)); 68 | } 69 | } 70 | 71 | private static void addLiquidBars(Block block){ 72 | boolean added = false; 73 | for(var consume : block.consumers){ 74 | if(consume instanceof ConsumeLiquid liq){ 75 | added = true; 76 | addLiquidBar(block, liq.liquid); 77 | }else if(consume instanceof ConsumeLiquids multi){ 78 | added = true; 79 | for(var stack : multi.liquids){ 80 | addLiquidBar(block, stack.liquid); 81 | } 82 | } 83 | } 84 | 85 | //nothing was added, so it's safe to add a dynamic liquid bar (probably?) 86 | if(!added){ 87 | addLiquidBar(block, build -> build.liquids.current()); 88 | } 89 | } 90 | 91 | private static void addLiquidBar(Block block, Liquid liq){ 92 | block.addBar("liquid-" + liq.name, e -> new Bar( 93 | () -> liq.localizedName + ": " + Strings.autoFixed(e.liquids.get(liq), 2), 94 | liq::barColor, 95 | () -> e.liquids.get(liq) / block.liquidCapacity 96 | )); 97 | } 98 | 99 | @SuppressWarnings("unchecked") 100 | private static void addLiquidBar(Block block, Func current){ 101 | block.addBar("liquid", e -> new Bar( 102 | () -> { 103 | if(current.get((T)e) == null || e.liquids.get(current.get((T)e)) <= 0.001f){ 104 | return Core.bundle.get("bar.liquid"); 105 | } 106 | Liquid liq = current.get((T)e); 107 | return liq.localizedName + ": " + Strings.autoFixed(e.liquids.get(liq), 2); 108 | }, 109 | () -> current.get((T)e) == null ? Color.clear : current.get((T)e).barColor(), 110 | () -> current.get((T)e) == null ? 0f : e.liquids.get(current.get((T)e)) / block.liquidCapacity) 111 | ); 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /src/MinerTools/content/override/MStats.java: -------------------------------------------------------------------------------- 1 | package MinerTools.content.override; 2 | 3 | import MinerTools.content.override.stats.*; 4 | import MinerTools.content.override.stats.unit.*; 5 | import arc.struct.*; 6 | import arc.util.*; 7 | import mindustry.*; 8 | import mindustry.ctype.*; 9 | import mindustry.type.*; 10 | import mindustry.ui.dialogs.*; 11 | import mindustry.world.*; 12 | import mindustry.world.meta.*; 13 | 14 | public class MStats{ 15 | private static final ContentOverrider blockOverrider = new ContentOverrider<>(); 16 | 17 | private static final ContentOverrider unitOverrider = new ContentOverrider<>(); 18 | 19 | public static void init(){ 20 | // blockOverrider.addOverriders(); 21 | unitOverrider.addOverriders(new MineTierOverrider()); 22 | 23 | addOverrideTrigger(); 24 | } 25 | 26 | private static void addOverrideTrigger(){ 27 | if(Vars.ui.content.getClass() == ContentInfoDialog.class){ 28 | Vars.ui.content = new ContentInfoDialog(){ 29 | @Override 30 | public void show(UnlockableContent content){ 31 | if(content instanceof Block block){ 32 | blockOverrider.override(block); 33 | }else if(content instanceof UnitType unitType){ 34 | unitOverrider.override(unitType); 35 | } 36 | 37 | super.show(content); 38 | } 39 | }; 40 | }else{ 41 | Log.warn("ContentInfoDialog has been replaced probably by other mod. If you want to enjoy more stat info, please uninstall the conflict mod"); 42 | } 43 | } 44 | 45 | public static class ContentOverrider{ 46 | private final IntSeq overridden = new IntSeq(); 47 | public ObjectMap>> map = new ObjectMap<>(); 48 | 49 | public void override(T type){ 50 | if(overridden.contains(type.id)){ 51 | return; 52 | } 53 | 54 | if(!type.stats.intialized){ 55 | type.checkStats(); 56 | } 57 | 58 | for(var seq : map.values()){ 59 | for(StatOverrider overrider : seq){ 60 | overrider.tryOverride(type.stats, type); 61 | } 62 | } 63 | 64 | overridden.add(type.id); 65 | } 66 | 67 | @SuppressWarnings("unchecked") 68 | public void addOverriders(StatOverrider... values){ 69 | for(StatOverrider overrider : values){ 70 | map.get(overrider.stat, Seq::new).add(overrider); 71 | } 72 | } 73 | 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/MinerTools/content/override/stats/StatOverrider.java: -------------------------------------------------------------------------------- 1 | package MinerTools.content.override.stats; 2 | 3 | import MinerTools.*; 4 | import arc.*; 5 | import arc.scene.ui.layout.*; 6 | import mindustry.ctype.*; 7 | import mindustry.world.meta.*; 8 | 9 | public abstract class StatOverrider{ 10 | public final Stat stat; 11 | 12 | public StatOverrider(Stat stat){ 13 | this.stat = stat; 14 | } 15 | 16 | public abstract boolean isValid(T type); 17 | 18 | public abstract void tryOverride(Stats stats, T type); 19 | 20 | protected abstract void override(Stats stats, Table table, T type); 21 | 22 | public static abstract class StatValueOverrider extends StatOverrider{ 23 | protected boolean clearStatValues = false; 24 | 25 | public StatValueOverrider(Stat stat){ 26 | super(stat); 27 | } 28 | 29 | public void tryOverride(Stats stats, T type){ 30 | if(!isValid(type)) return; 31 | 32 | if(clearStatValues){ 33 | clearStatValues(type); 34 | } 35 | 36 | stats.add(stat, table -> { 37 | override(stats, table, type); 38 | }); 39 | } 40 | 41 | protected final void clearStatValues(T type){ 42 | type.stats.remove(stat); 43 | } 44 | } 45 | 46 | public static abstract class StatAdder extends StatValueOverrider{ 47 | 48 | public StatAdder(String name){ 49 | this(name, StatCat.general); 50 | } 51 | 52 | public StatAdder(String name, StatCat category){ 53 | super(getStat(name, category)); 54 | } 55 | 56 | private static Stat getStat(String name, StatCat category){ 57 | Stat stat = Stat.all.find(s -> s.name.equals(name)); 58 | 59 | if(stat == null){ 60 | return new MStat(name, category); 61 | } 62 | 63 | return stat; 64 | } 65 | 66 | } 67 | 68 | public static class MStat extends Stat{ 69 | 70 | public MStat(String name, StatCat category){ 71 | super(name, category); 72 | } 73 | 74 | public MStat(String name){ 75 | super(name); 76 | } 77 | 78 | @Override 79 | public String localized(){ 80 | return Core.bundle.get("stat." + name) + MinerVars.modSymbol; 81 | } 82 | 83 | } 84 | } -------------------------------------------------------------------------------- /src/MinerTools/content/override/stats/unit/MineTierOverrider.java: -------------------------------------------------------------------------------- 1 | package MinerTools.content.override.stats.unit; 2 | 3 | import MinerTools.*; 4 | import MinerTools.content.override.stats.StatOverrider.*; 5 | import arc.scene.ui.layout.*; 6 | import arc.struct.*; 7 | import arc.util.*; 8 | import mindustry.*; 9 | import mindustry.graphics.*; 10 | import mindustry.type.*; 11 | import mindustry.ui.*; 12 | import mindustry.world.*; 13 | import mindustry.world.blocks.environment.*; 14 | import mindustry.world.meta.*; 15 | 16 | public class MineTierOverrider extends StatAdder{ 17 | public MineTierOverrider(){ 18 | super("mineTier"); 19 | 20 | clearStatValues = true; 21 | } 22 | 23 | private static Seq getMineBlocks(UnitType type){ 24 | return Vars.content.blocks().select(b -> 25 | b.itemDrop != null && 26 | (b instanceof Floor f && (((f.wallOre && type.mineWalls) || (!f.wallOre && type.mineFloor))) || 27 | (!(b instanceof Floor) && type.mineWalls)) && 28 | b.itemDrop.hardness <= type.mineTier 29 | ); 30 | } 31 | 32 | private static float getMineSpeed(UnitType type, Item item){ 33 | return 60 * type.mineSpeed / (50.0f + (!type.mineHardnessScaling ? 15f : (item.hardness * 15.0f))); 34 | } 35 | 36 | @Override 37 | public boolean isValid(UnitType type){ 38 | return type.mineTier >= 0; 39 | } 40 | 41 | @Override 42 | public void override(Stats stats, Table table, UnitType type){ 43 | table.row(); 44 | table.table(t -> { 45 | int index = 0; 46 | 47 | for(Block block : getMineBlocks(type)){ 48 | t.table(Styles.grayPanel, oreTable -> { 49 | oreTable.left(); 50 | 51 | oreTable.image(block.uiIcon).scaling(Scaling.fit).size(Vars.iconXLarge).padLeft(4f); 52 | 53 | oreTable.table(info -> { 54 | info.defaults().left(); 55 | 56 | info.add(block.localizedName).color(Pal.lightishGray); 57 | 58 | info.row(); 59 | 60 | info.image(block.itemDrop.uiIcon).scaling(Scaling.fit).size(Vars.iconSmall).padTop(2f); 61 | }).padLeft(4f); 62 | 63 | float mineSpeed = getMineSpeed(type, block.itemDrop); 64 | oreTable.add(Strings.autoFixed(mineSpeed, 2) + StatUnit.perSecond.localized() + MinerVars.modSymbol).labelAlign(Align.right).padLeft(8f).growX(); 65 | }).growX().margin(4f).pad(4f); 66 | 67 | if(++index % 2 == 0) t.row(); 68 | } 69 | }).growX(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/MinerTools/game/ConveyorUpdater.java: -------------------------------------------------------------------------------- 1 | package MinerTools.game; 2 | 3 | import arc.math.geom.*; 4 | import arc.struct.*; 5 | import mindustry.*; 6 | import mindustry.core.*; 7 | import mindustry.entities.units.*; 8 | import mindustry.gen.*; 9 | import mindustry.world.*; 10 | import mindustry.world.blocks.distribution.*; 11 | import mindustry.world.blocks.distribution.Conveyor.*; 12 | import mindustry.world.blocks.distribution.Duct.*; 13 | import mindustry.world.blocks.distribution.DuctBridge.*; 14 | import mindustry.world.blocks.distribution.DuctRouter.*; 15 | import mindustry.world.blocks.distribution.ItemBridge.*; 16 | import mindustry.world.blocks.distribution.Junction.*; 17 | import mindustry.world.blocks.distribution.OverflowDuct.*; 18 | import mindustry.world.blocks.distribution.OverflowGate.*; 19 | import mindustry.world.blocks.distribution.Router.*; 20 | import mindustry.world.blocks.distribution.Sorter.*; 21 | import mindustry.world.blocks.distribution.StackConveyor.*; 22 | import mindustry.world.blocks.distribution.StackRouter.*; 23 | 24 | import static arc.Core.input; 25 | 26 | public class ConveyorUpdater{ 27 | public static ObjectSet updatedBuildings = new ObjectSet<>(); 28 | public static boolean enable; 29 | public static Vec2 lastPos = new Vec2(); 30 | 31 | public static boolean toggle(){ 32 | return enable = !enable; 33 | } 34 | 35 | public static void tryUpdateConveyor(){ 36 | Vec2 pos = input.mouseWorld(input.mouseX(), input.mouseY()); 37 | 38 | if(pos.equals(lastPos)) return; 39 | 40 | lastPos.set(pos); 41 | 42 | Building target = Vars.world.build(World.toTile(pos.x), World.toTile(pos.y)); 43 | 44 | if(target == null) return; 45 | 46 | Block type = Vars.control.input.block; 47 | if(type != null && (type instanceof Conveyor || type instanceof StackConveyor || type instanceof Duct || type instanceof Junction) && target.block.size == type.size){ 48 | tryUpdateConveyor(target, type, target.rotation); 49 | updatedBuildings.clear(); 50 | } 51 | } 52 | 53 | public static void tryUpdateConveyor(Building start, Block type, int rotation){ 54 | /* StackOverflowError */ 55 | if(!updatedBuildings.add(start)) return; 56 | 57 | Building build = null; 58 | if(start instanceof ConveyorBuild || start instanceof DuctBuild || start instanceof StackConveyorBuild){ 59 | rotation = start.rotation; 60 | build = start.nearby(rotation); 61 | addPlan(start, type, rotation); 62 | }else if(start instanceof JunctionBuild junction){ 63 | if(type instanceof StackConveyor){ 64 | addPlan(start, type, rotation); 65 | } 66 | 67 | build = junction.nearby(rotation); 68 | }else if(start instanceof RouterBuild || start instanceof DuctRouterBuild || start instanceof SorterBuild || start instanceof OverflowDuctBuild || start instanceof OverflowGateBuild){ 69 | if(type instanceof StackConveyor && !(start instanceof StackRouterBuild)){ 70 | addPlan(start, type, rotation); 71 | } 72 | 73 | for(Building building : start.proximity){ 74 | tryUpdateConveyor(building, type, start.relativeTo(building)); 75 | } 76 | 77 | return; 78 | }else if(start instanceof DuctBridgeBuild duct){ 79 | DuctBridgeBuild other = (DuctBridgeBuild)duct.findLink(); 80 | 81 | if(other != null){ 82 | tryUpdateConveyor(other, type, start.rotation); 83 | }else{ 84 | for(Building building : start.proximity){ 85 | tryUpdateConveyor(building, type, start.relativeTo(building)); 86 | } 87 | } 88 | 89 | return; 90 | }else if(start instanceof ItemBridgeBuild bridge){ 91 | Tile otherTile = Vars.world.tile(bridge.link); 92 | ItemBridge block = (ItemBridge)bridge.block; 93 | 94 | if(block.linkValid(bridge.tile, otherTile)){ 95 | ItemBridgeBuild other = (ItemBridgeBuild)otherTile.build; 96 | tryUpdateConveyor(other, type, start.rotation); 97 | }else{ 98 | for(Building building : start.proximity){ 99 | tryUpdateConveyor(building, type, start.relativeTo(building)); 100 | } 101 | } 102 | 103 | return; 104 | } 105 | 106 | if(build == null || build.team != start.team){ 107 | return; 108 | } 109 | 110 | tryUpdateConveyor(build, type, rotation); 111 | } 112 | 113 | private static void addPlan(Building build, Block type, int rotation){ 114 | Vars.player.unit().addBuild(new BuildPlan(build.tileX(), build.tileY(), rotation, type)); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/MinerTools/game/MobileObserverMode.java: -------------------------------------------------------------------------------- 1 | package MinerTools.game; 2 | 3 | import arc.math.geom.*; 4 | import mindustry.*; 5 | import mindustry.input.*; 6 | 7 | public class MobileObserverMode{ 8 | public static boolean observing = false; 9 | 10 | private static final Vec2 movement = new Vec2(){ 11 | @Override 12 | public Vec2 setAngle(float degrees){ 13 | return super.setZero(); 14 | } 15 | }; 16 | private static Vec2 oldMovement; 17 | 18 | public static void toggle(){ 19 | 20 | if(Vars.mobile){ 21 | mobileObserver(); 22 | } 23 | 24 | } 25 | 26 | public static void mobileObserver(){ 27 | if(Vars.control.input instanceof MobileInput input){ 28 | if(oldMovement == null){ 29 | oldMovement = input.movement; 30 | } 31 | 32 | if(!observing){ 33 | input.movement = movement; 34 | }else{ 35 | input.movement = oldMovement; 36 | } 37 | 38 | observing = !observing; 39 | } 40 | } 41 | 42 | public static boolean isObserving(){ 43 | return observing; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/MinerTools/graphics/MDrawf.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics; 2 | 3 | import arc.graphics.*; 4 | import arc.graphics.g2d.*; 5 | import arc.math.geom.*; 6 | import arc.util.*; 7 | import arc.util.pooling.*; 8 | import mindustry.ui.*; 9 | 10 | public class MDrawf{ 11 | 12 | public static Rect drawText(String text, float scl, float dx, float dy){ 13 | return drawText(text, scl, dx, dy, Align.center); 14 | } 15 | 16 | public static Rect drawText(String text, float scl, float dx, float dy, int align){ 17 | return drawText(text, scl, dx, dy, Color.white, align); 18 | } 19 | 20 | public static Rect drawText(String text, float scl, float dx, float dy, Color color){ 21 | return drawText(text, scl, dx, dy, color, Align.center); 22 | } 23 | 24 | public static Rect drawText(String text, float scl, float dx, float dy, Color color, int align){ 25 | Font font = Fonts.outline; 26 | GlyphLayout layout = Pools.obtain(GlyphLayout.class, GlyphLayout::new); 27 | boolean ints = font.usesIntegerPositions(); 28 | font.setUseIntegerPositions(false); 29 | font.getData().setScale(scl); 30 | layout.setText(font, text); 31 | 32 | float ry = dy + layout.height + 1; 33 | float width = layout.width, height = layout.height; 34 | 35 | font.setColor(color); 36 | font.draw(text, dx, ry, align); 37 | 38 | font.setUseIntegerPositions(ints); 39 | font.setColor(Color.white); 40 | font.getData().setScale(1f); 41 | Draw.reset(); 42 | Pools.free(layout); 43 | 44 | return Tmp.r1.set(dx, ry, width, height); 45 | } 46 | 47 | public static float drawProgressBar(float x, float y, float x2, float y2, float progress, float backBarStroke, float backBarAlpha, Color backBarColor, float barStroke, float barAlpha, Color barColor){ 48 | /* Background */ 49 | Lines.stroke(backBarStroke, backBarColor); 50 | Draw.alpha(backBarAlpha); 51 | Lines.line(x, y, x2, y2); 52 | 53 | float barX = x + (x2 - x) * progress; 54 | 55 | /* Process bar */ 56 | Lines.stroke(barStroke, barColor); 57 | Draw.alpha(barAlpha); 58 | Lines.line(x, y, barX, y2); 59 | 60 | Draw.reset(); 61 | 62 | return barX; 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/MinerTools/graphics/MLayer.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics; 2 | 3 | public class MLayer{ 4 | public static final float 5 | overdriveZone = 118; 6 | } 7 | -------------------------------------------------------------------------------- /src/MinerTools/graphics/MRenderer.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics; 2 | 3 | import MinerTools.graphics.draw.build.*; 4 | import MinerTools.graphics.draw.build.select.*; 5 | import MinerTools.graphics.draw.player.*; 6 | import MinerTools.graphics.draw.unit.*; 7 | import MinerTools.graphics.provider.*; 8 | import arc.*; 9 | import arc.struct.*; 10 | import mindustry.game.EventType.*; 11 | 12 | public class MRenderer{ 13 | private static final Seq> providers = new Seq<>(); 14 | 15 | public static void init(){ 16 | MShaders.init(); 17 | 18 | BuildProvider buildProvider = new BuildProvider(); 19 | UnitProvider unitProvider = new UnitProvider(); 20 | PlayerProvider playerProvider = new PlayerProvider(); 21 | SelectProvider selectProvider = new SelectProvider(); 22 | 23 | buildProvider.addGlobalDrawers(new TurretAlert()) 24 | .addCameraDrawers( 25 | new TurretAmmoDisplay(), new BuildStatus(), 26 | new UnitBuildInfo(), new BuildHealthBar(), 27 | new UnitAssemblerInfo(), new OverdriveZone() 28 | ); 29 | unitProvider.addGlobalDrawers(new UnitAlert(), new EnemyIndicator()).addCameraDrawers(new UnitInfoBar()); 30 | playerProvider.addGlobalDrawers(new PlayerRange()).addLocalDrawers(new PayloadDropHint()); 31 | selectProvider.addBuildDrawers(new ConstructBlockInfo(), new BuildSelect(), new BridgeLinkedList()); 32 | 33 | providers.addAll(buildProvider, unitProvider, playerProvider, selectProvider); 34 | 35 | updateEnable(); 36 | 37 | updateSettings(); 38 | 39 | Events.run(Trigger.draw, () -> { 40 | for(DrawerProvider provider : providers){ 41 | provider.provide(); 42 | provider.drawShader(); 43 | } 44 | }); 45 | } 46 | 47 | public static void updateEnable(){ 48 | for(DrawerProvider provider : providers){ 49 | provider.updateEnable(); 50 | } 51 | } 52 | 53 | public static void updateSettings(){ 54 | for(DrawerProvider provider : providers){ 55 | provider.updateSetting(); 56 | } 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/MinerTools/graphics/MShaders.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics; 2 | 3 | import arc.*; 4 | import arc.files.*; 5 | import arc.graphics.gl.*; 6 | import arc.scene.ui.layout.*; 7 | import arc.util.*; 8 | import mindustry.*; 9 | 10 | public class MShaders{ 11 | public static MShader overdriveZone; 12 | 13 | public static void init(){ 14 | overdriveZone = new OverdriveZoneShader(); 15 | } 16 | 17 | static class OverdriveZoneShader extends MShader{ 18 | 19 | public OverdriveZoneShader(){ 20 | super("rangeZone", "screenspace"); 21 | } 22 | 23 | @Override 24 | public void apply(){ 25 | setUniformf("u_dp", Scl.scl(1f)); 26 | setUniformf("u_time", Time.time / Scl.scl(1f)); 27 | setUniformf("u_offset", 28 | Core.camera.position.x - Core.camera.width / 2, 29 | Core.camera.position.y - Core.camera.height / 2); 30 | setUniformf("u_texsize", Core.camera.width, Core.camera.height); 31 | setUniformf("u_invsize", 1f/Core.camera.width, 1f/Core.camera.height); 32 | } 33 | } 34 | 35 | static class MShader extends Shader{ 36 | 37 | public MShader(String frag, String vert){ 38 | super(getShaderFi(vert + ".vert"), getShaderFi(frag + ".frag")); 39 | } 40 | 41 | public static Fi getShaderFi(String file){ 42 | Fi fi = Core.files.internal("shaders/" + file); 43 | 44 | if(!fi.exists()){ 45 | fi = Vars.tree.get("shaders/" + file); 46 | 47 | if(!fi.exists()){ 48 | throw new ArcRuntimeException("Cannot get shader fi: " + file); 49 | } 50 | } 51 | 52 | return fi; 53 | } 54 | 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/MinerTools/graphics/draw/BuildDrawer.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics.draw; 2 | 3 | import arc.func.*; 4 | import mindustry.*; 5 | import mindustry.gen.*; 6 | import mindustry.world.*; 7 | 8 | public abstract class BuildDrawer extends Drawer{ 9 | private final Boolf shouldDrawBlock; 10 | 11 | public BuildDrawer(){ 12 | this(block -> true); 13 | } 14 | 15 | public BuildDrawer(Boolf shouldDrawBlock){ 16 | this.shouldDrawBlock = shouldDrawBlock; 17 | } 18 | 19 | @SuppressWarnings("unchecked") 20 | @Override 21 | public void tryDraw(Building type){ 22 | if(!shouldDrawBlock.get(type.block)) return; 23 | 24 | super.tryDraw((T)type); 25 | } 26 | 27 | @Override 28 | protected abstract void draw(T building); 29 | 30 | @Override 31 | public boolean shouldDraw(T building){ 32 | return building.isValid() && !building.inFogTo(Vars.player.team()); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/MinerTools/graphics/draw/Drawer.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics.draw; 2 | 3 | import arc.math.geom.*; 4 | 5 | public abstract class Drawer{ 6 | 7 | /* Read some settings */ 8 | public void readSetting(){ 9 | } 10 | 11 | /* Return true if the drawer is enabled */ 12 | public boolean isEnabled(){ 13 | return true; 14 | } 15 | 16 | /* Return true if the drawer is valid in game */ 17 | public boolean isValid(){ 18 | return true; 19 | } 20 | 21 | /* Return true if the drawer should draw this type */ 22 | public boolean shouldDraw(T type){ 23 | return true; 24 | } 25 | 26 | /* Draw Shader */ 27 | public void drawShader(){ 28 | } 29 | 30 | /* Try to draw */ 31 | public void tryDraw(T type){ 32 | if(shouldDraw(type)) draw(type); 33 | } 34 | 35 | /* Draw */ 36 | protected abstract void draw(T type); 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/MinerTools/graphics/draw/PlayerDrawer.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics.draw; 2 | 3 | import mindustry.gen.*; 4 | 5 | public abstract class PlayerDrawer extends Drawer{ 6 | 7 | @Override 8 | public boolean shouldDraw(Player player){ 9 | return !player.dead(); 10 | } 11 | 12 | @Override 13 | protected abstract void draw(Player player); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/MinerTools/graphics/draw/UnitDrawer.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics.draw; 2 | 3 | import mindustry.*; 4 | import mindustry.gen.*; 5 | 6 | public abstract class UnitDrawer extends Drawer{ 7 | 8 | @Override 9 | public boolean shouldDraw(Unit unit){ 10 | return unit.isValid() && !unit.inFogTo(Vars.player.team()); 11 | } 12 | 13 | @Override 14 | protected abstract void draw(Unit unit); 15 | } -------------------------------------------------------------------------------- /src/MinerTools/graphics/draw/build/BuildHealthBar.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics.draw.build; 2 | 3 | import MinerTools.*; 4 | import MinerTools.graphics.*; 5 | import MinerTools.graphics.draw.*; 6 | import arc.graphics.g2d.*; 7 | import mindustry.game.*; 8 | import mindustry.gen.*; 9 | import mindustry.graphics.*; 10 | import mindustry.world.blocks.defense.*; 11 | import mindustry.world.blocks.defense.ShieldWall.*; 12 | 13 | public class BuildHealthBar extends BuildDrawer{ 14 | public static float healthBarStroke = 1.7f, healthBarAlpha = 0.85f; 15 | public static float backBarStroke = healthBarStroke + 1.3f, backBarAlpha = healthBarAlpha - 0.25f; 16 | 17 | @Override 18 | public boolean isEnabled(){ 19 | return MinerVars.settings.getBool("buildHealthBar"); 20 | } 21 | 22 | @Override 23 | public boolean shouldDraw(Building building){ 24 | return super.shouldDraw(building) && building.team != Team.derelict; 25 | } 26 | 27 | @Override 28 | protected void draw(Building build){ 29 | float startX = build.x - build.hitSize() / 2f + build.hitSize() / 6f, startY = build.y - build.hitSize() / 2f + backBarStroke; 30 | float endX = build.x + build.hitSize() / 2f - build.hitSize() / 6f; 31 | 32 | Draw.z(Layer.power - 1f); 33 | 34 | if(build.damaged()){ 35 | MDrawf.drawProgressBar( 36 | startX, startY, endX, startY, build.healthf(), 37 | backBarStroke, backBarAlpha, build.team.color, 38 | healthBarStroke, healthBarAlpha, Pal.health 39 | ); 40 | 41 | startY += backBarStroke; 42 | } 43 | 44 | if(build instanceof ShieldWallBuild shieldWall && shieldWall.shield > 0.001f){ 45 | ShieldWall block = (ShieldWall)shieldWall.block; 46 | 47 | MDrawf.drawProgressBar( 48 | startX, startY, endX, startY, shieldWall.shield / block.shieldHealth, 49 | backBarStroke, backBarAlpha, shieldWall.team.color, 50 | healthBarStroke, healthBarAlpha, Pal.shield 51 | ); 52 | 53 | // start += backBarStroke; 54 | } 55 | 56 | Draw.reset(); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/MinerTools/graphics/draw/build/BuildStatus.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics.draw.build; 2 | 3 | import MinerTools.*; 4 | import MinerTools.graphics.draw.*; 5 | import arc.graphics.g2d.*; 6 | import mindustry.*; 7 | import mindustry.game.*; 8 | import mindustry.gen.*; 9 | import mindustry.graphics.*; 10 | 11 | public class BuildStatus extends BuildDrawer{ 12 | 13 | @Override 14 | public boolean isEnabled(){ 15 | return MinerVars.settings.getBool("buildStatus"); 16 | } 17 | 18 | @Override 19 | public boolean shouldDraw(Building building){ 20 | return super.shouldDraw(building) && building.team != Team.derelict && building.team != Vars.player.team(); 21 | } 22 | 23 | @Override 24 | protected void draw(Building build){ 25 | if(!build.enabled && build.block.drawDisabled){ 26 | Draw.z(Layer.overlayUI); 27 | build.drawDisabled(); 28 | } 29 | 30 | Draw.z(Layer.block); 31 | build.drawTeam(); 32 | 33 | if(Vars.renderer.drawStatus && build.block.hasConsumers){ 34 | Draw.z(Layer.block); 35 | build.drawStatus(); 36 | } 37 | 38 | Draw.reset(); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/MinerTools/graphics/draw/build/ConstructBlockInfo.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics.draw.build; 2 | 3 | import MinerTools.*; 4 | import MinerTools.graphics.*; 5 | import MinerTools.graphics.draw.*; 6 | import arc.graphics.g2d.*; 7 | import arc.util.*; 8 | import mindustry.*; 9 | import mindustry.core.*; 10 | import mindustry.graphics.*; 11 | import mindustry.type.*; 12 | import mindustry.world.blocks.*; 13 | import mindustry.world.blocks.ConstructBlock.*; 14 | import mindustry.world.blocks.storage.CoreBlock.*; 15 | 16 | public class ConstructBlockInfo extends BuildDrawer{ 17 | 18 | public ConstructBlockInfo(){ 19 | super(block -> block instanceof ConstructBlock); 20 | } 21 | 22 | @Override 23 | public boolean isEnabled(){ 24 | return MinerVars.settings.getBool("constructBuildInfo"); 25 | } 26 | 27 | @Override 28 | public boolean shouldDraw(ConstructBuild building){ 29 | return super.shouldDraw(building) && building.core() != null; 30 | } 31 | 32 | @Override 33 | protected void draw(ConstructBuild c){ 34 | CoreBuild core = c.core(); 35 | 36 | // Above building 37 | Draw.z(Layer.blockBuilding + 0.1f); 38 | 39 | ConstructBlock block = (ConstructBlock)c.block; 40 | float buildCostMultiplier = Vars.state.rules.buildCostMultiplier; 41 | float scl = block.size * MinerVars.worldFontScl / 2f; 42 | 43 | MDrawf.drawText(Strings.autoFixed(c.progress * 100, 2) + "%", scl, c.x, c.y + block.size * Vars.tilesize / 2f, Pal.accent, Align.center); 44 | 45 | float nextPad = 0f; 46 | for(int i = 0; i < c.current.requirements.length; i++){ 47 | ItemStack stack = c.current.requirements[i]; 48 | 49 | float dx = c.x - (block.size * Vars.tilesize) / 2f, dy = c.y - (block.size * Vars.tilesize) / 2f + nextPad; 50 | boolean hasItem = (1.0f - c.progress) * buildCostMultiplier * stack.amount <= core.items.get(stack.item); 51 | 52 | int needAmount = (int)(c.progress * buildCostMultiplier * stack.amount); 53 | int invertAmount = (int)(buildCostMultiplier * stack.amount); 54 | int coreAmount = core.items.get(stack.item); 55 | 56 | nextPad += MDrawf.drawText( 57 | stack.item.emoji() + needAmount + "/" + invertAmount + "/" + UI.formatAmount(coreAmount), 58 | scl, dx, dy, hasItem ? Pal.accent : Pal.remove, Align.left).height; 59 | nextPad++; 60 | } 61 | 62 | Draw.reset(); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/MinerTools/graphics/draw/build/OverdriveZone.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics.draw.build; 2 | 3 | import MinerTools.*; 4 | import MinerTools.graphics.*; 5 | import MinerTools.graphics.draw.*; 6 | import arc.graphics.*; 7 | import arc.graphics.g2d.*; 8 | import mindustry.world.blocks.defense.*; 9 | import mindustry.world.blocks.defense.OverdriveProjector.*; 10 | 11 | import static mindustry.Vars.renderer; 12 | 13 | public class OverdriveZone extends BuildDrawer{ 14 | 15 | public OverdriveZone(){ 16 | super(block -> block instanceof OverdriveProjector); 17 | } 18 | 19 | @Override 20 | public boolean isEnabled(){ 21 | return MinerVars.settings.getBool("overdriveZone"); 22 | } 23 | 24 | @Override 25 | public boolean shouldDraw(OverdriveBuild building){ 26 | return super.shouldDraw(building) && building.canConsume(); 27 | } 28 | 29 | @Override 30 | public void drawShader(){ 31 | Draw.drawRange(MLayer.overdriveZone, 0.2f, () -> renderer.effectBuffer.begin(Color.clear), () -> { 32 | renderer.effectBuffer.end(); 33 | renderer.effectBuffer.blit(MShaders.overdriveZone); 34 | }); 35 | } 36 | 37 | @Override 38 | protected void draw(OverdriveBuild build){ 39 | OverdriveProjector block = (OverdriveProjector)build.block; 40 | 41 | float realRange = block.range + build.phaseHeat * block.phaseRangeBoost; 42 | 43 | Draw.z(MLayer.overdriveZone); 44 | 45 | Draw.color(block.baseColor); 46 | Fill.circle(build.x, build.y, realRange); 47 | 48 | Draw.reset(); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/MinerTools/graphics/draw/build/TurretAlert.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics.draw.build; 2 | 3 | import MinerTools.*; 4 | import MinerTools.graphics.draw.*; 5 | import arc.graphics.g2d.*; 6 | import arc.util.*; 7 | import mindustry.graphics.*; 8 | import mindustry.world.blocks.defense.turrets.*; 9 | import mindustry.world.blocks.defense.turrets.BaseTurret.*; 10 | import mindustry.world.blocks.defense.turrets.TractorBeamTurret.*; 11 | import mindustry.world.blocks.defense.turrets.Turret.*; 12 | 13 | import static mindustry.Vars.*; 14 | 15 | public class TurretAlert extends BuildDrawer{ 16 | public float turretAlertRadius; 17 | 18 | public TurretAlert(){ 19 | super(block -> block instanceof Turret); 20 | } 21 | 22 | @Override 23 | public void readSetting(){ 24 | turretAlertRadius = MinerVars.settings.getInt("turretAlertRadius") * tilesize; 25 | } 26 | 27 | @Override 28 | public boolean isEnabled(){ 29 | return MinerVars.settings.getBool("turretAlert"); 30 | } 31 | 32 | @Override 33 | public boolean isValid(){ 34 | return !player.unit().isNull(); 35 | } 36 | 37 | @Override 38 | public boolean shouldDraw(BaseTurretBuild baseTurret){ 39 | if(!super.shouldDraw(baseTurret)) return false; 40 | 41 | if(baseTurret.team == player.team()) return false; 42 | 43 | if(!baseTurret.within(player, turretAlertRadius + baseTurret.range())) return false; 44 | 45 | BaseTurret baseBlock = (BaseTurret)baseTurret.block; 46 | 47 | boolean hasAmmo = false, canHitPlayer = false; 48 | if(baseTurret instanceof TurretBuild turret){ 49 | Turret block = (Turret)baseBlock; 50 | hasAmmo = turret.hasAmmo(); 51 | canHitPlayer = player.unit().isFlying() ? block.targetAir : block.targetGround; 52 | }else if(baseTurret instanceof TractorBeamBuild turret){ 53 | TractorBeamTurret block = (TractorBeamTurret)baseBlock; 54 | hasAmmo = turret.power.status > 0; 55 | canHitPlayer = player.unit().isFlying() ? block.targetAir : block.targetGround; 56 | } 57 | 58 | return hasAmmo && canHitPlayer; 59 | } 60 | 61 | @Override 62 | protected void draw(BaseTurretBuild turret){ 63 | Draw.z(Layer.overlayUI); 64 | 65 | Lines.stroke(1.2f); 66 | Drawf.dashCircle(turret.x, turret.y, turret.range(), turret.team.color); 67 | 68 | Draw.color(turret.team.color); 69 | 70 | float dst = turret.dst(player); 71 | if(dst > turret.range()){ 72 | Tmp.v1.set(turret).sub(player).setLength(dst - turret.range()); 73 | Draw.rect(turret.block.fullIcon, player.x + Tmp.v1.x, player.y + Tmp.v1.y, 10f + turret.block.size * 3f, 10f + turret.block.size * 3f, Tmp.v1.angle() - 90f); 74 | } 75 | 76 | Draw.reset(); 77 | } 78 | 79 | } -------------------------------------------------------------------------------- /src/MinerTools/graphics/draw/build/TurretAmmoDisplay.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics.draw.build; 2 | 3 | import MinerTools.*; 4 | import MinerTools.graphics.draw.*; 5 | import arc.graphics.g2d.*; 6 | import arc.math.*; 7 | import mindustry.graphics.*; 8 | import mindustry.type.*; 9 | import mindustry.world.blocks.defense.turrets.*; 10 | import mindustry.world.blocks.defense.turrets.ItemTurret.*; 11 | 12 | import static mindustry.Vars.tilesize; 13 | 14 | 15 | /** 16 | * 炮塔子弹类型显示 17 | */ 18 | public class TurretAmmoDisplay extends BuildDrawer{ 19 | 20 | public TurretAmmoDisplay(){ 21 | super(block -> block instanceof ItemTurret); 22 | } 23 | 24 | @Override 25 | public void readSetting(){ 26 | super.readSetting(); 27 | } 28 | 29 | @Override 30 | public boolean isEnabled(){ 31 | return MinerVars.settings.getBool("itemTurretAmmoShow"); 32 | } 33 | 34 | @Override 35 | public boolean shouldDraw(ItemTurretBuild turret){ 36 | return super.shouldDraw(turret) && turret.ammo.any(); 37 | } 38 | 39 | @Override 40 | protected void draw(ItemTurretBuild turret){ 41 | ItemTurret block = (ItemTurret)turret.block; 42 | ItemEntry entry = (ItemEntry)turret.ammo.peek(); 43 | 44 | Item item = entry.item; 45 | 46 | Draw.z(Layer.turret + 0.1f); 47 | 48 | float maxSize = Math.max(6f, block.size * tilesize / 2f); 49 | float x = turret.x + block.size * tilesize / 3f; 50 | float y = turret.y + block.size * tilesize / 3f; 51 | 52 | float realSize = Mathf.lerp(3f, maxSize, Math.min(1f, (float)entry.amount / block.maxAmmo)); 53 | 54 | Draw.alpha(0.45f); 55 | Draw.rect(item.uiIcon, x, y, maxSize, maxSize); 56 | 57 | Draw.alpha(1f); 58 | Draw.rect(item.uiIcon, x, y, realSize, realSize); 59 | 60 | Draw.reset(); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/MinerTools/graphics/draw/build/UnitAssemblerInfo.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics.draw.build; 2 | 3 | import MinerTools.*; 4 | import MinerTools.graphics.*; 5 | import MinerTools.graphics.draw.*; 6 | import arc.graphics.g2d.*; 7 | import arc.util.*; 8 | import mindustry.*; 9 | import mindustry.graphics.*; 10 | import mindustry.world.blocks.units.*; 11 | import mindustry.world.blocks.units.UnitAssembler.*; 12 | 13 | public class UnitAssemblerInfo extends BuildDrawer{ 14 | public static float proBarStroke = 1.7f, proBarAlpha = 0.85f; 15 | public static float backBarStroke = proBarStroke + 1.3f, backBarAlpha = 0.5f; 16 | 17 | public UnitAssemblerInfo(){ 18 | super(block -> block instanceof UnitAssembler); 19 | } 20 | 21 | @Override 22 | public boolean isEnabled(){ 23 | return MinerVars.settings.getBool("unitBuildInfo"); 24 | } 25 | 26 | @Override 27 | public boolean shouldDraw(UnitAssemblerBuild building){ 28 | return super.shouldDraw(building) && Math.min(building.powerWarmup, building.sameTypeWarmup) > 0; 29 | } 30 | 31 | @Override 32 | protected void draw(UnitAssemblerBuild build){ 33 | UnitAssembler block = (UnitAssembler)build.block; 34 | 35 | var spawnPos = build.getUnitSpawn().add(0, 14f); 36 | 37 | float size = build.plan().unit.hitSize; 38 | float x = spawnPos.x, y = spawnPos.y; 39 | 40 | float fraction = build.progress; 41 | float startX = x - size / 2f, startY = y + size / 2f; 42 | float endX = x + size / 2f; 43 | 44 | Draw.z(Layer.power + 0.3f); 45 | 46 | MDrawf.drawProgressBar( 47 | startX, startY, endX, startY, fraction, 48 | backBarStroke, backBarAlpha, build.team.color, 49 | proBarStroke, proBarAlpha, build.team.color 50 | ); 51 | 52 | startY += backBarStroke; 53 | 54 | float scale = build.timeScale() * Vars.state.rules.unitBuildSpeed(build.team); 55 | float time = (1 - fraction) * build.plan().time / scale; 56 | 57 | float scl = block.size * MinerVars.worldFontScl / 2f; 58 | MDrawf.drawText(Strings.autoFixed(time / 60, 1) + "s", scl, startX + size / 2, startY); 59 | 60 | Draw.reset(); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/MinerTools/graphics/draw/build/UnitBuildInfo.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics.draw.build; 2 | 3 | import MinerTools.*; 4 | import MinerTools.graphics.*; 5 | import MinerTools.graphics.draw.*; 6 | import arc.graphics.*; 7 | import arc.graphics.g2d.*; 8 | import arc.util.*; 9 | import mindustry.*; 10 | import mindustry.graphics.*; 11 | import mindustry.world.blocks.units.*; 12 | import mindustry.world.blocks.units.Reconstructor.*; 13 | import mindustry.world.blocks.units.UnitBlock.*; 14 | import mindustry.world.blocks.units.UnitFactory.*; 15 | 16 | public class UnitBuildInfo extends BuildDrawer{ 17 | public static float proBarStroke = 1.7f, proBarAlpha = 0.85f; 18 | public static float backBarStroke = proBarStroke + 1.3f, backBarAlpha = 0.5f; 19 | 20 | public UnitBuildInfo(){ 21 | super(block -> block instanceof UnitBlock); 22 | } 23 | 24 | @Override 25 | public boolean isEnabled(){ 26 | return MinerVars.settings.getBool("unitBuildInfo"); 27 | } 28 | 29 | @Override 30 | protected void draw(UnitBuild build){ 31 | UnitBlock block = (UnitBlock)build.block; 32 | 33 | float fraction = 0f; 34 | float conTime = 0f; 35 | if(build instanceof UnitFactoryBuild facBuild){ 36 | UnitFactory factory = (UnitFactory)block; 37 | fraction = facBuild.fraction(); 38 | conTime = facBuild.currentPlan == -1 ? 0 : (1 - facBuild.fraction()) * factory.plans.get(facBuild.currentPlan).time / facBuild.timeScale(); 39 | }else if(build instanceof ReconstructorBuild reconBuild){ 40 | Reconstructor reconstructor = (Reconstructor)block; 41 | fraction = reconBuild.fraction(); 42 | conTime = (1 - reconBuild.fraction()) * reconstructor.constructTime / reconBuild.timeScale(); 43 | } 44 | conTime /= Vars.state.rules.unitBuildSpeed(build.team); 45 | 46 | float size = build.hitSize(); 47 | 48 | float startX = build.x - size / 2f + 5f; 49 | float startY = build.y + size / 2f - 5f; 50 | 51 | float endX = startX + size - 5f * 2; 52 | 53 | Draw.z(Layer.power + 1f); 54 | 55 | float drawX = MDrawf.drawProgressBar( 56 | startX, startY, endX, startY, fraction, 57 | backBarStroke, backBarAlpha, build.team.color, 58 | proBarStroke, proBarAlpha, Pal.accent 59 | ); 60 | 61 | startY += backBarStroke; 62 | 63 | float scl = block.size * MinerVars.worldFontScl / 2f; 64 | 65 | MDrawf.drawText(Strings.autoFixed(conTime / 60f, 1) + "s", scl, drawX, startY, Color.white, Align.center); 66 | 67 | Draw.reset(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/MinerTools/graphics/draw/build/select/BridgeLinkedList.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics.draw.build.select; 2 | 3 | import MinerTools.*; 4 | import MinerTools.graphics.draw.*; 5 | import arc.graphics.g2d.*; 6 | import arc.math.*; 7 | import arc.struct.*; 8 | import arc.util.*; 9 | import mindustry.*; 10 | import mindustry.gen.*; 11 | import mindustry.graphics.*; 12 | import mindustry.world.*; 13 | import mindustry.world.blocks.distribution.*; 14 | import mindustry.world.blocks.distribution.ItemBridge.*; 15 | 16 | public class BridgeLinkedList extends BuildDrawer{ 17 | private static final Seq currentBridges = new Seq<>(); 18 | 19 | public BridgeLinkedList(){ 20 | super(block -> block instanceof ItemBridge); 21 | } 22 | 23 | @Override 24 | public boolean isEnabled(){ 25 | return MinerVars.settings.getBool("itemBridgeLinksShow"); 26 | } 27 | 28 | @Override 29 | protected void draw(ItemBridgeBuild build){ 30 | ItemBridge block = (ItemBridge)build.block; 31 | 32 | Draw.z(Layer.overlayUI); 33 | 34 | drawSelect(block, build, false); 35 | 36 | Draw.reset(); 37 | 38 | currentBridges.clear(); 39 | } 40 | 41 | private static ItemBridgeBuild getLinkBuild(ItemBridge block, ItemBridgeBuild build){ 42 | int linkPos = build.link; 43 | 44 | if(linkPos == -1) return null; 45 | 46 | Tile linkTile = Vars.world.tile(linkPos); 47 | 48 | if(!block.linkValid(build.tile, linkTile)) return null; 49 | 50 | return (ItemBridgeBuild)(linkTile.build); 51 | } 52 | 53 | private static Seq getDumpBridges(ItemBridgeBuild bridge){ 54 | Seq returnBridges = new Seq<>(); 55 | 56 | for(Building building : bridge.proximity){ 57 | if(building instanceof ItemBridgeBuild other && !currentBridges.contains(other) && bridge.canDump(other, null)){ 58 | returnBridges.add(other); 59 | } 60 | } 61 | 62 | return returnBridges; 63 | } 64 | 65 | private static void drawSelect(ItemBridge block, ItemBridgeBuild build){ 66 | drawSelect(block, build, true); 67 | } 68 | 69 | private static void drawSelect(ItemBridge block, ItemBridgeBuild build, boolean checkCons){ 70 | if(checkCons && currentBridges.contains(build)) return; 71 | 72 | currentBridges.add(build); 73 | 74 | ItemBridgeBuild linkBuild = getLinkBuild(block, build); 75 | 76 | if(linkBuild == null){ 77 | Seq bridges = getDumpBridges(build); 78 | 79 | if(bridges.isEmpty()) return; 80 | 81 | for(ItemBridgeBuild bridge : bridges){ 82 | drawSelect(block, bridge, false); 83 | } 84 | return; 85 | } 86 | 87 | drawInput(block, build, linkBuild); 88 | 89 | drawSelect(block, linkBuild); 90 | } 91 | 92 | private static void drawInput(ItemBridge block, ItemBridgeBuild build, ItemBridgeBuild linkBuild){ 93 | Tmp.v2.trns(build.angleTo(linkBuild), 2f); 94 | float tx = build.x, ty = build.y; 95 | float ox = linkBuild.x, oy = linkBuild.y; 96 | float alpha = Math.abs(100 - (Time.time * 2f) % 100f) / 100f; 97 | float x = Mathf.lerp(ox, tx, alpha); 98 | float y = Mathf.lerp(oy, ty, alpha); 99 | 100 | int rel = linkBuild.tile.absoluteRelativeTo(linkBuild.tileX(), linkBuild.tileY()); 101 | 102 | //draw "background" 103 | Draw.color(Pal.gray); 104 | Lines.stroke(2.5f); 105 | Lines.square(ox, oy, 2f, 45f); 106 | Lines.stroke(2.5f); 107 | Lines.line(tx + Tmp.v2.x, ty + Tmp.v2.y, ox - Tmp.v2.x, oy - Tmp.v2.y); 108 | 109 | //draw foreground colors 110 | Draw.color(Pal.place); 111 | Lines.stroke(1f); 112 | Lines.line(tx + Tmp.v2.x, ty + Tmp.v2.y, ox - Tmp.v2.x, oy - Tmp.v2.y); 113 | 114 | Lines.square(ox, oy, 2f, 45f); 115 | Draw.mixcol(Draw.getColor(), 1f); 116 | Draw.color(); 117 | Draw.rect(block.arrowRegion, x, y, rel * 90); 118 | Draw.mixcol(); 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /src/MinerTools/graphics/draw/build/select/BuildSelect.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics.draw.build.select; 2 | 3 | import MinerTools.*; 4 | import MinerTools.graphics.draw.*; 5 | import arc.graphics.g2d.*; 6 | import mindustry.*; 7 | import mindustry.gen.*; 8 | 9 | public class BuildSelect extends BuildDrawer{ 10 | 11 | @Override 12 | public boolean isEnabled(){ 13 | return MinerVars.settings.getBool("buildSelectInfo"); 14 | } 15 | 16 | @Override 17 | public boolean shouldDraw(Building building){ 18 | return super.shouldDraw(building) && building.team != Vars.player.team(); 19 | } 20 | 21 | @Override 22 | protected void draw(Building build){ 23 | build.drawSelect(); 24 | 25 | Draw.reset(); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/MinerTools/graphics/draw/player/PayloadDropHint.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics.draw.player; 2 | 3 | import MinerTools.*; 4 | import MinerTools.graphics.draw.*; 5 | import arc.graphics.*; 6 | import arc.graphics.g2d.*; 7 | import arc.math.*; 8 | import arc.util.*; 9 | import mindustry.*; 10 | import mindustry.core.*; 11 | import mindustry.entities.*; 12 | import mindustry.gen.*; 13 | import mindustry.graphics.*; 14 | import mindustry.world.*; 15 | import mindustry.world.blocks.payloads.*; 16 | 17 | public class PayloadDropHint extends PlayerDrawer{ 18 | 19 | @Override 20 | public boolean isEnabled(){ 21 | return MinerVars.settings.getBool("payloadDropHint"); 22 | } 23 | 24 | @Override 25 | public boolean shouldDraw(Player player){ 26 | return super.shouldDraw(player) && player.unit() instanceof PayloadUnit; 27 | } 28 | 29 | @Override 30 | protected void draw(Player player){ 31 | PayloadUnit unit = (PayloadUnit)player.unit(); 32 | 33 | Draw.z(Layer.flyingUnit + 0.1f); 34 | 35 | if(unit.payloads.any()){ 36 | Payload payload = unit.payloads.peek(); 37 | 38 | if(payload instanceof BuildPayload p){ 39 | buildDropHint(unit, p); 40 | }else if(payload instanceof UnitPayload p){ 41 | unitDropHint(unit, p); 42 | } 43 | } 44 | 45 | if(unit.payloadUsed() + Vars.tilesize < unit.type.payloadCapacity){ 46 | pickUpHint(unit); 47 | } 48 | 49 | Draw.reset(); 50 | } 51 | 52 | private static void pickUpHint(PayloadUnit unit){ 53 | if(!unitPickUpHint(unit)){ 54 | buildPickUpHint(unit); 55 | } 56 | } 57 | 58 | private static void buildPickUpHint(PayloadUnit unit){ 59 | Tile tile = unit.tileOn(); 60 | 61 | if(tile != null){ 62 | Building build = tile.build; 63 | 64 | if(build != null && build.interactable(unit.team) && unit.canPickup(tile.build)){ 65 | Block block = build.block; 66 | 67 | float size = block.size * Vars.tilesize + block.offset; 68 | 69 | Draw.mixcol(Pal.accent, 0.24f + Mathf.absin(Time.globalTime, 6f, 0.28f)); 70 | Draw.alpha(0.8f); 71 | Draw.rect(block.fullIcon, tile.build.x, tile.build.y, size, size, build.rotation * 90); 72 | 73 | Draw.reset(); 74 | } 75 | 76 | float drawX = tile.drawx(), drawY = tile.drawy(); 77 | float size = Vars.tilesize; 78 | 79 | if(build != null && build.interactable(unit.team)){ 80 | if(unit.canPickup(build)){ 81 | size *= build.block.size; 82 | 83 | drawX = build.x; 84 | drawY = build.y; 85 | } 86 | } 87 | 88 | Drawf.dashRect(Tmp.c1.set(Pal.accent).a(0.6f), drawX - size / 2, drawY - size / 2, size, size); 89 | 90 | Draw.reset(); 91 | } 92 | } 93 | 94 | private static boolean unitPickUpHint(PayloadUnit unit){ 95 | Unit target = Units.closest(unit.team(), unit.x, unit.y, unit.type.hitSize * 2f, u -> u.isAI() && u.isGrounded() && unit.canPickup(u) && u.within(unit, u.hitSize + unit.hitSize)); 96 | 97 | if(target != null && target.team == unit.team){ 98 | Draw.mixcol(Pal.accent, 0.24f + Mathf.absin(Time.globalTime, 6f, 0.28f)); 99 | Draw.alpha(0.8f); 100 | Draw.rect(target.type.fullIcon, target.x, target.y, target.rotation - 90); 101 | 102 | Draw.reset(); 103 | 104 | return true; 105 | } 106 | 107 | return false; 108 | } 109 | 110 | private static void buildDropHint(PayloadUnit unit, BuildPayload payload){ 111 | Building build = payload.build; 112 | int tx = World.toTile(unit.x - build.block.offset); 113 | int ty = World.toTile(unit.y - build.block.offset); 114 | 115 | Tile on = Vars.world.tile(tx, ty); 116 | if(on != null){ 117 | boolean valid = Build.validPlace(build.block, build.team, tx, ty, build.rotation, false); 118 | 119 | Block block = build.block; 120 | 121 | float size = block.size * Vars.tilesize + block.offset; 122 | 123 | int rot = block.rotate ? (int)((unit.rotation + 45f) / 90f) % 4 * 90 : 0; 124 | 125 | Draw.mixcol(!valid ? Pal.breakInvalid : Color.white, (!valid ? 0.4f : 0.24f) + Mathf.absin(Time.globalTime, 6f, 0.28f)); 126 | Draw.alpha(0.8f); 127 | Draw.rect(block.fullIcon, (on.x + 0.5f) * Vars.tilesize, (on.y + 0.5f) * Vars.tilesize, size, size, rot); 128 | 129 | Draw.reset(); 130 | } 131 | } 132 | 133 | private static void unitDropHint(PayloadUnit unit, UnitPayload payload){ 134 | Unit u = payload.unit; 135 | 136 | boolean valid = u.canPass(unit.tileX(), unit.tileY()) && Units.count(unit.x, unit.y, u.physicSize(), Flyingc::isGrounded) <= 1; 137 | 138 | Draw.mixcol(!valid ? Pal.breakInvalid : Color.white, (!valid ? 0.4f : 0.24f) + Mathf.absin(Time.globalTime, 6f, 0.28f)); 139 | Draw.alpha(0.8f); 140 | Draw.rect(u.type.fullIcon, unit.x, unit.y, unit.rotation - 90); 141 | 142 | Draw.reset(); 143 | } 144 | 145 | } -------------------------------------------------------------------------------- /src/MinerTools/graphics/draw/player/PlayerRange.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics.draw.player; 2 | 3 | import MinerTools.*; 4 | import MinerTools.graphics.draw.*; 5 | import arc.graphics.g2d.*; 6 | import mindustry.gen.*; 7 | import mindustry.graphics.*; 8 | import mindustry.world.blocks.defense.turrets.Turret.*; 9 | 10 | public class PlayerRange extends PlayerDrawer{ 11 | 12 | @Override 13 | public boolean isEnabled(){ 14 | return MinerVars.settings.getBool("playerRange"); 15 | } 16 | 17 | @Override 18 | protected void draw(Player player){ 19 | Draw.z(Layer.flyingUnitLow - 0.1f); 20 | 21 | Unit unit = player.unit(); 22 | 23 | float range = unit.range(); 24 | 25 | if(unit instanceof BlockUnitUnit blockUnit){ 26 | Building building = blockUnit.tile(); 27 | 28 | if(building instanceof TurretBuild turret){ 29 | range = turret.range(); 30 | } 31 | } 32 | 33 | Drawf.dashCircle(player.x, player.y, range, player.team().color); 34 | 35 | Draw.reset(); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/MinerTools/graphics/draw/unit/EnemyIndicator.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics.draw.unit; 2 | 3 | import MinerTools.*; 4 | import MinerTools.graphics.draw.*; 5 | import arc.*; 6 | import arc.graphics.g2d.*; 7 | import arc.math.*; 8 | import arc.math.geom.*; 9 | import arc.struct.*; 10 | import arc.util.*; 11 | import mindustry.game.*; 12 | import mindustry.gen.*; 13 | import mindustry.graphics.*; 14 | import mindustry.world.blocks.storage.CoreBlock.*; 15 | 16 | import static mindustry.Vars.*; 17 | 18 | public class EnemyIndicator extends UnitDrawer{ 19 | public float defEnemyRadius; 20 | 21 | private float enemyRadius = defEnemyRadius; 22 | 23 | private final Vec2 cameraPos; 24 | 25 | public EnemyIndicator(){ 26 | cameraPos = Core.camera.position; 27 | 28 | Events.on(EventType.WorldLoadEvent.class, e -> resetEnemyRadius()); 29 | } 30 | 31 | private void resetEnemyRadius(){ 32 | if(state.rules.polygonCoreProtection){ 33 | enemyRadius = defEnemyRadius; 34 | }else{ 35 | enemyRadius = Math.max(state.rules.enemyCoreBuildRadius, defEnemyRadius); 36 | } 37 | } 38 | 39 | @Override 40 | public void readSetting(){ 41 | defEnemyRadius = MinerVars.settings.getInt("enemyUnitIndicatorRadius") * tilesize; 42 | resetEnemyRadius(); 43 | } 44 | 45 | @Override 46 | public boolean isEnabled(){ 47 | return MinerVars.settings.getBool("enemyUnitIndicator"); 48 | } 49 | 50 | @Override 51 | public boolean isValid(){ 52 | return player.team().data().hasCore(); 53 | } 54 | 55 | @Override 56 | public boolean shouldDraw(Unit unit){ 57 | return super.shouldDraw(unit) && unit.team != player.team() && unit.hasWeapons(); 58 | } 59 | 60 | @Override 61 | protected void draw(Unit unit){ 62 | Seq cores = player.team().cores(); 63 | 64 | var wCores = cores.select(c -> c.within(unit, enemyRadius)); 65 | if(wCores.isEmpty()) return; 66 | 67 | CoreBuild core = wCores.min(c -> unit.dst(c)); 68 | 69 | Draw.z(Layer.overlayUI); 70 | 71 | float indicatorLength = Mathf.lerp(20f, 55f, unit.dst(core) / enemyRadius); 72 | 73 | Tmp.v1.set(unit).sub(cameraPos).setLength(indicatorLength); 74 | 75 | Draw.color(unit.team().color); 76 | Draw.rect(unit.type.fullIcon, cameraPos.x + Tmp.v1.x, cameraPos.y + Tmp.v1.y, 10f, 10f, Tmp.v1.angle() - 90f); 77 | 78 | Draw.reset(); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/MinerTools/graphics/draw/unit/UnitAlert.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics.draw.unit; 2 | 3 | import MinerTools.*; 4 | import MinerTools.graphics.draw.*; 5 | import arc.graphics.g2d.*; 6 | import arc.util.*; 7 | import mindustry.gen.*; 8 | import mindustry.graphics.*; 9 | import mindustry.type.*; 10 | 11 | import static MinerTools.MinerVars.settings; 12 | import static mindustry.Vars.*; 13 | 14 | /** 15 | * 敌方单位警戒 16 | */ 17 | public class UnitAlert extends UnitDrawer{ 18 | public float unitAlertRadius; 19 | 20 | @Override 21 | public void readSetting(){ 22 | unitAlertRadius = MinerVars.settings.getInt("unitAlertRadius") * tilesize; 23 | } 24 | 25 | @Override 26 | public boolean isEnabled(){ 27 | return settings.getBool("unitAlert"); 28 | } 29 | 30 | @Override 31 | public boolean isValid(){ 32 | return !player.unit().isNull(); 33 | } 34 | 35 | @Override 36 | public boolean shouldDraw(Unit unit){ 37 | UnitType type = unit.type; 38 | return super.shouldDraw(unit) && 39 | (type.hasWeapons()) && // has weapons 40 | (unit.team != player.team()) && // isEnemy 41 | (!state.rules.unitAmmo || unit.ammo > 0f) && // hasAmmo 42 | (player.unit().isFlying() ? type.targetAir : type.targetGround) && // can hit player 43 | (unit.within(player, unitAlertRadius + type.maxRange)); // within player 44 | } 45 | 46 | @Override 47 | protected void draw(Unit unit){ 48 | Draw.z(Layer.overlayUI); 49 | 50 | Lines.stroke(1.2f); 51 | Drawf.dashCircle(unit.x, unit.y, unit.range(), unit.team().color); 52 | 53 | float dst = unit.dst(player); 54 | if(dst > unit.range()){ 55 | Tmp.v1.set(unit).sub(player).setLength(dst - unit.range()); 56 | Draw.rect(unit.type.fullIcon, player.x + Tmp.v1.x, player.y + Tmp.v1.y, 10f + unit.hitSize / 3f, 10f + unit.hitSize / 3f, Tmp.v1.angle() - 90f); 57 | } 58 | 59 | Draw.reset(); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/MinerTools/graphics/draw/unit/UnitInfoBar.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics.draw.unit; 2 | 3 | import MinerTools.*; 4 | import MinerTools.graphics.*; 5 | import MinerTools.graphics.draw.*; 6 | import arc.graphics.g2d.*; 7 | import arc.math.*; 8 | import arc.struct.*; 9 | import arc.util.*; 10 | import mindustry.*; 11 | import mindustry.content.*; 12 | import mindustry.entities.abilities.*; 13 | import mindustry.gen.*; 14 | import mindustry.graphics.*; 15 | import mindustry.type.*; 16 | import mindustry.world.blocks.payloads.*; 17 | 18 | public class UnitInfoBar extends UnitDrawer{ 19 | public static float healthBarStroke = 1.7f, healthBarAlpha = 0.85f; 20 | public static float backBarStroke = healthBarStroke + 1.3f, backBarAlpha = healthBarAlpha - 0.25f; 21 | 22 | @Override 23 | public boolean isEnabled(){ 24 | return MinerVars.settings.getBool("unitInfoBar"); 25 | } 26 | 27 | @Override 28 | protected void draw(Unit unit){ 29 | float startX = unit.x - unit.hitSize / 2f, startY = unit.y + unit.hitSize / 2f; 30 | float endX = unit.x + unit.hitSize / 2f; 31 | 32 | float iconSize = unit.hitSize / Vars.tilesize; 33 | 34 | Draw.z(Layer.flyingUnit + 0.1f); 35 | 36 | /* HealthBar */ 37 | if(unit.damaged()){ 38 | MDrawf.drawProgressBar( 39 | startX, startY, endX, startY, unit.healthf(), 40 | backBarStroke, backBarAlpha, unit.team().color, 41 | healthBarStroke, healthBarAlpha, Pal.health 42 | ); 43 | 44 | startY += backBarStroke + 0.5f; 45 | } 46 | 47 | Draw.color(); 48 | 49 | /* Shield Bar */ 50 | var abilities = unit.abilities; 51 | if(abilities.length > 0){ 52 | Ability ability = Structs.find(abilities, a -> a instanceof ForceFieldAbility); 53 | 54 | if(ability instanceof ForceFieldAbility forceFieldAbility){ 55 | MDrawf.drawProgressBar( 56 | startX, startY, endX, startY, unit.shield / forceFieldAbility.max, 57 | backBarStroke, backBarAlpha, unit.team().color, 58 | healthBarStroke, healthBarAlpha, Pal.shield 59 | ); 60 | 61 | startY += healthBarStroke + 0.5f; 62 | } 63 | 64 | 65 | Draw.color(); 66 | } 67 | 68 | if(!Mathf.zero(unit.drownTime)){ 69 | MDrawf.drawProgressBar( 70 | startX, startY, endX, startY, (1f - unit.drownTime), 71 | backBarStroke, backBarAlpha, unit.team().color, 72 | healthBarStroke, healthBarAlpha, Liquids.water.color 73 | ); 74 | 75 | startY += healthBarStroke + 0.5f; 76 | } 77 | 78 | /* Status */ 79 | Bits applied = unit.statusBits(); 80 | int statusSize = applied.length(); 81 | 82 | if(statusSize != 0){ 83 | startY += iconSize / 2; 84 | 85 | int index = 0; 86 | for(StatusEffect effect : Vars.content.statusEffects()){ 87 | if(applied.get(effect.id)){ 88 | Draw.color(effect.color); 89 | Draw.rect(effect.uiIcon, startX + (index++ * iconSize), startY, iconSize, iconSize); 90 | } 91 | } 92 | 93 | startY += iconSize / 2; 94 | } 95 | 96 | Draw.color(); 97 | 98 | /* Payloads */ 99 | if(unit instanceof PayloadUnit payloadUnit){ 100 | Seq payloads = payloadUnit.payloads; 101 | 102 | startY += iconSize / 2; 103 | 104 | int index = 0; 105 | if(payloads.any()){ 106 | for(Payload payload : payloads){ 107 | Draw.rect(payload.icon(), startX + (index++ * iconSize), startY, iconSize, iconSize); 108 | } 109 | } 110 | 111 | // startY += iconSize / 2; 112 | } 113 | 114 | Draw.reset(); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/MinerTools/graphics/provider/BuildProvider.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics.provider; 2 | 3 | import MinerTools.graphics.draw.*; 4 | import arc.*; 5 | import arc.math.geom.*; 6 | import arc.struct.*; 7 | import arc.util.*; 8 | import mindustry.*; 9 | import mindustry.game.Teams.*; 10 | import mindustry.gen.*; 11 | 12 | public class BuildProvider extends CameraProvider>{ 13 | 14 | @Override 15 | public void globalProvide(Seq> validDrawers){ 16 | for(TeamData data : Vars.state.teams.present){ 17 | var buildings = data.buildings; 18 | 19 | for(Building building : buildings){ 20 | for(BuildDrawer drawer : validDrawers){ 21 | drawer.tryDraw(building); 22 | } 23 | } 24 | } 25 | } 26 | 27 | @Override 28 | public void cameraProvide(Seq> validDrawers){ 29 | Rect bounds = Core.camera.bounds(Tmp.r1); 30 | 31 | for(TeamData data : Vars.state.teams.present){ 32 | var buildingTree = data.buildingTree; 33 | 34 | if(buildingTree == null) continue; 35 | 36 | buildingTree.intersect(bounds, build -> { 37 | for(BuildDrawer drawer : validDrawers){ 38 | drawer.tryDraw(build); 39 | } 40 | }); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/MinerTools/graphics/provider/CameraProvider.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics.provider; 2 | 3 | import MinerTools.graphics.draw.*; 4 | import arc.struct.*; 5 | 6 | public abstract class CameraProvider> extends DrawerProvider{ 7 | private final Seq globalDrawers = new Seq<>(); 8 | private final Seq cameraDrawers = new Seq<>(); 9 | 10 | private Seq enableGlobalDrawers; 11 | private Seq enableCameraDrawers; 12 | 13 | @SuppressWarnings("unchecked") 14 | public final CameraProvider addGlobalDrawers(T... drawers){ 15 | globalDrawers.addAll(drawers); 16 | addDrawers(drawers); 17 | return this; 18 | } 19 | 20 | @SuppressWarnings("unchecked") 21 | public final CameraProvider addCameraDrawers(T... drawers){ 22 | cameraDrawers.addAll(drawers); 23 | addDrawers(drawers); 24 | return this; 25 | } 26 | 27 | @Override 28 | public void updateEnable(){ 29 | enableGlobalDrawers = globalDrawers.select(Drawer::isEnabled); 30 | enableCameraDrawers = cameraDrawers.select(Drawer::isEnabled); 31 | 32 | enableDrawers.clear(); 33 | enableDrawers.addAll(enableGlobalDrawers).addAll(enableCameraDrawers); 34 | } 35 | 36 | @Override 37 | public void provide(){ 38 | if(globalDrawers.any()){ 39 | globalProvide(enableGlobalDrawers.select(Drawer::isValid)); 40 | } 41 | 42 | if(cameraDrawers.any()){ 43 | cameraProvide(enableCameraDrawers.select(Drawer::isValid)); 44 | } 45 | } 46 | 47 | protected abstract void globalProvide(Seq validDrawers); 48 | 49 | protected abstract void cameraProvide(Seq validDrawers); 50 | } 51 | -------------------------------------------------------------------------------- /src/MinerTools/graphics/provider/DrawerProvider.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics.provider; 2 | 3 | import MinerTools.graphics.draw.*; 4 | import arc.struct.*; 5 | 6 | public abstract class DrawerProvider>{ 7 | protected Seq drawers = new Seq<>(); 8 | protected Seq enableDrawers = new Seq<>(); 9 | 10 | @SuppressWarnings("unchecked") 11 | protected DrawerProvider addDrawers(T... drawers){ 12 | this.drawers.addAll(drawers); 13 | return this; 14 | } 15 | 16 | protected DrawerProvider addDrawers(Seq drawers){ 17 | this.drawers.addAll(drawers); 18 | return this; 19 | } 20 | 21 | public void updateEnable(){ 22 | enableDrawers.selectFrom(drawers, Drawer::isEnabled); 23 | } 24 | 25 | public void updateSetting(){ 26 | for(T drawer : drawers){ 27 | drawer.readSetting(); 28 | } 29 | } 30 | 31 | public final void drawShader(){ 32 | for(T drawer : drawers){ 33 | drawer.drawShader(); 34 | } 35 | } 36 | 37 | public abstract void provide(); 38 | } 39 | -------------------------------------------------------------------------------- /src/MinerTools/graphics/provider/PlayerProvider.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics.provider; 2 | 3 | import MinerTools.graphics.draw.*; 4 | import arc.struct.*; 5 | import mindustry.*; 6 | import mindustry.gen.*; 7 | 8 | public class PlayerProvider extends DrawerProvider{ 9 | private final Seq globalDrawers = new Seq<>(); 10 | private final Seq localDrawers = new Seq<>(); 11 | 12 | private Seq enableGlobalDrawers; 13 | private Seq enableLocalDrawers; 14 | 15 | public final PlayerProvider addGlobalDrawers(PlayerDrawer... drawers){ 16 | globalDrawers.addAll(drawers); 17 | addDrawers(drawers); 18 | return this; 19 | } 20 | 21 | public final PlayerProvider addLocalDrawers(PlayerDrawer... drawers){ 22 | localDrawers.addAll(drawers); 23 | addDrawers(drawers); 24 | return this; 25 | } 26 | 27 | @Override 28 | public void updateEnable(){ 29 | enableGlobalDrawers = globalDrawers.select(Drawer::isEnabled); 30 | enableLocalDrawers = localDrawers.select(Drawer::isEnabled); 31 | 32 | enableDrawers.clear(); 33 | enableDrawers.addAll(enableGlobalDrawers).addAll(enableLocalDrawers); 34 | } 35 | 36 | @Override 37 | public void provide(){ 38 | if(globalDrawers.any()){ 39 | globalProvide(enableGlobalDrawers.select(Drawer::isValid)); 40 | } 41 | 42 | if(localDrawers.any()){ 43 | playerProvide(enableLocalDrawers.select(Drawer::isValid)); 44 | } 45 | } 46 | 47 | private void globalProvide(Seq validDrawers){ 48 | Groups.player.each(player -> { 49 | for(PlayerDrawer drawer : validDrawers){ 50 | drawer.tryDraw(player); 51 | } 52 | }); 53 | } 54 | 55 | /* Local player */ 56 | private void playerProvide(Seq validDrawers){ 57 | for(PlayerDrawer drawer : validDrawers){ 58 | drawer.tryDraw(Vars.player); 59 | } 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/MinerTools/graphics/provider/SelectProvider.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics.provider; 2 | 3 | import MinerTools.graphics.draw.*; 4 | import arc.math.geom.*; 5 | import arc.struct.*; 6 | import mindustry.*; 7 | import mindustry.entities.*; 8 | import mindustry.gen.*; 9 | 10 | import static arc.Core.input; 11 | 12 | public class SelectProvider extends DrawerProvider>{ 13 | private final Seq> allBuildDrawers = new Seq<>(); 14 | private final Seq allUnitDrawers = new Seq<>(); 15 | 16 | Seq> enableBuildDrawers; 17 | Seq enableUnitDrawers; 18 | 19 | public SelectProvider addBuildDrawers(BuildDrawer... drawers){ 20 | allBuildDrawers.addAll(drawers); 21 | addDrawers(drawers); 22 | return this; 23 | } 24 | 25 | public SelectProvider addUnitDrawers(UnitDrawer... drawers){ 26 | allUnitDrawers.addAll(drawers); 27 | addDrawers(drawers); 28 | return this; 29 | } 30 | 31 | @Override 32 | public void updateEnable(){ 33 | enableBuildDrawers = allBuildDrawers.select(Drawer::isEnabled); 34 | enableUnitDrawers = allUnitDrawers.select(Drawer::isEnabled); 35 | 36 | enableDrawers.clear(); 37 | enableDrawers.addAll(enableBuildDrawers).add(enableUnitDrawers); 38 | } 39 | 40 | @Override 41 | public void provide(){ 42 | Vec2 v = input.mouseWorld(); 43 | 44 | Building selectBuild = Vars.world.buildWorld(v.x, v.y); 45 | if(selectBuild != null){ 46 | for(BuildDrawer drawer : enableBuildDrawers){ 47 | drawer.tryDraw(selectBuild); 48 | } 49 | } 50 | 51 | Unit selectUnit = Units.closestOverlap(null, v.x, v.y, 5f, Entityc::isAdded); 52 | if(selectUnit != null){ 53 | for(UnitDrawer drawer : enableUnitDrawers){ 54 | drawer.tryDraw(selectUnit); 55 | } 56 | } 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/MinerTools/graphics/provider/UnitProvider.java: -------------------------------------------------------------------------------- 1 | package MinerTools.graphics.provider; 2 | 3 | import MinerTools.graphics.draw.*; 4 | import arc.*; 5 | import arc.math.geom.*; 6 | import arc.struct.*; 7 | import arc.util.*; 8 | import mindustry.*; 9 | import mindustry.game.Teams.*; 10 | import mindustry.gen.*; 11 | 12 | public class UnitProvider extends CameraProvider{ 13 | 14 | @Override 15 | public void globalProvide(Seq validDrawers){ 16 | for(TeamData data : Vars.state.teams.present){ 17 | for(Unit unit : data.units){ 18 | for(UnitDrawer drawer : validDrawers){ 19 | drawer.tryDraw(unit); 20 | } 21 | } 22 | } 23 | } 24 | 25 | @Override 26 | public void cameraProvide(Seq validDrawers){ 27 | Rect bounds = Core.camera.bounds(Tmp.r1); 28 | 29 | for(TeamData data : Vars.state.teams.present){ 30 | var unitTree = data.unitTree; 31 | 32 | if(unitTree == null) return; 33 | 34 | unitTree.intersect(bounds, unit -> { 35 | for(UnitDrawer drawer : validDrawers){ 36 | drawer.tryDraw(unit); 37 | } 38 | }); 39 | } 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/MinerTools/input/ModBinding.java: -------------------------------------------------------------------------------- 1 | package MinerTools.input; 2 | 3 | import arc.KeyBinds.*; 4 | import arc.input.InputDevice.*; 5 | import arc.input.*; 6 | 7 | public enum ModBinding implements KeyBind{ 8 | updateConveyor(KeyCode.altLeft, "MinerTools") 9 | ; 10 | 11 | private final KeybindValue defaultValue; 12 | private final String category; 13 | 14 | ModBinding(KeybindValue defaultValue, String category){ 15 | this.defaultValue = defaultValue; 16 | this.category = category; 17 | } 18 | 19 | ModBinding(KeybindValue defaultValue){ 20 | this(defaultValue, null); 21 | } 22 | 23 | @Override 24 | public KeybindValue defaultValue(DeviceType type){ 25 | return defaultValue; 26 | } 27 | 28 | @Override 29 | public String category(){ 30 | return category; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/MinerTools/interfaces/Displayable.java: -------------------------------------------------------------------------------- 1 | package MinerTools.interfaces; 2 | 3 | import arc.scene.ui.layout.*; 4 | 5 | public interface Displayable{ 6 | void display(Table table); 7 | } 8 | -------------------------------------------------------------------------------- /src/MinerTools/interfaces/OverrideUI.java: -------------------------------------------------------------------------------- 1 | package MinerTools.interfaces; 2 | 3 | public interface OverrideUI{ 4 | void doOverride(); 5 | 6 | void resetOverride(); 7 | } 8 | -------------------------------------------------------------------------------- /src/MinerTools/interfaces/TableBuilder.java: -------------------------------------------------------------------------------- 1 | package MinerTools.interfaces; 2 | 3 | import arc.scene.ui.layout.*; 4 | 5 | public interface TableBuilder{ 6 | void build(T table); 7 | } 8 | 9 | -------------------------------------------------------------------------------- /src/MinerTools/modules/AbstractModule.java: -------------------------------------------------------------------------------- 1 | package MinerTools.modules; 2 | 3 | import arc.struct.*; 4 | 5 | public abstract class AbstractModule implements Module{ 6 | protected final String name; 7 | protected boolean enable = true; 8 | 9 | protected final T parent; 10 | protected final ObjectSet children = new ObjectSet<>(); 11 | 12 | public AbstractModule(String name){ 13 | this(null, name); 14 | } 15 | 16 | public AbstractModule(T parent, String name){ 17 | this.parent = parent; 18 | this.name = name; 19 | 20 | if(parent != null){ 21 | parent.addChild(this); 22 | } 23 | } 24 | 25 | public void addChild(T child){ 26 | children.add(child); 27 | } 28 | 29 | @Override 30 | public boolean isEnable(){ 31 | return enable && dependencyEnable(); 32 | } 33 | 34 | public void setEnable(boolean enable){ 35 | this.enable = enable; 36 | 37 | if(this.enable){ 38 | enable(); 39 | }else{ 40 | disable(); 41 | } 42 | } 43 | 44 | public void toggle(){ 45 | setEnable(!enable); 46 | } 47 | 48 | public void enable(){ 49 | } 50 | 51 | public void disable(){ 52 | } 53 | 54 | protected boolean dependencyEnable(){ 55 | return parent == null || parent.isEnable(); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/MinerTools/modules/Module.java: -------------------------------------------------------------------------------- 1 | package MinerTools.modules; 2 | 3 | public interface Module{ 4 | void load(); 5 | 6 | boolean isEnable(); 7 | 8 | void setEnable(boolean enable); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/MinerTools/modules/Modules.java: -------------------------------------------------------------------------------- 1 | package MinerTools.modules; 2 | 3 | import MinerTools.modules.SpawnerInfo.*; 4 | import arc.struct.*; 5 | 6 | public class Modules{ 7 | public static Seq modules; 8 | 9 | public static SpawnerInfo spawnerInfo; 10 | 11 | public static void init(){ 12 | modules = new Seq<>(); 13 | 14 | modules.addAll( 15 | spawnerInfo = new SpawnerInfo() 16 | ); 17 | } 18 | 19 | public static void load(){ 20 | for(Module module : modules){ 21 | module.load(); 22 | } 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/MinerTools/modules/SettingModule.java: -------------------------------------------------------------------------------- 1 | package MinerTools.modules; 2 | 3 | import MinerTools.*; 4 | import MinerTools.ui.*; 5 | import MinerTools.ui.settings.CategorySetting.*; 6 | import MinerTools.ui.settings.*; 7 | import arc.*; 8 | import mindustry.gen.*; 9 | import mindustry.ui.*; 10 | 11 | public abstract class SettingModule extends AbstractModule{ 12 | public final String enableSettingName; 13 | 14 | public SettingModule(String name){ 15 | this(null, name); 16 | } 17 | 18 | public SettingModule(SettingModule parent, String name){ 19 | super(parent, name); 20 | 21 | enableSettingName = name + "Enable"; 22 | enable = MinerVars.settings.getBool(enableSettingName, true); 23 | } 24 | 25 | private static CategoryBuilder getBuilder(SettingModule module){ 26 | return (container, category) -> { 27 | boolean hasSetting = category.hasSetting(); 28 | 29 | container.table(table -> { 30 | table.button(button -> { 31 | button.add(category.localizedName()).left(); 32 | button.label(() -> { 33 | return module.isEnable() ? Core.bundle.get("enabled") : Core.bundle.get("disabled"); 34 | }).growX().right().style(Styles.outlineLabel); 35 | }, MStyles.toggleTranst, module::toggle) 36 | .minWidth(150f).height(32f).checked(b -> module.isEnable()).growX(); 37 | 38 | if(hasSetting){ 39 | table.button(b -> { 40 | b.image(() -> { 41 | return (category.isShown() ? Icon.downSmall : Icon.upSmall).getRegion(); 42 | }).size(24f); 43 | }, Styles.clearNoneTogglei, category::toggle).size(32f) 44 | .checked(b -> category.isShown()); 45 | } 46 | }).growX(); 47 | 48 | container.row(); 49 | 50 | if(hasSetting){ 51 | container.table(Tex.pane2, t -> { 52 | t.collapser(category, true, () -> module.isEnable() && category.isShown()) 53 | .growX().get().setDuration(0.4f); 54 | }).growX().padLeft(12f); 55 | } 56 | }; 57 | } 58 | 59 | @Override 60 | public void load(){ 61 | if(parent == null){ 62 | MinerVars.ui.settings.modules.addCategory(name, this::setSettings, getBuilder(this)); 63 | } 64 | 65 | for(SettingModule child : children){ 66 | child.load(); 67 | } 68 | } 69 | 70 | public void setSettings(MSettingTable settings){ 71 | for(SettingModule child : children){ 72 | settings.addCategory(child.name, child::setSettings, getBuilder(child)); 73 | } 74 | } 75 | 76 | @Override 77 | public void setEnable(boolean enable){ 78 | super.setEnable(enable); 79 | MinerVars.settings.put(enableSettingName, enable, false, true); 80 | } 81 | 82 | @Override 83 | public void toggle(){ 84 | boolean enable = MinerVars.settings.getBool(enableSettingName, true); 85 | setEnable(!enable); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/MinerTools/modules/SpawnerInfo/DestroyBuildings.java: -------------------------------------------------------------------------------- 1 | package MinerTools.modules.SpawnerInfo; 2 | 3 | import MinerTools.modules.*; 4 | import arc.*; 5 | import arc.func.*; 6 | import arc.graphics.*; 7 | import arc.graphics.g2d.*; 8 | import arc.math.*; 9 | import arc.math.geom.*; 10 | import arc.struct.*; 11 | import arc.util.*; 12 | import mindustry.*; 13 | import mindustry.game.EventType.*; 14 | import mindustry.gen.*; 15 | import mindustry.graphics.*; 16 | import mindustry.world.*; 17 | 18 | import static mindustry.Vars.*; 19 | 20 | public class DestroyBuildings extends SettingModule{ 21 | private final ObjectSet tiles = new ObjectSet<>(); 22 | private final ObjectSet buildings = new ObjectSet<>(); 23 | private Seq spawners; 24 | 25 | private float spawnRange; 26 | 27 | public DestroyBuildings(SettingModule parent){ 28 | super(parent, "destroyBuildings"); 29 | } 30 | 31 | public void setSpawnRange(float spawnRange){ 32 | this.spawnRange = spawnRange; 33 | } 34 | 35 | public void setSpawners(Seq spawners){ 36 | this.spawners = spawners; 37 | } 38 | 39 | public void load(){ 40 | Events.on(TilePreChangeEvent.class, e -> { 41 | if(isEnable() && e.tile != null){ 42 | removeTile(e.tile); 43 | } 44 | }); 45 | 46 | Events.on(TileChangeEvent.class, e -> { 47 | if(isEnable() && e.tile != null){ 48 | addTile(e.tile); 49 | } 50 | }); 51 | 52 | Events.run(Trigger.draw, () -> { 53 | if(isEnable() && !buildings.isEmpty()){ 54 | drawDestroyBuildings(); 55 | } 56 | }); 57 | } 58 | 59 | public void worldLoad(){ 60 | if(!isEnable()) return; 61 | 62 | tiles.clear(); 63 | buildings.clear(); 64 | 65 | for(Tile spawner : spawners){ 66 | eachSpawnerTiles(spawner, tile -> { 67 | tiles.add(tile); 68 | 69 | if(isValidBase(tile) && tile.isCenter()){ 70 | buildings.add(tile.build); 71 | } 72 | }); 73 | } 74 | } 75 | 76 | @Override 77 | public void enable(){ 78 | if(!Vars.state.isGame()){ 79 | return; 80 | } 81 | 82 | worldLoad(); 83 | } 84 | 85 | @Override 86 | public void disable(){ 87 | tiles.clear(); 88 | buildings.clear(); 89 | } 90 | 91 | private void removeTile(Tile tile){ 92 | if(isValidBase(tile) && tiles.contains(tile)){ 93 | buildings.remove(tile.build); 94 | } 95 | } 96 | 97 | private void addTile(Tile tile){ 98 | if(isValidBase(tile) && tiles.contains(tile)){ 99 | buildings.add(tile.build); 100 | } 101 | } 102 | 103 | private boolean isValidBase(Tile tile){ 104 | Building building = tile.build; 105 | return building != null && state.rules.waveTeam.isEnemy(building.team()); 106 | } 107 | 108 | private void eachSpawnerTiles(Tile spawner, Cons cons){ 109 | int trad = (int)(spawnRange / tilesize); 110 | 111 | float maxDst2 = trad * trad; 112 | int x = spawner.x, y = spawner.y; 113 | 114 | for(int dx = -trad; dx <= trad; dx++){ 115 | for(int dy = -trad; dy <= trad; dy++){ 116 | Tile tile = world.tile(x + dx, y + dy); 117 | 118 | if(tile != null && dx*dx + dy*dy <= maxDst2){ 119 | cons.get(tile); 120 | } 121 | } 122 | } 123 | } 124 | 125 | private void drawDestroyBuildings(){ 126 | Draw.z(Layer.overlayUI); 127 | 128 | Draw.color(Color.white, 0.4f); 129 | Draw.mixcol(Pal.remove, 0.4f + Mathf.absin(Time.globalTime, 6f, 0.28f)); 130 | 131 | Rect bounds = Core.camera.bounds(Tmp.r1); 132 | for(Building building : buildings){ 133 | if(!bounds.contains(building.x, building.y)){ 134 | continue; 135 | } 136 | 137 | float size = building.hitSize(); 138 | Fill.rect(building.x, building.y, size, size); 139 | } 140 | 141 | Draw.reset(); 142 | } 143 | 144 | } 145 | -------------------------------------------------------------------------------- /src/MinerTools/modules/SpawnerInfo/SpawnCounter.java: -------------------------------------------------------------------------------- 1 | package MinerTools.modules.SpawnerInfo; 2 | 3 | import arc.math.geom.*; 4 | import arc.struct.*; 5 | import mindustry.core.*; 6 | import mindustry.game.*; 7 | import mindustry.type.*; 8 | 9 | public class SpawnCounter{ 10 | private static final SpawnCounter counter = new SpawnCounter(); 11 | public final ObjectIntMap units = new ObjectIntMap<>(); 12 | public float totalHealth, totalShield; 13 | 14 | private SpawnCounter(){ 15 | } 16 | 17 | public static SpawnCounter count(Seq spawnGroups, Seq spawnerPos, int wave){ 18 | counter.clear(); 19 | 20 | for(Vec2 worldPos: spawnerPos){ 21 | for(SpawnGroup spawnGroup : spawnGroups){ 22 | int pos = Point2.pack(World.toTile(worldPos.x), World.toTile(worldPos.y)); 23 | 24 | if(!spawnGroup.canSpawn(pos)){ 25 | continue; 26 | } 27 | 28 | int count = spawnGroup.getSpawned(wave); 29 | 30 | if(count == 0){ 31 | continue; 32 | } 33 | 34 | UnitType type = spawnGroup.type; 35 | float shield = spawnGroup.getShield(wave); 36 | 37 | counter.units.increment(type, count); 38 | counter.totalHealth += type.health; 39 | counter.totalShield += shield; 40 | } 41 | } 42 | 43 | return counter; 44 | } 45 | 46 | private void clear(){ 47 | units.clear(); 48 | totalHealth = 0f; 49 | totalShield = 0f; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/MinerTools/modules/SpawnerInfo/SpawnerGroup.java: -------------------------------------------------------------------------------- 1 | package MinerTools.modules.SpawnerInfo; 2 | 3 | import MinRi2.ModCore.math.*; 4 | import arc.math.geom.*; 5 | import arc.struct.*; 6 | 7 | public class SpawnerGroup{ 8 | public final Seq spawnerPos = new Seq<>(); 9 | private Vec2 centroid = null; 10 | 11 | public static void getSpawnerGroups(Seq groups, Seq rawSpawnerPos, float maxDst){ 12 | handleSpawnerPos(groups, rawSpawnerPos, maxDst); 13 | } 14 | 15 | private static void handleSpawnerPos(Seq out, Seq spawnerPos, float maxDst){ 16 | for(Vec2 spawner : spawnerPos){ 17 | out.add(new SpawnerGroup().addSpawner(spawner)); 18 | } 19 | 20 | float maxDst2 = maxDst * maxDst; 21 | 22 | int size = spawnerPos.size; 23 | int lastSize = size - 1; 24 | 25 | outer: 26 | for(int i = 0; i < lastSize; i++){ 27 | Vec2 pos = spawnerPos.get(i); 28 | 29 | SpawnerGroup group = out.get(i); 30 | 31 | for(int j = i + 1; j < size; j++){ 32 | SpawnerGroup otherGroup = out.get(j); 33 | 34 | if(otherGroup == group){ 35 | continue; 36 | } 37 | 38 | Vec2 otherPos = spawnerPos.get(j); 39 | 40 | if(pos.dst2(otherPos) <= maxDst2){ 41 | group.addGroup(otherGroup); 42 | out.set(j, group); 43 | 44 | if(group.spawnerPos.size == size){ 45 | break outer; 46 | } 47 | } 48 | } 49 | } 50 | 51 | out.distinct().retainAll(SpawnerGroup::isValid); 52 | } 53 | 54 | public SpawnerGroup addSpawner(Vec2 spawner){ 55 | if(!spawnerPos.contains(spawner, true)){ 56 | spawnerPos.add(spawner); 57 | } 58 | return this; 59 | } 60 | 61 | public void addGroup(SpawnerGroup other){ 62 | for(Vec2 spawner : other.spawnerPos){ 63 | addSpawner(spawner); 64 | } 65 | other.spawnerPos.clear(); 66 | } 67 | 68 | public boolean isValid(){ 69 | return spawnerPos.any(); 70 | } 71 | 72 | public Vec2 getCentroid(){ 73 | if(centroid == null){ 74 | centroid = new Vec2(); 75 | 76 | float[] points = new float[spawnerPos.size * 2]; 77 | 78 | for(int i = 0, size = spawnerPos.size; i < size; i++){ 79 | Vec2 pos = spawnerPos.get(i); 80 | 81 | points[i * 2] = pos.x; 82 | points[i * 2 + 1] = pos.y; 83 | } 84 | 85 | Mathu.getCentroid(points, centroid); 86 | } 87 | 88 | return centroid; 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/MinerTools/modules/SpawnerInfo/SpawnerInfo.java: -------------------------------------------------------------------------------- 1 | package MinerTools.modules.SpawnerInfo; 2 | 3 | import MinRi2.ModCore.utils.*; 4 | import MinerTools.modules.*; 5 | import arc.*; 6 | import arc.func.*; 7 | import arc.math.geom.*; 8 | import arc.struct.*; 9 | import mindustry.*; 10 | import mindustry.ai.*; 11 | import mindustry.game.EventType.*; 12 | import mindustry.game.*; 13 | 14 | import java.lang.reflect.*; 15 | 16 | import static mindustry.Vars.spawner; 17 | 18 | public class SpawnerInfo extends SettingModule{ 19 | // World Position 20 | private static final Seq tmp = new Seq<>(); 21 | 22 | private static final Method eachFlyerSpawnMethod = ReflectUtils.getMethod( 23 | WaveSpawner.class, 24 | "eachFlyerSpawn", 25 | int.class, Floatc2.class 26 | ); 27 | 28 | private final GroupStat ground = new GroupStat(); 29 | private final GroupStat flyer = new GroupStat(); 30 | 31 | private final SpawnerTables tables; 32 | private final DestroyBuildings destroy; 33 | private final SpawnerRange render; 34 | private final SpawnerViewer viewer; 35 | 36 | public float groundRange = 0f; 37 | public float flayerRange = 6 * Vars.tilesize; 38 | 39 | public SpawnerInfo(){ 40 | super("spawnerInfo"); 41 | 42 | tables = new SpawnerTables(this); 43 | destroy = new DestroyBuildings(this); 44 | render = new SpawnerRange(this); 45 | viewer = new SpawnerViewer(this); 46 | } 47 | 48 | public static void eachGroundSpawn(Intc2 intc2){ 49 | spawner.eachGroundSpawn(intc2); 50 | } 51 | 52 | public static void eachFlyerSpawn(Floatc2 floatc2){ 53 | eachFlyerSpawn(-1, floatc2); 54 | } 55 | 56 | public static void eachFlyerSpawn(int filterPos, Floatc2 floatc2){ 57 | ReflectUtils.invokeMethod(spawner, eachFlyerSpawnMethod, filterPos, floatc2); 58 | } 59 | 60 | @Override 61 | public boolean isEnable(){ 62 | return super.isEnable() && spawner.countSpawns() <= 20; 63 | } 64 | 65 | @Override 66 | public void load(){ 67 | super.load(); 68 | 69 | tables.setGroupStats(ground, flyer); 70 | 71 | Events.on(WorldLoadEvent.class, e -> { 72 | if(isEnable()){ 73 | Core.app.post(this::worldLoad); 74 | } 75 | }); 76 | } 77 | 78 | private void worldLoad(){ 79 | ground.clear(); 80 | flyer.clear(); 81 | viewer.clear(); 82 | 83 | groundRange = Vars.state.rules.dropZoneRadius; 84 | 85 | loadSpawnerPos(); 86 | loadSpawnGroups(); 87 | 88 | destroy.setSpawnRange(groundRange); 89 | render.setRange(groundRange, flayerRange); 90 | 91 | viewer.addViewGroup(ground.groups); 92 | viewer.addViewGroup(flyer.groups); 93 | 94 | destroy.worldLoad(); 95 | tables.worldLoad(); 96 | viewer.worldLoad(); 97 | } 98 | 99 | private void loadSpawnerPos(){ 100 | eachGroundSpawn((spawnX, spawnY) -> { 101 | tmp.add(new Vec2(spawnX * Vars.tilesize, spawnY * Vars.tilesize)); 102 | }); 103 | 104 | SpawnerGroup.getSpawnerGroups(ground.groups, tmp, groundRange * 2.5f); 105 | render.setGroundSpawners(tmp); 106 | 107 | tmp.clear(); 108 | eachFlyerSpawn((spawnWorldX, spawnWorldY) -> { 109 | tmp.add(new Vec2(spawnWorldX, spawnWorldY)); 110 | }); 111 | 112 | SpawnerGroup.getSpawnerGroups(flyer.groups, tmp, flayerRange * 2.5f); 113 | render.setFlyerSpawners(tmp); 114 | 115 | tmp.clear(); 116 | 117 | destroy.setSpawners(spawner.getSpawns()); 118 | } 119 | 120 | private void loadSpawnGroups(){ 121 | for(SpawnGroup spawnGroup : Vars.state.rules.spawns){ 122 | if(spawnGroup.type.flying){ 123 | flyer.spawnGroups.add(spawnGroup); 124 | }else{ 125 | ground.spawnGroups.add(spawnGroup); 126 | } 127 | } 128 | } 129 | 130 | static class GroupStat{ 131 | public Seq groups = new Seq<>(); 132 | public Seq spawnGroups = new Seq<>(); 133 | 134 | public void clear(){ 135 | groups.clear(); 136 | spawnGroups.clear(); 137 | } 138 | 139 | } 140 | 141 | } 142 | -------------------------------------------------------------------------------- /src/MinerTools/modules/SpawnerInfo/SpawnerRange.java: -------------------------------------------------------------------------------- 1 | package MinerTools.modules.SpawnerInfo; 2 | 3 | import MinerTools.modules.*; 4 | import arc.*; 5 | import arc.graphics.g2d.*; 6 | import arc.math.geom.*; 7 | import arc.struct.*; 8 | import mindustry.game.EventType.*; 9 | import mindustry.graphics.*; 10 | 11 | public class SpawnerRange extends SettingModule{ 12 | private final Seq groundSpawners = new Seq<>(); 13 | private final Seq flyerSpawners = new Seq<>(); 14 | private float groundRange = -1f; 15 | private float flyerRange = -1f; 16 | 17 | public SpawnerRange(SettingModule parent){ 18 | super(parent, "spawnerRange"); 19 | } 20 | 21 | public void setRange(float groundRange, float flyerRange){ 22 | this.groundRange = groundRange; 23 | this.flyerRange = flyerRange; 24 | } 25 | 26 | public void setGroundSpawners(Seq spawners){ 27 | groundSpawners.set(spawners); 28 | } 29 | 30 | public void setFlyerSpawners(Seq spawners){ 31 | flyerSpawners.set(spawners); 32 | } 33 | 34 | @Override 35 | public void load(){ 36 | super.load(); 37 | 38 | Events.run(Trigger.draw, () -> { 39 | if(isEnable()){ 40 | draw(); 41 | } 42 | }); 43 | } 44 | 45 | public void draw(){ 46 | drawFlyerRange(); 47 | } 48 | 49 | private void drawFlyerRange(){ 50 | Draw.z(Layer.overlayUI); 51 | 52 | for(Vec2 spawn : flyerSpawners){ 53 | float spawnX = spawn.x, spawnY = spawn.y; 54 | 55 | Lines.dashCircle(spawnX, spawnY, flyerRange); 56 | } 57 | 58 | Draw.reset(); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/MinerTools/modules/SpawnerInfo/SpawnerViewer.java: -------------------------------------------------------------------------------- 1 | package MinerTools.modules.SpawnerInfo; 2 | 3 | import MinerTools.modules.*; 4 | import MinerTools.ui.settings.*; 5 | import MinerTools.utils.*; 6 | import arc.*; 7 | import arc.graphics.g2d.*; 8 | import arc.math.*; 9 | import arc.math.geom.*; 10 | import arc.struct.*; 11 | import arc.util.*; 12 | import mindustry.content.*; 13 | import mindustry.game.EventType.*; 14 | import mindustry.graphics.*; 15 | 16 | public class SpawnerViewer extends SettingModule{ 17 | private final Seq viewGroups = new Seq<>(); 18 | public boolean isViewing = false; 19 | public boolean preview; 20 | public boolean alwaysShow; 21 | 22 | public SpawnerViewer(SettingModule parent){ 23 | super(parent, "spawnerViewer"); 24 | } 25 | 26 | public void clear(){ 27 | viewGroups.clear(); 28 | } 29 | 30 | public void addViewGroup(Seq groups){ 31 | viewGroups.addAll(groups); 32 | } 33 | 34 | @Override 35 | public void load(){ 36 | Events.run(Trigger.draw, () -> { 37 | if(isEnable() && (alwaysShow || isViewing)){ 38 | drawSpawnerPos(); 39 | } 40 | }); 41 | } 42 | 43 | @Override 44 | public void setSettings(MSettingTable settings){ 45 | super.setSettings(settings); 46 | 47 | settings.checkPref(name + ".preview", true, b -> { 48 | preview = b; 49 | }).change(); 50 | 51 | settings.checkPref(name + ".alwaysShow", true, b -> { 52 | alwaysShow = b; 53 | }).change(); 54 | } 55 | 56 | public void worldLoad(){ 57 | if(!isEnable()){ 58 | return; 59 | } 60 | 61 | if(preview){ 62 | Timer.schedule(this::view, 0.75f); 63 | } 64 | } 65 | 66 | public void view(){ 67 | isViewing = true; 68 | 69 | CameraUtils.mark(); 70 | 71 | for(SpawnerGroup group : viewGroups){ 72 | CameraUtils.panWait(group.getCentroid(), 0.55f); 73 | } 74 | 75 | CameraUtils.panToLastMark().onFinished(() -> { 76 | isViewing = false; 77 | }); 78 | } 79 | 80 | private void drawSpawnerPos(){ 81 | float radius = 12f + Mathf.sin(Time.globalTime / 12) * 2; 82 | for(SpawnerGroup group : viewGroups){ 83 | for(Vec2 v : group.spawnerPos){ 84 | drawSpawnerTarget(v.x, v.y, radius); 85 | } 86 | } 87 | } 88 | 89 | private void drawSpawnerTarget(float x, float y, float radius){ 90 | Draw.z(Layer.overlayUI); 91 | 92 | Draw.rect(Blocks.spawn.fullIcon, x, y, 8f, 8f); 93 | 94 | Draw.color(Pal.accent, 0.6f); 95 | Draw.mixcol(Pal.remove, 0.4f + Mathf.absin(Time.globalTime, 6f, 0.28f)); 96 | 97 | Lines.stroke(2f); 98 | Lines.poly(x, y, 4, radius, 90f); 99 | 100 | Lines.stroke(1f); 101 | Lines.poly(x, y, 4, radius * 1.5f, 90f); 102 | 103 | Lines.spikes(x, y, radius * 1.5f, 8f, 4, 90f); 104 | 105 | Draw.reset(); 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/MinerTools/ui/BorderColorImage.java: -------------------------------------------------------------------------------- 1 | package MinerTools.ui; 2 | 3 | import arc.graphics.*; 4 | import arc.math.*; 5 | import arc.scene.actions.*; 6 | import mindustry.gen.*; 7 | import mindustry.ui.*; 8 | 9 | public class BorderColorImage extends BorderImage{ 10 | 11 | public BorderColorImage(){ 12 | super(Tex.whiteui); 13 | } 14 | 15 | public void colorAction(Color color){ 16 | colorAction(color, 0.5f, Interp.smooth); 17 | } 18 | 19 | public void colorAction(Color color, float duration, Interp interp){ 20 | addAction(Actions.color(color, duration, interp)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/MinerTools/ui/MStyles.java: -------------------------------------------------------------------------------- 1 | package MinerTools.ui; 2 | 3 | import MinerTools.*; 4 | import arc.*; 5 | import arc.graphics.*; 6 | import arc.graphics.g2d.*; 7 | import arc.scene.style.*; 8 | import arc.scene.ui.ImageButton.*; 9 | import arc.scene.ui.TextButton.*; 10 | import arc.scene.ui.TextField.*; 11 | import mindustry.graphics.*; 12 | 13 | import static MinRi2.ModCore.ui.MinTex.*; 14 | import static mindustry.gen.Tex.*; 15 | import static mindustry.ui.Styles.*; 16 | 17 | public class MStyles{ 18 | // TODO: 注解处理器生成 19 | public static TextureRegionDrawable accentGrayGran; 20 | 21 | public static ImageButtonStyle clearToggleAccentb, logicVarTogglet, chatb, rclearTransi; 22 | public static TextButtonStyle clearPartial2t, clearAccentt, toggleTranst, settingt; 23 | public static TextFieldStyle noneField; 24 | 25 | public static void load(){ 26 | loadModSprites(); 27 | 28 | clearToggleAccentb = new ImageButtonStyle(){{ 29 | over = flatOver; 30 | down = transAccent; 31 | checked = transAccent; 32 | imageDisabledColor = Pal.darkerGray; 33 | }}; 34 | 35 | logicVarTogglet = new ImageButtonStyle(){{ 36 | up = buttonOver; 37 | down = buttonDown; 38 | checked = buttonDown; 39 | }}; 40 | 41 | chatb = new ImageButtonStyle(defaulti){{ 42 | up = black6; 43 | over = flatOver; 44 | down = flatDown; 45 | }}; 46 | 47 | rclearTransi = new ImageButtonStyle(clearNonei){{ 48 | up = none; 49 | }}; 50 | 51 | clearPartial2t = new TextButtonStyle(defaultt){{ 52 | up = none; 53 | over = flatOver; 54 | down = flatDown; 55 | }}; 56 | 57 | clearAccentt = new TextButtonStyle(clearPartial2t){{ 58 | down = transAccent; 59 | }}; 60 | 61 | toggleTranst = new TextButtonStyle(defaultt){{ 62 | up = getColoredRegion(Color.gray); 63 | over = flatOver; 64 | down = transAccent; 65 | checked = transAccent; 66 | }}; 67 | 68 | settingt = new TextButtonStyle(toggleTranst){{ 69 | up = getColoredRegion(Pal.lightishGray, 0.3f); 70 | checked = getColoredRegion(Pal.lightishGray); 71 | }}; 72 | 73 | noneField = new TextFieldStyle(defaultField){{ 74 | background = none; 75 | }}; 76 | } 77 | 78 | public static void loadModSprites(){ 79 | accentGrayGran = new TextureRegionDrawable(getSprite("gradient")); 80 | } 81 | 82 | private static TextureRegion getSprite(String name){ 83 | return Core.atlas.find(MinerVars.modName + "-" + name); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/MinerTools/ui/MUI.java: -------------------------------------------------------------------------------- 1 | package MinerTools.ui; 2 | 3 | import MinRi2.ModCore.ui.*; 4 | import MinerTools.interfaces.*; 5 | import MinerTools.ui.override.*; 6 | import MinerTools.ui.settings.*; 7 | import MinerTools.ui.tables.floats.*; 8 | import arc.scene.*; 9 | import arc.scene.ui.*; 10 | import arc.struct.*; 11 | 12 | import static arc.Core.*; 13 | 14 | public class MUI{ 15 | /* 集中处理鼠标未指向ScrollPane但又占用滑动的情况 */ 16 | public static Seq panes = new Seq<>(); 17 | 18 | private final Seq addableTables = new Seq<>(); 19 | private final Seq floats = new Seq<>(); 20 | private final Seq overrides = new Seq<>(); 21 | 22 | // Override 23 | public CoreItemsDisplay coreItemsDisplay; 24 | public BetterInfoTable betterHover; 25 | 26 | // Settings 27 | public MSettingsMenu settings; 28 | public MSettingsDialog settingsDialog; 29 | 30 | // DraggableTable 31 | 32 | // FloatTable 33 | public ChatTable chat; 34 | public ToolsFloatTable toolsTable; 35 | public ScriptButtons scriptButtons; 36 | public MainTable main; 37 | 38 | public MUI(){ 39 | } 40 | 41 | public void init(){ 42 | MStyles.load(); 43 | 44 | settings = new MSettingsMenu(); 45 | settingsDialog = new MSettingsDialog(); 46 | 47 | floats.addAll( 48 | main = new MainTable(), 49 | chat = new ChatTable(), 50 | toolsTable = new ToolsFloatTable(), 51 | scriptButtons = new ScriptButtons() 52 | ); 53 | 54 | overrides.addAll( 55 | coreItemsDisplay = new CoreItemsDisplay(), 56 | betterHover = new BetterInfoTable() 57 | ); 58 | 59 | addableTables.addAll(floats); 60 | 61 | addUI(); 62 | } 63 | 64 | public void addUI(){ 65 | for(Addable addableTable : addableTables){ 66 | addableTable.addUI(); 67 | } 68 | } 69 | 70 | public void update(){ 71 | for(ScrollPane pane : panes){ 72 | if(pane.hasScroll()){ 73 | Element result = scene.hit(input.mouseX(), input.mouseY(), true); 74 | if(result == null || !result.isDescendantOf(pane)){ 75 | scene.setScrollFocus(null); 76 | } 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/MinerTools/ui/settings/BaseSetting.java: -------------------------------------------------------------------------------- 1 | package MinerTools.ui.settings; 2 | 3 | import MinRi2.ModCore.ui.*; 4 | import MinerTools.*; 5 | import MinerTools.ui.*; 6 | import arc.func.*; 7 | import arc.graphics.*; 8 | import arc.scene.*; 9 | import arc.scene.event.*; 10 | import arc.scene.ui.*; 11 | import arc.scene.ui.layout.*; 12 | import arc.util.*; 13 | import mindustry.graphics.*; 14 | import mindustry.ui.*; 15 | import mindustry.ui.dialogs.SettingsMenuDialog.*; 16 | 17 | import static arc.Core.bundle; 18 | 19 | public abstract class BaseSetting{ 20 | protected String name, title, describe; 21 | 22 | protected T defaultValue; 23 | 24 | public BaseSetting(String name){ 25 | this.name = name; 26 | title = bundle.get("miner-tools.setting." + name + ".name"); 27 | describe = bundle.get("miner-tools.setting." + name + ".describe", ""); 28 | } 29 | 30 | public BaseSetting(String name, T defaultValue){ 31 | this(name); 32 | 33 | MinerVars.settings.put(name, defaultValue, true, true); 34 | } 35 | 36 | public abstract void setup(Table table); 37 | 38 | protected void addDescribeTo(Element element){ 39 | if(!describe.isEmpty()){ 40 | ElementUtils.addTooltip(element, describe, Align.topLeft, true); 41 | } 42 | } 43 | 44 | protected T getValue(){ 45 | return MinerVars.settings.get(name, defaultValue); 46 | } 47 | 48 | protected void setValue(T value){ 49 | MinerVars.settings.put(name, value, false, true); 50 | } 51 | 52 | public static class CheckSetting extends BaseSetting{ 53 | public @Nullable Boolc changed; 54 | 55 | public CheckSetting(String name, boolean defaultValue, Boolc changed){ 56 | super(name, defaultValue); 57 | this.changed = changed; 58 | } 59 | 60 | @Override 61 | public void setup(Table table){ 62 | BorderColorImage image = new BorderColorImage(); 63 | 64 | image.setColor(getValue() ? Pal.accent : Color.red); 65 | 66 | table.button(b -> { 67 | b.left(); 68 | b.add(image).size(32f).pad(4f); 69 | b.add(title); 70 | }, MStyles.clearAccentt, () -> { 71 | boolean value = !getValue(); 72 | 73 | setValue(value); 74 | 75 | image.colorAction(getValue() ? Pal.accent : Color.red); 76 | 77 | if(changed != null){ 78 | changed.get(value); 79 | } 80 | }).with(this::addDescribeTo).growX(); 81 | } 82 | 83 | public void change(){ 84 | changed.get(getValue()); 85 | } 86 | } 87 | 88 | public static class SliderSetting extends BaseSetting{ 89 | private StringProcessor processor; 90 | private int min, max, step; 91 | 92 | public SliderSetting(String name, int defaultValue, int min, int max, int step, StringProcessor processor){ 93 | super(name, defaultValue); 94 | this.min = min; 95 | this.max = max; 96 | this.step = step; 97 | this.processor = processor; 98 | } 99 | 100 | @Override 101 | public void setup(Table table){ 102 | Slider slider = new Slider(min, max, step, false); 103 | 104 | slider.setValue(getValue()); 105 | 106 | Label value = new Label("", Styles.outlineLabel); 107 | Table content = new Table(); 108 | content.add(title, Styles.outlineLabel).left().growX().wrap(); 109 | content.add(value).padLeft(10f).right(); 110 | content.margin(3f, 33f, 3f, 33f); 111 | content.touchable = Touchable.disabled; 112 | 113 | slider.changed(() -> { 114 | setValue((int)slider.getValue()); 115 | value.setText(processor.get((int)slider.getValue())); 116 | }); 117 | 118 | slider.change(); 119 | 120 | Stack stack = table.stack(slider, content).maxWidth(400f).padTop(4f).growX().left().get(); 121 | addDescribeTo(stack); 122 | } 123 | 124 | public void change(){ 125 | processor.get(MinerVars.settings.getInt(name)); 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/MinerTools/ui/settings/CategorySetting.java: -------------------------------------------------------------------------------- 1 | package MinerTools.ui.settings; 2 | 3 | import MinerTools.ui.*; 4 | import arc.*; 5 | import arc.scene.ui.layout.*; 6 | import mindustry.gen.*; 7 | 8 | /** 9 | * 设置分类组 10 | */ 11 | public class CategorySetting extends MSettingTable{ 12 | private CategoryBuilder builder; 13 | 14 | private boolean shown = true; 15 | 16 | public CategorySetting(String name){ 17 | this(name, CategoryBuilder.defaultBuilder); 18 | } 19 | 20 | public CategorySetting(String name, CategoryBuilder builder){ 21 | super(null, name); 22 | 23 | this.builder = builder; 24 | 25 | top().left(); 26 | } 27 | 28 | public String localizedName(){ 29 | return Core.bundle.format("miner-tools.setting.category." + name() + ".name"); 30 | } 31 | 32 | public void toggle(){ 33 | shown = !shown; 34 | } 35 | 36 | public boolean isShown(){ 37 | return shown; 38 | } 39 | 40 | public void build(Table container){ 41 | builder.build(container, this); 42 | } 43 | 44 | public interface CategoryBuilder{ 45 | CategoryBuilder defaultBuilder = (container, category) -> { 46 | container.button(category.localizedName(), MStyles.toggleTranst, category::toggle) 47 | .height(32f).checked(b -> category.isShown()).growX(); 48 | 49 | container.row(); 50 | 51 | container.table(Tex.pane2, t -> { 52 | t.collapser(category, true, category::isShown) 53 | .growX().get().setDuration(0.4f); 54 | }).growX(); 55 | }; 56 | 57 | void build(Table container, CategorySetting category); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/MinerTools/ui/settings/MSettingTable.java: -------------------------------------------------------------------------------- 1 | package MinerTools.ui.settings; 2 | 3 | import MinerTools.ui.settings.BaseSetting.*; 4 | import MinerTools.ui.settings.CategorySetting.*; 5 | import arc.*; 6 | import arc.func.*; 7 | import arc.scene.style.*; 8 | import arc.scene.ui.layout.*; 9 | import arc.struct.*; 10 | import mindustry.ui.dialogs.SettingsMenuDialog.*; 11 | 12 | public class MSettingTable extends Table{ 13 | private final Drawable icon; 14 | 15 | private final Seq> settings = new Seq<>(); 16 | private final Seq categories = new Seq<>(); 17 | 18 | public MSettingTable(Drawable icon, String name){ 19 | this.icon = icon; 20 | this.name = name; 21 | 22 | top(); 23 | } 24 | 25 | public void rebuild(){ 26 | clearChildren(); 27 | 28 | defaults().growX(); 29 | 30 | for(BaseSetting setting : settings){ 31 | table(setting::setup); 32 | row(); 33 | } 34 | 35 | if(categories.any()){ 36 | for(CategorySetting category : categories){ 37 | category.rebuild(); 38 | table(category::build).padTop(8f); 39 | row(); 40 | } 41 | } 42 | } 43 | 44 | public Drawable icon(){ 45 | return icon; 46 | } 47 | 48 | public String name(){ 49 | return Core.bundle.get("miner-tools.setting." + name + ".name", name); 50 | } 51 | 52 | public boolean hasSetting(){ 53 | return settings.any() || categories.any(); 54 | } 55 | 56 | public CategorySetting addCategory(String name){ 57 | return addCategory(name, categorySetting -> { 58 | }); 59 | } 60 | 61 | public CategorySetting addCategory(String name, Cons cons){ 62 | CategorySetting category = new CategorySetting(this.name + "." + name); 63 | categories.add(category); 64 | 65 | cons.get(category); 66 | 67 | return category; 68 | } 69 | 70 | public void addCategory(String name, Cons cons, CategoryBuilder builder){ 71 | CategorySetting category = new CategorySetting(this.name + "." + name, builder); 72 | categories.add(category); 73 | 74 | cons.get(category); 75 | } 76 | 77 | public CheckSetting checkPref(String name, boolean def){ 78 | return checkPref(name, def, null); 79 | } 80 | 81 | public CheckSetting checkPref(String name, boolean def, Boolc changed){ 82 | CheckSetting setting; 83 | settings.add(setting = new CheckSetting(name, def, changed)); 84 | return setting; 85 | } 86 | 87 | public SliderSetting sliderPref(String name, int def, int min, int max, StringProcessor s){ 88 | return sliderPref(name, def, min, max, 1, s); 89 | } 90 | 91 | public SliderSetting sliderPref(String name, int def, int min, int max, int step, StringProcessor s){ 92 | SliderSetting setting; 93 | settings.add(setting = new SliderSetting(name, def, min, max, step, s)); 94 | return setting; 95 | } 96 | 97 | } -------------------------------------------------------------------------------- /src/MinerTools/ui/settings/MSettingsDialog.java: -------------------------------------------------------------------------------- 1 | package MinerTools.ui.settings; 2 | 3 | import MinerTools.*; 4 | import arc.*; 5 | import arc.scene.ui.*; 6 | import arc.scene.ui.layout.*; 7 | import mindustry.gen.*; 8 | import mindustry.ui.*; 9 | 10 | public class MSettingsDialog extends Dialog{ 11 | private final Table buttons; 12 | private final ScrollPane pane; 13 | public MSettingsMenu menu; 14 | 15 | public MSettingsDialog(){ 16 | menu = MinerVars.ui.settings; 17 | 18 | buttons = new Table(); 19 | pane = new ScrollPane(menu, Styles.noBarPane); 20 | 21 | buttons.bottom(); 22 | 23 | setFillParent(true); 24 | addCloseButton(); 25 | 26 | top(); 27 | 28 | menu.addUI(); 29 | 30 | resized(this::rebuild); 31 | shown(this::rebuild); 32 | } 33 | 34 | private void rebuild(){ 35 | clearChildren(); 36 | 37 | menu.rebuild(); 38 | 39 | Cell cell = stack(pane, buttons).grow(); 40 | 41 | if(Core.scene.getWidth() >= 1920f / 2f){ 42 | cell.maxWidth(Core.scene.getWidth() * 3f / 4f); 43 | } 44 | } 45 | 46 | @Override 47 | public void addCloseButton(){ 48 | buttons.defaults().size(width, 64f); 49 | buttons.button("@back", Icon.left, this::hide).size(width, 64f); 50 | 51 | closeOnBack(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/MinerTools/ui/settings/MSettingsMenu.java: -------------------------------------------------------------------------------- 1 | package MinerTools.ui.settings; 2 | 3 | import MinRi2.ModCore.ui.*; 4 | import MinerTools.*; 5 | import MinerTools.graphics.*; 6 | import MinerTools.ui.*; 7 | import MinerTools.ui.tables.*; 8 | import arc.flabel.*; 9 | import arc.scene.actions.*; 10 | import arc.scene.ui.layout.*; 11 | import arc.struct.*; 12 | import arc.util.*; 13 | import mindustry.*; 14 | import mindustry.gen.*; 15 | import mindustry.graphics.*; 16 | 17 | public class MSettingsMenu extends Table implements Addable{ 18 | private final Table settingTableCont; 19 | public Seq settingTables = new Seq<>(); 20 | public MSettingTable modules, graphics, ui; 21 | private MSettingTable select; 22 | 23 | public MSettingsMenu(){ 24 | settingTableCont = new Table(Tex.pane2); 25 | 26 | addSettings(); 27 | 28 | setup(); 29 | } 30 | 31 | public void addSettings(){ 32 | modules = new MSettingTable(Icon.list, "modules"){ 33 | }; 34 | 35 | graphics = new MSettingTable(Icon.image, "graphics"){ 36 | { 37 | addCategory("unit", setting -> { 38 | drawerCheck(setting, "enemyUnitIndicator", true); 39 | drawerRadiusSlider(setting, "enemyUnitIndicatorRadius", 100, 25, 250); 40 | 41 | drawerCheck(setting, "unitAlert", true); 42 | drawerRadiusSlider(setting, "unitAlertRadius", 10, 5, 50); 43 | 44 | drawerCheck(setting, "unitInfoBar", true); 45 | }); 46 | 47 | addCategory("build", setting -> { 48 | drawerCheck(setting, "turretAlert", true); 49 | drawerRadiusSlider(setting, "turretAlertRadius", 10, 5, 50); 50 | 51 | drawerCheck(setting, "itemTurretAmmoShow", true); 52 | 53 | drawerCheck(setting, "overdriveZone", true); 54 | 55 | setting.addCategory("info", info -> { 56 | drawerCheck(info, "buildStatus", true); 57 | drawerCheck(info, "buildHealthBar", true); 58 | 59 | drawerCheck(info, "constructBuildInfo", true); 60 | drawerCheck(info, "unitBuildInfo", true); 61 | }); 62 | }); 63 | 64 | addCategory("select", setting -> { 65 | drawerCheck(setting, "buildSelectInfo", true); 66 | drawerCheck(setting, "itemBridgeLinksShow", true); 67 | }); 68 | 69 | addCategory("player", setting -> { 70 | drawerCheck(setting, "payloadDropHint", true); 71 | drawerCheck(setting, "playerRange", true); 72 | }); 73 | } 74 | 75 | public void drawerCheck(MSettingTable table, String name, boolean def){ 76 | table.checkPref(name, def, b -> MRenderer.updateEnable()); 77 | } 78 | 79 | public void drawerRadiusSlider(MSettingTable table, String name, int def, int min, int max){ 80 | table.sliderPref(name, def, min, max, s -> { 81 | MRenderer.updateSettings(); 82 | return s + "(Tile)"; 83 | }); 84 | } 85 | }; 86 | 87 | ui = new MSettingTable(Icon.chat, "ui"); 88 | 89 | settingTables.addAll(modules, graphics, ui); 90 | } 91 | 92 | public void rebuild(){ 93 | if(select != null){ 94 | select.rebuild(); 95 | } 96 | } 97 | 98 | private void setup(){ 99 | top(); 100 | settingTableCont.top(); 101 | 102 | ElementUtils.addTitle(this, "@miner-tools.settings", Pal.accent); 103 | 104 | table(buttons -> { 105 | buttons.defaults().grow(); 106 | 107 | boolean isFirst = true; 108 | for(MSettingTable settingTable : settingTables){ 109 | buttons.button(b -> { 110 | b.image(settingTable.icon()).size(48f); 111 | b.add(settingTable.name()).padLeft(8f); 112 | }, MStyles.settingt, () -> { 113 | select(settingTable); 114 | }).checked(b -> select == settingTable).padLeft(isFirst ? 0f : 4f); 115 | 116 | isFirst = false; 117 | } 118 | }).height(80f).growX(); 119 | 120 | row(); 121 | 122 | add(settingTableCont).grow(); 123 | } 124 | 125 | private void select(MSettingTable settingTable){ 126 | settingTableCont.clear(); 127 | 128 | if(select != settingTable){ 129 | select = settingTable; 130 | 131 | rebuild(); 132 | settingTableCont.add(settingTable).grow(); 133 | }else{ 134 | select = null; 135 | } 136 | } 137 | 138 | @Override 139 | public void addUI(){ 140 | Table menu = Reflect.get(Vars.ui.settings, "menu"); 141 | 142 | Runnable addCustomButton = () -> { 143 | menu.button(b -> { 144 | b.add(new FLabel("{rainbow}[M]")).padLeft(6f); 145 | b.add("[accent]MinerTools").labelAlign(Align.center).growX(); 146 | }, MStyles.clearAccentt, () -> { 147 | MinerVars.ui.settingsDialog.show(); 148 | }).name(MinerVars.modName); 149 | }; 150 | 151 | Runnable updater = () -> { 152 | if(menu.find(MinerVars.modName) == null){ 153 | addCustomButton.run(); 154 | } 155 | }; 156 | 157 | menu.addAction(Actions.forever(Actions.run(updater))); 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /src/MinerTools/ui/tables/DraggableTable.java: -------------------------------------------------------------------------------- 1 | package MinerTools.ui.tables; 2 | 3 | import MinerTools.*; 4 | import arc.input.*; 5 | import arc.math.geom.*; 6 | import arc.scene.*; 7 | import arc.scene.event.*; 8 | import arc.scene.ui.layout.*; 9 | import arc.util.*; 10 | 11 | /** Table that can be dragged */ 12 | public class DraggableTable extends Table{ 13 | public Element draggier; 14 | public boolean isDragging = false; 15 | 16 | private boolean savePos; 17 | 18 | public DraggableTable(boolean savePos){ 19 | this("", savePos); 20 | } 21 | 22 | public DraggableTable(String name, boolean savePos){ 23 | this(name, null, savePos); 24 | } 25 | 26 | public DraggableTable(String name, Element draggier, boolean savePos){ 27 | this.name = name; 28 | this.savePos = savePos; 29 | 30 | setDraggier(draggier); 31 | 32 | if(savePos){ 33 | setLastPos(); 34 | } 35 | } 36 | 37 | public void setLastPos(){ 38 | if(name != null && !name.isEmpty()){ 39 | float x = MinerVars.settings.getFloat("ui." + name + ".pos" + ".x"); 40 | float y = MinerVars.settings.getFloat("ui." + name + ".pos" + ".y"); 41 | setPosition(x, y); 42 | keepInStage(); 43 | } 44 | } 45 | 46 | public void setDraggier(Element draggier){ 47 | Element lastDraggier = this.draggier; 48 | if(lastDraggier != draggier){ 49 | this.draggier = draggier; 50 | if(lastDraggier != null) lastDraggier.getListeners().removeAll(l -> l instanceof DragListener); 51 | addListener(); 52 | } 53 | } 54 | 55 | public boolean isLocked(){ 56 | return MinerVars.settings.getBool("ui." + name + ".pos" + ".locked"); 57 | } 58 | 59 | public void toggleLocked(){ 60 | MinerVars.settings.put("ui." + name + ".pos" + ".locked", !isLocked()); 61 | } 62 | 63 | public void addListener(){ 64 | if(draggier == null){ 65 | return; 66 | } 67 | 68 | draggier.addListener(new DragListener(this)); 69 | } 70 | 71 | public static class DragListener extends InputListener{ 72 | DraggableTable target; 73 | float lastX, lastY; 74 | 75 | public DragListener(DraggableTable target){ 76 | this.target = target; 77 | } 78 | 79 | @Override 80 | public boolean touchDown(InputEvent event, float x, float y, int pointer, KeyCode button){ 81 | lastX = x; 82 | lastY = y; 83 | target.isDragging = true; 84 | return true; 85 | } 86 | 87 | @Override 88 | public void touchDragged(InputEvent event, float x, float y, int pointer){ 89 | if(!target.isLocked()){ 90 | Vec2 v = target.localToStageCoordinates(Tmp.v1.set(x, y)); 91 | target.setPosition(v.x - lastX, v.y - lastY); 92 | 93 | target.keepInStage(); 94 | 95 | if(target.savePos){ 96 | MinerVars.settings.put("ui." + target.name + ".pos" + ".x", target.x); 97 | MinerVars.settings.put("ui." + target.name + ".pos" + ".y", target.y); 98 | } 99 | } 100 | } 101 | 102 | @Override 103 | public void touchUp(InputEvent e, float x, float y, int pointer, KeyCode button){ 104 | target.isDragging = false; 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /src/MinerTools/ui/tables/MembersTable.java: -------------------------------------------------------------------------------- 1 | package MinerTools.ui.tables; 2 | 3 | import MinerTools.*; 4 | import MinerTools.interfaces.*; 5 | import MinerTools.ui.*; 6 | import arc.scene.style.*; 7 | import arc.scene.ui.layout.*; 8 | import arc.struct.*; 9 | import mindustry.*; 10 | import mindustry.ui.*; 11 | 12 | public class MembersTable extends Table{ 13 | public final Seq members = new Seq<>(); 14 | public MembersBuilder builder; 15 | 16 | private Table container; 17 | private MemberTable currentMember; 18 | 19 | public MembersTable(){ 20 | this(MembersBuilder.defaultBuilder); 21 | } 22 | 23 | public MembersTable(MembersBuilder builder){ 24 | this.builder = builder; 25 | } 26 | 27 | public void setContainer(Table container){ 28 | this.container = container; 29 | } 30 | 31 | public void rebuildCont(){ 32 | clearChildren(); 33 | builder.build(this); 34 | } 35 | 36 | public void addMember(MemberTable... members){ 37 | this.members.addAll(members); 38 | } 39 | 40 | public void setMember(MemberTable member){ 41 | container.clear(); 42 | currentMember = member; 43 | if(member != null){ 44 | container.add(member).grow().padRight(2.0f); 45 | member.onSelected(); 46 | } 47 | } 48 | 49 | public void toggleMember(MemberTable member){ 50 | if(isShowing(member)){ 51 | setMember(null); 52 | }else{ 53 | setMember(member); 54 | } 55 | } 56 | 57 | public boolean isShowing(){ 58 | return currentMember != null; 59 | } 60 | 61 | public boolean isShowing(MemberTable memberTable){ 62 | return currentMember == memberTable; 63 | } 64 | 65 | public Seq getMembers(){ 66 | return members; 67 | } 68 | 69 | public interface MembersBuilder extends TableBuilder{ 70 | /** 71 | * 横向排布 72 | */ 73 | MembersBuilder defaultBuilder = table -> { 74 | table.top(); 75 | 76 | Seq members = table.getMembers(); 77 | 78 | table.table(buttons -> { 79 | buttons.background(Styles.black3); 80 | 81 | for(MemberTable member : members){ 82 | if(!member.canShown()) continue; 83 | 84 | member.left().top(); 85 | 86 | buttons.button(member.icon, MStyles.clearToggleAccentb, () -> { 87 | table.toggleMember(member); 88 | }).height(32f).padTop(4.0f).growX().checked(b -> table.isShowing(member)); 89 | } 90 | }).growX().top(); 91 | 92 | table.row(); 93 | 94 | table.table(table::setContainer).grow().top(); 95 | }; 96 | } 97 | 98 | public static class MemberTable extends Table{ 99 | public boolean desktopOnly; 100 | public boolean mobileOnly; 101 | public Drawable icon; 102 | 103 | public MemberTable(Drawable icon){ 104 | this.icon = icon; 105 | } 106 | 107 | public boolean canShown(){ 108 | return !(this.mobileOnly && !Vars.mobile || this.desktopOnly && !MinerVars.desktop); 109 | } 110 | 111 | public void onSelected(){ 112 | } 113 | } 114 | 115 | } 116 | 117 | -------------------------------------------------------------------------------- /src/MinerTools/ui/tables/floats/FloatManager.java: -------------------------------------------------------------------------------- 1 | package MinerTools.ui.tables.floats; 2 | 3 | import arc.func.*; 4 | import arc.struct.*; 5 | 6 | public class FloatManager{ 7 | private static final ObjectMap map = new ObjectMap<>(); 8 | 9 | public static void add(FloatTable table){ 10 | map.put(table.name, table); 11 | } 12 | 13 | public static void remove(FloatTable table){ 14 | map.remove(table.name); 15 | } 16 | 17 | @SuppressWarnings("unchecked") 18 | public static T get(String name){ 19 | return (T)map.get(name); 20 | } 21 | 22 | @SuppressWarnings("unchecked") 23 | public static T getOrCreate(String name, Prov prov){ 24 | return (T)map.get(name, prov); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/MinerTools/ui/tables/floats/MainTable.java: -------------------------------------------------------------------------------- 1 | package MinerTools.ui.tables.floats; 2 | 3 | import MinRi2.ModCore.ui.*; 4 | import MinerTools.*; 5 | import MinerTools.ui.*; 6 | import arc.scene.ui.layout.*; 7 | import mindustry.gen.*; 8 | import mindustry.ui.*; 9 | 10 | public class MainTable extends FloatTable{ 11 | public MainTable(){ 12 | super("main", false, false); 13 | 14 | title.background(MinTex.transAccent); 15 | } 16 | 17 | @Override 18 | protected void rebuildBody(Table body){ 19 | super.rebuildBody(body); 20 | 21 | body.background(Styles.black3); 22 | 23 | body.defaults().height(40f).growX(); 24 | 25 | body.button("@miner-tools.settings", Icon.settingsSmall, MStyles.clearAccentt, () -> { 26 | MinerVars.ui.settingsDialog.show(); 27 | }); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/MinerTools/ui/tables/floats/ScriptButtons.java: -------------------------------------------------------------------------------- 1 | package MinerTools.ui.tables.floats; 2 | 3 | import MinerTools.game.*; 4 | import MinerTools.ui.*; 5 | import arc.func.*; 6 | import arc.scene.style.*; 7 | import arc.scene.ui.*; 8 | import arc.scene.ui.Button.*; 9 | import arc.scene.ui.layout.*; 10 | import mindustry.*; 11 | import mindustry.gen.*; 12 | import mindustry.ui.*; 13 | 14 | import static arc.Core.bundle; 15 | 16 | public class ScriptButtons extends FloatTable{ 17 | private static final String bundleName = "miner-tools.buttons.tooltips"; 18 | 19 | private Table buttons; 20 | private int index = 0; 21 | 22 | public ScriptButtons(){ 23 | super("scriptButtons"); 24 | } 25 | 26 | @Override 27 | protected void rebuildBody(Table body){ 28 | super.rebuildBody(body); 29 | 30 | body.table(Styles.black3, buttons -> { 31 | this.buttons = buttons; 32 | }).growX(); 33 | 34 | setupButtons(); 35 | } 36 | 37 | private void setupButtons(){ 38 | buttons.defaults().minSize(80f, 64f).growX(); 39 | 40 | if(Vars.mobile){ 41 | addScriptButton("stopBuilding", Icon.hammer, Styles.clearNoneTogglei, () -> { 42 | Vars.control.input.isBuilding = !Vars.control.input.isBuilding; 43 | }, b -> !Vars.control.input.isBuilding); 44 | 45 | addScriptButton("updateConveyor", Icon.distribution, Styles.clearNoneTogglei, ConveyorUpdater::toggle, b -> ConveyorUpdater.enable); 46 | 47 | addScriptButton("observerMode", Icon.pause, Styles.clearNoneTogglei, 48 | MobileObserverMode::toggle, b -> MobileObserverMode.isObserving()); 49 | } 50 | 51 | addScriptButton("wayzerObserver", Icon.eyeSmall, MStyles.rclearTransi, () -> { 52 | Call.sendChatMessage("/ob"); 53 | }); 54 | 55 | addScriptButton("quickVoteGameOver", Icon.trashSmall, Styles.clearNonei, () -> { 56 | Vars.ui.showConfirm("@confirm", "@confirmvotegameover", () -> { 57 | Call.sendChatMessage("/vote gameover"); 58 | Call.sendChatMessage("1"); 59 | }); 60 | }); 61 | } 62 | 63 | private Cell