├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── crash-report.md │ ├── feature_request.md │ └── improvment---enhancement-request.md └── workflows │ └── gradle.yml ├── .gitignore ├── LICENSE ├── README.md ├── assets ├── bundles │ ├── bundle.properties │ ├── bundle_ko.properties │ ├── bundle_ru.properties │ ├── bundle_tr.properties │ ├── bundle_uk_UA.properties │ └── bundle_zh_CN.properties ├── mod.json ├── shaders │ ├── line.frag │ ├── transparent.frag │ └── turretrange.frag └── sprites │ ├── effects │ ├── Slaser-end.png │ └── Slaser.png │ └── ui │ ├── bars │ ├── barS-top.png │ ├── barS.png │ ├── onepx.png │ └── sidebar.9.png │ └── icons │ ├── ammo.png │ ├── health.png │ ├── item.png │ ├── liquid.png │ ├── power.png │ ├── reload.png │ └── shield.png ├── build.bat ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── src └── informatis ├── Informatis.java ├── SUtils.java ├── SVars.java ├── core ├── EventEmitter.java ├── ModMetadata.java ├── Pathfinder.java ├── UpdateChecker.java ├── VDOM.java └── setting │ ├── SettingHelper.java │ ├── SharSetting.java │ └── SharSettingUI.java ├── shaders ├── RangeShader.java ├── Shaders.java └── TransparentShader.java └── ui ├── components ├── FreeBar.java ├── IntervalTableWrapper.java ├── PageTabsFragment.java ├── SBar.java ├── SIcons.java └── TabsFragment.java └── fragments ├── ElementViewFragment.java ├── FragmentManager.java ├── QuickSchemFragment.java ├── ServerSearchFragment.java ├── SidebarSwitcher.java ├── TileInfoFragment.java └── sidebar ├── TroopingFragment.java ├── TroopingManager.java ├── dialogs ├── DialogManager.java └── ResourcePreviewDialog.java └── windows ├── CoreWindow.java ├── MapEditorWindow.java ├── SettingConfiger.java ├── ToolConfigable.java ├── ToolWindow.java ├── UnitWindow.java ├── WaveWindow.java ├── Window.java ├── WindowManager.java └── tools ├── draws ├── BlockBarDraw.java ├── BlockStatusDraw.java ├── CommandLineDraw.java ├── DistanceLineDraw.java ├── LogicLineDraw.java ├── MagicCursorDraw.java ├── MassLinkDraw.java ├── MemoViewDraw.java ├── OverDraw.java ├── OverDrawCategory.java ├── OverDrawManager.java ├── PathLineDraw.java ├── PowerNodeDraw.java ├── RangeDraw.java ├── SelectArrawDraw.java ├── SpawnerArrawDraw.java ├── UnitBarDraw.java ├── UnitCargoLinkDraw.java ├── UnitItemDraw.java └── UnitPathLineDraw.java └── tools ├── AutoShooter.java ├── CameraScaler.java ├── FogRemover.java ├── Tool.java ├── ToolManager.java └── UnitVisualizer.java /.gitattributes: -------------------------------------------------------------------------------- 1 | */** linguist-vendored 2 | src/** linguist-vendored=false -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a bug report when something not working or has weird behaviour. 4 | title: '' 5 | labels: bug 6 | assignees: Sharlottes 7 | 8 | --- 9 | 10 | ## Describe the bug 11 | A clear and concise description of what the bug is. 12 | 13 | ## Reproduction 14 | Steps to reproduce the behavior 15 | 16 | ## Expected behavior 17 | A clear and concise description of what you expected to happen. 18 | 19 | ## Screenshots 20 | If applicable, add screenshots to help explain your problem. 21 | 22 | ## Additional context 23 | Add any other context about the problem here. 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/crash-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Crash Report 3 | about: the Report format only for mindustry crash. 4 | title: '' 5 | labels: crash 6 | assignees: Sharlottes 7 | 8 | --- 9 | 10 | ## Reproduction 11 | Post a video or describe how to reproduce the crash situation in detail. 12 | 13 | ## Crash report log 14 | Just copy-paste the report log, please. crash log is the best information to fix the crash issue. 15 | 16 | ## Addition Context 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest new Feature idea, not the improvment or bug report. 4 | title: '' 5 | labels: feature 6 | assignees: Sharlottes 7 | 8 | --- 9 | 10 | ## Describe Feature 11 | Tell me what the feature should do in detail. 12 | 13 | ## Related context 14 | If this feature is related to some issue, mention or describe please. 15 | 16 | ## Additional context 17 | Please feel free to add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/improvment---enhancement-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Improvment & Enhancement Request 3 | about: tell me the feedback, improvment or enhancement request for existing feature. 4 | title: '' 5 | labels: enhancement 6 | assignees: Sharlottes 7 | 8 | --- 9 | 10 | ## Target Feature 11 | What feature do you want to change? 12 | 13 | ## Describe Detailly 14 | So what point of that feature needs to be changed? tell me the reason and solution detailly. 15 | 16 | ## Additional Context 17 | -------------------------------------------------------------------------------- /.github/workflows/gradle.yml: -------------------------------------------------------------------------------- 1 | name: Java CI with Gradle 2 | 3 | on: push 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/checkout@v3 11 | 12 | - name: Set up JDK 16 13 | uses: actions/setup-java@v3 14 | with: 15 | distribution: 'zulu' 16 | java-version: 16 17 | 18 | - name: Setup Android SDK Tools 19 | uses: android-actions/setup-android@v2 20 | env: 21 | ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true' 22 | 23 | - name: build-tools 24 | run: sdkmanager "build-tools;30.0.3" 25 | 26 | - name: Add Android SDK to PATH 27 | run: echo "${ANDROID_HOME}/build-tools/30.0.3" >> $GITHUB_PATH 28 | 29 | - name: Grant execute permission for gradlew 30 | run: chmod +x gradlew 31 | 32 | - name: Build with Gradle 33 | run: ./gradlew deploy 34 | 35 | - name: Upload artifact 36 | uses: actions/upload-artifact@v3 37 | with: 38 | name: informatis 39 | path: build/libs/*.jar 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/* 2 | .gradle/* 3 | build/* 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Sharlotte 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Informatis 2 | 3 | [![GitHub all releases](https://img.shields.io/github/downloads/sharlottes/informatis/total?color=ffd700&label=total%20downloads&style=flat-square)](https://github.com/Sharlottes/informatis/) 4 | 5 | [![Java CI with Gradle](https://github.com/sharlottes/informatis/workflows/Java%20CI%20with%20Gradle/badge.svg)](https://github.com/sharlottes/informatis/actions) 6 | [![GitHub all releases](https://img.shields.io/github/downloads/anuken/mindustry/total?label=Made%20on%20Mindustry&style=flat-square)](https://github.com/Anuken/Mindustry/) 7 | [![GitHub Repo stars](https://img.shields.io/github/stars/sharlottes/informatis?label=Please%20star%20me%21&style=social)](https://github.com/sharlottes/informatis/stargazers) 8 | 9 | This mod displays some extra information. 10 | -------------------------------------------------------------------------------- /assets/bundles/bundle.properties: -------------------------------------------------------------------------------- 1 | ## Setting 2 | setting.shar-ui = HUD UI Settings 3 | setting.shar-title = Informatis Settings 4 | setting.shar-draw = Overdrawing Settings 5 | 6 | setting.tileinfo.name = Display tile information HUD 7 | setting.tileinfo.description = Displays tile information HUD on left-top-side, which displays tile information on the cursor. 8 | setting.schem.name = Display Schematic HUD 9 | setting.schem.description = Displays schematic quick slot HUD on right-side, which helps select schematic quickly. 10 | setting.sidebar.name = Display Sidebar HUD 11 | setting.sidebar.description = Displays sidebar HUD on left-side, which provides various of advantages. 12 | setting.elementdebug.name = Element Debug 13 | setting.elementdebug.description = Show all Element outline 14 | setting.hiddenElem.name = Display hidden element 15 | setting.hiddenElem.description = display hidden element outline too. 16 | setting.serverfilter.name = Turn on Server filter 17 | setting.serverfilter.description = active server filter system (WIP) 18 | 19 | setting.selectopacity.name = Select Arrow Opacity 20 | setting.selectopacity.description = Sets the opacity of selection arrow. 21 | setting.baropacity.name = Health Bar Opacity 22 | setting.baropacity.description = Sets the opacity of the unit health bar. 23 | 24 | setting.blockBar.name = enable Block Bar 25 | setting.blockBar.description = display block health bar 26 | setting.memoView.name = preview message block 27 | setting.memoView.description = preview message blocks' text at once 28 | 29 | setting.powerNode.name = enable Power Node 30 | setting.powerNode.description = display power node link lines 31 | setting.massLink.name = enable Mass Driver 32 | setting.massLink.description = display mass driver link lines 33 | setting.unitCargoLink.name = Display unit-cargo link 34 | setting.unitCargoLink.description = display unit cargo block's link line 35 | 36 | setting.range.name = Display Range 37 | setting.range.description = Displays every available turrets/units range 38 | setting.blockRange.name = Display Block Range 39 | setting.blockRange.description = Displays every available turrets range 40 | setting.unitRange.name = Display Unit Range 41 | setting.unitRange.description = Displays every available units range 42 | setting.invalidRange.name = Display Invalid Range 43 | setting.invalidRange.description = Displays every range of turrets/units which cannot shot 44 | setting.airRange.name = Display Air range 45 | setting.airRange.description = display every available range of turrets/units which can target air units 46 | setting.groundRange.name = Display Ground range 47 | setting.groundRange.description = display every available range of turrets/units which can target ground units or blocks 48 | setting.allianceRange.name = Display Alice Range 49 | setting.allianceRange.description = Displays every alice turret/unit range 50 | setting.rangeShader.name = Enable Animation 51 | setting.rangeShader.description = Use animation shader for make it ease to see 52 | 53 | setting.pathLine.name = enable Path Line 54 | setting.pathLine.description = display wave ground unit's ai path lineline 55 | setting.logicLine.name = enable Logic Line 56 | setting.logicLine.description = display lines between logic processor and controlled units 57 | setting.unitPathLine.name = enable Unit Line 58 | setting.unitPathLine.description = display ai path each ground unit 59 | setting.commandLine.name = enable Command Line 60 | setting.commandLine.description = display unit path line, controlled by rts command 61 | setting.unitItem.name = enable Unit Item 62 | setting.unitItem.description = display item amount under each unit 63 | setting.unitBar.name = enable Unit Bar 64 | setting.unitBar.description = display health bar under each unit 65 | 66 | setting.spawnerarrow.name = Indicate Wave Spawn-Point 67 | setting.spawnerarrow.description = Displays arrow pointing to wave spawn-points. 68 | setting.select.name = Display Selection Arrow 69 | setting.select.description = Shows which unit or block is selected. 70 | setting.distanceLine.name = Display Distance Line From Selected Target 71 | setting.distanceLine.description = Displays dotted lines and numbers to indicate how far away the target is. 72 | 73 | setting.gaycursor.name = Magic Cursor 74 | setting.gaycursor.description = makes your cursor more fency! 75 | 76 | #Hud 77 | hud.schematic-list = Schematic List 78 | 79 | #Window 80 | window.unit.name = Unit Display 81 | window.wave.name = Wave Display 82 | window.core.name = Core Display 83 | window.player.name = Player Display 84 | window.tool.name = Tool Display [red](WIP)[] 85 | window.editor.name = Map Editor Display [red](WIP)[] 86 | 87 | # UnitWindow - Stats 88 | shar-stat.health = Health: {0} 89 | shar-stat.shield = Shield: {0} 90 | shar-stat.payloadCapacity = Payloads: {0}�/{1}� 91 | shar-stat.capacity = {0}: {1}/{2} 92 | shar-stat.power = Power: {0}/{1} 93 | shar-stat.powerIn = InPower: {0}/s 94 | shar-stat.powerOut = OutPower: {0}/s 95 | shar-stat.ammos = Ammo: {0}/{1} 96 | shar-stat.reload = Reload: {0}% 97 | shar-stat.progress = Progress: {0}% 98 | shar-stat.attr = Attribute: x{0} 99 | shar-stat-waveAmount = [lightgray]Enemy Amount:[] {0} 100 | shar-stat-waveShield = [lightgray]Shield:[] {0} 101 | shar-stat.waveStatus = [lightgray]Status:[] 102 | 103 | #ToolWindow - Tool 104 | setting.fogremover.name = Fog Remover 105 | setting.fogremover.description = remove every fog in the world! 106 | setting.camerascaler.name = Camera Scaler 107 | setting.camerascaler.description = set camera zoom scale to maximum. 108 | setting.autoShoot.name = Enable Auto Shooting 109 | setting.autoShoot.description = no don't do hack 110 | 111 | #Other 112 | mode.custom.name = Custom 113 | empty = [lightgray][] 114 | none = 115 | tiles = tiles 116 | 117 | #Mod 118 | shar-description = Multifunctional information mod that shows various information in game.\n\n[#AE00FB]In-game UI:[] Located at left side, shows unit/build by cursor, wave list, core and resource info.\n\n[#B5FFD9]Unit/Build Info:[] Shows unit/build information by cursor.\n\n[#B5FFD9]Wave Info:[] Shows wave list, including type/amount/boss. can click to view detail info.\n\n[#B5FFD9]Core Info:[] Shows core position/health for each team. can click to change camera.\n\n[#B5FFD9]Tile Info:[] Shows block/floor/ore icon and position on the cursor. if map has wave, shows remaining wave units too.\n\n[#B5FFD9]Resource Info:[] Shows current resources(inc/decrement), unit amount for each team.\n\n\n[#AE00FB]In-game Drawer:[] draws on the screen, drawing location can be each block or unit.\n\n[#B5FFD9]Block Scanner:[] draws turret/wall health and range near the cursor.\n\n[#B5FFD9]Unit Bar:[] draws unit ammo/shield/health under each unit.\n\n[#B5FFD9]Turret Range:[] draws turret range.\n\n[#B5FFD9]Power Link:[] overdraws green power node on blocks which is power-connected with the selected block.\n\n[#B5FFD9]Mass Link:[] draws mass link lines between selected mass driver and another mass driver. 119 | informatis.update-reloadexit = to reload Informatis, exiting is required. Are you sure to exit now? 120 | informatis.update-check = Informatis Update Check 121 | informatis.update = A new Informatis version is avaliable: {0} -------------------------------------------------------------------------------- /assets/bundles/bundle_ko.properties: -------------------------------------------------------------------------------- 1 | ## Setting 2 | setting.shar-ui = HUD 설정 3 | setting.shar-title = Informatis 설정 4 | setting.shar-draw = 덧그리기 설정 5 | 6 | setting.tileinfo.name = 타일 정보 HUD 표시 7 | setting.tileinfo.description = 커서 위 타일 정보를 알 수 있는 타일 정보 HUD를 화면 좌상단에 표시합니다. 8 | setting.schem.name = 설계도 HUD 표시 9 | setting.schem.description = 빠르게 설계도 선택을 할 수 있는 설계도 퀵슬롯 HUD를 화면 우측에 표시합니다. 10 | setting.sidebar.name = 사이드바 HUD 표시 11 | setting.sidebar.description = 다양한 기능들을 제공하는 사이드바 HUD를 화면 좌측에 표시합니다. 12 | setting.elementdebug.name = UI 디버깅 13 | setting.elementdebug.description = 모든 UI 요소의 외곽선을 표시합니다. 14 | setting.hiddenElem.name = 숨겨진 요소 표시 15 | setting.hiddenElem.description = 숨겨진 요소의 외곽선도 표시합니다. 16 | setting.serverfilter.name = 서버 필터 표시 17 | setting.serverfilter.description = 서버 필터 기능을 활성화합니다. (WIP) 18 | 19 | setting.selectopacity.name = 선택 화살표 투명도 20 | setting.selectopacity.description = 선택한 화살표의 투명도를 조절합니다. 21 | setting.baropacity.name = 유닛 바 투명도 22 | setting.baropacity.description = 유닛 바의 투명도를 조절합니다. 23 | 24 | setting.blockBar.name = 블록 바 표시 25 | setting.blockBar.description = 블록 체력 바를 표시합니다. 26 | setting.memoView.name = 메시지 블록 내용 미리보기 27 | setting.memoView.description = 메시지 블록에 기록된 내용물을 한눈에 볼 수 있습니다. 28 | 29 | setting.powerNode.name = 노드 연결선 표시 30 | setting.powerNode.description = 선택한 블록과 전기적으로 연결된 블록들을 선으로 이어서 표시합니다. 31 | setting.massLink.name = 매스 드라이버 연결선 표시 32 | setting.massLink.description = 선택한 매스 드라이버와 연결된 매스 드라이버들을 선으로 이어서 표시합니다. 33 | setting.unitCargoLink.name = 기체 화물 적제소 연결선 표시 34 | setting.unitCargoLink.description = 모든 기체 화물 적제소의 매니폴트의 이동 경로를 표시합니다. 35 | 36 | setting.range.name = 사거리 표시 37 | setting.range.description = 가능한 모든 포탑과 유닛의 사거리를 표시합니다. 38 | setting.blockRange.name = 블록 사거리 표시 39 | setting.blockRange.description = 가능한 모든 포탑 사거리를 표시합니다. 40 | setting.unitRange.name = 유닛 사거리 표시 41 | setting.unitRange.description = 가능한 모든 유닛 사거리를 표시합니다. 42 | setting.invalidRange.name = 유효하지 않은 사거리 표시 43 | setting.invalidRange.description = 당신을 공격할 수 없는 모든 포탑/유닛 사거리를 표시합니다. 44 | setting.airRange.name = 공중 사거리 표시 45 | setting.airRange.description = 공중 유닛을 공격할 수 있는 모든 포탑/유닛 사거리를 표시합니다. 46 | setting.groundRange.name = 지상 사거리 표시 47 | setting.groundRange.description = 지상 유닛을 공격할 수 있는 모든 포탑/유닛 사거리를 표시합니다. 48 | setting.allianceRange.name = 아군 사거리 표시 49 | setting.allianceRange.description = 가능한 모든 아군 포탑/유닛 사거리를 표시합니다. 50 | setting.rangeShader.name = 애니메이션 활성화 51 | setting.rangeShader.description = 사거리를 더 쉽게 보기 위한 애니메이션 쉐이더를 활성화합니다. 비활성화 시 점선이 표시됩니다. 52 | 53 | setting.pathLine.name = 단계 길 표시 54 | setting.pathLine.description = 단계 지상/해상 유닛들의 AI 길 찾기를 가시화합니다. 55 | setting.logicLine.name = 로직 조종선 표시 56 | setting.logicLine.description = 프로세서와 조종 중인 유닛의 관계를 가시화합니다. 57 | setting.unitPathLine.name = 유닛 길 표시 58 | setting.unitPathLine.description = 지상/해상 유닛들의 AI 길 찾기를 가시화합니다. 단계 길 표시보다 더 정확합니다. 59 | setting.commandLine.name = 지휘 길 표시 60 | setting.commandLine.description = 자동 길 찾기 대신 직접 지휘로 인해 이동 중인 유닛들의 경로를 가시화합니다. 61 | setting.unitItem.name = 유닛 아이템 표시 62 | setting.unitItem.description = 유닛이 들고 있는 아이템의 수량을 표시합니다. 63 | setting.unitBar.name = 유닛 바 표시 64 | setting.unitBar.description = 각 유닛의 체력, 탄약, 방어막, 상태이상, 화물에 대해서 간략하게 표시합니다. 65 | 66 | setting.spawnerarrow.name = 스폰포인트 화살표 67 | setting.spawnerarrow.description = 적 단계 생성 지점을 가리키는 화살표를 표시합니다. 68 | setting.select.name = 선택 화살표 표시 69 | setting.select.description = 어떤 유닛이나 블록을 선택했는지 표시합니다. 70 | setting.distanceLine.name = 목표물과의 거리선 표시 71 | setting.distanceLine.description = 목표물과 어느 정도나 멀어졌는지 점선과 숫자로 표시합니다. 72 | 73 | setting.gaycursor.name = 마법 커서 74 | setting.gaycursor.description = 커서를 마법적이게 만듭니다. 75 | 76 | #Hud 77 | hud.schematic-list = 설계도 퀵 슬롯 78 | 79 | #Window 80 | window.unit.name = 유닛 디스플레이 81 | window.wave.name = 단계 디스플레이 82 | window.core.name = 코어 디스플레이 83 | window.player.name = 플레이어 디스플레이 84 | window.tool.name = 도구 디스플레이 [red](WIP)[] 85 | window.editor.name = 맵 편집 디스플레이 [red](WIP)[] 86 | 87 | # UnitWindow - Stats 88 | shar-stat.health = 체력: {0} 89 | shar-stat.shield = 방어막: {0} 90 | shar-stat.payloadCapacity = 화물: {0}²/{1}² 91 | shar-stat.capacity = {0}: {1}/{2} 92 | shar-stat.power = 전력: {0}/{1} 93 | shar-stat.powerIn = 전력 생산량: {0}/s 94 | shar-stat.powerOut = 전력 소모량: {0}/s 95 | shar-stat.ammos = 탄약: {0}/{1} 96 | shar-stat.reload = 재장전: {0}% 97 | shar-stat.progress = 진행도: {0}% 98 | shar-stat.attr = 친화력: x{0} 99 | shar-stat-waveAmount = [lightgray]유닛 수:[] {0} 100 | shar-stat-waveShield = [lightgray]방어막:[] {0} 101 | shar-stat.waveStatus = [lightgray]상태이상:[] 102 | 103 | #ToolWindow - Tool 104 | setting.fogremover.name = 안개 제거하기 105 | setting.fogremover.description = 맵에 있는 모든 안개를 제거합니다!! 106 | setting.camerascaler.name = 카메라 스케일러 107 | setting.camerascaler.description = 카메라 줌을 최대치까지 높힙니다. 108 | setting.autoShoot.name = 자동 사격 활성화 109 | setting.autoShoot.description = 데스크톱에서 모바일의 자동 사격을 사용할 수 있게 됩니다. 110 | 111 | #Other 112 | mode.custom.name = 사용자 지정 113 | empty = [lightgray]<텅 빔>[] 114 | none = <없음> 115 | tiles = 타일 116 | 117 | #Mod 118 | shar-description = 여러 가지 다양한 정보들을 인 게임에서 보여주는 다기능 정보 모드입니다.\n\n[#AE00FB]인 게임 UI:[] 좌측 탭에 위치했으며 커서를 통한 유닛/건물이나 단계 목록, 코어, 자원 정보를 알려줍니다.\n\n[#B5FFD9]유닛/건물 정보:[] 커서로 유닛이나 건물의 정보를 표시합니다.\n\n[#B5FFD9]단계 정보:[] 유닛 종류와 수, 보스 유무를 목록에 담아 보여줍니다. 클릭해서 유닛 정보도 열람할 수 있습니다.\n\n[#B5FFD9]코어 정보:[] 각 팀의 코어 위치와 체력을 보여줍니다. 클릭해서 카메라 위치를 변경할 수 있습니다.\n\n[#B5FFD9]타일 정보:[] 커서 위치의 블록/타일/광물 아이콘과 좌표를 보여줍니다. 남은 단계 유닛도 보여줍니다.\n\n[#B5FFD9]자원 정보:[] 각 팀의 현재 자원(증감치)와 유닛 수를 보여줍니다.\n\n\n[#AE00FB]인 게임 그리기:[] 각 유닛이나 블록 같은 특정 위치에 여러 가지 정보를 덧그립니다.\n\n[#B5FFD9]블록 스캐너:[] 커서 주변의 포탑과 벽의 사거리와 체력을 바로 표시합니다.\n\n[#B5FFD9]유닛 바:[] 각 팀의 유닛의 탄약, 방어막, 체력을 바로 보여줍니다.\n\n[#B5FFD9]포탑 사거리:[] 포탑 사거리를 표시합니다.\n\n[#B5FFD9]전선 연결 표시:[] 커서에 있는 블록과 전력으로 연결된 다른 블록들을 초록색 전선으로 이어서 그립니다.\n\n[#B5FFD9]매스 연결 표시:[] 커서에 있는 드라이버와 연결된 다른 드라이버들을 선으로 이어서 그립니다. 119 | informatis.update-reloadexit = Informatis를 불러오기 위해선 게임이 종료되어야 합니다. 지금 나가시겠습니까? 120 | informatis.update-check = Informatis 업데이트 확인하기 121 | informatis.update = 새로운 Informatis 버전 사용 가능: {0} -------------------------------------------------------------------------------- /assets/bundles/bundle_ru.properties: -------------------------------------------------------------------------------- 1 | ## Setting 2 | setting.shar-ui = HUD UI Settings 3 | setting.shar-title = Настройки informatis 4 | setting.shar-draw = Overdrawing Setting 5 | 6 | setting.powerNode.name = Отображать линию соединения силовых узлов. 7 | setting.powerNode.description = отображает соединения с блоками, находящимися в той же электросети, при помощи линий. 8 | setting.massLink.name = Отображать линию соединения ЭМ катапульт. 9 | setting.massLink.description = отображает все соединения ЭМ катапульт ведущих к/от выбранной. 10 | 11 | setting.unitBar.name = Отображать панель юнита 12 | setting.unitBar.description = информация о здоровье, патронах, щите, эффекте статуса и грузе для каждого юнита. 13 | 14 | setting.select.name = Отображать "выбранную сущность" 15 | setting.select.description = показывает, какой юнит/блок выбран. 16 | setting.distanceLine.name = Display distance line from info target 17 | setting.distanceLine.description = display dotted lines and numbers how far away the target is. 18 | 19 | setting.gaycursor.name = Включить след курсора 20 | setting.gaycursor.description = Создает радужный эффект, следующий за курсором. 21 | 22 | 23 | #Hud 24 | hud.schematic-list = Список схемы 25 | 26 | # Window 27 | 28 | # UnitWindow - Stats 29 | shar-stat.health = Здоровье: {0} 30 | shar-stat.shield = Щит: {0} 31 | shar-stat.payloadCapacity = Груз: {0}² / {1}² 32 | shar-stat.capacity = {0}: {1} / {2} 33 | shar-stat.power = Энергия: {0} / {1} 34 | shar-stat.powerIn = Выработка энергии: {0}/s 35 | shar-stat.powerOut = Потребление энергии: {0}/s 36 | shar-stat.ammos = Патроны: {0} / {1} 37 | shar-stat.reload = Перезарядка: {0}% 38 | shar-stat.progress = Прогресс: {0}% 39 | shar-stat.attr = Эффективность: x{0} 40 | shar-stat-waveAmount = [lightgray]Количество:[] {0} 41 | shar-stat-waveShield = [lightgray]Щит:[] {0} 42 | shar-stat.waveStatus = [lightgray]Статус:[] 43 | 44 | #ToolWindow - Tool 45 | setting.autoShoot.name = Включить автострельбу. 46 | setting.autoShoot.description = [red]не читери, не будь какахой 47 | 48 | #Other 49 | mode.custom.name = Пользовательские 50 | empty = [lightgray]<пусто>[] 51 | none = <ничего> 52 | tiles = плитки 53 | 54 | #Mod 55 | shar-description = Multifunctional information mod that shows various information in game.\n\n[#AE00FB]In-game UI:[] Located at left side, shows unit/build by cursor, wave list, core and resource info.\n\n[#B5FFD9]Unit/Build Info:[] Shows unit/build information by cursor.\n\n[#B5FFD9]Wave Info:[] Shows wave list, including type/amount/boss. can click to view detail info.\n\n[#B5FFD9]Core Info:[] Shows core position/health for each team. can click to change camera.\n\n[#B5FFD9]Tile Info:[] Shows block/floor/ore icon and position on the cursor. if map has wave, shows remaining wave units too.\n\n[#B5FFD9]Resource Info:[] Shows current resources(inc/decrement), unit amount for each team.\n\n\n[#AE00FB]In-game Drawer:[] draws on the screen, drawing location can be each block or unit.\n\n[#B5FFD9]Block Scanner:[] draws turret/wall health and range near the cursor.\n\n[#B5FFD9]Unit Bar:[] draws unit ammo/shield/health under each unit.\n\n[#B5FFD9]Turret Range:[] draws turret range.\n\n[#B5FFD9]Power Link:[] overdraws green power node on blocks which is power-connected with the selected block.\n\n[#B5FFD9]Mass Link:[] draws mass link lines between selected mass driver and another mass driver. 56 | -------------------------------------------------------------------------------- /assets/bundles/bundle_tr.properties: -------------------------------------------------------------------------------- 1 | ## Setting 2 | setting.shar-ui = Arayüz Ayarları 3 | setting.shar-title = informatis Ayarları 4 | setting.shar-draw = Çizim ayarları 5 | 6 | setting.selectopacity.name = Ok Opaklığını Seç 7 | setting.selectopacity.description = Seçim okunun opaklığını ayarlar. 8 | setting.baropacity.name = Can Barı Opaklığı 9 | setting.baropacity.description = Birlik can barının opaklığını ayarlar. 10 | 11 | setting.powerNode.name = Elektriksel Bağlantı Çizgilerini Göster 12 | setting.powerNode.description = Seçili blok ile elektrisel bağlantıda olan bloklar arasında çizgi gösterir. 13 | setting.massLink.name = Kütle Sürücü Bağlantı Çizgilerini Göster 14 | setting.massLink.description = Seçili kütle sürücü bloğuna bağlı olan diğer kütle sürücüler arasında çizgi gösterir. 15 | 16 | setting.rangeShader.name = Alan Animasyonunu Aç 17 | 18 | setting.unitBar.name = Birlik Bilgisi Göster 19 | setting.unitBar.description = Her birlik hakkında can, cephane, kalkan, etki ve taşıma bilgisi gösterir. 20 | 21 | setting.spawnerarrow.name = Dalga Başlangıç Noktasını Göster 22 | setting.select.name = Seçim Okunu Göster 23 | setting.select.description = Seçili birlik/bloğu ok işareti ile gösterir. 24 | setting.distanceLine.name = Seçili Birlik İle Arada Çizgi Göster 25 | setting.distanceLine.description = Hedef ile oyuncu arasındaki mesafeyi kesikli çizgiler ve sayılar ile gösterir. 26 | 27 | setting.gaycursor.name = Fareye Kuyruk Ekle 28 | setting.gaycursor.description = İmlecin altına renk değiştiren bir kuyruk efekti ekler. 29 | 30 | #Hud 31 | hud.schematic-list = Şema listede 32 | 33 | #Window 34 | 35 | # UnitWindow - Stats 36 | shar-stat.health = Sağlık: {0} 37 | shar-stat.shield = Kalkan: {0} 38 | shar-stat.payloadCapacity = Taşıma Kapasitesi: {0}²/{1}² 39 | shar-stat.capacity = {0}: {1}/{2} 40 | shar-stat.power = Güç: {0}/{1} 41 | shar-stat.powerIn = InPower: {0}/s 42 | shar-stat.powerOut = OutPower: {0}/s 43 | shar-stat.ammos = Mermi: {0}/{1} 44 | shar-stat.reload = Yeniden Y.: {0}% 45 | shar-stat.progress = Süreç: {0}% 46 | shar-stat.attr = Attribute: x{0} 47 | shar-stat-waveAmount = [lightgray]Miktar:[] {0} 48 | shar-stat-waveShield = [lightgray]Kalkan:[] {0} 49 | shar-stat.waveStatus = [lightgray]Durum:[] 50 | 51 | #ToolWindow - Tool 52 | 53 | #Other 54 | mode.custom.name = Özel 55 | empty = [lightgray][] 56 | none = 57 | tiles = Kare 58 | 59 | #Mod 60 | shar-description = Oyun içi çeşitli bilgiler gösteren çok-işlevli bilgi modu.\n\n[#AE00FB]Oyun-içi arayüz:[] Sol tarafta bulunur, imleç ile birim/yapı, dalga listesi, çekirdek ve kaynak bilgisi gösterir.\n\n[#B5FFD9]Birim/Yapı Bilgisi:[] İmleç ile yapı/birim bilgisi gösterir.\n\n[#B5FFD9]Dalga bilgisi:[] Tür/miktar/boss bilgilerini de içeren dalga listesi gösterir. Tıklayarak detaylı bilgi alınabilir.\n\n[#B5FFD9]Çekirdek Bilgisi:[] Her takımın çekirdek konum/sağlığını gösterir. Tıklanarak kamera değiştirilebilir.\n\n[#B5FFD9]Blok Bilgisi:[] Farenin yanında blok/yer/maden simgesi ve konumunu gösterir. Eğer mevcut dalga varsa, kalan düşman sayısını da gösterir.\n\n[#B5FFD9]Kaynak Bilgisi:[] Her takımın mevcut madenlerini(azalma/artma), ve birlik sayısını gösterir.\n\n\n[#AE00FB]Oyun-içi Çizici:[] Ekranı çizer, çizim konumu herhangi bir blok veya birim olabilir.\n\n[#B5FFD9]Blok Tarayıcısı:[] Farenin yakınında taret/duvar can ve alanını gösterir.\n\n[#B5FFD9]Birim Barı:[] Her birliğin altında can/mermi/kalkan oranını çizer.\n\n[#B5FFD9]Taret Alanı:[] Taret alanını çizer.\n\n[#B5FFD9]Güç Bağlantısı:[] Seçili blok ile güç bağlantısı olan blokları gösterir.\n\n[#B5FFD9]Kütle Sürücüsü Bağlantısı:[] İki kütle sürücüsü arasındaki bağlantıyı çizer. 61 | -------------------------------------------------------------------------------- /assets/bundles/bundle_uk_UA.properties: -------------------------------------------------------------------------------- 1 | #Settings 2 | setting.shar-ui = Налаштування накладання інтерфейсу 3 | setting.shar-title = Налаштування Informatis 4 | setting.shar-draw = Налаштування промальовки 5 | 6 | setting.schem.name = Показувати HUD схем 7 | setting.schem.description = Показує HUD схем праворуч, що дозволяє швидко їх вибирати. 8 | setting.elementdebug.name = Зневадження елемента 9 | setting.elementdebug.description = Показати всі контури елемента 10 | setting.hiddenElem.name = Показати прихований елемент 11 | setting.hiddenElem.description = Показати всі контури прихованого елемента також. 12 | 13 | setting.selectopacity.name = Прозорість стрілки вибору 14 | setting.selectopacity.description = Встановлює прозорість стрілки вибору. 15 | setting.baropacity.name = Прозорість панелі здоров’я 16 | setting.baropacity.description = Установлює прозорість панелі здоров’я бойових одиниць. 17 | 18 | setting.blockBar.name = Увімкнути панель блоків 19 | setting.blockBar.description = Показати панель здоров'я блоків 20 | setting.memoView.name = Попередній перегляд блоку повідомлення 21 | setting.memoView.description = Попередній перегляд тексту з блоку повідомлення 22 | 23 | setting.powerNode.name = Увімкнути енергетичний вузол 24 | setting.powerNode.description = Показувати з'єднання ліній енергетичних вузлів 25 | setting.massLink.name = Увімкнути електромагнітну катапульту 26 | setting.massLink.description = Показувати лінії з'єднання електромагнітних катапульт 27 | setting.unitCargoLink.name = Показувати з'єднання вантажів-одиниць 28 | setting.unitCargoLink.description = Показувати лінії з'єднання вантажів-одиниць 29 | 30 | setting.blockRange.name = Показувати радіус дії блоків 31 | setting.blockRange.description = Показує радіус дії кожної доступної башти 32 | setting.unitRange.name = Показувати радіус дії одиниці 33 | setting.unitRange.description = Показувати радіус дії кожної доступної одиниці 34 | setting.invalidRange.name = Показувати недійсний радіус дії 35 | setting.invalidRange.description = Показувати радіус дії кожної доступної одиниці 36 | setting.airRange.name = Показувати повітряний радіус дії 37 | setting.airRange.description = Показує кожну доступну башту чи одиницю, яка може стріляти по повітряних одиницях 38 | setting.groundRange.name = Показувати наземний радіус дії 39 | setting.groundRange.description = Показує кожну доступну башту чи одиницю, яка може стріляти по наземних одиницях чи блокам 40 | setting.allianceRange.name = Показувати союзний радіус дії 41 | setting.allianceRange.description = Показує радіус дії башт чи одиниць союзників теж. 42 | setting.rangeShader.name = Увімкнути анімацію 43 | setting.rangeShader.description = Вмикає плавну анімацію в обмін на великі пропуски кадрів. 44 | 45 | setting.pathLine.name = Увімкнути лінію шляху 46 | setting.pathLine.description = Показує шлях ШІ наземних одиниць з хвиль 47 | setting.logicLine.name = Увімкнути лінію логіки 48 | setting.logicLine.description = Показує лінії між логічним процесором та контрольованими ним одиницями 49 | setting.unitPathLine.name = Увімкнути лінію одиниць 50 | setting.unitPathLine.description = Показує шлях ШІ кожної наземної одиниці. 51 | setting.commandLine.name = Увімкнути лінію команд 52 | setting.commandLine.description = Увімкнути лінію шляху одиниць, керовані командами стратегії в реальному часі. 53 | setting.unitItem.name = Увімкнути предмети одиниць 54 | setting.unitItem.description = Показує кількість предметів під кожною одиницею. 55 | setting.unitBar.name = Увімкнути панель одиниць 56 | setting.unitBar.description = Показує панель здоров'я під кожною одиницею. 57 | 58 | setting.spawnerarrow.name = Вказує точку появи хвиль. 59 | setting.spawnerarrow.description = Показує стрілку, направлену на точку появи хвиль. 60 | setting.select.name = Показувати стрілку вибору 61 | setting.select.description = Показує вибраний блок чи одиницю. 62 | setting.distanceLine.name = Показати лінію, що показує відстань до вибраної цілі 63 | setting.distanceLine.description = Показує пунктирні лінії й числа, щоб показати відстань до цілі. 64 | 65 | setting.gaycursor.name = Увімкнути ефект веселки під курсором 66 | setting.gaycursor.description = Створює ефект веселки під курсором миші. 67 | 68 | #Hud 69 | hud.schematic-list = Перелік схем 70 | 71 | #Window 72 | window.unit.name = Показ одиниць 73 | window.wave.name = Показ хвиль 74 | window.core.name = Показ ядра 75 | window.player.name = Показ гравця 76 | window.tool.name = Показ інструментів[red](У розробці)[] 77 | window.editor.name = Показ редактора мап [red](У розробці)[] 78 | 79 | # UnitWindow - Stats 80 | shar-stat.health = Здоров'я: {0} 81 | shar-stat.shield = Щит: {0} 82 | shar-stat.payloadCapacity = Вантаж: {0}²/{1}² 83 | shar-stat.capacity = {0}: {1}/{2} 84 | shar-stat.power = Енергія: {0}/{1} 85 | shar-stat.powerIn = Виробництво енергії: {0}/s 86 | shar-stat.powerOut = Споживання енергії: {0}/s 87 | shar-stat.ammos = Патрони: {0}/{1} 88 | shar-stat.reload = Перезаряджання: {0}% 89 | shar-stat.progress = Прогрес: {0}% 90 | shar-stat.attr = Ефективність: x{0} 91 | shar-stat-waveAmount = [lightgray]Кількість ворогів:[] {0} 92 | shar-stat-waveShield = [lightgray]Щит:[] {0} 93 | shar-stat.waveStatus = [lightgray]Статус:[] 94 | 95 | #ToolWindow - Tool 96 | setting.autoShoot.name = Увімкнути автострільбу 97 | setting.autoShoot.description = Не треба, ти ж не гакер. 98 | 99 | #Other 100 | mode.custom.name = Користувацький\nрежим гри 101 | empty = [lightgray]<Порожньо>[] 102 | none = <нічого> 103 | tiles = плиток 104 | 105 | #Mod 106 | shar-description = Багатофункціональна інформаційна модифікація, яка показує різні види інформації в грі.\n\n~~~~~\nПерекладено організацією [blue]Ukrainian[][yellow]Mindustry[]\n~~~~~\n\n[#AE00FB]Ігровий інтерфейс:[] розташований ліворуч, показує інформацію про одиницю чи будівлю, на яку наведений ваш, список хвиль, інформацію про ресурси та ядро.\n\n[#B5FFD9]Інформація про одиницю чи будівлю:[] показує інформацію про одиницю чи будівлю, на яку наведений ваш курсор.\n\n[#B5FFD9]Інформація про хвилі:[] показує список хвиль, включаючи їхній тип, кількість та фінального боса. Можна натиснути для перегляду подробиць.\n\n[#B5FFD9]Інформація про ядро:[] показує розташування та здоров'я ядра для кожної команди. Наведіть та натисніть на нього, щоб опинитися біля вибраного союзного ядра.\n\n[#B5FFD9]Інформація про плитки:[] показує значок та позицію блоку, поверхні або руди, на яку наведений ваш курсор. Якщо мапа має хвилі, то також показує залишок ворожих бойових одиниць.\n\n[#B5FFD9]Інформація про ресурси:[] показує поточні ресурси та їхнє збільшення чи зменшення, кількість одиниць кожної команди.\n\n\n[#AE00FB]Ігровий малювальник:[] малює на екрані, кінцевою позицією може бути блок чи одиниця.\n\n[#B5FFD9]Сканер блоків:[] показує здоров'я та радіус дії башти чи стіни, на яку наведений ваш курсор.\n\n[#B5FFD9]Панель одиниць:[] показує під кожною одиницею її боєприпаси, щит та здоров'я.\n\n[#B5FFD9]Радіус дії:[] показує радіус дії башти.\n\n[#B5FFD9]З'єднання енергетичних ліній:[] перемальовує колір енергетичних з'єднань на блоках, які підключені до вибраного вами блоку.\n\n[#B5FFD9]Пунктирне з'єднання:[] малює пунктирні лінії з'єднання між електромагнітними катапультами. 107 | -------------------------------------------------------------------------------- /assets/bundles/bundle_zh_CN.properties: -------------------------------------------------------------------------------- 1 | ## Setting 2 | setting.shar-ui = HUD UI设置 3 | setting.shar-title = 数据信息Mod设置 4 | setting.shar-draw = 绘制设置 5 | 6 | setting.tileinfo.name = 显示方块信息HUD 7 | setting.tileinfo.description = 在左上方显示方块信息HUD, 显示当前光标所方块的信息. 8 | setting.schem.name = 显示蓝图HUD 9 | setting.schem.description = 在右侧显示蓝图HUD, 有助于快速选择蓝图. 10 | setting.sidebar.name = 显示侧栏HUD 11 | setting.sidebar.description = 在左侧显示侧栏HUD,,提供各种功能. 12 | setting.elementdebug.name = 元素Debug 13 | setting.elementdebug.description = 显示所有元素轮廓 14 | setting.hiddenElem.name = 显示隐藏的元素 15 | setting.hiddenElem.description = 显示隐藏的元素轮廓. 16 | setting.serverfilter.name = 启用服务器筛选 17 | setting.serverfilter.description = 激活服务器筛选系统 (WIP) 18 | 19 | setting.selectopacity.name = 指示箭头的不透明度 20 | setting.selectopacity.description = 设置指示箭头的不透明度. 21 | setting.baropacity.name = 生命栏的不透明度 22 | setting.baropacity.description = 设置生命栏的不透明度. 23 | 24 | setting.blockBar.name = 启用方块栏 25 | setting.blockBar.description = 显示方块生命栏 26 | setting.memoView.name = 预览信息板 27 | setting.memoView.description = 立即预览信息板的文本 28 | 29 | setting.powerNode.name = 启用电力节点 30 | setting.powerNode.description = 显示电力节点连接线 31 | setting.massLink.name = 启用质量驱动器 32 | setting.massLink.description = 显示质量驱动器连接线 33 | setting.unitCargoLink.name = 显示单位运载路径 34 | setting.unitCargoLink.description = 显示单位运载目标方块的路径 35 | 36 | setting.range.name = 显示范围 37 | setting.range.description = 显示每个可用炮塔/单位的范围 38 | setting.blockRange.name = 显示方块范围 39 | setting.blockRange.description = 显示每个可用炮塔的范围 40 | setting.unitRange.name = 显示单位范围 41 | setting.unitRange.description = 显示每个可用单位的范围 42 | setting.invalidRange.name = 显示无效的范围 43 | setting.invalidRange.description = 显示因各种原因而无法攻击而无效的范围 44 | setting.airRange.name = 显示对空范围 45 | setting.airRange.description = 显示可以瞄准空中单位的每个可用炮塔/单位 46 | setting.groundRange.name = 显示对地范围 47 | setting.groundRange.description = 显示可以瞄准地面单位或方块的每个可用炮塔/单位 48 | setting.allianceRange.name = 显示己方范围 49 | setting.allianceRange.description = 显示己方炮塔/单位的范围 50 | setting.rangeShader.name = 启用动画 51 | setting.rangeShader.description = 使用动画着色器以使其易于查看 52 | 53 | setting.pathLine.name = 启用路径线 54 | setting.pathLine.description = 显示波次中地面单位AI的路径 55 | setting.logicLine.name = 启用逻辑线 56 | setting.logicLine.description = 在逻辑处理器和受控单位之间显示连接线 57 | setting.unitPathLine.name = 启用单位线 58 | setting.unitPathLine.description = 显示地面单位的AI路径 59 | setting.commandLine.name = 启用命令线 60 | setting.cocmmandLine.description = 显示由RTS命令控制的单位的行进路径线 61 | setting.unitItem.name = 启用单位物品 62 | setting.unitItem.description = 显示单位的物品数量 63 | setting.unitBar.name = 启用单位栏 64 | setting.unitBar.description = 显示单位的生命栏 65 | 66 | setting.spawnerarrow.name = 指示波次生成点 67 | setting.spawnerarrow.description = 显示指向波次生成点的箭头. 68 | setting.select.name = 指示箭头 69 | setting.select.description = 若启用此项, 则显示会提示你选择了哪个方块的箭头. 70 | setting.distanceLine.name = 显示被锁定的目标的信息和距离线 71 | setting.distanceLine.description = 用虚线和数字显示你与目标之间的距离. 72 | 73 | setting.gaycursor.name = 魔法光标 74 | setting.gaycursor.description = 让你的光标更加的神奇! 75 | 76 | #Hud 77 | hud.schematic-list = 蓝图列表 78 | 79 | #Window 80 | window.unit.name = 单位显示 81 | window.wave.name = 波次显示 82 | window.core.name = 核心显示 83 | window.player.name = 玩家显示 84 | window.tool.name = 工具显示 [red](WIP)[] 85 | window.editor.name = 地图编辑器显示 [red](WIP)[] 86 | 87 | # UnitWindow - Stats 88 | shar-stat.health = 生命值: {0} 89 | shar-stat.shield = 护盾容量: {0} 90 | shar-stat.payloadCapacity = 载荷容量: {0}²/{1}² 91 | shar-stat.capacity = {0}: {1}/{2} 92 | shar-stat.power = 电力: {0}/{1} 93 | shar-stat.powerIn = 发电量: {0}/s 94 | shar-stat.powerOut = 耗电量: {0}/s 95 | shar-stat.ammos = 弹药: {0}/{1} 96 | shar-stat.reload = 装填进度: {0}% 97 | shar-stat.progress = 进度: {0}% 98 | shar-stat.attr = 效率: x{0} 99 | shar-stat-waveAmount = [lightgray]敌人数量:[] {0} 100 | shar-stat-waveShield = [lightgray]护盾:[] {0} 101 | shar-stat.waveStatus = [lightgray]状态效果:[] 102 | 103 | #ToolWindow - Tool 104 | setting.fogremover.name = 移除迷雾 105 | setting.fogremover.description = 移除世界中的所有迷雾! 106 | setting.camerascaler.name = 相机缩放 107 | setting.camerascaler.description = 将相机缩放比例设为最大. 108 | setting.autoShoot.name = 启用自动射击 109 | setting.autoShoot.description = 这不好 110 | 111 | #Other 112 | mode.custom.name = 自定义 113 | empty = [lightgray]<空>[] 114 | none = <无> 115 | tiles = 方块 116 | 117 | #Mod 118 | shar-description = 在游戏内显示各种数据信息的多功能Mod.\n\n[#AE00FB]游戏中的UI:[] 位于左侧, 显示波次列表、核心资源信息和光标所指的单位和方块信息\n\n[#B5FFD9]单位/方块信息:[] 显示光标所指的单位和方块信息.\n\n[#B5FFD9]波次信息:[] 显示波次列表, 包括单位种类/数量/Boss. 可单击查看详细信息\n\n[#B5FFD9]核心信息:[] 显示每个队伍的核心位置/生命值. 可单击以将镜头移动至核心位置.\n\n[#B5FFD9]方块信息:[] 显示光标位置的方块/地板方块/矿石图标和位置. 如果地图有怪物波次设置, 则同样显示剩余的波次单位.\n\n[#B5FFD9]资源信息:[] 显示每个队伍的当前资源(包括资源消耗量)和单位.\n\n\n[#AE00FB]绘制器:[] 在屏幕上进行绘制, 绘制位置可以是方块或单位.\n\n[#B5FFD9]方块扫描器:[] 绘制光标附近炮塔和墙壁的生命值和剩余弹药.\n\n[#B5FFD9]单位UI:[] 绘制每个单位的弹药/护盾/生命值.\n\n[#B5FFD9]炮塔范围:[] 绘制炮塔的攻击范围.\n\n[#B5FFD9]电力链接:[] 在已选的耗电方块和与其有关联的电源方块之间进行连线, 用绿色线进行显示.\n\n[#B5FFD9]质驱链接:[] 在已选的质量驱动器和与其有关联的质量驱动器之间进行连线. 119 | informatis.update-reloadexit = 需要退出以重新加载数据信息Mod. 你确定要现在退出吗? 120 | informatis.update-check = 数据信息Mod升级检查 121 | informatis.update = 一个新的数据信息Mod版本现已可用: {0} 122 | -------------------------------------------------------------------------------- /assets/mod.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "informatis", 3 | "displayName": "Informatis", 4 | "author": "Sharlotte", 5 | "description": "The mod displays more information in-game, such as unit/building, wave, core, tile, item/unit total info etc", 6 | "subtitle": "hacky ui tool", 7 | "version": "1.9.2", 8 | "main": "informatis.Informatis", 9 | "minGameVersion": "145.1", 10 | "dependencies": [], 11 | "hidden": true, 12 | "java": true 13 | } 14 | -------------------------------------------------------------------------------- /assets/shaders/line.frag: -------------------------------------------------------------------------------- 1 | #define HIGHP 2 | 3 | uniform sampler2D u_texture; 4 | uniform vec2 u_texsize; 5 | uniform vec2 u_invsize; 6 | uniform float u_time; 7 | uniform float u_dp; 8 | uniform vec2 u_offset; 9 | varying vec2 v_texCoords; 10 | 11 | void main(){ 12 | vec2 T = v_texCoords.xy; 13 | vec2 coords = (T * u_texsize) + u_offset; 14 | vec4 color = texture2D(u_texture, T); 15 | vec2 v = u_invsize; 16 | vec4 maxed = max(max(max( 17 | texture2D(u_texture, T + vec2(0, 2.0) * v), 18 | texture2D(u_texture, T + vec2(0, -2.0) * v)), 19 | texture2D(u_texture, T + vec2(2.0, 0) * v)), 20 | texture2D(u_texture, T + vec2(-2.0, 0) * v)); 21 | 22 | color.a *= (0.5 + abs(sin(u_time / 15.0)) * .05 + 0.2 * (step(mod(coords.x / u_dp + coords.y / u_dp + u_time / 4.0, 10.0), 3.0))); 23 | gl_FragColor = color; 24 | } -------------------------------------------------------------------------------- /assets/shaders/transparent.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D u_texture; 2 | uniform float u_alpha; 3 | 4 | varying vec2 v_texCoords; 5 | 6 | void main(){ 7 | vec4 color = texture2D(u_texture, v_texCoords); 8 | color.a *= u_alpha; 9 | gl_FragColor = color; 10 | } -------------------------------------------------------------------------------- /assets/shaders/turretrange.frag: -------------------------------------------------------------------------------- 1 | #define HIGHP 2 | 3 | uniform sampler2D u_texture; 4 | uniform vec2 u_texsize; 5 | uniform vec2 u_invsize; 6 | uniform float u_time; 7 | uniform float u_dp; 8 | uniform vec2 u_offset; 9 | varying vec2 v_texCoords; 10 | 11 | void main(){ 12 | vec2 T = v_texCoords.xy; 13 | vec2 coords = (T * u_texsize) + u_offset; 14 | vec4 color = texture2D(u_texture, T); 15 | vec2 v = u_invsize; 16 | vec4 maxed = max(max(max( 17 | texture2D(u_texture, T + vec2(0, 2.0) * v), 18 | texture2D(u_texture, T + vec2(0, -2.0) * v)), 19 | texture2D(u_texture, T + vec2(2.0, 0) * v)), 20 | texture2D(u_texture, T + vec2(-2.0, 0) * v)); 21 | 22 | if(texture2D(u_texture, T).a < 0.9 && maxed.a > 0.9){ 23 | gl_FragColor = vec4(maxed.rgb, maxed.a * 100.0); 24 | }else{ 25 | color.a *= (0.37 + abs(sin(u_time / 15.0)) * .05 + 0.2 * (step(mod(coords.x / u_dp + coords.y / u_dp + u_time / 4.0, 10.0), 3.0))); 26 | gl_FragColor = color; 27 | } 28 | } -------------------------------------------------------------------------------- /assets/sprites/effects/Slaser-end.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sharlottes/Informatis/eaa67ce9128f52bd19cf736be6db5e98d62e7257/assets/sprites/effects/Slaser-end.png -------------------------------------------------------------------------------- /assets/sprites/effects/Slaser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sharlottes/Informatis/eaa67ce9128f52bd19cf736be6db5e98d62e7257/assets/sprites/effects/Slaser.png -------------------------------------------------------------------------------- /assets/sprites/ui/bars/barS-top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sharlottes/Informatis/eaa67ce9128f52bd19cf736be6db5e98d62e7257/assets/sprites/ui/bars/barS-top.png -------------------------------------------------------------------------------- /assets/sprites/ui/bars/barS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sharlottes/Informatis/eaa67ce9128f52bd19cf736be6db5e98d62e7257/assets/sprites/ui/bars/barS.png -------------------------------------------------------------------------------- /assets/sprites/ui/bars/onepx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sharlottes/Informatis/eaa67ce9128f52bd19cf736be6db5e98d62e7257/assets/sprites/ui/bars/onepx.png -------------------------------------------------------------------------------- /assets/sprites/ui/bars/sidebar.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sharlottes/Informatis/eaa67ce9128f52bd19cf736be6db5e98d62e7257/assets/sprites/ui/bars/sidebar.9.png -------------------------------------------------------------------------------- /assets/sprites/ui/icons/ammo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sharlottes/Informatis/eaa67ce9128f52bd19cf736be6db5e98d62e7257/assets/sprites/ui/icons/ammo.png -------------------------------------------------------------------------------- /assets/sprites/ui/icons/health.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sharlottes/Informatis/eaa67ce9128f52bd19cf736be6db5e98d62e7257/assets/sprites/ui/icons/health.png -------------------------------------------------------------------------------- /assets/sprites/ui/icons/item.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sharlottes/Informatis/eaa67ce9128f52bd19cf736be6db5e98d62e7257/assets/sprites/ui/icons/item.png -------------------------------------------------------------------------------- /assets/sprites/ui/icons/liquid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sharlottes/Informatis/eaa67ce9128f52bd19cf736be6db5e98d62e7257/assets/sprites/ui/icons/liquid.png -------------------------------------------------------------------------------- /assets/sprites/ui/icons/power.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sharlottes/Informatis/eaa67ce9128f52bd19cf736be6db5e98d62e7257/assets/sprites/ui/icons/power.png -------------------------------------------------------------------------------- /assets/sprites/ui/icons/reload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sharlottes/Informatis/eaa67ce9128f52bd19cf736be6db5e98d62e7257/assets/sprites/ui/icons/reload.png -------------------------------------------------------------------------------- /assets/sprites/ui/icons/shield.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sharlottes/Informatis/eaa67ce9128f52bd19cf736be6db5e98d62e7257/assets/sprites/ui/icons/shield.png -------------------------------------------------------------------------------- /build.bat: -------------------------------------------------------------------------------- 1 | @rem put this project's path into PATH_FROM 2 | setlocal 3 | set PATH_FROM=C:\Users\user\Documents\GitHub 4 | @rem put your mindustry local path into PATH_TO 5 | setlocal 6 | set PATH_TO=C:\Users\user\AppData\Roaming\Mindustry 7 | 8 | @rem clean up 9 | if exist %PATH_TO%\mods\SharlottesInformatis*.zip del %PATH_TO%\mods\SharlottesInformatis*.zip 10 | if exist %PATH_TO%\mods\InformatisDesktop.jar del %PATH_TO%\mods\InformatisDesktop.jar 11 | 12 | xcopy %PATH_FROM%\Informatis\build\libs\InformatisDesktop.jar %PATH_TO%\mods\ /k /y 13 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "java" 2 | 3 | sourceSets { 4 | main.java.srcDir("src/") 5 | main.resources.srcDir("assets/") 6 | } 7 | 8 | ext { 9 | mindustryVersion = 'v145.1' 10 | artifactFilename = "Informatis" 11 | sdkRoot = System.getenv("ANDROID_HOME") ?: System.getenv("ANDROID_SDK_ROOT") 12 | } 13 | 14 | java { 15 | targetCompatibility = 8 16 | sourceCompatibility = JavaVersion.VERSION_17 17 | } 18 | 19 | repositories { 20 | mavenCentral() 21 | maven { url "https://raw.githubusercontent.com/Zelaux/MindustryRepo/master/repository" } 22 | maven { url "https://jitpack.io" } 23 | } 24 | 25 | dependencies { 26 | compileOnly "com.github.Anuken.Mindustry:core:$mindustryVersion" 27 | compileOnly "com.github.Anuken.Arc:arc-core:$mindustryVersion" 28 | 29 | annotationProcessor 'com.github.Anuken:jabel:0.8.0' 30 | } 31 | 32 | jar { 33 | archiveFileName = "${artifactFilename}Desktop.jar" 34 | 35 | from{ 36 | configurations.runtimeClasspath.collect{ it.isDirectory() ? it : zipTree(it) } 37 | } 38 | } 39 | 40 | tasks.register('jarAndroid', Jar) { 41 | dependsOn "jar" 42 | 43 | doLast{ 44 | if(!sdkRoot || !new File(sdkRoot.toString()).exists()) throw new GradleException("No valid Android SDK found. Ensure that ANDROID_HOME is set to your Android SDK directory.") 45 | 46 | def platformRoot = new File("$sdkRoot/platforms/").listFiles().sort().reverse().find{ f -> new File(f, "android.jar").exists()} 47 | 48 | if(!platformRoot) throw new GradleException("No android.jar found. Ensure that you have an Android platform installed.") 49 | 50 | //collect dependencies needed for de-sugaring 51 | def dependencies = (configurations.compileClasspath.asList() + configurations.runtimeClasspath.asList() + [new File(platformRoot, "android.jar")]).collect{ "--classpath $it.path" }.join(" ") 52 | 53 | //dex and desugar files - this requires d8 in your PATH 54 | "d8 $dependencies --min-api 14 --output ${artifactFilename}Android.jar ${artifactFilename}Desktop.jar" 55 | .execute(null, new File("$buildDir/libs")).waitForProcessOutput(System.out, System.err) 56 | } 57 | } 58 | 59 | tasks.register('deploy', Jar) { 60 | dependsOn "jarAndroid" 61 | dependsOn "jar" 62 | 63 | archiveFileName.set("${artifactFilename}.jar") 64 | 65 | from{ [zipTree("$buildDir/libs/${artifactFilename}Desktop.jar"), zipTree("$buildDir/libs/${artifactFilename}Android.jar")] } 66 | 67 | doLast{ 68 | delete{ 69 | delete "$buildDir/libs/${artifactFilename}Desktop.jar" 70 | delete "$buildDir/libs/${artifactFilename}Android.jar" 71 | } 72 | } 73 | } 74 | 75 | tasks.withType(JavaCompile).configureEach { 76 | options.encoding = "UTF-8" 77 | options.compilerArgs += ["-Xlint:all"] 78 | if (JavaVersion.current() != JavaVersion.VERSION_1_8) { 79 | options.compilerArgs.addAll(['--release', '8']) 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sharlottes/Informatis/eaa67ce9128f52bd19cf736be6db5e98d62e7257/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-7.4-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | Please set the JAVA_HOME variable in your environment to match the 97 | location of your Java installation." 98 | fi 99 | else 100 | JAVACMD="java" 101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 102 | Please set the JAVA_HOME variable in your environment to match the 103 | location of your Java installation." 104 | fi 105 | 106 | # Increase the maximum file descriptors if we can. 107 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 108 | MAX_FD_LIMIT=`ulimit -H -n` 109 | if [ $? -eq 0 ] ; then 110 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 111 | MAX_FD="$MAX_FD_LIMIT" 112 | fi 113 | ulimit -n $MAX_FD 114 | if [ $? -ne 0 ] ; then 115 | warn "Could not set maximum file descriptor limit: $MAX_FD" 116 | fi 117 | else 118 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 119 | fi 120 | fi 121 | 122 | # For Darwin, add options to specify how the application appears in the dock 123 | if $darwin; then 124 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 125 | fi 126 | 127 | # For Cygwin or MSYS, switch paths to Windows format before running java 128 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 129 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 130 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 131 | 132 | JAVACMD=`cygpath --unix "$JAVACMD"` 133 | 134 | # We build the pattern for arguments to be converted via cygpath 135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 136 | SEP="" 137 | for dir in $ROOTDIRSRAW ; do 138 | ROOTDIRS="$ROOTDIRS$SEP$dir" 139 | SEP="|" 140 | done 141 | OURCYGPATTERN="(^($ROOTDIRS))" 142 | # Add a user-defined pattern to the cygpath arguments 143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 145 | fi 146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 147 | i=0 148 | for arg in "$@" ; do 149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 151 | 152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 154 | else 155 | eval `echo args$i`="\"$arg\"" 156 | fi 157 | i=`expr $i + 1` 158 | done 159 | case $i in 160 | 0) set -- ;; 161 | 1) set -- "$args0" ;; 162 | 2) set -- "$args0" "$args1" ;; 163 | 3) set -- "$args0" "$args1" "$args2" ;; 164 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 165 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 166 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 167 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 168 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 169 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 170 | esac 171 | fi 172 | 173 | # Escape application args 174 | save () { 175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 176 | echo " " 177 | } 178 | APP_ARGS=`save "$@"` 179 | 180 | # Collect all arguments for the java command, following the shell quoting and substitution rules 181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 182 | 183 | exec "$JAVACMD" "$@" -------------------------------------------------------------------------------- /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 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | 44 | if "%ERRORLEVEL%" == "0" goto init 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 init 59 | 60 | 61 | echo. 62 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 63 | echo. 64 | echo Please set the JAVA_HOME variable in your environment to match the 65 | echo location of your Java installation. 66 | 67 | goto fail 68 | 69 | :init 70 | @rem Get command-line arguments, handling Windows variants 71 | 72 | if not "%OS%" == "Windows_NT" goto win9xME_args 73 | 74 | :win9xME_args 75 | @rem Slurp the command line arguments. 76 | set CMD_LINE_ARGS= 77 | set _SKIP=2 78 | 79 | :win9xME_args_slurp 80 | if "x%~1" == "x" goto execute 81 | 82 | set CMD_LINE_ARGS=%* 83 | 84 | :execute 85 | @rem Setup the command line 86 | 87 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 88 | 89 | 90 | @rem Execute Gradle 91 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 92 | 93 | 94 | :end 95 | @rem End local scope for the variables with windows NT shell 96 | if "%ERRORLEVEL%"=="0" goto mainEnd 97 | 98 | :fail 99 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 100 | rem the _cmd.exe /c_ return code! 101 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 102 | exit /b 1 103 | 104 | :mainEnd 105 | if "%OS%"=="Windows_NT" endlocal 106 | 107 | :omega -------------------------------------------------------------------------------- /src/informatis/Informatis.java: -------------------------------------------------------------------------------- 1 | package informatis; 2 | 3 | import informatis.core.setting.SharSettingUI; 4 | import informatis.core.UpdateChecker; 5 | import informatis.ui.fragments.sidebar.windows.tools.draws.OverDrawManager; 6 | import informatis.ui.fragments.sidebar.windows.tools.tools.ToolManager; 7 | import informatis.ui.fragments.sidebar.dialogs.DialogManager; 8 | import informatis.ui.fragments.sidebar.windows.*; 9 | import informatis.ui.fragments.FragmentManager; 10 | import informatis.core.ModMetadata; 11 | 12 | import mindustry.game.EventType.*; 13 | import mindustry.mod.*; 14 | import arc.*; 15 | 16 | public class Informatis extends Mod { 17 | @Override 18 | public void init(){ 19 | Events.on(ClientLoadEvent.class, e -> { 20 | ModMetadata.init(); 21 | SharSettingUI.init(); 22 | WindowManager.init(); 23 | DialogManager.init(); 24 | FragmentManager.init(); 25 | OverDrawManager.init(); 26 | ToolManager.init(); 27 | SVars.init(); 28 | UpdateChecker.init(); 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/informatis/SUtils.java: -------------------------------------------------------------------------------- 1 | package informatis; 2 | 3 | import arc.Core; 4 | import arc.func.*; 5 | import arc.graphics.g2d.*; 6 | import arc.math.geom.Position; 7 | import arc.scene.style.*; 8 | import arc.struct.Seq; 9 | import arc.util.*; 10 | import informatis.core.Pathfinder; 11 | import mindustry.Vars; 12 | import mindustry.core.UI; 13 | import mindustry.game.Team; 14 | import mindustry.gen.*; 15 | import mindustry.input.DesktopInput; 16 | import mindustry.world.Tile; 17 | 18 | import java.util.Iterator; 19 | 20 | import static arc.Core.*; 21 | import static mindustry.Vars.*; 22 | 23 | public class SUtils { 24 | /** 25 | * loop iterator with "final i", which can be referenced in callback scope. 26 | * @param iterator - just an iterator to loop. 27 | * @param callback - callback function with "i" parameter. 28 | */ 29 | public static void loop(Iterator iterator, Cons2 callback) { 30 | SUtils.loop(iterator, (t, i) -> { 31 | callback.get(t, i); 32 | return false; 33 | }); 34 | } 35 | public static void loop(Iterator iterator, Func2 callback) { 36 | int i = 0; 37 | while(iterator.hasNext()) { 38 | if(callback.get(iterator.next(), i)) break; 39 | i++; 40 | } 41 | } 42 | 43 | /** 44 | * loop array with "final i", which can be referenced in callback scope. 45 | * @param array - just an array object to loop. 46 | * @param callback - callback function with "i" parameter. 47 | */ 48 | public static void loop(T[] array, Cons2 callback) { 49 | SUtils.loop(array, (t, i) -> { 50 | callback.get(t, i); 51 | return false; 52 | }); 53 | } 54 | public static void loop(T[] array, Func2 callback) { 55 | for(int i = 0; i < array.length; i++) { 56 | if(callback.get(array[i], i)) break; 57 | } 58 | } 59 | 60 | /** 61 | * loop iterable object with "final i", which can be referenced in callback scope. 62 | * @param iterable - just an iterable object to loop. 63 | * @param callback - callback function with "i" parameter. 64 | */ 65 | public static void loop(Iterable iterable, Cons2 callback) { 66 | SUtils.loop(iterable, (t, i) -> { 67 | callback.get(t, i); 68 | return false; 69 | }); 70 | } 71 | public static void loop(Iterable iterable, Func2 callback) { 72 | int i = 0; 73 | for(T t : iterable) { 74 | if(callback.get(t, i)) break; 75 | i++; 76 | } 77 | } 78 | 79 | /** 80 | * for-loop with "final i", which can be referenced in callback scope. 81 | * @param number - max loop count number. 82 | * @param callback - callback function with "i" parameter. 83 | */ 84 | public static void loop(int number, Cons callback) { 85 | SUtils.loop(number, (i) -> { 86 | callback.get(i); 87 | return false; 88 | }); 89 | } 90 | public static void loop(int number, Func callback) { 91 | for(int i = 0; i < number; i++) { 92 | if(callback.get(i)) break; 93 | } 94 | } 95 | 96 | public static RT[] pickFromArray(T[] array, Class returnType, Boolf condition) { 97 | Seq list = new Seq<>(); 98 | for(int i = 0; i < array.length; i++) { 99 | if(condition.get(i)) list.add((RT) array[i]); 100 | } 101 | return list.toArray(returnType); 102 | } 103 | 104 | /** 105 | * move camera to given coordination 106 | * @param x world unit x 107 | * @param y world unit y 108 | */ 109 | public static void moveCamera(float x, float y) { 110 | if(control.input instanceof DesktopInput) 111 | ((DesktopInput) control.input).panning = true; 112 | Core.camera.position.set(x, y); 113 | } 114 | /** 115 | * move camera to given coordination 116 | * @param pos world unit coordination 117 | */ 118 | public static void moveCamera(Position pos) { 119 | moveCamera(pos.getX(), pos.getY()); 120 | } 121 | @SuppressWarnings("unchecked") 122 | public static T getTarget(){ 123 | Seq units = Groups.unit.intersect(input.mouseWorldX(), input.mouseWorldY(), 4, 4); // well, 0.5tile is enough to search them 124 | if(units.size > 0) 125 | return (T) units.peek(); //if there is unit, return it. 126 | else if(getTile() != null && getTile().build != null) 127 | return (T) getTile().build; //if there isn't unit but there is build, return it. 128 | else if(player.unit() instanceof BlockUnitUnit b && b.tile() != null) 129 | return (T)b.tile(); 130 | return (T) player.unit(); //if there aren't unit and not build, return player. 131 | } 132 | 133 | @Nullable 134 | public static Tile getTile(){ 135 | return Vars.world.tileWorld(input.mouseWorldX(), input.mouseWorldY()); 136 | } 137 | 138 | public static Drawable getDrawable(TextureAtlas.AtlasRegion region, int left, int right, int top, int bottom){ 139 | int[] splits = {left, right, top, bottom}; 140 | int[] pads = region.pads; 141 | NinePatch patch = new NinePatch(region, splits[0], splits[1], splits[2], splits[3]); 142 | if(pads != null) patch.setPadding(pads[0], pads[1], pads[2], pads[3]); 143 | 144 | return new ScaledNinePatchDrawable(patch, 1); 145 | } 146 | 147 | public static String formatNumber(T number){ 148 | return formatNumber(number, 1); 149 | } 150 | public static String formatNumber(T number, int step){ 151 | if(number.intValue() >= 1000) return UI.formatAmount(number.longValue()); 152 | if(number instanceof Integer || number.longValue() % 10 == 0) return String.valueOf(number.intValue()); 153 | return Strings.fixed(number.floatValue(), step); 154 | } 155 | 156 | public static Seq generatePathTiles() { 157 | Seq pathTiles = new Seq<>(); 158 | 159 | spawner.getSpawns().each(tile -> pathTiles.addAll(generatePathTiles(tile))); 160 | 161 | return pathTiles; 162 | } 163 | public static Seq generatePathTiles(Tile startTile) { 164 | Seq pathTiles = new Seq<>(); 165 | 166 | for(int p = 0; p < 3; p++) { 167 | getNextTile(startTile, SVars.pathfinder.getField(state.rules.waveTeam, p, Pathfinder.fieldCore), pathTiles); 168 | } 169 | 170 | return pathTiles; 171 | } 172 | 173 | public static Seq generatePathTiles(Tile startTile, Team team, int type) { 174 | Seq pathTiles = new Seq<>(); 175 | 176 | getNextTile(startTile, SVars.pathfinder.getField(team, type, Pathfinder.fieldCore), pathTiles); 177 | 178 | return pathTiles; 179 | } 180 | 181 | static void getNextTile(Tile tile, Pathfinder.Flowfield field, Seq pathTiles) { 182 | Tile nextTile = SVars.pathfinder.getTargetTile(tile, field); 183 | pathTiles.add(nextTile); 184 | if(nextTile == tile || nextTile == null) return; 185 | getNextTile(nextTile, field, pathTiles); 186 | } 187 | 188 | public static boolean isInCamera(float x, float y, float size) { 189 | Tmp.r2.setCentered(x, y, size); 190 | return Tmp.r1.overlaps(Tmp.r2); 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /src/informatis/SVars.java: -------------------------------------------------------------------------------- 1 | package informatis; 2 | 3 | import arc.Events; 4 | import informatis.shaders.*; 5 | import arc.graphics.g2d.TextureRegion; 6 | import mindustry.entities.abilities.ShieldRegenFieldAbility; 7 | import mindustry.game.EventType; 8 | import mindustry.type.UnitType; 9 | 10 | import static arc.Core.atlas; 11 | import static mindustry.Vars.content; 12 | 13 | public class SVars { 14 | public static final TextureRegion clear = atlas.find("clear"); 15 | public static final TextureRegion error = atlas.find("error"); 16 | public static informatis.core.Pathfinder pathfinder; 17 | 18 | public static void init() { 19 | pathfinder = new informatis.core.Pathfinder(); 20 | } 21 | 22 | public static float maxShieldAmongUnits = 0; 23 | 24 | static { 25 | Events.on(EventType.ClientLoadEvent.class, e -> { 26 | for(UnitType unitType : content.units()) { 27 | ShieldRegenFieldAbility ability = (ShieldRegenFieldAbility) unitType.abilities.find(abil -> abil instanceof ShieldRegenFieldAbility); 28 | if(ability == null) continue; 29 | if(ability.max > maxShieldAmongUnits) maxShieldAmongUnits = ability.max; 30 | } 31 | }); 32 | } 33 | } 34 | 35 | class Cl { 36 | public Cl(string asdf = "how") { 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/informatis/core/EventEmitter.java: -------------------------------------------------------------------------------- 1 | package informatis.core; 2 | 3 | import arc.struct.*; 4 | import informatis.SUtils; 5 | 6 | public class EventEmitter { 7 | final ObjectMap> events = new ObjectMap<>(); 8 | 9 | public Runnable subscribe(T event, Runnable listener) { 10 | ObjectSet listeners = events.get(event); 11 | if(listeners == null) events.put(event, ObjectSet.with(listener)); 12 | else listeners.add(listener); 13 | return () -> unsubscribe(event, listener); 14 | } 15 | 16 | public void unsubscribe(T event, Runnable listener) { 17 | ObjectSet listeners = events.get(event); 18 | if(listeners == null) return; 19 | listeners.remove(listener); 20 | } 21 | 22 | public void unsubscribe(Runnable listener) { 23 | ObjectMap.Entries> eventEntries = events.entries(); 24 | while (eventEntries.hasNext()) { 25 | ObjectMap.Entry> eventEntry = eventEntries.next(); 26 | SUtils.loop(eventEntry.value, (otherListener, i) -> { 27 | if(otherListener == listener) { 28 | events.get(eventEntry.key).remove(listener); 29 | return true; 30 | } 31 | return false; 32 | }); 33 | 34 | } 35 | } 36 | 37 | public void fire(T event) { 38 | ObjectSet listeners = events.get(event); 39 | if(listeners == null) return; 40 | for (Runnable listener : listeners) { 41 | listener.run(); 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /src/informatis/core/ModMetadata.java: -------------------------------------------------------------------------------- 1 | package informatis.core; 2 | 3 | import arc.Core; 4 | import mindustry.Vars; 5 | import mindustry.mod.Mods; 6 | 7 | public class ModMetadata { 8 | public static Mods.ModMeta metadata; 9 | 10 | public static void init() { 11 | Core.app.post(() -> { 12 | Mods.ModMeta meta = Vars.mods.locateMod("informatis").meta; 13 | meta.displayName = "[#B5FFD9]Informatis[]"; 14 | meta.author = "[#B5FFD9]Sharlotte[lightgray]#0018[][]"; 15 | meta.description = Core.bundle.get("shar-description"); 16 | metadata = meta; 17 | }); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/informatis/core/UpdateChecker.java: -------------------------------------------------------------------------------- 1 | package informatis.core; 2 | 3 | import arc.Core; 4 | import arc.graphics.Color; 5 | import arc.math.Mathf; 6 | import arc.func.*; 7 | import arc.util.*; 8 | import arc.util.serialization.Jval; 9 | 10 | import mindustry.Vars; 11 | import mindustry.gen.Icon; 12 | import mindustry.graphics.Pal; 13 | 14 | import java.util.Objects; 15 | 16 | public class UpdateChecker { 17 | private static boolean updateAvailable = false; 18 | private static String updateBuild; 19 | 20 | public static void init() { 21 | Vars.ui.menuGroup.fill(c -> { 22 | c.bottom().right(); 23 | c.button("@informatis.update-check", Icon.refresh, () -> { 24 | Vars.ui.loadfrag.show(); 25 | checkUpdate(result -> { 26 | Vars.ui.loadfrag.hide(); 27 | if(!result){ 28 | Vars.ui.showInfo("@be.noupdates"); 29 | } 30 | }); 31 | }).size(200, 60).padBottom(45).update(t -> { 32 | t.getLabel().setColor(updateAvailable ? Tmp.c1.set(Color.white).lerp(Pal.accent, Mathf.absin(5f, 1f)) : Color.white); 33 | }); 34 | }); 35 | } 36 | 37 | private static void checkUpdate(Boolc done) { 38 | Http.get("https://api.github.com/repos/Sharlottes/Informatis/releases/latest") 39 | .error(e -> { 40 | done.get(false); 41 | }) 42 | .submit(res -> { 43 | Jval json = Jval.read(res.getResultAsString()); 44 | String version = json.getString("tag_name"); 45 | if(Objects.equals("v"+ModMetadata.metadata.version, version)) { 46 | done.get(false); 47 | } else { 48 | updateAvailable = true; 49 | updateBuild = version; 50 | showUpdateDialog(); 51 | done.get(true); 52 | } 53 | }); 54 | } 55 | 56 | private static void showUpdateDialog(){ 57 | Vars.ui.showCustomConfirm( 58 | Core.bundle.format("informatis.update", updateBuild), "@be.update.confirm", 59 | "@ok", "@be.ignore", 60 | () -> { 61 | Vars.ui.showCustomConfirm("", "@informatis.update-reloadexit", "@ok", "@be.ignore", 62 | () -> Core.app.exit(), () -> {} 63 | ); 64 | Vars.ui.mods.githubImportMod("Sharlottes/Informatis", true); 65 | updateAvailable = false; 66 | }, 67 | () -> {} 68 | ); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/informatis/core/VDOM.java: -------------------------------------------------------------------------------- 1 | package informatis.core; 2 | 3 | import arc.Events; 4 | import arc.func.Cons; 5 | import arc.struct.Seq; 6 | import mindustry.game.EventType; 7 | 8 | /** 9 | * 제공받은 상태(Status)의 변화를 감지하여 제공받은 렌더러(renderer)를 재렌더링합니다. 10 | */ 11 | public class VDOM { 12 | private final Seq builders = new Seq<>(); 13 | 14 | public VDOM() { 15 | Events.run(EventType.Trigger.update, () -> { 16 | for(BuilderData builderData : builders) { 17 | for(Status status : builderData.statuses) { 18 | if(status.prevStatus != status.currStatus) { 19 | status.prevStatus = status.currStatus; 20 | builderData.render.get(builderData.statuses.map(Status::getValue).toArray()); 21 | break; 22 | } 23 | } 24 | } 25 | }); 26 | } 27 | 28 | public VDOM addBuilder(IRebuildable buildable, Status... statuses) { 29 | builders.add(new BuilderData(buildable::rebuild, statuses)); 30 | return this; 31 | } 32 | 33 | public VDOM addBuilder(Runnable render, Status... statuses) { 34 | addBuilder((objects) -> render.run(), statuses); 35 | return this; 36 | } 37 | 38 | private static class BuilderData { 39 | private final Seq statuses = new Seq<>(); 40 | private final Cons render; 41 | 42 | public BuilderData(Cons render, Status... statuses) { 43 | this.render = render; 44 | this.statuses.addAll(statuses); 45 | } 46 | } 47 | 48 | public static class Status { 49 | T prevStatus, currStatus; 50 | 51 | public Status() { 52 | this(null); 53 | } 54 | 55 | public Status(T initStatus) { 56 | this.prevStatus = initStatus; 57 | this.currStatus = initStatus; 58 | } 59 | 60 | /** 61 | * set currStatus to given value.
62 | * the VDOM will detect diff prevStatus and currStatus, then call render of BuilderData. 63 | * @param currStatus new status value 64 | */ 65 | public void setStatus(T currStatus) { 66 | this.currStatus = currStatus; 67 | } 68 | 69 | /** 70 | * get current value to be used somewhere 71 | * @return current status' value 72 | */ 73 | public T getValue() { 74 | return currStatus; 75 | } 76 | } 77 | 78 | public interface IRebuildable { 79 | void rebuild(Object[] statuses); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/informatis/core/setting/SettingHelper.java: -------------------------------------------------------------------------------- 1 | package informatis.core.setting; 2 | 3 | import arc.Core; 4 | import arc.func.Boolp; 5 | import arc.func.Func; 6 | import arc.graphics.Color; 7 | import arc.scene.event.Touchable; 8 | import arc.scene.ui.CheckBox; 9 | import arc.scene.ui.Label; 10 | import arc.scene.ui.Slider; 11 | import arc.scene.ui.layout.Table; 12 | import arc.struct.Seq; 13 | import arc.util.Strings; 14 | import mindustry.ui.Styles; 15 | import mindustry.ui.dialogs.SettingsMenuDialog; 16 | 17 | import static arc.Core.settings; 18 | 19 | public class SettingHelper { 20 | public static void addGraphicCheckSetting(String key, boolean def, Seq list) { 21 | addGraphicCheckSetting(key, def, list, () -> { 22 | }); 23 | } 24 | 25 | public static void addGraphicCheckSetting(String key, boolean def, Seq list, Runnable onSetted) { 26 | list.add(new SharSetting(key, def) { 27 | 28 | @Override 29 | public void add(Table table) { 30 | CheckBox box = new CheckBox(title); 31 | box.update(() -> box.setChecked(settings.getBool(name))); 32 | box.changed(() -> { 33 | settings.put(name, box.isChecked()); 34 | onSetted.run(); 35 | }); 36 | 37 | box.left(); 38 | addDesc(table.add(box).left().padTop(3f).get()); 39 | table.row(); 40 | } 41 | }); 42 | } 43 | 44 | public static void addGraphicSlideSetting(String key, int def, int min, int max, int step, SettingsMenuDialog.StringProcessor sp, Seq list) { 45 | list.add(new SharSetting(key, def) { 46 | 47 | @Override 48 | public void add(Table table) { 49 | 50 | Label value = new Label("", Styles.outlineLabel); 51 | Table content = new Table(); 52 | content.add(title, Styles.outlineLabel).left().growX().wrap(); 53 | content.add(value).padLeft(10f).right(); 54 | content.margin(3f, 33f, 3f, 33f); 55 | content.touchable = Touchable.disabled; 56 | 57 | Slider slider = new Slider(min, max, step, false); 58 | slider.setValue(settings.getInt(name)); 59 | slider.changed(() -> { 60 | settings.put(name, (int) slider.getValue()); 61 | value.setText(sp.get((int) slider.getValue())); 62 | }); 63 | slider.change(); 64 | 65 | addDesc(table.stack(slider, content).width(Math.min(Core.graphics.getWidth() / 1.2f, 460f)).left().padTop(4f).get()); 66 | table.row(); 67 | } 68 | }); 69 | } 70 | 71 | public static void addGraphicTypeSetting(String key, float min, float max, int def, boolean integer, Boolp condition, Func h, Seq list) { 72 | list.add(new SharSetting(key, def) { 73 | 74 | @Override 75 | public void add(Table table) { 76 | final String[] str = {""}; 77 | Table table1 = new Table(t -> { 78 | final float[] value = {def}; 79 | t.add(new Label(title + ": ")).left().padRight(5) 80 | .update(a -> a.setColor(condition.get() ? Color.white : Color.gray)); 81 | 82 | t.field((integer ? String.valueOf(value[0]).split("[.]")[0] : value[0]) + str[0], s -> { 83 | str[0] = h.get(s); 84 | value[0] = s.isEmpty() ? def : Strings.parseFloat(s); 85 | 86 | if (integer) settings.put(key, (int) value[0]); 87 | else settings.put(key, value[0]); 88 | 89 | }).update(a -> a.setDisabled(!condition.get())) 90 | .valid(f -> Strings.canParsePositiveFloat(f) && Strings.parseFloat(f) >= min && Strings.parseFloat(f) <= max).width(120f).left(); 91 | }); 92 | 93 | addDesc(table.add(table1).left().padTop(4f).get()); 94 | table.row(); 95 | } 96 | }); 97 | } 98 | 99 | } -------------------------------------------------------------------------------- /src/informatis/core/setting/SharSetting.java: -------------------------------------------------------------------------------- 1 | package informatis.core.setting; 2 | 3 | import arc.Core; 4 | import arc.scene.ui.layout.Table; 5 | import mindustry.ui.dialogs.SettingsMenuDialog; 6 | 7 | abstract class SharSetting extends SettingsMenuDialog.SettingsTable.Setting { 8 | 9 | public SharSetting(String name) { 10 | super(name); 11 | } 12 | 13 | public SharSetting(String name, Object def) { 14 | this(name); 15 | Core.settings.defaults(name, def); 16 | } 17 | 18 | public void add(Table table) { } 19 | public void add(SettingsMenuDialog.SettingsTable table) { } 20 | } 21 | -------------------------------------------------------------------------------- /src/informatis/core/setting/SharSettingUI.java: -------------------------------------------------------------------------------- 1 | package informatis.core.setting; 2 | 3 | import arc.*; 4 | import arc.scene.ui.TextButton; 5 | import arc.scene.ui.layout.*; 6 | import arc.struct.*; 7 | import arc.util.Align; 8 | import mindustry.ui.*; 9 | import informatis.ui.fragments.FragmentManager; 10 | 11 | import static arc.Core.*; 12 | import static informatis.core.setting.SettingHelper.*; 13 | import static mindustry.Vars.*; 14 | 15 | public class SharSettingUI { 16 | public static void init(){ 17 | Seq> settingSeq = new Seq<>(); 18 | Seq tapSeq = new Seq<>(); 19 | addGraphicCheckSetting("tileinfo", true, tapSeq, () -> FragmentManager.tileInfoFragment.rebuildTileInfoTable()); 20 | addGraphicCheckSetting("schem", !mobile, tapSeq, () -> FragmentManager.quickSchemFragment.rebuildBody()); 21 | addGraphicCheckSetting("sidebar", !mobile, tapSeq, () -> FragmentManager.sidebarSwitcherFragment.rebuildSidebarTable()); 22 | addGraphicCheckSetting("elementdebug", false, tapSeq); 23 | addGraphicCheckSetting("hiddenElem", false, tapSeq); 24 | addGraphicCheckSetting("serverfilter", false, tapSeq, () -> {}); 25 | 26 | //TODO: remove all drawing settings 27 | Seq drawSeq = new Seq<>(); 28 | addGraphicSlideSetting("selectopacity", 50, 0, 100, 5, s -> s + "%", drawSeq); 29 | addGraphicSlideSetting("baropacity", 50, 0, 100, 5, s -> s + "%", drawSeq); 30 | addGraphicCheckSetting("rangeShader", false, drawSeq); 31 | addGraphicCheckSetting("select", false, drawSeq); 32 | addGraphicCheckSetting("distanceLine", false, drawSeq); 33 | addGraphicCheckSetting("spawnerarrow", false, drawSeq); 34 | 35 | settingSeq.add(tapSeq, drawSeq); 36 | 37 | ui.settings.addCategory(bundle.get("setting.shar-title"), settingsTable -> { 38 | settingsTable.table(t -> { 39 | Seq buttons = new Seq<>(); 40 | buttons.add(new TextButton(bundle.get("setting.shar-ui"), Styles.cleart)); 41 | buttons.add(new TextButton(bundle.get("setting.shar-draw"), Styles.cleart)); 42 | buttons.each(b -> b.clicked(() -> buttons.each(b1 -> b1.setChecked(b1 == b)))); 43 | t.table(Styles.black8, bt -> { 44 | bt.top().align(Align.top); 45 | buttons.each(b -> { 46 | b.getLabel().setFontScale(0.85f); 47 | bt.add(b).minHeight(60f * 0.85f).minWidth(150f * 0.85f).top(); 48 | }); 49 | }).grow().row(); 50 | 51 | Stack stack = new Stack(); 52 | for (int i = 0; i < settingSeq.size; i++) { 53 | int finalI = i; 54 | stack.add(new Table(st -> { 55 | for (SharSetting setting : settingSeq.get(finalI)) 56 | st.table(setting::add).left().row(); 57 | 58 | st.button(Core.bundle.get("settings.reset", "Reset to Defaults"), () -> { 59 | settingSeq.get(finalI).each(s -> Core.settings.put(s.name, Core.settings.getDefault(s.name))); 60 | }).margin(14.0f).width(240.0f).pad(6.0f); 61 | st.visibility = () -> buttons.get(finalI).isChecked(); 62 | st.pack(); 63 | })); 64 | } 65 | t.add(stack); 66 | t.fillParent = true; 67 | }); 68 | }); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/informatis/shaders/RangeShader.java: -------------------------------------------------------------------------------- 1 | package informatis.shaders; 2 | 3 | import arc.Core; 4 | import arc.graphics.gl.Shader; 5 | import arc.scene.ui.layout.Scl; 6 | import arc.util.Time; 7 | import mindustry.Vars; 8 | 9 | public class RangeShader extends Shader { 10 | public RangeShader() { 11 | super(Core.files.internal("shaders/screenspace.vert"), Vars.tree.get("shaders/turretrange.frag")); 12 | } 13 | 14 | @Override 15 | public void apply(){ 16 | setUniformf("u_dp", Scl.scl(1f)); 17 | setUniformf("u_time", Time.time / Scl.scl(1f)); 18 | setUniformf("u_offset", 19 | Core.camera.position.x - Core.camera.width / 2, 20 | Core.camera.position.y - Core.camera.height / 2); 21 | setUniformf("u_texsize", Core.camera.width, Core.camera.height); 22 | setUniformf("u_invsize", 1f/Core.camera.width, 1f/Core.camera.height); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/informatis/shaders/Shaders.java: -------------------------------------------------------------------------------- 1 | package informatis.shaders; 2 | 3 | public class Shaders { 4 | public static final RangeShader turretRange = new RangeShader(); 5 | public static final TransparentShader transparent = new TransparentShader(); 6 | } 7 | -------------------------------------------------------------------------------- /src/informatis/shaders/TransparentShader.java: -------------------------------------------------------------------------------- 1 | package informatis.shaders; 2 | 3 | import arc.Core; 4 | import arc.graphics.gl.Shader; 5 | import mindustry.Vars; 6 | 7 | public class TransparentShader extends Shader { 8 | public float alpha = 1; 9 | 10 | public TransparentShader() { 11 | super(Core.files.internal("shaders/screenspace.vert"), Vars.tree.get("shaders/transparent.frag")); 12 | } 13 | 14 | @Override 15 | public void apply(){ 16 | setUniformf("u_alpha", alpha); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/informatis/ui/components/FreeBar.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.components; 2 | 3 | import arc.graphics.g2d.*; 4 | import arc.math.*; 5 | import arc.struct.*; 6 | import mindustry.*; 7 | import mindustry.entities.abilities.*; 8 | import mindustry.gen.*; 9 | import mindustry.graphics.*; 10 | import mindustry.type.*; 11 | import mindustry.world.blocks.payloads.Payload; 12 | 13 | import informatis.SVars; 14 | 15 | import static arc.Core.*; 16 | import static mindustry.Vars.*; 17 | 18 | public class FreeBar { 19 | public static void draw(Unit unit){ 20 | if(unit.dead()) return; 21 | 22 | Draw.z(Layer.flyingUnit + 1); 23 | 24 | Bits statuses = new Bits(); 25 | Bits applied = unit.statusBits(); 26 | if(!statuses.equals(applied) && applied != null){ 27 | int i = 0; 28 | int row = 0; 29 | for(StatusEffect effect : content.statusEffects()){ 30 | if(applied.get(effect.id) && !effect.isHidden()){ 31 | Draw.rect(effect.uiIcon, unit.x - (unit.type.hitSize + 4)/2 + i * 4, unit.y - 4 + 4 * row, 4,4); 32 | if(++i > 2 * (unit.type.hitSize + 4)) row++; 33 | } 34 | } 35 | statuses.set(applied); 36 | } 37 | 38 | if(unit instanceof Payloadc payload && payload.payloads().any()){ 39 | int i = 0; 40 | int row = 0; 41 | for(Payload p : payload.payloads()){ 42 | Draw.rect(p.icon(), unit.x - (unit.type.hitSize + 4)/2 + i * 4, unit.y - 12 - 4 * row, 4,4); 43 | if(++i > 2 * (unit.type.hitSize + 4)) row++; 44 | } 45 | } 46 | 47 | Draw.color(0.1f, 0.1f, 0.1f, (settings.getInt("baropacity") / 100f)); 48 | float width = unit.type.hitSize + 4f; 49 | float height = 2f; 50 | float x = unit.x; 51 | float y = unit.y - 8; 52 | for(int i : Mathf.signs) { 53 | for(int ii = 0; ii < 2; ii++){ 54 | float shadowx = x + ii * 0.25f; 55 | float shadowy = y - ii * 0.5f; 56 | Fill.poly(FloatSeq.with( 57 | shadowx - (width / 2 + height), shadowy, 58 | shadowx - width / 2, shadowy + i * height, 59 | shadowx + width / 2, shadowy + i * height, 60 | shadowx + (width / 2 + height), shadowy, 61 | shadowx + width / 2, shadowy + i * -height, 62 | shadowx - width / 2, shadowy + i * -height)); 63 | } 64 | } 65 | 66 | { 67 | Draw.color(Pal.health.cpy().a((settings.getInt("baropacity") / 100f))); 68 | float topWidth = - width / 2 + width * Mathf.clamp(unit.healthf()); 69 | float moser = topWidth + height; 70 | if(unit.health <= 0) moser = (width / 2 + height) * (2 * Mathf.clamp(unit.healthf()) - 1); 71 | 72 | for(int i : Mathf.signs) { 73 | Fill.poly(FloatSeq.with( 74 | x - (width / 2 + height), y, 75 | x - width / 2, y + i * height, 76 | x + topWidth, y + i * height, 77 | x + moser, y, 78 | x + topWidth, y + i * -height, 79 | x - width / 2, y + i * -height)); 80 | } 81 | } 82 | 83 | if(Vars.state.rules.unitAmmo) { 84 | float topWidth = - width / 2 + width * Mathf.clamp(unit.ammof()); 85 | float moser = topWidth + height; 86 | if(unit.ammo <= 0) moser = (width / 2 + height) * (2 * Mathf.clamp(unit.ammof()) - 1); 87 | 88 | Draw.color((unit.dead() || unit instanceof BlockUnitc ? Pal.ammo : unit.type.ammoType.color()).cpy().a((settings.getInt("baropacity") / 100f))); 89 | Fill.poly(FloatSeq.with( 90 | x - (width / 2 + height), y, 91 | x - width / 2, y + height, 92 | x + topWidth, y + height, 93 | x + moser, y, 94 | x + topWidth, y - height, 95 | x - width / 2, y - height)); 96 | } 97 | 98 | float maxShield = -1; 99 | for(Ability ability : unit.abilities) { 100 | if(ability instanceof ForceFieldAbility forceFieldAbility) { 101 | maxShield = forceFieldAbility.max; 102 | } 103 | } 104 | if(maxShield != -1) { 105 | 106 | float max = Mathf.clamp(unit.shield / Math.max(SVars.maxShieldAmongUnits, maxShield)); 107 | 108 | float topWidth = - width / 2 + width * max; 109 | float moser = topWidth + height; 110 | if(unit.shield <= 0) moser = (width / 2 + height) * (2 * max - 1); 111 | 112 | Draw.color(Pal.surge.cpy().a((settings.getInt("baropacity") / 100f))); 113 | Fill.poly(FloatSeq.with( 114 | x - (width / 2 + height), y, 115 | x - width / 2, y - height, 116 | x + topWidth, y - height, 117 | x + moser, y, 118 | x + topWidth, y + height, 119 | x - width / 2, y + height)); 120 | } 121 | 122 | Draw.reset(); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/informatis/ui/components/IntervalTableWrapper.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.components; 2 | 3 | import arc.func.Boolf; 4 | import arc.func.Cons; 5 | import arc.scene.ui.layout.Table; 6 | import arc.util.Time; 7 | 8 | public 9 | class IntervalTableWrapper { 10 | final Cons tableCons; 11 | final Boolf
condition; 12 | final int interval; 13 | 14 | public IntervalTableWrapper() { 15 | this(t -> {}); 16 | } 17 | public IntervalTableWrapper(Cons
tableCons) { 18 | this(tableCons, (t) -> true, 60); 19 | } 20 | public IntervalTableWrapper(Cons
tableCons, int interval) { 21 | this(tableCons, (t) -> true, interval); 22 | } 23 | public IntervalTableWrapper(Cons
tableCons, Boolf
condition, int interval) { 24 | this.tableCons = tableCons; 25 | this.condition = condition; 26 | this.interval = interval; 27 | } 28 | 29 | float t = 0; 30 | public Table build() { 31 | Table table = new Table(tableCons); 32 | 33 | table.update(() -> { 34 | t -= Time.delta; 35 | if(t <= 0) { 36 | t = interval; 37 | if(!condition.get(table)) return; 38 | table.clearChildren(); 39 | tableCons.get(table); 40 | } 41 | }); 42 | 43 | return table; 44 | } 45 | } -------------------------------------------------------------------------------- /src/informatis/ui/components/PageTabsFragment.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.components; 2 | 3 | import arc.func.Prov; 4 | import arc.scene.Element; 5 | import arc.scene.ui.layout.Table; 6 | import informatis.SUtils; 7 | 8 | public class PageTabsFragment extends TabsFragment { 9 | public final Table content; 10 | 11 | public PageTabsFragment(Object... tabPages) { 12 | this(new Table(), tabPages); 13 | } 14 | 15 | public PageTabsFragment(Table content, Object... tabPages) { 16 | super(SUtils.pickFromArray(tabPages, String.class, i -> i % 2 == 0)); 17 | Object[] pages = SUtils.pickFromArray(tabPages, Object.class, i -> i % 2 != 0); 18 | 19 | this.content = content; 20 | this.content.add(buildPage(pages[0])).grow(); 21 | eventEmitter.subscribe(TabsFragment.Event.TabChanged, () -> { 22 | this.content.clearChildren(); 23 | this.content.add(buildPage(pages[currentTabIndex])).grow(); 24 | }); 25 | } 26 | 27 | private Element buildPage(Object page) { 28 | if(page instanceof Element element) { 29 | return element; 30 | } else { 31 | Prov prov = (Prov) page; 32 | return prov.get(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/informatis/ui/components/SBar.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.components; 2 | 3 | import informatis.SUtils; 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.scene.*; 11 | import arc.scene.style.*; 12 | import arc.util.Align; 13 | import arc.util.Tmp; 14 | import informatis.ui.fragments.sidebar.windows.UnitWindow; 15 | import mindustry.graphics.*; 16 | import mindustry.ui.Fonts; 17 | 18 | public class SBar extends Element { 19 | static final Rect scissor = new Rect(); 20 | private static final Drawable 21 | barSprite = SUtils.getDrawable(Core.atlas.find("informatis-barS"), 10, 10, 9, 9), 22 | barTopSprite = SUtils.getDrawable(Core.atlas.find("informatis-barS-top"), 10, 10, 9, 9); 23 | 24 | public final UnitWindow.BarData barData; 25 | float value, lastValue, blink; 26 | 27 | public SBar(String name, Color color, Floatp fraction){ 28 | this(new UnitWindow.BarData(() -> name, () -> color, fraction)); 29 | } 30 | public SBar(String name, Color fromColor, Color toColor, Floatp fraction){ 31 | this(new UnitWindow.BarData(pro -> name, pro -> Tmp.c1.set(fromColor).lerp(toColor, pro), fraction)); 32 | } 33 | public SBar(UnitWindow.BarData barData){ 34 | this.barData = barData; 35 | lastValue = value = Mathf.clamp(barData.fraction.get()); 36 | } 37 | 38 | @Override 39 | public void draw(){ 40 | float computed = Mathf.clamp(barData.fraction.get()); 41 | 42 | if(lastValue > computed){ 43 | blink = 1f; 44 | lastValue = computed; 45 | } 46 | 47 | blink = Mathf.lerpDelta(blink, 0f, 0.2f); 48 | value = Mathf.lerpDelta(value, computed, 0.05f); 49 | setColor(barData.color.get()); 50 | 51 | Draw.colorl(0.1f); 52 | barSprite.draw(x, y, width, height); 53 | drawBarSprite(Tmp.c1.set(color).mul(Pal.lightishGray), width * value); 54 | drawBarSprite(color, width * Math.min(value, computed)); 55 | Fonts.outline.draw(barData.name.get(), x + width / 2f, y + height * 0.75f, Color.white, 1, false, Align.center); 56 | } 57 | 58 | private void drawBarSprite(Color color, float width) { 59 | Draw.color(color, Color.white, blink); 60 | if(width > barSprite.getMinWidth()){ 61 | SBar.barTopSprite.draw(x, y, width, height); 62 | } else if(ScissorStack.push(scissor.set(x, y, width, height))){ 63 | SBar.barTopSprite.draw(x, y, barSprite.getMinWidth(), height); 64 | ScissorStack.pop(); 65 | } 66 | } 67 | 68 | public static class SBarData { 69 | public final String name; 70 | public final Floatp fraction; 71 | public final Color fromColor; 72 | public final Color toColor; 73 | 74 | public SBarData(String name, Color fromColor, Color toColor, Floatp fraction) { 75 | this.name = name; 76 | this.fromColor = fromColor; 77 | this.toColor = toColor; 78 | this.fraction = fraction; 79 | } 80 | 81 | public SBarData(String name, Color color, Floatp fraction) { 82 | this(name, color, color, fraction); 83 | } 84 | } 85 | } 86 | 87 | -------------------------------------------------------------------------------- /src/informatis/ui/components/SIcons.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.components; 2 | 3 | import arc.Core; 4 | import arc.graphics.g2d.TextureRegion; 5 | 6 | public class SIcons { 7 | public static final TextureRegion health = Core.atlas.find("informatis-health"); 8 | public static final TextureRegion shield = Core.atlas.find("informatis-shield"); 9 | public static final TextureRegion item = Core.atlas.find("informatis-item"); 10 | public static final TextureRegion liquid = Core.atlas.find("informatis-liquid"); 11 | public static final TextureRegion power = Core.atlas.find("informatis-power"); 12 | public static final TextureRegion ammo = Core.atlas.find("informatis-ammo"); 13 | public static final TextureRegion reload = Core.atlas.find("informatis-reload"); 14 | } 15 | -------------------------------------------------------------------------------- /src/informatis/ui/components/TabsFragment.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.components; 2 | 3 | import arc.scene.ui.TextButton; 4 | import arc.scene.ui.layout.Table; 5 | import informatis.SUtils; 6 | import informatis.core.EventEmitter; 7 | import mindustry.ui.Styles; 8 | 9 | public class TabsFragment extends Table { 10 | public int currentTabIndex = 0; 11 | public final EventEmitter eventEmitter = new EventEmitter<>(); 12 | 13 | public TabsFragment(String... tabs) { 14 | super(); 15 | TextButton[] buttons = new TextButton[tabs.length]; 16 | 17 | SUtils.loop(tabs.length, i -> { 18 | TextButton button = new TextButton(tabs[i], Styles.flatToggleMenut); 19 | buttons[i] = button; 20 | button.clicked(() -> { 21 | currentTabIndex = i; 22 | button.toggle(); 23 | SUtils.loop(buttons, (otherButton, bi) -> { 24 | otherButton.setChecked(currentTabIndex == bi); 25 | }); 26 | eventEmitter.fire(Event.TabChanged); 27 | }); 28 | button.setChecked(i == currentTabIndex); 29 | add(button).height(50).growX(); 30 | }); 31 | } 32 | 33 | public enum Event { 34 | TabChanged 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/ElementViewFragment.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments; 2 | 3 | import arc.Core; 4 | import arc.graphics.Color; 5 | import arc.graphics.g2d.Draw; 6 | import arc.graphics.g2d.Lines; 7 | import arc.scene.Element; 8 | import arc.scene.Group; 9 | import arc.scene.event.Touchable; 10 | import arc.struct.SnapshotSeq; 11 | import arc.util.Align; 12 | import arc.util.Time; 13 | import arc.util.Tmp; 14 | import mindustry.graphics.Layer; 15 | import mindustry.graphics.Pal; 16 | import mindustry.ui.Fonts; 17 | 18 | import static arc.Core.settings; 19 | 20 | public class ElementViewFragment extends Element { 21 | private final Group[] roots; 22 | 23 | public ElementViewFragment(Group... roots) { 24 | this.roots = roots; 25 | fillParent = true; 26 | touchable = Touchable.disabled; 27 | Core.scene.root.addChild(this); 28 | } 29 | 30 | @Override 31 | public void draw() { 32 | if(!settings.getBool("elementdebug")) return; 33 | 34 | super.draw(); 35 | Draw.z(Layer.max); 36 | Lines.stroke(1); 37 | for(Group root : roots) 38 | drawElementRect(root.getChildren()); 39 | } 40 | 41 | private void drawElementRect(SnapshotSeq elements) { 42 | elements.each(elem -> { 43 | elem.updateVisibility(); 44 | if(elem.visible || settings.getBool("hiddenElem")) { 45 | Draw.color(); 46 | Lines.stroke(1); 47 | elem.localToStageCoordinates(Tmp.v1.set(0, 0)); 48 | if(elem.hasMouse()) { 49 | Draw.color(Pal.accent); 50 | Lines.stroke(3); 51 | drawElementTransform(elem); 52 | } 53 | if(elem.hasScroll()) { 54 | Draw.color(Pal.lancerLaser); 55 | Lines.stroke(3); 56 | } 57 | if(elem.hasKeyboard()) { 58 | Draw.color(Pal.sap); 59 | Lines.stroke(5); 60 | } 61 | Lines.rect(Tmp.v1.x, Tmp.v1.y, elem.getWidth(), elem.getHeight()); 62 | 63 | if(elem instanceof Group group) drawElementRect(group.getChildren()); 64 | } 65 | }); 66 | } 67 | 68 | private void drawElementTransform(Element element) { 69 | element.localToStageCoordinates(Tmp.v1.set(0, 0)); 70 | Draw.color(Tmp.c1.set(Color.red).shiftHue(Time.time * 1.5f)); 71 | Lines.stroke(1.5f); 72 | Lines.rect(Tmp.v1.x, Tmp.v1.y, element.getWidth(), element.getHeight()); 73 | Fonts.outline.draw(element.getWidth() + ", " + element.getHeight(), Tmp.v1.x, Tmp.v1.y, 74 | Pal.accent, 1f, false, Align.center); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/FragmentManager.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments; 2 | 3 | import informatis.ui.fragments.sidebar.dialogs.DialogManager; 4 | import informatis.ui.fragments.sidebar.TroopingFragment; 5 | import informatis.ui.fragments.sidebar.windows.WindowManager; 6 | 7 | import static arc.Core.scene; 8 | import static mindustry.Vars.ui; 9 | 10 | public class FragmentManager { 11 | public static ElementViewFragment elementViewFragment; 12 | public static QuickSchemFragment quickSchemFragment; 13 | public static TileInfoFragment tileInfoFragment; 14 | public static ServerSearchFragment serverSearchFragment; 15 | public static SidebarSwitcher sidebarSwitcherFragment; 16 | 17 | public static void init() { 18 | elementViewFragment = new ElementViewFragment( 19 | scene.root, 20 | ui.picker, ui.editor, ui.controls, ui.restart, ui.join, ui.discord, 21 | ui.load, ui.custom, ui.language, ui.database, ui.settings, ui.host, 22 | ui.paused, ui.about, ui.bans, ui.admins, ui.traces, ui.maps, ui.content, 23 | ui.planet, ui.research, ui.mods, ui.schematics, ui.logic 24 | ); 25 | serverSearchFragment = new ServerSearchFragment(); 26 | 27 | quickSchemFragment = new QuickSchemFragment(); 28 | tileInfoFragment = new TileInfoFragment(); 29 | sidebarSwitcherFragment = new SidebarSwitcher( 30 | WindowManager.body, 31 | DialogManager.body, 32 | new TroopingFragment() // cache later? 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/ServerSearchFragment.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments; 2 | 3 | import arc.Core; 4 | import arc.scene.ui.*; 5 | import arc.scene.ui.layout.*; 6 | import arc.struct.*; 7 | import arc.util.*; 8 | import arc.util.serialization.Jval; 9 | import mindustry.Vars; 10 | import mindustry.game.*; 11 | import mindustry.gen.Tex; 12 | import mindustry.net.*; 13 | import mindustry.ui.Styles; 14 | 15 | import static mindustry.Vars.*; 16 | 17 | public class ServerSearchFragment extends Table { 18 | final ObjectMap> servers = new ObjectMap<>(); 19 | static final String[] modeNames = new String[]{ "Survival", "PvP", "Attack", "Sandbox", "Custom" }; 20 | 21 | public ServerSearchFragment() { 22 | super(); 23 | setBackground(Tex.button); 24 | addButtons(modeNames); 25 | Core.app.post(() -> { 26 | Table header = (Table) Vars.ui.join.getChildren().get(0); 27 | header.row(); 28 | header.add(this); 29 | 30 | loadServers(); 31 | }); 32 | } 33 | 34 | void addButtons(String[] modes) { 35 | TextButton[] buttons = new TextButton[modes.length]; 36 | for(int i = 0; i < modes.length; i++) { 37 | String mode = modes[i]; 38 | TextButton button = new TextButton("@mode." + mode.toLowerCase() + ".name", Styles.flatTogglet) {{ 39 | getLabel().setWrap(false); 40 | clicked(()-> { 41 | for(TextButton otherButton : buttons) { 42 | if(otherButton == this) continue; 43 | otherButton.setChecked(false); 44 | } 45 | if(isChecked()) filterServers(mode); 46 | else defaultServers.set(servers.keys().toSeq()); 47 | Reflect.invoke(Vars.ui.join, "refreshCommunity"); 48 | }); 49 | }}; 50 | buttons[i] = button; 51 | add(button).minWidth(100).height(50); 52 | } 53 | } 54 | 55 | void filterServers(String mode) { 56 | Vars.defaultServers.clear(); 57 | Seq serverGroups = new Seq<>(); 58 | 59 | ObjectMap.Entries> serverEntries = servers.entries(); 60 | int i = 0; 61 | while(serverEntries.hasNext) { 62 | ObjectMap.Entry> serverEntry = serverEntries.next(); 63 | ServerGroup serverGroup = serverEntry.key; 64 | Seq hosts = serverEntry.value.toSeq(); 65 | Seq addresses = new Seq<>(); 66 | for(Host host : hosts) { 67 | if(mode.equals("Custom") 68 | ? host.modeName != null 69 | ? !Structs.contains(modeNames, h -> host.modeName.equals(h.toLowerCase())) 70 | : host.mode.equals(Gamemode.editor) 71 | : host.modeName != null 72 | ? host.modeName.equals(mode) 73 | : host.mode.equals(Gamemode.valueOf(mode.toLowerCase())) 74 | ) { 75 | addresses.add(host.address +":"+ host.port); 76 | } 77 | } 78 | if(addresses.any()) { 79 | i++; 80 | serverGroups.add(new ServerGroup(serverGroup.name, addresses.toArray(String.class))); 81 | } 82 | } 83 | defaultServers.set(serverGroups); 84 | } 85 | 86 | void loadServers() { 87 | var url = becontrol.active() ? serverJsonBeURL : serverJsonURL; 88 | Log.info("[Informatis] Fetching community servers at @", url); 89 | 90 | //get servers 91 | Http.get(url) 92 | .error(t -> Log.err("[Informatis] Failed to fetch community servers", t)) 93 | .submit(result -> { 94 | Jval val = Jval.read(result.getResultAsString()); 95 | Seq serverGroups = new Seq<>(); 96 | val.asArray().each(child -> { 97 | String name = child.getString("name", ""); 98 | String[] addresses; 99 | if(child.has("addresses") || (child.has("address") && child.get("address").isArray())){ 100 | addresses = (child.has("addresses") ? child.get("addresses") : child.get("address")).asArray().map(Jval::asString).toArray(String.class); 101 | }else{ 102 | addresses = new String[]{child.getString("address", "")}; 103 | } 104 | serverGroups.add(new ServerGroup(name, addresses)); 105 | }); 106 | serverGroups.sort(s -> s.name == null ? Integer.MAX_VALUE : s.name.hashCode()); 107 | Log.info("[Informatis] Fetched @ community servers at @", serverGroups.size, url); 108 | 109 | refreshServers(serverGroups); 110 | }); 111 | } 112 | 113 | void refreshServers(Seq serverGroups) { 114 | refreshServers(serverGroups, () -> {}); 115 | } 116 | 117 | void refreshServers(Seq serverGroups, Runnable onDone) { 118 | Runnable onDoneWrapper = () -> { 119 | Log.info("[Informatis] Fetched @ community servers.", servers.size); 120 | onDone.run(); 121 | }; 122 | 123 | Log.info("[Informatis] Fetching community servers"); 124 | final int[] doneCount = {0, 0}; 125 | for(ServerGroup server : serverGroups) { 126 | servers.put(server, new ObjectSet<>()); 127 | 128 | for(String address : server.addresses) { 129 | doneCount[1]++; 130 | net.pingHost( 131 | address.contains(":") ? address.split(":")[0] : address, 132 | address.contains(":") ? Strings.parseInt(address.split(":")[1]) : Vars.port, 133 | host -> { 134 | servers.get(server).add(host); 135 | 136 | if (++doneCount[0] == doneCount[1]) onDoneWrapper.run(); 137 | }, 138 | (e) -> { 139 | if (++doneCount[0] == doneCount[1]) onDoneWrapper.run(); 140 | }); 141 | } 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/SidebarSwitcher.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments; 2 | 3 | import arc.*; 4 | import arc.graphics.g2d.Lines; 5 | import arc.math.*; 6 | import arc.scene.*; 7 | import arc.scene.actions.*; 8 | import arc.scene.ui.*; 9 | import arc.scene.ui.layout.*; 10 | import arc.util.Log; 11 | import mindustry.*; 12 | import mindustry.game.EventType; 13 | import mindustry.gen.*; 14 | import mindustry.graphics.Pal; 15 | 16 | public class SidebarSwitcher { 17 | private int showIndex = 0; 18 | private final Table sidebarTable = new Table(); 19 | private final Table[] sidebars; 20 | 21 | private final ImageButton switchButton = new ImageButton() { 22 | @Override 23 | public void draw() { 24 | super.draw(); 25 | Lines.stroke(5, Pal.gray); 26 | Lines.line(this.x, this.y + this.height, this.x + this.width, this.y + this.height); 27 | } 28 | { 29 | setStyle(new ImageButton.ImageButtonStyle() {{ 30 | up = Tex.buttonEdge4; 31 | imageUp = Icon.right; 32 | }}); 33 | clicked(() -> { 34 | Table[] sidebars = getSidebars(); 35 | Element currentSidebar = sidebars[showIndex]; 36 | showIndex = (showIndex + 1) % sidebars.length; 37 | Element nextSidebar = sidebars[showIndex]; 38 | 39 | Log.info(sidebars[showIndex].getWidth()); 40 | Log.info(sidebars[showIndex].getMinWidth()); 41 | Log.info(sidebars[showIndex].getPrefWidth()); 42 | actShowMoveX(currentSidebar, 0, -currentSidebar.getWidth()); 43 | actShowMoveX(nextSidebar, -nextSidebar.getWidth(),0); 44 | actResizeWidth(this, nextSidebar.getWidth()); 45 | }); 46 | }}; 47 | 48 | public SidebarSwitcher(Table ...sidebars) { 49 | this.sidebars = sidebars; 50 | 51 | Vars.ui.hudGroup.fill(t -> { 52 | t.name = "informatis sidebar"; 53 | t.left(); 54 | t.add(sidebarTable); 55 | }); 56 | rebuildSidebarTable(); 57 | } 58 | 59 | private static void actShowMoveX(Element element, float from, float to) { 60 | MoveToAction moveToAction = new MoveToAction(); 61 | moveToAction.setDuration(0.2f); 62 | moveToAction.setX(to); 63 | moveToAction.setInterpolation(Interp.circleOut); 64 | VisibleAction visibleAction = new VisibleAction(); 65 | visibleAction.setVisible(to >= 0); 66 | 67 | element.setPosition(from, element.y); 68 | if(to >= 0) element.actions(visibleAction, moveToAction); 69 | else element.actions(moveToAction, visibleAction); 70 | element.act(Core.graphics.getDeltaTime()); 71 | element.draw(); 72 | } 73 | 74 | private static void actResizeWidth(Element element, float width) { 75 | SizeToAction sizeToAction = new SizeToAction(); 76 | sizeToAction.setSize(width, element.getHeight()); 77 | sizeToAction.setDuration(0.2f); 78 | sizeToAction.setInterpolation(Interp.circleOut); 79 | element.actions(sizeToAction); 80 | element.act(Core.graphics.getDeltaTime()); 81 | element.draw(); 82 | } 83 | 84 | public void rebuildSidebarTable() { 85 | sidebarTable.visible = Core.settings.getBool("sidebar"); 86 | if(!sidebarTable.visible) return; 87 | 88 | Stack sidebarTables = new Stack(); 89 | for(Table elem : sidebars) { 90 | sidebarTables.add(new Table(table -> { 91 | table.left(); 92 | table.add(elem).growY(); 93 | })); 94 | elem.setBackground(Tex.buttonEdge3); 95 | elem.visible = false; 96 | } 97 | sidebars[showIndex].visible = true; 98 | 99 | sidebarTable.clear(); 100 | sidebarTable.top().left(); 101 | sidebarTable.add(sidebarTables).grow(); 102 | sidebarTable.row(); 103 | Cell cell = sidebarTable.add(switchButton).left(); 104 | 105 | sidebars[showIndex].invalidate(); 106 | Log.info(sidebars[showIndex].getWidth()); 107 | Log.info(sidebars[showIndex].getMinWidth()); 108 | Log.info(sidebars[showIndex].getPrefWidth()); 109 | cell.minWidth(sidebars[showIndex].getPrefWidth()); 110 | } 111 | 112 | private Table[] getSidebars() { 113 | return sidebars; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/TileInfoFragment.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments; 2 | 3 | import arc.scene.style.TextureRegionDrawable; 4 | import arc.scene.ui.ImageButton; 5 | import arc.scene.ui.layout.*; 6 | import arc.util.*; 7 | import mindustry.gen.*; 8 | import mindustry.ui.*; 9 | import mindustry.world.Block; 10 | import mindustry.world.Tile; 11 | import mindustry.world.blocks.environment.Floor; 12 | 13 | import static informatis.SUtils.*; 14 | import static informatis.SVars.*; 15 | import static arc.Core.*; 16 | import static mindustry.Vars.*; 17 | 18 | public class TileInfoFragment { 19 | private boolean waveShown; 20 | final Table tileInfoTable = new Table(Tex.buttonEdge4); 21 | final Table tileInfoContainer; 22 | 23 | public TileInfoFragment() { 24 | Table waveTable = (Table) scene.find("waves"); 25 | Table infoTable = (Table) scene.find("infotable"); 26 | waveTable.removeChild(infoTable); 27 | waveTable.row(); 28 | tileInfoContainer = waveTable.table(titleInfoBody -> { 29 | titleInfoBody.left(); 30 | titleInfoBody.stack( 31 | new Table(collapse -> { 32 | collapse.collapser(tileInfoTable, true, () -> waveShown).growX(); 33 | }).top(), 34 | new Table(collapseButton -> { 35 | ImageButton button = new ImageButton(Icon.downOpen, Styles.clearTogglei); 36 | button.clicked(() -> { 37 | waveShown = !waveShown; 38 | 39 | TextureRegionDrawable icon = waveShown ? Icon.upOpen : Icon.downOpen; 40 | button.getStyle().imageUp = icon; 41 | button.resizeImage(icon.imageSize()); 42 | button.setChecked(waveShown); 43 | }); 44 | collapseButton.add(button); 45 | }).left().top() 46 | ).growX(); 47 | titleInfoBody.row(); 48 | titleInfoBody.add(infoTable).left(); 49 | }).growX().get(); 50 | rebuildTileInfoTable(); 51 | } 52 | 53 | public void rebuildTileInfoTable() { 54 | tileInfoContainer.visible = settings.getBool("tileinfo"); 55 | if(!tileInfoContainer.visible) return; 56 | 57 | tileInfoTable.clear(); 58 | tileInfoTable.center(); 59 | tileInfoTable.table(head -> { 60 | head.table(image -> { 61 | image.left(); 62 | image.image(() -> { 63 | Tile tile = getTile(); 64 | if(tile == null) return clear; 65 | Floor floor = tile.floor(); 66 | if(floor.uiIcon == error) return clear; 67 | return floor.uiIcon; 68 | }).size(iconSmall); 69 | image.image(() -> { 70 | Tile tile = getTile(); 71 | if(tile == null) return clear; 72 | Floor floor = tile.overlay(); 73 | if(floor.uiIcon == error) return clear; 74 | return floor.uiIcon; 75 | }).size(iconSmall); 76 | image.image(() -> { 77 | Tile tile = getTile(); 78 | if(tile == null) return clear; 79 | Block floor = tile.block(); 80 | if(floor.uiIcon == error) return clear; 81 | return floor.uiIcon; 82 | }).size(iconSmall); 83 | }); 84 | head.label(() -> { 85 | Tile tile = getTile(); 86 | if(tile == null) return "(NaN, NaN)"; 87 | return Strings.format("(@, @)", tile.x, tile.y); 88 | }).center(); 89 | }); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/TroopingFragment.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar; 2 | 3 | import arc.input.KeyCode; 4 | import arc.scene.ui.layout.Table; 5 | import arc.struct.IntSeq; 6 | import informatis.SUtils; 7 | import mindustry.Vars; 8 | import mindustry.gen.*; 9 | import mindustry.graphics.Pal; 10 | import mindustry.ui.Styles; 11 | 12 | import static arc.Core.input; 13 | 14 | public class TroopingFragment extends Table { 15 | public TroopingFragment() { 16 | defaults().growX(); 17 | 18 | table(header -> { 19 | header.center().defaults().pad(10).growX(); 20 | header.button("all", Styles.defaultt, () -> { 21 | Vars.control.input.selectedUnits.clear(); 22 | Vars.control.input.selectedUnits.addAll(Vars.player.team().data().units); 23 | }).wrapLabel(false); 24 | header.button(Icon.cancel, Styles.defaulti, () -> Vars.control.input.selectedUnits.clear()); 25 | }); 26 | row(); 27 | image().height(5f).color(Pal.gray).pad(10, 0, 10, 0); 28 | row(); 29 | table(list -> { 30 | SUtils.loop(10, (i) -> { 31 | list.table(tab -> { 32 | IntSeq troop = TroopingManager.troops.get(i); 33 | tab.clicked(() -> TroopingManager.selectTrooping(i)); 34 | tab.left(); 35 | 36 | tab.add(String.valueOf(i)).fontScale(0.75f).width(15).padRight(30); 37 | tab.image(() -> { 38 | if(troop.isEmpty()) return Icon.cancel.getRegion(); 39 | Unit unit = Groups.unit.getByID(troop.peek()); 40 | if(unit == null) return Icon.cancel.getRegion(); 41 | return unit.type.fullIcon; 42 | }).size(10).padRight(10); 43 | tab.label(() -> { 44 | int amount = 0; 45 | for(int id : troop.toArray()) { 46 | Unit unit = Groups.unit.getByID(id); 47 | if(unit != null && !unit.dead()) amount++; 48 | } 49 | return String.valueOf(amount); 50 | }).minWidth(30).fontScale(0.5f); 51 | tab.table(icons -> { 52 | icons.defaults().size(10).padLeft(10).grow(); 53 | icons.image(Icon.cancelSmall).color(Pal.health).get().clicked(troop::clear); 54 | icons.image(Icon.upSmall).color(Pal.heal).size(10).get().clicked(() -> TroopingManager.updateTrooping(i)); 55 | icons.image(Icon.addSmall).color(Pal.gray).size(10).get().clicked(() -> TroopingManager.applyTrooping(i)); 56 | }).padLeft(10).grow(); 57 | }).pad(10).grow(); 58 | list.row(); 59 | list.image().height(2f).color(Pal.gray).grow(); 60 | list.row(); 61 | }); 62 | }); 63 | 64 | update(() -> { 65 | int i = 0; 66 | for(KeyCode numCode : KeyCode.numbers) { 67 | if(input.keyTap(numCode)) { 68 | if(input.keyDown(KeyCode.altLeft)) TroopingManager.applyTrooping(i); 69 | else if(input.keyDown(KeyCode.capsLock)) TroopingManager.updateTrooping(i); 70 | else TroopingManager.selectTrooping(i); 71 | break; 72 | } 73 | i++; 74 | } 75 | }); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/TroopingManager.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar; 2 | 3 | import arc.struct.IntSeq; 4 | import arc.struct.Seq; 5 | import informatis.SUtils; 6 | import mindustry.Vars; 7 | import mindustry.gen.Groups; 8 | import mindustry.gen.Unit; 9 | 10 | public class TroopingManager { 11 | static final Seq troops = new Seq<>(10) {{ 12 | SUtils.loop(10, (i) -> { 13 | add(new IntSeq()); 14 | }); 15 | }}; 16 | 17 | public static void applyTrooping(int index) { 18 | IntSeq seq = troops.get(index); 19 | Vars.control.input.selectedUnits.each(unit -> seq.add(unit.id)); 20 | } 21 | 22 | public static void selectTrooping(int index) { 23 | Vars.control.input.commandMode = true; 24 | Vars.control.input.selectedUnits.clear(); 25 | IntSeq troop = troops.get(index); 26 | for(int i = 0; i < troop.size; i++) { 27 | int id = troop.get(i); 28 | Unit unit = Groups.unit.getByID(id); 29 | if(unit != null) Vars.control.input.selectedUnits.add(unit); 30 | } 31 | } 32 | 33 | public static void updateTrooping(int index) { 34 | IntSeq seq = troops.get(index); 35 | seq.clear(); 36 | Vars.control.input.selectedUnits.each(unit -> seq.add(unit.id)); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/dialogs/DialogManager.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.dialogs; 2 | 3 | import arc.scene.ui.Dialog; 4 | import arc.scene.ui.layout.Table; 5 | import mindustry.gen.Icon; 6 | 7 | public class DialogManager { 8 | public static Dialog resourcePreview; 9 | public static Table body; 10 | 11 | public static void init() { 12 | resourcePreview = new ResourcePreviewDialog(); 13 | 14 | body = new Table(t -> { 15 | t.button(Icon.file, () -> resourcePreview.show()); 16 | }); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/dialogs/ResourcePreviewDialog.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.dialogs; 2 | 3 | import arc.func.*; 4 | import arc.graphics.*; 5 | import arc.graphics.g2d.*; 6 | import arc.input.KeyCode; 7 | import arc.scene.Element; 8 | import arc.scene.style.*; 9 | import arc.scene.ui.*; 10 | import arc.scene.ui.layout.*; 11 | import arc.scene.utils.Elem; 12 | import arc.struct.*; 13 | import arc.util.*; 14 | import informatis.ui.components.*; 15 | import mindustry.gen.*; 16 | import mindustry.graphics.*; 17 | import mindustry.ui.*; 18 | import mindustry.ui.dialogs.*; 19 | 20 | import java.lang.reflect.Field; 21 | import java.util.Objects; 22 | 23 | public class ResourcePreviewDialog extends BaseDialog { 24 | private final PageTabsFragment tabsFragment = new PageTabsFragment( 25 | "Textures", new TexturePreviewFragment(), 26 | "Styles", new StylePreviewFragment(), 27 | "Colors", new ColorPreviewFragment() 28 | ); 29 | 30 | public ResourcePreviewDialog() { 31 | super("resource previews"); 32 | setFillParent(true); 33 | addCloseButton(); 34 | 35 | cont.add(tabsFragment).growX(); 36 | cont.row(); 37 | cont.add(tabsFragment.content).grow(); 38 | } 39 | } 40 | 41 | class TexturePreviewFragment extends Table { 42 | boolean showName = false; 43 | String search = ""; 44 | 45 | private final TabsFragment tabsFragment = new TabsFragment("Texture Resources", "Icon Resources"); 46 | 47 | public TexturePreviewFragment() { 48 | super(); 49 | 50 | ScrollPane pane = new ScrollPane(tabsFragment.currentTabIndex == 0 ? buildTexResources() : buildIconResources()); 51 | refreshPane(pane); 52 | 53 | add(tabsFragment).growX(); 54 | row(); 55 | table(options -> { 56 | options.top().center(); 57 | options.table(t -> { 58 | t.button(Icon.zoom, () -> refreshPane(pane)); 59 | t.field(search, value -> search = value).get().keyDown(KeyCode.enter, () -> refreshPane(pane)); 60 | }).minWidth(200).pad(20); 61 | options.check("show resource with its name", showName, (checkBox) -> { 62 | showName = !showName; 63 | refreshPane(pane); 64 | }).pad(20); 65 | }).padBottom(20f).growX(); 66 | row(); 67 | add(pane).grow(); 68 | 69 | tabsFragment.eventEmitter.subscribe(TabsFragment.Event.TabChanged, () -> refreshPane(pane)); 70 | } 71 | 72 | void refreshPane(ScrollPane pane) { 73 | pane.setWidget(tabsFragment.currentTabIndex == 0 ? buildTexResources() : buildIconResources()); 74 | } 75 | 76 | Table buildIconResources() { 77 | return new Table(table -> { 78 | int r = 0; 79 | for(ObjectMap.Entry entry : Icon.icons.entries()) { 80 | if(!entry.key.contains(search)) continue; 81 | addResourceImage(table, entry.value, entry.key, 0); 82 | if(++r % 15 == 0) table.row(); 83 | } 84 | }); 85 | } 86 | 87 | Table buildTexResources() { 88 | return new Table(table -> { 89 | Field[] fields = Tex.class.getDeclaredFields(); 90 | int r = 0; 91 | for(int i = 0; i < fields.length; i++) { 92 | Field field = fields[i]; 93 | if(!field.getName().contains(search)) continue; 94 | addResourceImage(table, Reflect.get(field), field.getName(), i); 95 | if(++r % 15 == 0) table.row(); 96 | } 97 | }); 98 | } 99 | 100 | void addResourceImage(Table table, Drawable res, String name, int i) { 101 | table.table(t -> { 102 | t.center().defaults(); 103 | 104 | Image image = new Image(res).setScaling(Scaling.bounded); 105 | if(!showName) { 106 | t.add(image).size(100); 107 | } else { 108 | Label label = new Label(name); 109 | label.setWidth(100); 110 | label.setFontScale(0.75f); 111 | label.setAlignment(Align.center); 112 | t.stack( 113 | new Table(tt -> { 114 | tt.center(); 115 | tt.add(image).size(100); 116 | }), 117 | new Table(tt -> { 118 | tt.center(); 119 | tt.addChild(label); 120 | label.setPosition(t.x + t.getWidth() / 2, label.y + (name.length() >= 13 && i % 2 == 0 ? -label.getHeight() * 0.9f : 0)); 121 | tt.pack(); 122 | }) 123 | ).center().maxSize(100); 124 | } 125 | }).size(100).pad(10).tooltip(name); 126 | } 127 | } 128 | 129 | class StylePreviewFragment extends Table { 130 | private final PageTabsFragment tabsFragment = new PageTabsFragment( 131 | "Drawable", buildStyleTable(Drawable.class), 132 | "ButtonStyle", buildStyleTable(Button.ButtonStyle.class), 133 | "TextButtonStyle", buildStyleTable(TextButton.TextButtonStyle.class), 134 | "ImageButtonsStyle", buildStyleTable(ImageButton.ImageButtonStyle.class) 135 | ); 136 | 137 | public StylePreviewFragment() { 138 | super(); 139 | 140 | add(tabsFragment).growX(); 141 | row(); 142 | pane(tabsFragment.content).grow(); 143 | } 144 | 145 | private Table buildStyleTable(Class styleClass) { 146 | return new Table(table -> { 147 | table.top().left().defaults().labelAlign(Align.center).center().maxHeight(50).pad(10).grow(); 148 | 149 | Seq defaultStyles = Seq.select(Styles.class.getFields(), field -> field.getType().equals(styleClass)); 150 | if (styleClass.equals(Drawable.class)) { 151 | for (Field field : defaultStyles) { 152 | table.table(tt -> { 153 | tt.left(); 154 | tt.add(field.getName()); 155 | tt.image(Reflect.get(field)).grow().padLeft(40f); 156 | }); 157 | table.row(); 158 | } 159 | return; 160 | } 161 | 162 | Seq styleFields = Seq.select(styleClass.getFields(), style -> defaultStyles.contains(field -> { 163 | Object value = Reflect.get(Reflect.get(field), style); 164 | return !(value == null || value instanceof Font || value.toString().matches("^\\d*.\\d*$")); //wtf 165 | })); 166 | 167 | table.add("styles\\fields").center(); 168 | styleFields.each(style -> table.table(tt -> { 169 | tt.center(); 170 | tt.add(style.getName()); 171 | })); 172 | table.row(); 173 | table.image().height(4f).color(Pal.accent).growX().colspan(styleFields.size + 1).row(); 174 | for (Field defaultStyle : defaultStyles) { 175 | table.add(defaultStyle.getName()); 176 | styleFields.each(styleField -> { 177 | table.table(tt -> { 178 | Object value = Reflect.get(Reflect.get(defaultStyle), styleField); //. ex) . 179 | tt.center(); 180 | if (value == null) tt.add(""); 181 | else if (value instanceof Drawable drawable) tt.image(drawable).grow(); 182 | else tt.add(value.toString()).color(value.toString().matches("^#?[a-fA-F0-9]{6,8}$") 183 | ? Color.valueOf(value.toString()) 184 | : Color.gray 185 | ); 186 | }); 187 | }); 188 | table.row(); 189 | table.image().height(4f).color(Pal.gray).growX().colspan(styleFields.size + 1); 190 | table.row(); 191 | } 192 | }); 193 | } 194 | } 195 | 196 | class ColorPreviewFragment extends Table { 197 | private final PageTabsFragment tabsFragment = new PageTabsFragment( 198 | "Colors", buildColors(Color.class), 199 | "Pal", buildColors(Pal.class) 200 | ); 201 | private final ColorMixer colorMixer = new ColorMixer(); 202 | 203 | public ColorPreviewFragment() { 204 | super(); 205 | 206 | add(colorMixer).growX(); 207 | row(); 208 | add(tabsFragment).growX(); 209 | row(); 210 | pane(tabsFragment.content).grow(); 211 | } 212 | 213 | Table buildColors(Class colorClass) { 214 | final String[] cachedId = {""}; 215 | return new IntervalTableWrapper(t -> { 216 | t.top().left().defaults().maxWidth(300).pad(20); 217 | 218 | float sum = 0; 219 | for(Field colorField : colorClass.getDeclaredFields()) { 220 | if(!colorField.getType().equals(Color.class)) continue; 221 | 222 | Color color = Reflect.get(colorField); 223 | sum += t.table(colorCell -> { 224 | colorCell.left(); 225 | colorCell.image().size(30).color(color); 226 | colorCell.add(colorField.getName()).padLeft(10); 227 | colorCell.clicked(() -> { 228 | if(colorMixer.currentField != null) colorMixer.currentField.setter.get(color); 229 | }); 230 | }).tooltip("#" + color.toString()).growX().maxWidth(); 231 | 232 | if(sum >= getWidth()) { 233 | sum -= getWidth(); 234 | t.row(); 235 | } 236 | } 237 | }, table -> { 238 | if(!Objects.equals(cachedId[0], getWidth() + ":" + tabsFragment.currentTabIndex)) { 239 | cachedId[0] = getWidth()+":"+tabsFragment.currentTabIndex; 240 | return true; 241 | } 242 | return false; 243 | }, 60).build(); 244 | } 245 | 246 | static class ColorMixer extends Table { 247 | @Nullable 248 | public FieldColorLabel currentField; 249 | public float colorMixProgress = 0; 250 | public Color color1 = Color.white, color2 = Color.white; 251 | 252 | public ColorMixer() { 253 | top().center().defaults().pad(20); 254 | 255 | table(table -> { 256 | table.add(new FieldColorLabel(() -> color1, color -> color1 = color)); 257 | table.slider(0, 100, 1, 0, progress -> colorMixProgress = progress); 258 | table.add(new FieldColorLabel(() -> color2, color -> color2 = color)); 259 | }); 260 | row(); 261 | add(new ColorLabel(() -> color1.cpy().lerp(color2, colorMixProgress / 100))); 262 | } 263 | 264 | class FieldColorLabel extends ColorLabel { 265 | public final Cons setter; 266 | 267 | public FieldColorLabel(Prov color, Cons setter) { 268 | super(color); 269 | this.setter = setter; 270 | } 271 | 272 | protected Image buildImage() { 273 | return new Image() { 274 | @Override 275 | public void draw() { 276 | this.setColor(FieldColorLabel.this.color.get()); 277 | super.draw(); 278 | int size = 8; 279 | Draw.color(currentField == FieldColorLabel.this ? Pal.accent : Pal.gray); 280 | Draw.alpha(parentAlpha); 281 | Lines.stroke(Scl.scl(3f)); 282 | Lines.rect(x - size / 2f, y - size / 2f, width + size, height + size); 283 | Draw.reset(); 284 | } 285 | { 286 | clicked(() -> { 287 | if(currentField == FieldColorLabel.this) currentField = null; 288 | else currentField = FieldColorLabel.this; 289 | }); 290 | } 291 | }; 292 | } 293 | 294 | protected Element buildLabel() { 295 | TextField field = Elem.newField(color.get().toString(), (value) -> setter.get(Color.valueOf(value.matches("^#?[a-fA-F0-9]{6,8}$") ? value : "ffffff"))); 296 | field.update(() -> { 297 | field.setText(color.get().toString()); 298 | }); 299 | return field; 300 | } 301 | } 302 | 303 | static class ColorLabel extends Table { 304 | protected final Prov color; 305 | 306 | public ColorLabel(Prov color) { 307 | this.color = color; 308 | add(buildImage()).size(30).pad(10); 309 | add(buildLabel()); 310 | } 311 | 312 | protected Image buildImage() { 313 | return new Image(){ 314 | @Override 315 | public void draw() { 316 | this.setColor(ColorLabel.this.color.get()); 317 | super.draw(); 318 | } 319 | }; 320 | } 321 | 322 | protected Element buildLabel() { 323 | return new Label(() -> color.get().toString()); 324 | } 325 | } 326 | } 327 | } 328 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/CoreWindow.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows; 2 | 3 | import arc.*; 4 | import informatis.SUtils; 5 | import informatis.ui.components.SBar; 6 | import mindustry.game.*; 7 | import arc.graphics.*; 8 | import arc.math.*; 9 | import arc.scene.event.*; 10 | import arc.scene.ui.*; 11 | import arc.scene.ui.layout.*; 12 | import arc.struct.*; 13 | import arc.util.*; 14 | import mindustry.*; 15 | import mindustry.content.*; 16 | import mindustry.core.*; 17 | import mindustry.gen.*; 18 | import mindustry.graphics.*; 19 | import mindustry.type.*; 20 | import mindustry.ui.*; 21 | import mindustry.world.blocks.storage.*; 22 | 23 | import static mindustry.Vars.*; 24 | 25 | public class CoreWindow extends Window { 26 | Table window; 27 | float heat; 28 | final ObjectMap itemData = new ObjectMap<>(); 29 | 30 | public CoreWindow() { 31 | super(Icon.list, "core"); 32 | height = 300; 33 | width = 300; 34 | 35 | resetUsed(); 36 | 37 | Events.run(EventType.Trigger.update, () -> { 38 | heat += Time.delta; 39 | if(heat >= 60f) { 40 | heat = 0f; 41 | ScrollPane pane = find("core-pane"); 42 | pane.setWidget(rebuild()); 43 | for(Team team : getTeams()) { 44 | if(!itemData.containsKey(team)) itemData.put(team, new ItemData()); 45 | itemData.get(team).updateItems(team); 46 | } 47 | } 48 | }); 49 | } 50 | 51 | @Override 52 | public void buildBody(Table table) { 53 | window = table; 54 | 55 | table.background(Styles.black8).top(); 56 | table.pane(Styles.noBarPane, rebuild()).grow().name("core-pane").get().setScrollingDisabled(true, false); 57 | Events.on(EventType.WorldLoadEvent.class, e -> resetUsed()); 58 | } 59 | 60 | Table rebuild() { 61 | return new Table(table -> { 62 | table.top(); 63 | for(Team team : getTeams()) { 64 | table.table(row-> { 65 | row.center(); 66 | row.add(setTable(team)).margin(8f).row(); 67 | row.image().height(4f).color(team.color).growX(); 68 | }).growX().row(); 69 | } 70 | }); 71 | } 72 | 73 | public Seq getTeams(){ 74 | return Seq.with(Team.all).filter(Team::active); 75 | } 76 | 77 | public void resetUsed(){ 78 | for(Team team : getTeams()) { 79 | itemData.put(team, new ItemData()); 80 | } 81 | } 82 | 83 | public Table setTable(Team team){ 84 | return new Table(table -> { 85 | table.add(team.name).color(team.color).row(); 86 | int max = Math.max(1, Math.round(window.getWidth()/2/60)); 87 | table.table(coretable -> { 88 | int row = 0; 89 | 90 | for(CoreBlock.CoreBuild core : team.cores()) { 91 | coretable.table(tt -> { 92 | tt.stack( 93 | new Table(s -> { 94 | s.center(); 95 | Image image = getCoreImage(core); 96 | Tooltip.Tooltips option = new Tooltip.Tooltips(); 97 | option.animations=false; 98 | s.add(image).size(iconLarge).get().addListener(new Tooltip(tool -> { 99 | tool.background(Styles.black6).label(() -> "([#" + Tmp.c1.set(Color.green).lerp(Color.red, 1 - core.healthf()).toString() + "]" + Strings.fixed(core.health, 2) + "[]/" + Strings.fixed(core.block.health, 2) + ")"); 100 | }, option)); 101 | }), 102 | new Table(h -> { 103 | h.bottom().defaults().height(9f).width(iconLarge * 1.5f).growX(); 104 | h.add(new SBar("", Pal.health, () -> core.health / core.block.health)); 105 | h.pack(); 106 | }) 107 | ).row(); 108 | Label label = new Label(Strings.format("(@, @)",core.tileX(), core.tileY())); 109 | label.setFontScale(0.75f); 110 | tt.add(label); 111 | }).padTop(2).padLeft(4).padRight(4); 112 | if(row++ % max == max-1){ 113 | coretable.row(); 114 | } 115 | } 116 | }).row(); 117 | 118 | table.table(itemTable -> { 119 | int row = 0; 120 | 121 | CoreBlock.CoreBuild core = team.core(); 122 | if(core == null || core.items == null) { 123 | return; 124 | } 125 | for(int i = 0; i < Vars.content.items().size; i++){ 126 | Item item = Vars.content.item(i); 127 | if(!team.items().has(item)) continue; 128 | itemTable.stack( 129 | new Table(ttt -> { 130 | ttt.image(item.uiIcon).size(iconSmall).tooltip(tttt -> tttt.background(Styles.black6).add(item.localizedName).style(Styles.outlineLabel).margin(2f)); 131 | ttt.add(UI.formatAmount(core.items.get(item))).minWidth(5 * 8f).left(); 132 | }), 133 | new Table(ttt -> { 134 | ttt.bottom().right(); 135 | if(itemData == null || itemData.get(team) == null) return; 136 | int amount = itemData.get(team).updateItems.isEmpty()?0:Mathf.floor(itemData.get(team).updateItems.get(item.id).amount); 137 | Label label = new Label(amount + "/s"); 138 | label.setFontScale(0.65f); 139 | label.setColor(amount > 0 ? Color.green : amount == 0 ? Color.orange : Color.red); 140 | ttt.add(label).bottom().right().padTop(16f); 141 | ttt.pack(); 142 | })).padRight(3).left(); 143 | if(row++ % max == max-1){ 144 | itemTable.row(); 145 | } 146 | } 147 | }).row(); 148 | 149 | table.table(unitTable -> { 150 | int row = 0; 151 | 152 | for(UnitType unit : Vars.content.units()){ 153 | if(unit != UnitTypes.block && Groups.unit.contains(u -> u.type == unit && u.team == team)){ 154 | unitTable.table(tt -> { 155 | tt.center(); 156 | tt.image(unit.uiIcon).size(iconSmall).padRight(3).tooltip(ttt -> ttt.background(Styles.black6).add(unit.localizedName).style(Styles.outlineLabel).margin(2f)); 157 | tt.add(UI.formatAmount(Groups.unit.count(u -> u.team == team && u.type == unit))).padRight(3).minWidth(5 * 8f).left(); 158 | }); 159 | if(row++ % max == max-1){ 160 | unitTable.row(); 161 | } 162 | } 163 | } 164 | }); 165 | }); 166 | } 167 | 168 | private static Image getCoreImage(CoreBlock.CoreBuild core) { 169 | Image image = new Image(core.block.uiIcon); 170 | image.clicked(() -> SUtils.moveCamera(core)); 171 | HandCursorListener listener1 = new HandCursorListener(); 172 | image.addListener(listener1); 173 | image.update(() -> { 174 | image.color.lerp(!listener1.isOver() ? Color.lightGray : Color.white, Mathf.clamp(0.4f * Time.delta)); 175 | }); 176 | return image; 177 | } 178 | 179 | static class ItemData { 180 | final Seq prevItems = new Seq<>(); 181 | final Seq updateItems = new Seq<>(); 182 | 183 | ItemData() { 184 | resetItems(); 185 | } 186 | 187 | public void resetItems(){ 188 | Seq stacks = Vars.content.items().map(item -> new ItemStack(item, 0)); 189 | updateItems.clear().addAll(stacks); 190 | prevItems.clear().addAll(stacks); 191 | } 192 | 193 | public void updateItems(Team team){ 194 | CoreBlock.CoreBuild core = team.core(); 195 | if (core == null || core.items == null) return; 196 | 197 | Seq stack = updateItems; 198 | if(stack.isEmpty()) { 199 | Vars.content.items().each(i -> stack.add(new ItemStack(i, 0))); 200 | } 201 | 202 | for (Item item : Vars.content.items()) { 203 | stack.get(item.id).set(item, core.items.get(item) - prevItems.get(item.id).amount); 204 | prevItems.get(item.id).set(item, core.items.get(item)); 205 | } 206 | prevItems.clear().addAll(Vars.content.items().map(i -> new ItemStack(i, core.items.get(i)))); 207 | } 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/SettingConfiger.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows; 2 | 3 | import arc.Core; 4 | import informatis.ui.fragments.sidebar.windows.ToolConfigable; 5 | 6 | public class SettingConfiger implements ToolConfigable { 7 | public final String name; 8 | private boolean enabled; 9 | 10 | public SettingConfiger(String name) { 11 | this.name = name; 12 | this.enabled = Core.settings.getBool(name, false); 13 | } 14 | 15 | @Override 16 | public String getName() { 17 | return name; 18 | } 19 | 20 | @Override 21 | public boolean isEnabled() { 22 | return enabled; 23 | } 24 | 25 | 26 | @Override 27 | public void setEnabled(boolean value) { 28 | enabled = value; 29 | Core.settings.put(name, value); 30 | } 31 | 32 | @Override 33 | public ToolConfigable[] getSubConfigs() { 34 | return new ToolConfigable[0]; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/ToolConfigable.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows; 2 | 3 | public interface ToolConfigable { 4 | String getName(); 5 | void setEnabled(boolean value); 6 | boolean isEnabled(); 7 | ToolConfigable[] getSubConfigs(); 8 | } 9 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/ToolWindow.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows; 2 | 3 | import arc.graphics.Color; 4 | import arc.scene.ui.CheckBox; 5 | import arc.scene.ui.ScrollPane; 6 | import informatis.ui.fragments.sidebar.windows.tools.draws.*; 7 | import arc.scene.ui.layout.*; 8 | import arc.util.*; 9 | import informatis.ui.components.PageTabsFragment; 10 | import informatis.ui.fragments.sidebar.windows.tools.tools.ToolManager; 11 | import mindustry.gen.*; 12 | import mindustry.graphics.*; 13 | import mindustry.ui.*; 14 | 15 | import static arc.Core.*; 16 | import static mindustry.Vars.*; 17 | 18 | public class ToolWindow extends Window { 19 | private final PageTabsFragment tabsFragment = new PageTabsFragment( 20 | "OverDraw", buildOverDrawTable(), 21 | "Tools", rebuildToolsTable() 22 | ); 23 | 24 | public ToolWindow() { 25 | super(Icon.edit, "tool"); 26 | disableRootScroll = true; 27 | height = 300; 28 | width = 300; 29 | } 30 | 31 | @Override 32 | public void buildBody(Table table) { 33 | table.background(Styles.black8); 34 | table.add(tabsFragment).growX(); 35 | table.row(); 36 | table.add(tabsFragment.content).grow(); 37 | } 38 | 39 | private Table buildOverDrawTable() { 40 | final ScrollPane[] bodyScroll = new ScrollPane[1]; 41 | final OverDrawCategory[] categories = OverDrawCategory.values(); 42 | final float[] anchorPoints = new float[categories.length]; 43 | 44 | return new Table(mainTable -> { 45 | mainTable.top().left().defaults().top(); 46 | mainTable.table(sidebarTable -> { 47 | sidebarTable.top(); 48 | for (int i = 0; i < categories.length; i++) { 49 | final int j = i; 50 | final OverDrawCategory category = categories[i]; 51 | sidebarTable.button(category.icon, Styles.cleari, () -> { 52 | if(bodyScroll[0] == null) return; 53 | bodyScroll[0].setScrollY(anchorPoints[j]); 54 | }).size(iconLarge); 55 | sidebarTable.row(); 56 | } 57 | }).padRight(2 * 8f); 58 | bodyScroll[0] = mainTable.pane(Styles.smallPane, bodyTable -> { 59 | bodyTable.top().left().margin(12).defaults().growX(); 60 | for (int i = 0; i < categories.length; i++) { 61 | final OverDrawCategory category = categories[i]; 62 | 63 | //set current corrination to next point so that scroll position is not end of this element. 64 | anchorPoints[Math.min(i + 1, anchorPoints.length - 1)] = anchorPoints[i] + bodyTable.table(categoryTable -> { 65 | categoryTable.top().left().defaults().growX().left(); 66 | categoryTable.add(category.name).color(Pal.accent).labelAlign(Align.left); 67 | categoryTable.row(); 68 | categoryTable.image().color(Color.gray).height(2f).pad(8, 0, 8, 0); 69 | categoryTable.row(); 70 | categoryTable.table(configListTable -> { 71 | configListTable.top().left().defaults().left().grow(); 72 | for (ToolConfigable toolConfigable : OverDrawManager.draws.get(category)) { 73 | configListTable.add(buildConfigTable(toolConfigable)); 74 | configListTable.row(); 75 | } 76 | }); 77 | }).marginBottom(32f).prefHeight(); 78 | bodyTable.row(); 79 | } 80 | }).growX().get(); 81 | }); 82 | } 83 | 84 | private Table rebuildToolsTable() { 85 | return new Table(mainTable -> { 86 | mainTable.pane(Styles.smallPane, bodyTable -> { 87 | bodyTable.top().left().defaults().top().left().grow(); 88 | for (ToolConfigable toolConfigable : ToolManager.tools) { 89 | bodyTable.add(buildConfigTable(toolConfigable)); 90 | bodyTable.row(); 91 | } 92 | }).grow(); 93 | }); 94 | } 95 | 96 | private Table buildConfigTable(ToolConfigable toolConfigable) { 97 | return new Table(configTable -> { 98 | configTable.top().left().defaults().left().grow(); 99 | configTable.button(bundle.get("setting." + toolConfigable.getName() + ".name"), Styles.flatToggleMenut, () -> toolConfigable.setEnabled(!toolConfigable.isEnabled())) 100 | .tooltip(t -> { 101 | t.background(Styles.black8).add(bundle.get("setting." + toolConfigable.getName() + ".description")); 102 | }).checked(toolConfigable.isEnabled()).padBottom(4).get().getLabelCell().labelAlign(Align.left).pad(8, 16, 8, 8).get().setFontScale(0.9f); 103 | configTable.row(); 104 | if(toolConfigable.getSubConfigs().length == 0) return; 105 | configTable.table(subConfigTable -> { 106 | subConfigTable.left().defaults().left().padBottom(4).labelAlign(Align.left); 107 | 108 | for (ToolConfigable subConfigable : toolConfigable.getSubConfigs()) { 109 | CheckBox checkBox = subConfigTable.check(bundle.get("setting." + subConfigable.getName() + ".name"), subConfigable.isEnabled(), subConfigable::setEnabled) 110 | .tooltip(t -> { 111 | t.background(Styles.black8).add(bundle.get("setting." + subConfigable.getName() + ".description")); 112 | }).disabled(x -> !toolConfigable.isEnabled()).get(); 113 | checkBox.getLabel().setFontScale(0.8f); 114 | checkBox.getImage().setScale(0.7f); 115 | subConfigTable.row(); 116 | } 117 | }).pad(4, 24, 16, 4); 118 | }); 119 | } 120 | } -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/WaveWindow.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows; 2 | 3 | import mindustry.*; 4 | import mindustry.type.*; 5 | import arc.*; 6 | import arc.graphics.*; 7 | import arc.math.*; 8 | import arc.scene.event.*; 9 | import arc.scene.ui.*; 10 | import arc.scene.ui.layout.*; 11 | import arc.struct.*; 12 | import arc.util.*; 13 | import mindustry.content.*; 14 | import mindustry.game.*; 15 | import mindustry.gen.*; 16 | import mindustry.graphics.*; 17 | import mindustry.ui.*; 18 | 19 | import static arc.Core.*; 20 | import static mindustry.Vars.*; 21 | 22 | public class WaveWindow extends Window { 23 | ScrollPane wavePane; 24 | 25 | public WaveWindow() { 26 | super(Icon.waves, "wave"); 27 | disableRootScroll = true; 28 | height = 300; 29 | width = 300; 30 | 31 | Events.on(EventType.WorldLoadEvent.class, e -> { 32 | wavePane.clearChildren(); 33 | wavePane.setWidget(rebuild()); 34 | }); 35 | 36 | Events.on(EventType.WaveEvent.class, e -> { 37 | wavePane.clearChildren(); 38 | wavePane.setWidget(rebuild()); 39 | }); 40 | } 41 | 42 | @Override 43 | public void buildBody(Table table) { 44 | wavePane = new ScrollPane(rebuild(), Styles.noBarPane); 45 | table.top().background(Styles.black8).margin(40f).defaults().grow(); 46 | table.add(wavePane); 47 | table.row(); 48 | table.table(bottomTable -> { 49 | bottomTable.top().center().defaults().growX(); 50 | bottomTable.table(total -> { 51 | total.center(); 52 | total.label(() -> '~' + String.valueOf(state.wave) + '+'); 53 | total.field(String.valueOf(settings.getInt("wavemax")), f -> { 54 | String str = f.replaceAll("\\D", ""); 55 | settings.put("wavemax", str.isEmpty() ? 0 : Integer.parseInt(str)); 56 | }); 57 | total.table().update(units -> { 58 | units.clear(); 59 | units.left(); 60 | 61 | if(Groups.unit.count(u -> u.team == state.rules.waveTeam) <= 0) { 62 | units.add("[lightgray][]"); 63 | return; 64 | } 65 | 66 | int row = 0; 67 | int max = Math.max(1, Math.round(getWidth() / 2 / 8 / 2)); 68 | for (UnitType unit : Vars.content.units()) { 69 | int amount = Groups.unit.count(u -> u.type == unit && u.team == state.rules.waveTeam); 70 | if(amount <= 0) continue; 71 | units.stack( 72 | new Table(ttt -> { 73 | ttt.center(); 74 | ttt.image(unit.uiIcon).size(iconMed); 75 | ttt.pack(); 76 | }), 77 | new Table(ttt -> { 78 | ttt.bottom().left(); 79 | ttt.add(String.valueOf(amount)).padTop(2f).fontScale(0.9f); 80 | ttt.pack(); 81 | }) 82 | ).pad(2f); 83 | if(row++ % max == max - 1){ 84 | units.row(); 85 | } 86 | } 87 | }).growX(); 88 | }); 89 | bottomTable.row(); 90 | bottomTable.image().height(4f).color(Pal.gray); 91 | bottomTable.row(); 92 | bottomTable.table(option -> { 93 | option.check("Show empty wave", settings.getBool("emptywave"), b -> settings.put("emptywave", b)).margin(4f); 94 | option.check("Show previous wave", settings.getBool("pastwave"), b -> settings.put("pastwave", b)).margin(4f); 95 | }); 96 | }); 97 | } 98 | 99 | private ObjectIntMap getWaveGroup(int index) { 100 | ObjectIntMap groups = new ObjectIntMap<>(); 101 | for (SpawnGroup group : state.rules.spawns) { 102 | if (group.getSpawned(index) <= 0) continue; 103 | SpawnGroup sameTypeKey = groups.keys().toArray().find(g -> g.type == group.type && g.effect != StatusEffects.boss); 104 | if (sameTypeKey != null) groups.increment(sameTypeKey, sameTypeKey.getSpawned(index)); 105 | else groups.put(group, group.getSpawned(index)); 106 | } 107 | Seq groupSorted = groups.keys().toArray().copy().sort((g1, g2) -> { 108 | int boss = Boolean.compare(g1.effect != StatusEffects.boss, g2.effect != StatusEffects.boss); 109 | if (boss != 0) return boss; 110 | int hitSize = Float.compare(-g1.type.hitSize, -g2.type.hitSize); 111 | if (hitSize != 0) return hitSize; 112 | return Integer.compare(-g1.type.id, -g2.type.id); 113 | }); 114 | ObjectIntMap groupsTmp = new ObjectIntMap<>(); 115 | groupSorted.each(g -> groupsTmp.put(g, groups.get(g))); 116 | 117 | return groupsTmp; 118 | } 119 | 120 | private Table rebuild() { 121 | return new Table(table -> { 122 | table.touchable = Touchable.enabled; 123 | table.center().defaults().growX(); 124 | for (int i = settings.getBool("pastwave") ? 1 : state.wave; i <= Math.min(state.wave + settings.getInt("wavemax"), (state.isCampaign() && state.rules.winWave > 0 ? state.rules.winWave : Integer.MAX_VALUE)); i++) { 125 | final int index = i; 126 | 127 | if (state.rules.spawns.find(g -> g.getSpawned(index-1) > 0) == null && !settings.getBool("emptywave")) continue; 128 | 129 | table.table(waveRow -> { 130 | waveRow.left(); 131 | 132 | waveRow.add(String.valueOf(index)).update(label -> { 133 | Color color = Pal.accent; 134 | if (state.wave == index) color = Color.red; 135 | else if (state.wave - 1 == index && state.enemies > 0) color = Color.red.cpy().shiftHue(Time.time); 136 | label.setColor(color); 137 | }); 138 | waveRow.table(unitTable -> { 139 | unitTable.center(); 140 | 141 | if (state.rules.spawns.find(g -> g.getSpawned(index - 1) > 0) == null) { 142 | if (settings.getBool("emptywave")) unitTable.add(bundle.get("empty")); 143 | return; 144 | } 145 | 146 | ObjectIntMap groups = getWaveGroup(index-1); 147 | 148 | int row = 0; 149 | int max = Math.max(1, Math.round(getWidth() / 64) - 5); 150 | for (SpawnGroup group : groups.keys()) { 151 | int spawners = state.rules.waveTeam.cores().size + (group.type.flying ? spawner.countFlyerSpawns() : spawner.countGroundSpawns()); 152 | int amount = groups.get(group); 153 | unitTable.stack( 154 | new Table(ttt -> { 155 | ttt.center(); 156 | ttt.image(group.type.uiIcon).size(iconMed); 157 | ttt.pack(); 158 | }), 159 | new Table(ttt -> { 160 | ttt.bottom().left(); 161 | ttt.add(amount + "").padTop(2f).fontScale(0.9f); 162 | ttt.add("[gray]x" + spawners).padTop(10f).fontScale(0.7f); 163 | ttt.pack(); 164 | }), 165 | new Table(ttt -> { 166 | ttt.top().right(); 167 | ttt.image(Icon.warning.getRegion()).update(img -> img.setColor(Tmp.c2.set(Color.orange).lerp(Color.scarlet, Mathf.absin(Time.time, 2f, 1f)))).size(12f); 168 | ttt.visible(() -> group.effect == StatusEffects.boss); 169 | ttt.pack(); 170 | }) 171 | ).pad(2f).get().addListener(new Tooltip(to -> { 172 | to.background(Styles.black6); 173 | to.margin(4f).left(); 174 | to.add("[stat]" + group.type.localizedName + "[]"); 175 | to.row(); 176 | to.add(bundle.format("shar-stat-waveAmount", amount + " [lightgray]x" + spawners + "[]")); 177 | to.row(); 178 | to.add(bundle.format("shar-stat-waveShield", group.getShield(index - 1))); 179 | to.row(); 180 | if (group.effect != null && group.effect != StatusEffects.none) { 181 | to.add(bundle.get("shar-stat.waveStatus") + group.effect.emoji() + "[stat]" + group.effect.localizedName); 182 | } 183 | })); 184 | if(row++ % max == max - 1){ 185 | unitTable.row(); 186 | } 187 | } 188 | }).growX().margin(12f); 189 | }); 190 | table.row(); 191 | 192 | table.image().height(4f).color(Pal.gray); 193 | table.row(); 194 | } 195 | }); 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/Window.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows; 2 | 3 | import arc.*; 4 | import arc.func.*; 5 | import arc.input.*; 6 | import arc.math.Mathf; 7 | import arc.math.geom.*; 8 | import arc.scene.Element; 9 | import arc.scene.event.*; 10 | import arc.scene.style.*; 11 | import arc.scene.ui.layout.*; 12 | import arc.util.*; 13 | import mindustry.gen.*; 14 | import mindustry.ui.*; 15 | 16 | import static arc.Core.scene; 17 | 18 | public class Window extends Table { 19 | public final TextureRegionDrawable icon; 20 | @Nullable 21 | public final Cons
content; 22 | public boolean shown = false, disableRootScroll = false; 23 | 24 | public float minWindowWidth = 160; 25 | public final float minWindowHeight = 60; 26 | public static final float maxWindowWidth = Float.MAX_VALUE; 27 | public static final float maxWindowHeight = Float.MAX_VALUE; 28 | 29 | public Window(String name){ 30 | this(new TextureRegionDrawable(Core.atlas.find("clear")), name, null); 31 | } 32 | public Window(TextureRegionDrawable icon, String name){ 33 | this(icon, name, null); 34 | } 35 | public Window(TextureRegionDrawable icon, String name, @Nullable Cons
content) { 36 | this.icon = icon; 37 | this.name = name; 38 | this.content = content; 39 | 40 | addListener(new HandCursorListener() { 41 | @Override 42 | public void exit(InputEvent event, float x, float y, int pointer, Element toActor) { 43 | super.exit(event, x, y, pointer, toActor); 44 | scene.setScrollFocus(null); 45 | } 46 | }); 47 | } 48 | 49 | public void build() { 50 | float width = table(t -> { 51 | t.table(Tex.buttonEdge1, b -> { 52 | b.left(); 53 | b.image(icon.getRegion()).scaling(Scaling.fill).size(20f); 54 | b.add(Core.bundle.get("window." + name + ".name")).padLeft(20); 55 | }).grow(); 56 | 57 | t.table(Tex.buttonEdge3, b -> 58 | b.button(Icon.cancel, Styles.emptyi, () -> shown = false).grow() 59 | ).maxWidth(8 * 15f).growY(); 60 | 61 | t.touchable = Touchable.enabled; 62 | t.addListener(new DragHandleListener(this)); 63 | }).height(8 * 6f).growX().prefWidth(); 64 | this.minWindowWidth = Math.max(this.minWindowWidth, width); 65 | 66 | row(); 67 | table(Styles.black5, pt -> { 68 | pt.pane(Styles.noBarPane, new Table(this::buildBody)).scrollX(!disableRootScroll).scrollY(!disableRootScroll).grow(); 69 | }).grow(); 70 | row(); 71 | table(Styles.black5, t -> { 72 | t.right(); 73 | t.image(Icon.resizeSmall).size(20f).get().addListener(new ScaleInputListener(this)); 74 | }).height(8 * 2f).growX(); 75 | 76 | visible(() -> shown); 77 | update(() -> { 78 | setPosition( 79 | Mathf.clamp(x, 0, Core.graphics.getWidth() - getWidth()), 80 | Mathf.clamp(y, 0, Core.graphics.getHeight() - getHeight()) 81 | ); 82 | }); 83 | } 84 | 85 | protected void buildBody(Table t){ 86 | if(content != null) content.get(t); 87 | } 88 | 89 | public void toggle(){ 90 | shown = !shown; 91 | if(shown) toFront(); 92 | } 93 | 94 | private static class TouchPosInputListener extends InputListener { 95 | protected float lastX, lastY; 96 | 97 | @Override 98 | public boolean touchDown(InputEvent event, float x, float y, int pointer, KeyCode button) { 99 | Vec2 v = event.listenerActor.localToStageCoordinates(Tmp.v1.set(x, y)); 100 | lastX = v.x; 101 | lastY = v.y; 102 | return true; 103 | } 104 | 105 | @Override 106 | public void touchDragged(InputEvent event, float dx, float dy, int pointer) { 107 | Vec2 v = event.listenerActor.localToStageCoordinates(Tmp.v1.set(dx, dy)); 108 | lastX = v.x; 109 | lastY = v.y; 110 | } 111 | } 112 | 113 | private static class DragHandleListener extends TouchPosInputListener { 114 | final Window targetWindow; 115 | public DragHandleListener(Window targetWindow) { 116 | this.targetWindow = targetWindow; 117 | } 118 | 119 | @Override 120 | public boolean touchDown(InputEvent event, float x, float y, int pointer, KeyCode button) { 121 | Vec2 v = event.listenerActor.localToStageCoordinates(Tmp.v1.set(x, y)); 122 | lastX = v.x; 123 | lastY = v.y; 124 | targetWindow.toFront(); 125 | return true; 126 | } 127 | 128 | @Override 129 | public void touchDragged(InputEvent event, float dx, float dy, int pointer) { 130 | Vec2 v = event.listenerActor.localToStageCoordinates(Tmp.v1.set(dx, dy)); 131 | targetWindow.setPosition( targetWindow.x + (v.x - lastX), targetWindow.y + (v.y - lastY)); 132 | lastX = v.x; 133 | lastY = v.y; 134 | } 135 | } 136 | 137 | private static class ScaleInputListener extends TouchPosInputListener { 138 | final Window targetWindow; 139 | public ScaleInputListener(Window targetWindow) { 140 | this.targetWindow = targetWindow; 141 | } 142 | 143 | @Override 144 | public void touchDragged(InputEvent event, float dx, float dy, int pointer) { 145 | Vec2 v = event.listenerActor.localToStageCoordinates(Tmp.v1.set(dx, dy)); 146 | float w = v.x - lastX; 147 | float h = v.y - lastY; 148 | 149 | if(targetWindow.getWidth() < targetWindow.minWindowWidth) targetWindow.setWidth(targetWindow.minWindowWidth); 150 | if(targetWindow.getWidth() + w < targetWindow.minWindowWidth || targetWindow.getWidth() + w > Window.maxWindowWidth) w = 0; 151 | if(targetWindow.getHeight() - h < targetWindow.minWindowHeight || targetWindow.getHeight() - h > Window.maxWindowHeight) h = 0; 152 | targetWindow.sizeBy(w, -h); 153 | targetWindow.moveBy(0, h); 154 | lastX = v.x; 155 | lastY = v.y; 156 | } 157 | } 158 | } -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/WindowManager.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows; 2 | 3 | import arc.*; 4 | import arc.scene.ui.layout.Table; 5 | import arc.struct.*; 6 | import mindustry.*; 7 | import mindustry.ui.*; 8 | 9 | public class WindowManager { 10 | public static final Seq windows = new Seq<>(); 11 | public static UnitWindow unitWindow; 12 | public static MapEditorWindow mapEditorWindow; 13 | public static Table body; 14 | 15 | public static void init(){ 16 | windows.addAll( 17 | unitWindow = new UnitWindow(), 18 | new WaveWindow(), 19 | new CoreWindow(), 20 | new ToolWindow(), 21 | mapEditorWindow = new MapEditorWindow() 22 | ); 23 | 24 | // windows place for dragging 25 | Vars.ui.hudGroup.fill(t -> { 26 | t.name = "Windows"; 27 | for(Window window : windows) { 28 | window.build(); 29 | t.add(window).height(window.getHeight()).width(window.getWidth()); 30 | } 31 | }); 32 | 33 | body = new Table(t -> { 34 | t.name = "Window Buttons"; 35 | t.left(); 36 | 37 | for(Window window : windows){ 38 | t.button(window.icon, Styles.emptyi, () -> { 39 | window.parent.setLayoutEnabled(false); 40 | window.toggle(); 41 | for (Window w : windows) { 42 | w.setLayoutEnabled(true); 43 | } 44 | }).size(40f).tooltip(tt -> { 45 | tt.setBackground(Styles.black6); 46 | tt.label(() -> Core.bundle.get("window."+window.name+".name")).pad(2f); 47 | }); 48 | t.row(); 49 | } 50 | }).left(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/tools/draws/BlockBarDraw.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows.tools.draws; 2 | 3 | import arc.graphics.Color; 4 | import arc.graphics.g2d.Draw; 5 | import arc.graphics.g2d.Fill; 6 | import mindustry.gen.Building; 7 | import mindustry.graphics.Pal; 8 | import mindustry.world.Tile; 9 | import mindustry.world.blocks.ConstructBlock; 10 | import mindustry.world.blocks.defense.turrets.Turret; 11 | import mindustry.world.blocks.units.Reconstructor; 12 | import mindustry.world.blocks.units.UnitFactory; 13 | 14 | import static arc.Core.settings; 15 | import static informatis.SUtils.isInCamera; 16 | 17 | public class BlockBarDraw extends OverDraw { 18 | public BlockBarDraw() { 19 | super("blockBar"); 20 | } 21 | 22 | @Override 23 | public void onTile(Tile tile) { 24 | if(!isInCamera(tile.worldx(), tile.worldy(), 8) || tile.build == null) return; 25 | 26 | Building b = tile.build; 27 | 28 | if(settings.getBool("blockBar")) { 29 | drawBar(b, 0, -(b.block.size * 4 - 2), b.healthf(), Pal.health); 30 | 31 | if (b instanceof Turret.TurretBuild turretBuild) { 32 | drawBar(b, 0, b.block.size * 4 - 2, turretBuild.reloadCounter / ((Turret) b.block).reload, Pal.ammo); 33 | } 34 | if(b instanceof ConstructBlock.ConstructBuild constructBuild) 35 | drawBar(b, 0, b.block.size * 4 - 2, constructBuild.progress(), b.team.color); 36 | if(b instanceof Reconstructor.ReconstructorBuild reconstructorBuild) 37 | drawBar(b, 0, b.block.size * 4 - 2, reconstructorBuild.fraction(), b.team.color); 38 | if(b instanceof UnitFactory.UnitFactoryBuild factoryBuild) 39 | drawBar(b, 0, b.block.size * 4 - 2, factoryBuild.fraction(), b.team.color); 40 | } 41 | } 42 | 43 | void drawBar(Building b, float offsetX, float offsetY, float progress, Color color) { 44 | float bx = b.x + offsetX, by = b.y + offsetY; 45 | float width = b.block.size * 7.5f, height = 2; 46 | Draw.color(Pal.gray); 47 | Fill.quad( 48 | bx - width/2, by + height/2, 49 | bx - width/2, by - height/2, 50 | bx + width/2, by - height/2, 51 | bx + width/2, by + height/2); 52 | Draw.color(color); 53 | width = b.block.size * 7.5f - 0.5f; height = 2 - 0.5f; 54 | Fill.quad( 55 | bx - width/2, by + height/2, 56 | bx - width/2, by - height/2, 57 | bx - width/2 + width * progress, by - height/2, 58 | bx - width/2 + width * progress, by + height/2); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/tools/draws/BlockStatusDraw.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows.tools.draws; 2 | 3 | import arc.graphics.g2d.Draw; 4 | import arc.graphics.g2d.Fill; 5 | import mindustry.Vars; 6 | import mindustry.gen.Building; 7 | import mindustry.graphics.Pal; 8 | 9 | import static informatis.SUtils.isInCamera; 10 | 11 | public class BlockStatusDraw extends OverDraw { 12 | public BlockStatusDraw() { 13 | super("blockstatus"); 14 | } 15 | @Override 16 | public void onBuilding(Building build) { 17 | if(!isInCamera(build.x, build.y, build.block.size/2f)) return; 18 | if(build.team != Vars.player.team() && build.block.consumers.length > 0) { 19 | float multiplier = build.block.size > 1 ? 1.0F : 0.64F; 20 | float brcx = build.x + (float)(build.block.size * 8) / 2.0F - 8.0F * multiplier / 2.0F; 21 | float brcy = build.y - (float)(build.block.size * 8) / 2.0F + 8.0F * multiplier / 2.0F; 22 | Draw.z(71.0F); 23 | Draw.color(Pal.gray); 24 | Fill.square(brcx, brcy, 2.5F * multiplier, 45.0F); 25 | Draw.color(build.status().color); 26 | Fill.square(brcx, brcy, 1.5F * multiplier, 45.0F); 27 | Draw.color(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/tools/draws/CommandLineDraw.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows.tools.draws; 2 | 3 | import arc.graphics.g2d.Lines; 4 | import mindustry.ai.types.CommandAI; 5 | import mindustry.gen.Unit; 6 | 7 | public class CommandLineDraw extends OverDraw { 8 | public CommandLineDraw() { 9 | super("commandLine"); 10 | } 11 | 12 | @Override 13 | public void onUnit(Unit unit) { 14 | if(unit.controller() instanceof CommandAI com && com.targetPos != null) { 15 | Lines.stroke(1, unit.team.color); 16 | Lines.line(unit.x(), unit.y(), com.targetPos.x, com.targetPos.y); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/tools/draws/DistanceLineDraw.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows.tools.draws; 2 | 3 | import arc.graphics.g2d.Lines; 4 | import arc.math.Angles; 5 | import arc.math.Mathf; 6 | import arc.math.geom.Position; 7 | import arc.util.Align; 8 | import arc.util.Strings; 9 | import arc.util.Time; 10 | import arc.util.Tmp; 11 | import mindustry.gen.BlockUnitUnit; 12 | import mindustry.gen.Posc; 13 | import mindustry.graphics.Pal; 14 | import mindustry.ui.Fonts; 15 | 16 | import static arc.Core.*; 17 | import static informatis.SUtils.getTarget; 18 | import static mindustry.Vars.*; 19 | 20 | public class DistanceLineDraw extends OverDraw { 21 | public DistanceLineDraw() { 22 | super("distanceLine"); 23 | } 24 | 25 | @Override 26 | public void draw() { 27 | float sin = Mathf.absin(Time.time, 6f, 1f); 28 | Posc from = player; 29 | Position to = getTarget(); 30 | if(to == from || to == null) to = input.mouseWorld(); 31 | if(player.unit() instanceof BlockUnitUnit bu) Tmp.v1.set(bu.x() + bu.tile().block.offset, bu.y() + bu.tile().block.offset).sub(to.getX(), to.getY()).limit(bu.tile().block.size * tilesize + sin + 0.5f); 32 | else Tmp.v1.set(from.x(), from.y()).sub(to.getX(), to.getY()).limit((player.unit() == null ? 0 : player.unit().hitSize) + sin + 0.5f); 33 | 34 | float x2 = from.x() - Tmp.v1.x, y2 = from.y() - Tmp.v1.y, x1 = to.getX() + Tmp.v1.x, y1 = to.getY() + Tmp.v1.y; 35 | int segs = (int) (to.dst(from.x(), from.y()) / tilesize); 36 | if(segs > 0){ 37 | Lines.stroke(2.5f, Pal.gray); 38 | Lines.dashLine(x1, y1, x2, y2, segs); 39 | Lines.stroke(1f, Pal.placing); 40 | Lines.dashLine(x1, y1, x2, y2, segs); 41 | 42 | Fonts.outline.draw(Strings.fixed(to.dst(from.x(), from.y()), 2) + " (" + segs + " " + bundle.get("tiles") + ")", 43 | from.x() + Angles.trnsx(Angles.angle(from.x(), from.y(), to.getX(), to.getY()), player.unit().hitSize() + Math.min(segs, 6) * 8f), 44 | from.y() + Angles.trnsy(Angles.angle(from.x(), from.y(), to.getX(), to.getY()), player.unit().hitSize() + Math.min(segs, 6) * 8f) - 3, 45 | Pal.accent, 0.25f, false, Align.center); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/tools/draws/LogicLineDraw.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows.tools.draws; 2 | 3 | import arc.graphics.g2d.Lines; 4 | import arc.math.Mathf; 5 | import arc.util.Tmp; 6 | import mindustry.ai.types.LogicAI; 7 | import mindustry.gen.Unit; 8 | import mindustry.graphics.Pal; 9 | import mindustry.logic.LUnitControl; 10 | 11 | public class LogicLineDraw extends OverDraw { 12 | public LogicLineDraw() { 13 | super("logicLine"); 14 | } 15 | 16 | @Override 17 | public void onUnit(Unit unit) { 18 | if(unit.controller() instanceof LogicAI ai && ai.controller != null && (ai.control == LUnitControl.approach || ai.control == LUnitControl.move)) { 19 | Lines.stroke(1, unit.team.color); 20 | Lines.line(unit.x(), unit.y(), ai.moveX, ai.moveY); 21 | Lines.stroke(0.5f + Mathf.absin(6f, 0.5f), Tmp.c1.set(Pal.logicOperations).lerp(Pal.sap, Mathf.absin(6f, 0.5f))); 22 | Lines.line(unit.x(), unit.y(), ai.controller.x, ai.controller.y); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/tools/draws/MagicCursorDraw.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows.tools.draws; 2 | 3 | import arc.Core; 4 | import arc.graphics.Color; 5 | import arc.util.Time; 6 | import arc.util.Tmp; 7 | import mindustry.Vars; 8 | import mindustry.content.Fx; 9 | 10 | import static mindustry.Vars.mobile; 11 | 12 | public class MagicCursorDraw extends OverDraw { 13 | public MagicCursorDraw() { 14 | super("gaycursor"); 15 | } 16 | 17 | @Override 18 | public void draw() { 19 | if(!mobile && !Vars.state.isPaused()) { 20 | Fx.mine.at(Core.input.mouseWorldX(), Core.input.mouseWorldY(), Tmp.c2.set(Color.red).shiftHue(Time.time * 1.5f)); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/tools/draws/MassLinkDraw.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows.tools.draws; 2 | 3 | import arc.graphics.g2d.Lines; 4 | import arc.math.Mathf; 5 | import arc.struct.Seq; 6 | import arc.util.Time; 7 | import arc.util.Tmp; 8 | import mindustry.gen.Building; 9 | import mindustry.gen.Groups; 10 | import mindustry.gen.Teamc; 11 | import mindustry.graphics.Drawf; 12 | import mindustry.graphics.Pal; 13 | import mindustry.world.blocks.distribution.MassDriver; 14 | import mindustry.world.blocks.payloads.PayloadMassDriver; 15 | 16 | import static informatis.SUtils.getTarget; 17 | import static mindustry.Vars.tilesize; 18 | import static mindustry.Vars.world; 19 | 20 | public class MassLinkDraw extends OverDraw { 21 | final Seq linkedMasses = new Seq<>(); 22 | final Seq linkedPayloadMasses = new Seq<>(); 23 | 24 | public MassLinkDraw() { 25 | super("massLink"); 26 | } 27 | 28 | 29 | @Override 30 | public void draw() { 31 | Teamc target = getTarget(); 32 | if(target instanceof Building build) { 33 | if (target instanceof MassDriver.MassDriverBuild mass) { 34 | linkedMasses.clear(); 35 | drawMassLink(mass); 36 | } else if (target instanceof PayloadMassDriver.PayloadDriverBuild mass) { 37 | linkedPayloadMasses.clear(); 38 | drawMassPayloadLink(mass); 39 | } 40 | } 41 | } 42 | 43 | 44 | void drawMassPayloadLink(PayloadMassDriver.PayloadDriverBuild from){ 45 | float sin = Mathf.absin(Time.time, 6f, 1f); 46 | 47 | //call every mass drivers that link to this driver 48 | for(Building b : Groups.build) { 49 | if (b != from && b instanceof PayloadMassDriver.PayloadDriverBuild fromMass && world.build(fromMass.link) == from && !linkedPayloadMasses.contains(fromMass)) { 50 | linkedPayloadMasses.add(fromMass); 51 | drawMassPayloadLink(fromMass); 52 | } 53 | } 54 | 55 | //get and draw line between this mass driver and linked one 56 | Building target = world.build(from.link); 57 | if(target instanceof PayloadMassDriver.PayloadDriverBuild targetDriver) { 58 | Tmp.v1.set(from.x + from.block.offset, from.y + from.block.offset).sub(targetDriver.x, targetDriver.y).limit(from.block.size * tilesize + sin + 0.5f); 59 | float x2 = from.x - Tmp.v1.x, y2 = from.y - Tmp.v1.y, x1 = targetDriver.x + Tmp.v1.x, y1 = targetDriver.y + Tmp.v1.y; 60 | int segs = (int) (targetDriver.dst(from.x, from.y) / tilesize); 61 | Lines.stroke(4f, Pal.gray); 62 | Lines.dashLine(x1, y1, x2, y2, segs); 63 | Lines.stroke(2f, Pal.placing); 64 | Lines.dashLine(x1, y1, x2, y2, segs); 65 | Lines.stroke(1f, Pal.accent); 66 | Drawf.circles(from.x, from.y, (from.tile.block().size / 2f + 1) * tilesize + sin - 2f, Pal.accent); 67 | Drawf.arrow(from.x, from.y, targetDriver.x, targetDriver.y, from.block.size * tilesize + sin, 4f + sin); 68 | for (Building shooter : from.waitingShooters) { 69 | Drawf.circles(shooter.x, shooter.y, (from.tile.block().size / 2f + 1) * tilesize + sin - 2f); 70 | Drawf.arrow(shooter.x, shooter.y, from.x, from.y, from.block.size * tilesize + sin, 4f + sin); 71 | } 72 | 73 | //call method again when target links to another mass driver which isn't stored in array 74 | if(!linkedPayloadMasses.contains(targetDriver)) { 75 | linkedPayloadMasses.add(targetDriver); 76 | drawMassPayloadLink(targetDriver); 77 | } 78 | } 79 | } 80 | 81 | void drawMassLink(MassDriver.MassDriverBuild from){ 82 | float sin = Mathf.absin(Time.time, 6f, 1f); 83 | 84 | //call every mass drivers that link to this driver 85 | for(Building b : Groups.build) { 86 | if (b != from && b instanceof MassDriver.MassDriverBuild fromMass && world.build(fromMass.link) == from && !linkedMasses.contains(fromMass)) { 87 | linkedMasses.add(fromMass); 88 | drawMassLink(fromMass); 89 | } 90 | } 91 | 92 | //get and draw line between this mass driver and linked one 93 | Building target = world.build(from.link); 94 | if(target instanceof MassDriver.MassDriverBuild targetDriver) { 95 | Tmp.v1.set(from.x + from.block.offset, from.y + from.block.offset).sub(targetDriver.x, targetDriver.y).limit(from.block.size * tilesize + sin + 0.5f); 96 | float x2 = from.x - Tmp.v1.x, y2 = from.y - Tmp.v1.y, x1 = targetDriver.x + Tmp.v1.x, y1 = targetDriver.y + Tmp.v1.y; 97 | int segs = (int) (targetDriver.dst(from.x, from.y) / tilesize); 98 | Lines.stroke(4f, Pal.gray); 99 | Lines.dashLine(x1, y1, x2, y2, segs); 100 | Lines.stroke(2f, Pal.placing); 101 | Lines.dashLine(x1, y1, x2, y2, segs); 102 | Lines.stroke(1f, Pal.accent); 103 | Drawf.circles(from.x, from.y, (from.tile.block().size / 2f + 1) * tilesize + sin - 2f, Pal.accent); 104 | Drawf.arrow(from.x, from.y, targetDriver.x, targetDriver.y, from.block.size * tilesize + sin, 4f + sin); 105 | for (Building shooter : from.waitingShooters) { 106 | Drawf.circles(shooter.x, shooter.y, (from.tile.block().size / 2f + 1) * tilesize + sin - 2f); 107 | Drawf.arrow(shooter.x, shooter.y, from.x, from.y, from.block.size * tilesize + sin, 4f + sin); 108 | } 109 | 110 | //call method again when target links to another mass driver which isn't stored in array 111 | if(!linkedMasses.contains(targetDriver)) { 112 | linkedMasses.add(targetDriver); 113 | drawMassLink(targetDriver); 114 | } 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/tools/draws/MemoViewDraw.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows.tools.draws; 2 | 3 | import mindustry.world.Tile; 4 | import mindustry.world.blocks.logic.MessageBlock; 5 | 6 | public class MemoViewDraw extends OverDraw { 7 | public MemoViewDraw() { 8 | super("memoView"); 9 | } 10 | 11 | @Override 12 | public void onTile(Tile tile) { 13 | if(tile.build instanceof MessageBlock.MessageBuild message) { 14 | message.drawSelect(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/tools/draws/OverDraw.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows.tools.draws; 2 | 3 | import informatis.ui.fragments.sidebar.windows.SettingConfiger; 4 | import informatis.ui.fragments.sidebar.windows.ToolConfigable; 5 | import mindustry.gen.Building; 6 | import mindustry.gen.Unit; 7 | import mindustry.world.Tile; 8 | 9 | public class OverDraw extends SettingConfiger { 10 | private final ToolConfigable[] subConfigs; 11 | 12 | public OverDraw(String name, String... subConfigNames) { 13 | super(name); 14 | subConfigs = new ToolConfigable[subConfigNames.length]; 15 | for(int i = 0; i < subConfigNames.length; i++) { 16 | subConfigs[i] = new SettingConfiger(subConfigNames[i]); 17 | } 18 | } 19 | 20 | @Override 21 | public ToolConfigable[] getSubConfigs() { 22 | return subConfigs; 23 | } 24 | 25 | /** 26 | * Groups.build 에서 각 건물에 대한 그리기를 처리합니다. 27 | * @param build 각 Building 엔티티 28 | */ 29 | public void onBuilding(Building build) { } 30 | 31 | /** 32 | * Groups.unit 에서 각 유닛에 대한 그리기를 처리합니다. 33 | * @param unit 각 Unit 엔티티 34 | */ 35 | public void onUnit(Unit unit) { } 36 | 37 | /** 38 | * Vars.world.tiles 에서 각 타일에 대한 그리기를 처리합니다. 39 | * @param tile 각 Tile 엔티티 40 | */ 41 | public void onTile(Tile tile) { } 42 | 43 | /** 44 | * 매 프레임에 대한 그리기를 처리합니다. 45 | */ 46 | public void draw() {} 47 | } 48 | 49 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/tools/draws/OverDrawCategory.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows.tools.draws; 2 | 3 | import arc.scene.style.Drawable; 4 | import mindustry.gen.Icon; 5 | 6 | public enum OverDrawCategory { 7 | Range("Range", Icon.commandRallySmall), 8 | Link("Link", Icon.lineSmall), 9 | Unit("Unit", Icon.unitsSmall), 10 | Block("Block", Icon.craftingSmall), 11 | Util("Util", Icon.githubSmall); 12 | 13 | public final String name; 14 | public final Drawable icon; 15 | 16 | OverDrawCategory(String name, Drawable icon) { 17 | this.name = name; 18 | this.icon = icon; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/tools/draws/OverDrawManager.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows.tools.draws; 2 | 3 | import arc.Core; 4 | import arc.Events; 5 | import arc.graphics.Color; 6 | import arc.graphics.g2d.Draw; 7 | import arc.graphics.gl.FrameBuffer; 8 | import arc.struct.*; 9 | import arc.util.Tmp; 10 | import informatis.shaders.Shaders; 11 | import mindustry.Vars; 12 | import mindustry.game.EventType; 13 | import mindustry.game.Team; 14 | import mindustry.gen.Building; 15 | import mindustry.gen.Groups; 16 | import mindustry.gen.Unit; 17 | import mindustry.world.Tile; 18 | 19 | import static arc.Core.graphics; 20 | 21 | public class OverDrawManager { 22 | public static final ObjectMap draws = ObjectMap.of( 23 | OverDrawCategory.Block, new OverDraw[]{ new BlockBarDraw(), new BlockStatusDraw(), new PowerNodeDraw(), new MemoViewDraw() }, 24 | OverDrawCategory.Unit, new OverDraw[] { new PathLineDraw(), new LogicLineDraw(), new CommandLineDraw(), new UnitPathLineDraw(), new UnitItemDraw(), new UnitBarDraw(), }, 25 | OverDrawCategory.Range, new OverDraw[] { new RangeDraw() }, 26 | OverDrawCategory.Link, new OverDraw[] { new UnitCargoLinkDraw(), new MassLinkDraw() }, 27 | OverDrawCategory.Util, new OverDraw[] { new MagicCursorDraw(),new SelectArrawDraw(), new SpawnerArrawDraw(), new DistanceLineDraw() } 28 | ); 29 | public static final Seq overDraws = new Seq<>(); 30 | public static final float[] zIndexTeamCache = new float[Team.baseTeams.length]; 31 | private static final FrameBuffer effectBuffer = new FrameBuffer(); 32 | 33 | public static void init() { 34 | for(OverDraw[] draws : draws.values()) { 35 | overDraws.addAll(draws); 36 | } 37 | 38 | for (int i = 0; i < Team.baseTeams.length; i++) { 39 | zIndexTeamCache[i] = 166 + (Team.baseTeams.length - Team.baseTeams[i].id) * 3 * 0.001f; 40 | } 41 | 42 | Events.run(EventType.Trigger.draw, () -> { 43 | Core.camera.bounds(Tmp.r1); 44 | effectBuffer.resize(graphics.getWidth(), graphics.getHeight()); 45 | for(float zIndex : zIndexTeamCache) { 46 | Draw.drawRange(zIndex, () -> effectBuffer.begin(Color.clear), () -> { 47 | effectBuffer.end(); 48 | effectBuffer.blit(Shaders.turretRange); 49 | }); 50 | } 51 | 52 | for(OverDraw draw : overDraws) { 53 | if(!draw.isEnabled()) continue; 54 | 55 | for(Building building : Groups.build) { 56 | draw.onBuilding(building); 57 | Draw.reset(); 58 | } 59 | 60 | for(Unit unit : Groups.unit) { 61 | draw.onUnit(unit); 62 | Draw.reset(); 63 | } 64 | 65 | for(Tile tile : Vars.world.tiles) { 66 | draw.onTile(tile); 67 | Draw.reset(); 68 | } 69 | draw.draw(); 70 | Draw.reset(); 71 | } 72 | }); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/tools/draws/PathLineDraw.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows.tools.draws; 2 | 3 | import arc.graphics.g2d.Lines; 4 | import arc.struct.Seq; 5 | import informatis.SUtils; 6 | import mindustry.world.Tile; 7 | 8 | import static mindustry.Vars.state; 9 | 10 | public class PathLineDraw extends OverDraw { 11 | public PathLineDraw() { 12 | super("pathLine"); 13 | } 14 | 15 | @Override 16 | public void draw() { 17 | Seq pathTiles = SUtils.generatePathTiles(); 18 | 19 | Lines.stroke(1, state.rules.waveTeam.color); 20 | for(int i = 0; i < pathTiles.size - 1; i++) { 21 | Tile from = pathTiles.get(i), to = pathTiles.get(i + 1); 22 | if(from == null || to == null) continue; 23 | Lines.line(from.worldx(), from.worldy(), to.worldx(), to.worldy()); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/tools/draws/PowerNodeDraw.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows.tools.draws; 2 | 3 | import arc.graphics.*; 4 | import arc.graphics.g2d.*; 5 | import arc.math.*; 6 | import arc.struct.*; 7 | import mindustry.core.*; 8 | import mindustry.gen.*; 9 | import mindustry.graphics.*; 10 | 11 | import static arc.Core.atlas; 12 | import static informatis.SUtils.getTarget; 13 | import static mindustry.Vars.tilesize; 14 | import static mindustry.Vars.world; 15 | 16 | public class PowerNodeDraw extends OverDraw { 17 | final Seq linkedNodes = new Seq<>(); 18 | 19 | public PowerNodeDraw() { 20 | super("powerNode"); 21 | } 22 | 23 | @Override 24 | public void draw() { 25 | if(getTarget() instanceof Building build) { 26 | linkedNodes.clear(); 27 | drawNodeLink(build); 28 | } 29 | } 30 | 31 | void drawNodeLink(Building node) { 32 | if(node.power == null) return; 33 | if(linkedNodes.contains(node)) return; 34 | 35 | linkedNodes.add(node); 36 | IntSeq seq = node.proximity().mapInt(Building::pos); 37 | seq.addAll(node.power.links); 38 | for(int i : seq.items) { 39 | Building other = world.build(i); 40 | if(other == null || other.power == null) return; 41 | float angle1 = Angles.angle(node.x, node.y, other.x, other.y), 42 | vx = Mathf.cosDeg(angle1), vy = Mathf.sinDeg(angle1), 43 | len1 = node.block.size * tilesize / 2f - 1.5f, len2 = other.block.size * tilesize / 2f - 1.5f; 44 | Draw.color(Color.white, Color.valueOf("98ff98"), (1f - node.power.graph.getSatisfaction()) * 0.86f + Mathf.absin(3f, 0.1f)); 45 | Draw.alpha(Renderer.laserOpacity); 46 | Drawf.laser(atlas.find("informatis-Slaser"), atlas.find("informatis-Slaser"), atlas.find("informatis-Slaser-end"), node.x + vx * len1, node.y + vy * len1, other.x - vx * len2, other.y - vy * len2, 0.25f); 47 | 48 | drawNodeLink(other); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/tools/draws/RangeDraw.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows.tools.draws; 2 | 3 | import arc.graphics.g2d.*; 4 | import informatis.ui.fragments.sidebar.windows.ToolConfigable; 5 | import mindustry.game.*; 6 | import mindustry.gen.*; 7 | import mindustry.graphics.*; 8 | import mindustry.logic.Ranged; 9 | import mindustry.world.blocks.defense.turrets.*; 10 | 11 | import static informatis.SUtils.isInCamera; 12 | import static mindustry.Vars.player; 13 | 14 | public class RangeDraw extends OverDraw { 15 | private final ToolConfigable blockRange, unitRange, airRange, groundRange, allianceRange, invalidRange, rangeShader; 16 | public RangeDraw() { 17 | super("range", "blockRange", "unitRange", "airRange", "groundRange", "allianceRange", "invalidRange", "rangeShader"); 18 | ToolConfigable[] subConfigs = getSubConfigs(); 19 | blockRange = subConfigs[0]; 20 | unitRange = subConfigs[1]; 21 | airRange = subConfigs[2]; 22 | groundRange = subConfigs[3]; 23 | allianceRange = subConfigs[4]; 24 | invalidRange = subConfigs[5]; 25 | rangeShader = subConfigs[6]; 26 | } 27 | private final static RangeData rangeData = new RangeData(); 28 | 29 | private boolean validate(Ranged target) { 30 | if(!isInCamera(target.x(), target.y(), target.range() * 2)) return false; 31 | 32 | if(!allianceRange.isEnabled() && player.team() == target.team()) return false; 33 | 34 | rangeData.init(target); 35 | if(groundRange.isEnabled() && rangeData.canDetectGround()) return true; 36 | return airRange.isEnabled() && rangeData.canDetectAir(); 37 | } 38 | 39 | @Override 40 | public void onBuilding(Building build) { 41 | if(!blockRange.isEnabled()) return; 42 | if(!(build instanceof BaseTurret.BaseTurretBuild turret)) return; 43 | if(!validate(turret)) return; 44 | drawRange(turret); 45 | } 46 | 47 | @Override 48 | public void onUnit(Unit unit) { 49 | if(!unitRange.isEnabled()) return; 50 | if(!validate(unit)) return; 51 | drawRange(unit); 52 | } 53 | 54 | private void drawRange(Ranged target) { 55 | boolean canShoot = rangeData.canShoot(); 56 | if(!canShoot && !invalidRange.isEnabled()) return; 57 | int index = canShoot ? target.team().id > 5 ? 2 : target.team().id : 0; 58 | float range = target.range(); 59 | Draw.color(Team.baseTeams[index].color.cpy().shiftSaturation(target instanceof Unit ? 0.25f : 0)); 60 | if (rangeShader.isEnabled()) { 61 | Draw.z(OverDrawManager.zIndexTeamCache[index]); 62 | Fill.poly(target.x(), target.y(), Lines.circleVertices(range), range); 63 | } else { 64 | Drawf.dashCircle(target.x(), target.y(), range, Team.baseTeams[index].color); 65 | } 66 | } 67 | } 68 | 69 | class RangeData { 70 | private boolean canDetectGround; // 지상유닛 감지 여부 71 | private boolean canDetectAir; // 지상유닛 감지 여부 72 | private boolean canShoot; // 실제로 발사가 가능한지 73 | 74 | public boolean canDetectGround() { 75 | return canDetectGround; 76 | } 77 | 78 | public boolean canDetectAir() { 79 | return canDetectAir; 80 | } 81 | 82 | public boolean canShoot() { 83 | return canShoot; 84 | } 85 | 86 | public void init(Entityc entity) { 87 | Unit playerUnit = player.unit(); 88 | 89 | boolean isAir = playerUnit == null || playerUnit.isFlying(), 90 | isGround = playerUnit == null || !playerUnit.isFlying(); 91 | 92 | if (entity instanceof Unit unit) { 93 | canDetectAir = unit.type.targetAir; 94 | canDetectGround = unit.type.targetGround; 95 | canShoot = unit.canShoot() && ((canDetectGround && isGround) || (canDetectAir && isAir)); 96 | } 97 | else if (entity instanceof BaseTurret.BaseTurretBuild build) { 98 | if (build instanceof Turret.TurretBuild turretBuild) { 99 | Turret block = (Turret) turretBuild.block; 100 | canDetectAir = block.targetAir; 101 | canDetectGround = block.targetGround; 102 | canShoot = turretBuild.hasAmmo() && ((canDetectGround && isGround) || (canDetectAir && isAir)); 103 | } else if (build instanceof TractorBeamTurret.TractorBeamBuild tractorBeamBuild) { 104 | TractorBeamTurret block = (TractorBeamTurret) tractorBeamBuild.block; 105 | canDetectAir = block.targetAir; 106 | canDetectGround = block.targetGround; 107 | canShoot = tractorBeamBuild.canConsume() && ((canDetectGround && isGround) || (canDetectAir && isAir)); 108 | } 109 | } 110 | } 111 | } -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/tools/draws/SelectArrawDraw.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows.tools.draws; 2 | 3 | import arc.graphics.Color; 4 | import arc.graphics.g2d.Draw; 5 | import arc.math.Angles; 6 | import arc.math.Mathf; 7 | import arc.util.Time; 8 | import arc.util.Tmp; 9 | import informatis.ui.fragments.sidebar.windows.WindowManager; 10 | import mindustry.gen.Building; 11 | import mindustry.gen.Teamc; 12 | import mindustry.gen.Unit; 13 | import mindustry.graphics.Layer; 14 | 15 | import static arc.Core.settings; 16 | import static informatis.SUtils.getTarget; 17 | import static mindustry.Vars.*; 18 | 19 | public class SelectArrawDraw extends OverDraw { 20 | public SelectArrawDraw() { 21 | super("select"); 22 | } 23 | 24 | @Override 25 | public void draw() { 26 | Teamc target = getTarget(); 27 | Draw.z(Layer.max); 28 | Draw.color(Tmp.c1.set(WindowManager.unitWindow.isLocked() ? Color.orange : Color.darkGray).lerp(WindowManager.unitWindow.isLocked() ? Color.scarlet : Color.gray, Mathf.absin(Time.time, 3f, 1f)).a(settings.getInt("selectopacity") / 100f)); 29 | 30 | float length = (target instanceof Unit u 31 | ? u.hitSize 32 | : target instanceof Building b 33 | ? b.block.size * tilesize 34 | : 0 35 | ) * 1.5f + 2.5f; 36 | 37 | for(int i = 0; i < 4; i++){ 38 | float rot = i * 90f + 45f + (-Time.time) % 360f; 39 | Draw.rect("select-arrow", target.x() + Angles.trnsx(rot, length), target.y() + Angles.trnsy(rot, length), length / 1.9f, length / 1.9f, rot - 135f); 40 | } 41 | 42 | Draw.color(); 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/tools/draws/SpawnerArrawDraw.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows.tools.draws; 2 | 3 | import arc.graphics.g2d.Draw; 4 | import arc.graphics.g2d.Lines; 5 | import arc.math.Mathf; 6 | import arc.util.Time; 7 | import arc.util.Tmp; 8 | import mindustry.graphics.Drawf; 9 | import mindustry.graphics.Layer; 10 | import mindustry.graphics.Pal; 11 | 12 | import static arc.Core.camera; 13 | import static mindustry.Vars.player; 14 | import static mindustry.Vars.spawner; 15 | 16 | public class SpawnerArrawDraw extends OverDraw { 17 | public SpawnerArrawDraw() { 18 | super("spawnerarrow"); 19 | } 20 | 21 | @Override 22 | public void draw() { 23 | Draw.z(Layer.max); 24 | float sin = Mathf.absin(Time.time, 6f, 1f); 25 | float leng = (player.unit() != null && player.unit().hitSize > 4 * 8f ? player.unit().hitSize * 1.5f : 4 * 8f) + sin; 26 | Tmp.v1.set(camera.position); 27 | Lines.stroke(1f + sin / 2, Pal.accent); 28 | Lines.circle(Tmp.v1.x, Tmp.v1.y, leng - 4f); 29 | spawner.getSpawns().each(t -> Drawf.arrow(Tmp.v1.x, Tmp.v1.y, t.worldx(), t.worldy(), leng, (Math.min(200 * 8f, Mathf.dst(Tmp.v1.x, Tmp.v1.y, t.worldx(), t.worldy())) / (200 * 8f)) * (5f + sin))); 30 | Draw.color(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/tools/draws/UnitBarDraw.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows.tools.draws; 2 | 3 | import informatis.ui.components.FreeBar; 4 | import mindustry.gen.Unit; 5 | 6 | public class UnitBarDraw extends OverDraw { 7 | public UnitBarDraw() { 8 | super("unitBar"); 9 | } 10 | 11 | @Override 12 | public void onUnit(Unit unit) { 13 | FreeBar.draw(unit); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/tools/draws/UnitCargoLinkDraw.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows.tools.draws; 2 | 3 | import arc.graphics.g2d.*; 4 | import mindustry.ai.types.CargoAI; 5 | import mindustry.gen.*; 6 | import mindustry.world.blocks.units.*; 7 | 8 | public class UnitCargoLinkDraw extends OverDraw { 9 | public UnitCargoLinkDraw() { 10 | super("unitCargoLink"); 11 | } 12 | 13 | @Override 14 | public void onBuilding(Building building) { 15 | if(building instanceof UnitCargoLoader.UnitTransportSourceBuild build) { 16 | Unit unit = build.unit; 17 | if(unit != null && unit.item() != null && unit.controller() instanceof CargoAI ai && ai.unloadTarget != null) { 18 | Building targetBuild = ai.unloadTarget; 19 | 20 | Lines.stroke(2); 21 | Draw.color(build.team.color); 22 | Draw.alpha(0.5f); 23 | Lines.line(build.x, build.y, unit.x, unit.y); 24 | Draw.color(unit.item().color); 25 | Draw.alpha(0.5f); 26 | Lines.line(unit.x, unit.y, targetBuild.x, targetBuild.y); 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/tools/draws/UnitItemDraw.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows.tools.draws; 2 | 3 | import arc.math.Angles; 4 | import arc.scene.ui.layout.Scl; 5 | import arc.util.Align; 6 | import mindustry.gen.Unit; 7 | import mindustry.graphics.Pal; 8 | import mindustry.ui.Fonts; 9 | 10 | import static informatis.SUtils.isInCamera; 11 | import static mindustry.Vars.renderer; 12 | 13 | public class UnitItemDraw extends OverDraw { 14 | public UnitItemDraw() { 15 | super("unitItem"); 16 | } 17 | 18 | @Override 19 | public void onUnit(Unit unit) { 20 | if(isInCamera(unit.x, unit.y, unit.hitSize) && !renderer.pixelator.enabled() && unit.item() != null && unit.itemTime > 0.01f) { 21 | Fonts.outline.draw(String.valueOf(unit.stack.amount), 22 | unit.x + Angles.trnsx(unit.rotation + 180f, unit.type.itemOffsetY), 23 | unit.y + Angles.trnsy(unit.rotation + 180f, unit.type.itemOffsetY) - 3, 24 | Pal.accent, 0.25f * unit.itemTime / Scl.scl(1f), false, Align.center); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/tools/draws/UnitPathLineDraw.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows.tools.draws; 2 | 3 | import arc.graphics.g2d.Lines; 4 | import arc.struct.Seq; 5 | import informatis.SUtils; 6 | import mindustry.ai.types.*; 7 | import mindustry.entities.units.UnitController; 8 | import mindustry.gen.Unit; 9 | import mindustry.world.Tile; 10 | 11 | import static mindustry.Vars.state; 12 | 13 | public class UnitPathLineDraw extends OverDraw { 14 | public UnitPathLineDraw() { 15 | super("unitPathLine"); 16 | } 17 | 18 | @Override 19 | public void onUnit(Unit unit) { 20 | UnitController c = unit.controller(); 21 | if(unit.team == state.rules.waveTeam && !unit.type.flying && !(c instanceof MinerAI || c instanceof BuilderAI || c instanceof RepairAI || c instanceof DefenderAI || c instanceof FlyingAI)) { 22 | Lines.stroke(1, unit.team.color); 23 | 24 | Seq pathTiles = SUtils.generatePathTiles(unit.tileOn(),unit.team, unit.controller() instanceof SuicideAI ? 0 : unit.pathType()); 25 | for(int i = 0; i < pathTiles.size - 1; i++) { 26 | Tile from = pathTiles.get(i), to = pathTiles.get(i + 1); 27 | if(from == null || to == null) continue; 28 | Lines.line(from.worldx(), from.worldy(), to.worldx(), to.worldy()); 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/tools/tools/AutoShooter.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows.tools.tools; 2 | import arc.input.KeyCode; 3 | import arc.math.Angles; 4 | import arc.math.geom.Geometry; 5 | import mindustry.entities.Units; 6 | import mindustry.game.Team; 7 | import mindustry.gen.*; 8 | import mindustry.logic.Ranged; 9 | import mindustry.world.blocks.ControlBlock; 10 | import mindustry.world.blocks.defense.turrets.Turret; 11 | import static arc.Core.*; 12 | import static mindustry.Vars.*; 13 | 14 | public class AutoShooter extends Tool { 15 | Teamc shotTarget; 16 | public AutoShooter() { 17 | super("autoShoot"); 18 | } 19 | 20 | @Override 21 | public void onUpdate() { 22 | Unit unit = player.unit(); 23 | if (unit.type == null) return; 24 | boolean omni = unit.type.omniMovement; 25 | boolean validHealTarget = unit.type.canHeal && shotTarget instanceof Building b && b.isValid() && b.damaged() && shotTarget.team() == unit.team && shotTarget.within(unit, unit.type.range); 26 | boolean boosted = (unit instanceof Mechc && unit.isFlying()); 27 | if ((unit.type != null && Units.invalidateTarget(shotTarget, unit, unit.type.range) && !validHealTarget) || state.isEditor()) { 28 | shotTarget = null; 29 | } 30 | float mouseAngle = unit.angleTo(unit.aimX(), unit.aimY()); 31 | boolean aimCursor = omni && player.shooting && unit.type.hasWeapons() && unit.type.faceTarget && !boosted && unit.type.rotateToBuilding; 32 | unit.lookAt(aimCursor ? mouseAngle : unit.prefRotation()); 33 | //update shooting if not building + not mining 34 | if(!player.unit().activelyBuilding() && player.unit().mineTile == null) { 35 | if(input.keyDown(KeyCode.mouseLeft)) { 36 | player.shooting = !boosted; 37 | unit.aim(player.mouseX = input.mouseWorldX(), player.mouseY = input.mouseWorldY()); 38 | } else if(shotTarget == null) { 39 | player.shooting = false; 40 | if(unit instanceof BlockUnitUnit b) { 41 | if(b.tile() instanceof ControlBlock c && !c.shouldAutoTarget()) { 42 | Building build = b.tile(); 43 | float range = build instanceof Ranged ? ((Ranged) build).range() : 0f; 44 | boolean targetGround = build instanceof Turret.TurretBuild && ((Turret) build.block).targetAir; 45 | boolean targetAir = build instanceof Turret.TurretBuild && ((Turret) build.block).targetGround; 46 | shotTarget = Units.closestTarget(build.team, build.x, build.y, range, u -> u.checkTarget(targetAir, targetGround), u -> targetGround); 47 | } 48 | else shotTarget = null; 49 | } else if(unit.type != null) { 50 | float range = unit.hasWeapons() ? unit.range() : 0f; 51 | shotTarget = Units.closestTarget(unit.team, unit.x, unit.y, range, u -> u.checkTarget(unit.type.targetAir, unit.type.targetGround), u -> unit.type.targetGround); 52 | if(unit.type.canHeal && shotTarget == null) { 53 | shotTarget = Geometry.findClosest(unit.x, unit.y, indexer.getDamaged(Team.sharded)); 54 | if (shotTarget != null && !unit.within(shotTarget, range)) { 55 | shotTarget = null; 56 | } 57 | } 58 | } 59 | } else { 60 | player.shooting = !boosted; 61 | unit.rotation(Angles.angle(unit.x, unit.y, shotTarget.x(), shotTarget.y())); 62 | unit.aim(shotTarget.x(), shotTarget.y()); 63 | } 64 | } 65 | unit.controlWeapons(player.shooting && !boosted); 66 | } 67 | } -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/tools/tools/CameraScaler.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows.tools.tools; 2 | 3 | import arc.Events; 4 | import mindustry.Vars; 5 | import mindustry.game.EventType; 6 | 7 | public class CameraScaler extends Tool { 8 | private float lastMinZoom = 1.5f; 9 | 10 | // TODO: set subconfig by slider later 11 | private final float targetMinZoom = 0.35f; 12 | 13 | public CameraScaler() { 14 | super("camerascaler"); 15 | 16 | Events.on(EventType.WorldLoadEndEvent.class, x -> { 17 | toggleScaler(); 18 | }); 19 | } 20 | 21 | @Override 22 | public void setEnabled(boolean value) { 23 | super.setEnabled(value); 24 | toggleScaler(); 25 | } 26 | 27 | private void toggleScaler() { 28 | if(isEnabled()) { 29 | lastMinZoom = Vars.renderer.minZoom; 30 | Vars.renderer.minZoom = targetMinZoom; 31 | } else { 32 | Vars.renderer.minZoom = lastMinZoom; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/tools/tools/FogRemover.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows.tools.tools; 2 | 3 | import arc.Events; 4 | import arc.graphics.Color; 5 | import mindustry.Vars; 6 | import mindustry.game.EventType; 7 | 8 | public class FogRemover extends Tool { 9 | Color lastStaticColor, lastDynamicColor; 10 | 11 | public FogRemover() { 12 | super("fogremover"); 13 | 14 | Events.on(EventType.WorldLoadEndEvent.class, x -> { 15 | toggleRemover(); 16 | }); 17 | } 18 | 19 | @Override 20 | public void setEnabled(boolean value) { 21 | super.setEnabled(value); 22 | toggleRemover(); 23 | } 24 | 25 | private void toggleRemover() { 26 | if(isEnabled()) { 27 | lastStaticColor = Vars.state.rules.staticColor; 28 | lastDynamicColor = Vars.state.rules.dynamicColor; 29 | Vars.state.rules.staticColor = Color.clear; 30 | Vars.state.rules.dynamicColor = Color.clear; 31 | } else { 32 | Vars.state.rules.staticColor = lastStaticColor == null ? Vars.state.rules.staticColor : lastStaticColor; 33 | Vars.state.rules.dynamicColor = lastDynamicColor == null ? Vars.state.rules.dynamicColor : lastDynamicColor; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/tools/tools/Tool.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows.tools.tools; 2 | 3 | import informatis.ui.fragments.sidebar.windows.SettingConfiger; 4 | 5 | public class Tool extends SettingConfiger { 6 | public Tool(String name) { 7 | super(name); 8 | } 9 | 10 | public void onUpdate() {} 11 | } 12 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/tools/tools/ToolManager.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows.tools.tools; 2 | 3 | import arc.Events; 4 | import mindustry.game.EventType; 5 | 6 | public class ToolManager { 7 | public static final Tool[] tools = new Tool[] { new FogRemover(), new CameraScaler(), new UnitVisualizer(), new AutoShooter() }; 8 | 9 | public static void init() { 10 | Events.run(EventType.Trigger.update, () -> { 11 | for (Tool tool : tools) { 12 | if(tool.isEnabled()) { 13 | tool.onUpdate(); 14 | } 15 | } 16 | }); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/informatis/ui/fragments/sidebar/windows/tools/tools/UnitVisualizer.java: -------------------------------------------------------------------------------- 1 | package informatis.ui.fragments.sidebar.windows.tools.tools; 2 | 3 | import arc.Core; 4 | import arc.Events; 5 | import arc.graphics.Color; 6 | import arc.graphics.g2d.Draw; 7 | import arc.graphics.gl.FrameBuffer; 8 | import arc.math.Mathf; 9 | import arc.struct.Seq; 10 | import arc.util.Log; 11 | import informatis.shaders.Shaders; 12 | import mindustry.game.EventType; 13 | import mindustry.graphics.Layer; 14 | 15 | public class UnitVisualizer extends Tool { 16 | Seq[] cachedTextures; 17 | final float[] layers = { Layer.flyingUnit, Layer.flyingUnitLow, Layer.legUnit, Layer.groundUnit}; 18 | final FrameBuffer buffer = new FrameBuffer(); 19 | float alpha = 1; 20 | 21 | public UnitVisualizer() { 22 | super("unitVisualizer"); 23 | 24 | Events.run(EventType.Trigger.draw, () -> { 25 | float alphaTo = isEnabled() ? 0.5f : 1f; 26 | alpha = Mathf.lerpDelta(alpha, alphaTo, 0.06f); 27 | Shaders.transparent.alpha = alpha; 28 | if (Mathf.equal(alpha, 1f)) return; 29 | Log.info(alpha); 30 | buffer.resize(Core.graphics.getWidth(), Core.graphics.getHeight()); 31 | for (float layer : layers) { 32 | Draw.drawRange(layer, () -> buffer.begin(Color.clear), () -> { 33 | buffer.end(); 34 | buffer.blit(Shaders.transparent); 35 | }); 36 | } 37 | }); 38 | } 39 | } 40 | /* 41 | Core.app.post(() -> { 42 | cachedTextures = new Seq[Vars.content.units().size]; 43 | 44 | Seq unitTypes = Vars.content.units(); 45 | for(int i = 0; i < cachedTextures.length; i++) { 46 | UnitType unitType = unitTypes.get(i); 47 | Seq regions = new Seq<>(); 48 | for (var part : unitType.parts) { 49 | regions.add(part); 50 | } 51 | regions.add((Object) null); 52 | 53 | for (var engine : unitType.engines) { 54 | regions.add(engine); 55 | } 56 | regions.add((Object) null); 57 | 58 | regions.add(unitType.baseRegion); 59 | regions.add(unitType.legRegion); 60 | regions.add(unitType.region); 61 | regions.add(unitType.previewRegion); 62 | regions.add(unitType.shadowRegion); 63 | regions.add(unitType.cellRegion); 64 | regions.add(unitType.itemCircleRegion); 65 | regions.add(unitType.softShadowRegion); 66 | regions.add(unitType.jointRegion); 67 | regions.add(unitType.footRegion); 68 | regions.add(unitType.legBaseRegion); 69 | regions.add(unitType.baseJointRegion); 70 | regions.add(unitType.outlineRegion); 71 | regions.add(unitType.treadRegion); 72 | 73 | for(Weapon weapon : unitType.weapons) { 74 | for (var part : weapon.parts) { 75 | regions.add(part); 76 | } 77 | regions.add((Object) null); 78 | regions.add(weapon.region); 79 | regions.add(weapon.cellRegion); 80 | regions.add(weapon.heatRegion); 81 | regions.add(weapon.outlineRegion); 82 | } 83 | cachedTextures[i] = regions; 84 | } 85 | }); 86 | } 87 | 88 | @Override 89 | public void setEnabled(boolean value) { 90 | super.setEnabled(value); 91 | if(this.isEnabled()) clearRegions(); 92 | else restoreRegions(); 93 | } 94 | 95 | private void restoreRegions() { 96 | Seq unitTypes = Vars.content.units(); 97 | for(int i = 0; i < cachedTextures.length; i++) { 98 | Iterator regions = cachedTextures[i].iterator(); 99 | UnitType unitType = unitTypes.get(i); 100 | while(true) { 101 | DrawPart region = (DrawPart) regions.next(); 102 | if(region == null) break; 103 | unitType.parts.add(region); 104 | } 105 | while(true) { 106 | UnitType.UnitEngine region = (UnitType.UnitEngine) regions.next(); 107 | if(region == null) break; 108 | unitType.engines.add(region); 109 | } 110 | 111 | 112 | unitType.baseRegion = (TextureRegion) regions.next(); 113 | unitType.legRegion = (TextureRegion) regions.next(); 114 | unitType.region = (TextureRegion) regions.next(); 115 | unitType.previewRegion = (TextureRegion) regions.next(); 116 | unitType.shadowRegion = (TextureRegion) regions.next(); 117 | unitType.cellRegion = (TextureRegion) regions.next(); 118 | unitType.itemCircleRegion = (TextureRegion) regions.next(); 119 | unitType.softShadowRegion = (TextureRegion) regions.next(); 120 | unitType.jointRegion = (TextureRegion) regions.next(); 121 | unitType.footRegion = (TextureRegion) regions.next(); 122 | unitType.legBaseRegion = (TextureRegion) regions.next(); 123 | unitType.baseJointRegion = (TextureRegion) regions.next(); 124 | unitType.outlineRegion = (TextureRegion) regions.next(); 125 | unitType.treadRegion = (TextureRegion) regions.next(); 126 | 127 | for(Weapon weapon : unitType.weapons) { 128 | while(true) { 129 | DrawPart part = (DrawPart) regions.next(); 130 | if(part == null) break; 131 | weapon.parts.add(part); 132 | } 133 | weapon.region = (TextureRegion) regions.next(); 134 | 135 | weapon.region = (TextureRegion) regions.next(); 136 | weapon.cellRegion = (TextureRegion) regions.next(); 137 | weapon.heatRegion = (TextureRegion) regions.next(); 138 | weapon.outlineRegion = (TextureRegion) regions.next(); 139 | } 140 | } 141 | } 142 | private void clearRegions() { 143 | Seq unitTypes = Vars.content.units(); 144 | for(int i = 0; i < cachedTextures.length; i++) { 145 | UnitType unitType = unitTypes.get(i); 146 | unitType.parts.clear(); 147 | unitType.engines.clear(); 148 | 149 | unitType.baseRegion = 150 | unitType.legRegion = 151 | unitType.region = 152 | unitType.previewRegion = 153 | unitType.shadowRegion = 154 | unitType.cellRegion = 155 | unitType.itemCircleRegion = 156 | unitType.softShadowRegion = 157 | unitType.jointRegion = 158 | unitType.footRegion = 159 | unitType.legBaseRegion = 160 | unitType.baseJointRegion = 161 | unitType.outlineRegion = 162 | unitType.treadRegion = SVars.clear; 163 | unitType.wreckRegions = unitType.segmentRegions = unitType.segmentOutlineRegions = new TextureRegion[]{}; 164 | unitType.treadRegions = new TextureRegion[][] {}; 165 | 166 | for(Weapon weapon : unitType.weapons) { 167 | weapon.parts.clear(); 168 | weapon.region = weapon.cellRegion = weapon.heatRegion = weapon.outlineRegion = SVars.clear; 169 | } 170 | } 171 | } 172 | } 173 | */ --------------------------------------------------------------------------------