├── .github
└── workflows
│ └── build.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── build.gradle.kts
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle.kts
└── src
└── main
├── java
└── com
│ └── jelly
│ └── mightyminerv2
│ ├── MightyMiner.java
│ ├── command
│ └── RouteBuilderCommand.java
│ ├── config
│ └── MightyMinerConfig.java
│ ├── event
│ ├── BlockChangeEvent.java
│ ├── BlockDestroyEvent.java
│ ├── MotionUpdateEvent.java
│ ├── PacketEvent.java
│ ├── SpawnParticleEvent.java
│ ├── UpdateEntityEvent.java
│ ├── UpdateScoreboardEvent.java
│ ├── UpdateScoreboardLineEvent.java
│ ├── UpdateTablistEvent.java
│ └── UpdateTablistFooterEvent.java
│ ├── failsafe
│ ├── AbstractFailsafe.java
│ ├── FailsafeManager.java
│ └── impl
│ │ ├── BadEffectFailsafe.java
│ │ ├── BedrockBlockChangeFailsafe.java
│ │ ├── BedrockCheckFailsafe.java
│ │ ├── DisconnectFailsafe.java
│ │ ├── ItemChangeFailsafe.java
│ │ ├── KnockbackFailsafe.java
│ │ ├── NameMentionFailsafe.java
│ │ ├── PlayerFailsafe.java
│ │ ├── ProfileFailsafe.java
│ │ ├── RotationFailsafe.java
│ │ ├── SlotChangeFailsafe.java
│ │ ├── TeleportFailsafe.java
│ │ └── WorldChangeFailsafe.java
│ ├── feature
│ ├── AbstractFeature.java
│ ├── FeatureManager.java
│ └── impl
│ │ ├── AutoChestUnlocker.java
│ │ ├── AutoCommissionClaim.java
│ │ ├── AutoDrillRefuel
│ │ ├── AutoDrillRefuel.java
│ │ └── states
│ │ │ ├── AbiphoneState.java
│ │ │ ├── AutoDrillRefuelState.java
│ │ │ ├── GreatforgeState.java
│ │ │ └── StartingState.java
│ │ ├── AutoGetStats
│ │ ├── AutoGetStats.java
│ │ └── tasks
│ │ │ ├── AbstractInventoryTask.java
│ │ │ ├── TaskStatus.java
│ │ │ └── impl
│ │ │ ├── MiningBoostRetrievalTask.java
│ │ │ ├── MiningSpeedRetrievalTask.java
│ │ │ └── PickaxeAbilityRetrievalTask.java
│ │ ├── AutoMobKiller
│ │ ├── AutoMobKiller.java
│ │ └── states
│ │ │ ├── AutoMobKillerState.java
│ │ │ ├── FindMobState.java
│ │ │ ├── KillState.java
│ │ │ ├── PathfindingState.java
│ │ │ └── StartingState.java
│ │ ├── AutoSell.java
│ │ ├── AutoWarp.java
│ │ ├── BlockMiner
│ │ ├── BlockMiner.java
│ │ └── states
│ │ │ ├── ApplyAbilityState.java
│ │ │ ├── BlockMinerState.java
│ │ │ ├── BreakingState.java
│ │ │ ├── ChoosingBlockState.java
│ │ │ └── StartingState.java
│ │ ├── LagDetector.java
│ │ ├── MouseUngrab.java
│ │ ├── PathExecutor.java
│ │ ├── Pathfinder.java
│ │ ├── RouteBuilder.java
│ │ ├── RouteNavigator.java
│ │ └── WorldScanner.java
│ ├── handler
│ ├── GameStateHandler.java
│ ├── GraphHandler.java
│ ├── RotationHandler.java
│ └── RouteHandler.java
│ ├── hud
│ ├── CommissionHUD.java
│ ├── DebugHUD.java
│ └── GlacialCommissionHUD.java
│ ├── macro
│ ├── AbstractMacro.java
│ ├── MacroManager.java
│ └── impl
│ │ ├── CommissionMacro
│ │ ├── Commission.java
│ │ ├── CommissionMacro.java
│ │ └── states
│ │ │ ├── ClaimingCommissionState.java
│ │ │ ├── CommissionMacroState.java
│ │ │ ├── GettingStatsState.java
│ │ │ ├── MiningState.java
│ │ │ ├── MobKillingState.java
│ │ │ ├── NewLobbyState.java
│ │ │ ├── PathingState.java
│ │ │ ├── RefuelState.java
│ │ │ ├── StartingState.java
│ │ │ └── WarpingState.java
│ │ ├── GlacialMacro
│ │ ├── GlacialMacro.java
│ │ ├── GlaciteVeins.java
│ │ └── states
│ │ │ ├── ClaimingCommissionState.java
│ │ │ ├── ErrorHandlingState.java
│ │ │ ├── GettingStatsState.java
│ │ │ ├── GlacialMacroState.java
│ │ │ ├── MiningState.java
│ │ │ ├── NewLobbyState.java
│ │ │ ├── PathfindingState.java
│ │ │ ├── StartingState.java
│ │ │ └── TeleportingState.java
│ │ ├── MiningMacro
│ │ └── MiningMacro.java
│ │ └── RouteMiner
│ │ ├── RouteMinerMacro.java
│ │ └── states
│ │ ├── GettingStatsState.java
│ │ ├── MiningState.java
│ │ ├── MovingState.java
│ │ ├── RouteMinerMacroState.java
│ │ └── StartingState.java
│ ├── mixin
│ ├── FML
│ │ └── MixinFMLHandshakeMessage.java
│ ├── client
│ │ ├── EntityPlayerSPAccessor.java
│ │ ├── MinecraftAccessor.java
│ │ ├── MixinBlockStainedGlassPane.java
│ │ ├── MixinChunk.java
│ │ ├── MixinChunkProviderClient.java
│ │ ├── MixinEntityLivingBase.java
│ │ ├── MixinEntityPlayerSP.java
│ │ ├── MixinMinecraft.java
│ │ ├── MixinScoreboard.java
│ │ └── MixinSoundManager.java
│ ├── gui
│ │ ├── MixinGuiContainer.java
│ │ └── MixinInventoryPlayer.java
│ ├── network
│ │ ├── MixinNetHandlerPlayClient.java
│ │ └── MixinNetworkManager.java
│ └── render
│ │ └── MixinModelBiped.java
│ └── util
│ ├── AngleUtil.java
│ ├── BlockUtil.java
│ ├── CommissionUtil.java
│ ├── EntityUtil.java
│ ├── IChunkProviderClient.java
│ ├── InventoryUtil.java
│ ├── KeyBindUtil.java
│ ├── Logger.java
│ ├── PlayerUtil.java
│ ├── RaytracingUtil.java
│ ├── ReflectionUtils.java
│ ├── RenderUtil.java
│ ├── ScoreboardUtil.java
│ ├── StrafeUtil.java
│ ├── TablistUtil.java
│ └── helper
│ ├── Angle.java
│ ├── AudioManager.java
│ ├── Clock.java
│ ├── FifoQueue.java
│ ├── MineableBlock.java
│ ├── RotationConfiguration.java
│ ├── Target.java
│ ├── graph
│ ├── Graph.java
│ └── GraphSerializer.java
│ ├── heap
│ ├── HeapNode.java
│ └── MinHeap.java
│ ├── location
│ ├── Location.java
│ └── SubLocation.java
│ └── route
│ ├── Route.java
│ ├── RouteWaypoint.java
│ ├── TransportMethod.java
│ └── WaypointType.java
├── kotlin
└── com
│ └── jelly
│ └── mightyminerv2
│ └── pathfinder
│ ├── calculate
│ ├── Path.kt
│ ├── PathNode.kt
│ ├── openset
│ │ └── BinaryHeapOpenSet.kt
│ └── path
│ │ └── AStarPathFinder.kt
│ ├── costs
│ └── ActionCost.kt
│ ├── goal
│ ├── Goal.kt
│ └── IGoal.kt
│ ├── helper
│ ├── BlockStateAccessor.kt
│ ├── BlockStateInterfaceAccessWrapper.kt
│ └── player
│ │ ├── IPlayerContext.kt
│ │ └── PlayerContext.kt
│ ├── movement
│ ├── CalculationContext.kt
│ ├── IMovement.kt
│ ├── Movement.kt
│ ├── MovementHelper.kt
│ ├── MovementResult.kt
│ ├── Moves.kt
│ └── movements
│ │ ├── MovementAscend.kt
│ │ ├── MovementDescend.kt
│ │ ├── MovementDiagonal.kt
│ │ ├── MovementFall.kt
│ │ └── MovementTraverse.kt
│ └── util
│ ├── BlockUtil.kt
│ ├── Extension.kt
│ └── Ref.kt
└── resources
├── mcmod.info
├── mightyminer
├── Commission Macro.json
├── Glacial Macro.json
└── sounds
│ ├── AAAAAAAAAA.wav
│ ├── loud_buzz.wav
│ ├── metal_pipe.wav
│ └── staff_check_voice_notification.wav
└── mixins.mightyminerv2.json
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Run Gradle Build
2 | on: [push]
3 | jobs:
4 | gradle:
5 | runs-on: ubuntu-latest
6 | steps:
7 | - name: Checkout source
8 | uses: actions/checkout@v4
9 | - name: Get Gradle version and check if it's pre release
10 | run: |
11 | VERSION=$(grep -Po '^version=.*' gradle.properties | cut -d= -f2)
12 | VERSION=${VERSION#[[:space:]]}
13 | SHOULD_RELEASE=$(grep -Po '^shouldRelease=.*' gradle.properties | cut -d= -f2)
14 | SHOULD_RELEASE=${SHOULD_RELEASE#[[:space:]]}
15 | echo "$VERSION"
16 | echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
17 | if [[ $VERSION == *-pre* ]]
18 | then
19 | echo "Version is pre-release"
20 | RELEASE_TYPE="pre-release"
21 | else
22 | echo "Version is full release"
23 | RELEASE_TYPE="full"
24 | fi
25 | echo "Version is $VERSION and release type is $RELEASE_TYPE"
26 | echo "RELEASE_TYPE=$RELEASE_TYPE" >> $GITHUB_OUTPUT
27 | echo "shouldRelease=$SHOULD_RELEASE" >> $GITHUB_OUTPUT
28 | id: get_version
29 | - name: Get short commit sha
30 | id: short_sha
31 | run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
32 | - uses: actions/setup-java@v4
33 | name: Setup Java
34 | with:
35 | distribution: temurin
36 | java-version: 17
37 | - uses: gradle/actions/setup-gradle@v3
38 | name: Setup Gradle
39 | - name: Execute Gradle build
40 | run: ./gradlew build
41 | - uses: actions/upload-artifact@v4
42 | name: Upload built mod JAR
43 | with:
44 | name: mod-jar
45 | path: build/libs/*.jar
46 | - name: Create release with files
47 | uses: softprops/action-gh-release@v2
48 | id: create_release
49 | if: steps.get_version.outputs.shouldRelease == 'true'
50 | with:
51 | draft: false
52 | prerelease: ${{ steps.get_version.outputs.RELEASE_TYPE == 'pre-release' }}
53 | name: MightyMinerV2 ${{ steps.get_version.outputs.VERSION }}
54 | tag_name: ${{ steps.get_version.outputs.VERSION }}.${{ steps.short_sha.outputs.sha_short }}
55 | files: |
56 | build/libs/*.jar
57 | body: |
58 | Changelog:
59 | ${{ github.event.head_commit.message }}
60 | env:
61 | GITHUB_TOKEN: ${{ github.token }}
62 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | .vscode/
3 | run/
4 | build/
5 | .gradle/
6 |
7 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # MightyMiner V2 Changelog
2 |
3 | ## v2.7.1 (2025-1-7)
4 |
5 | ## Changes
6 | - New name-mention failsafe
7 | - New option to auto warp to forge in Commission Macro
8 | - Will no longer start Dwarven Commissions if the slayer weapon has not been set in the config
9 | - Will warp to a new mining lobby if the pathfinding fails
10 | - Changed the error message getMiningStats throws
11 |
12 | ## Fixes
13 | - Duplicate mining tools causing ItemChangeFailsafe to trigger
14 | - Pickaxe ability issue
15 | - Issues with macro not mining after tabbing out
16 |
17 | ## v2.7.0 (2025-18-6)
18 |
19 | This update marks the first stable update of MightyMiner v2.7.0
20 |
21 | ## Current Macros Included
22 | - Commission Macro
23 | - Powder Macro
24 |
25 | ## Changes
26 | - Auto Refuel is now usable
27 | - Fixed lag issues
28 | - Fixed personal compactors not working
29 | - Fixed accidentally clicking on players
30 | - Fixed calling royal pigeons twice
31 | - Detecting item names properly
32 | - Added support for all pickaxe abilities
33 | - Added options to disable using pickaxe ability
34 | - New commission HUD and configs
35 | - Enhanced mining algorithm
36 |
37 | ## v2.7.0-alpha (2025-5-1)
38 |
39 | This update marks the official resumption of development on Mighty Miner.
40 |
41 | ## Current Macros Included
42 | - Commission Macro
43 | - Powder Macro
44 | - Glacial Macro
45 | - Mining Macro
46 | - Route Mining Macro
47 |
48 | ## Changes
49 | - Completely rewritten Mining Macro for improved efficiency and maintainability.
50 | - Block Miner has been overhauled with cleaner structure and better logic separation.
51 | - Automatically disable macro when there is an error
52 |
53 | ## Updated Coding Standards
54 | - Avoid deeply nested switch statements when possible. Implement PROPER state machine patterns (see BlockMiner.java for a reference implementation).
55 | - Add Javadocs and inline comments, especially for abstract classes. (Tip: ChatGPT can assist with generating documentation.)
56 | - Standardize logging and error handling across the project. For example, all errors should be routed through the main macro class for consistency.
57 | - Disable macro automatically when there is an error
58 |
59 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JellyLabScripts/MightyMiner/62aec611784d81973a9ce9fcba02d659b776d0b8/LICENSE
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MightyMinerV2
2 |
3 | MightyMinerV2 is a cutting-edge mining macro designed specifically for Hypixel Skyblock. This powerful tool enhances your gameplay experience by automating various mining-related tasks, allowing you to focus on progressing through the game. With a host of advanced features and many more under development, MightyMinerV2 is your ultimate companion for efficient mining.
4 |
5 | ## Features
6 |
7 | ### Current Features:
8 | - **Commission Macro**: Automatically completes mining commissions, helping you earn rewards faster and with minimal effort.
9 | - **Mining Macro**: Optimized for efficient mithril / pure ore mining, ensuring you collect the maximum amount of resources.
10 | - **Glacial Macro**: Experimental!
11 | - **Route Mining Macro**: Experimental!
12 | - **Powder Macro**: Re-release soon!
13 |
14 | ### Upcoming Features:
15 | Our dedicated development team is actively working on integrating more features, including but not limited to:
16 | - Advanced gemstone mining automation.
17 | - Customized pathing for specific resource collection.
18 | - Enhanced anti-detection mechanisms to ensure safe usage.
19 | - And much more! Stay tuned for updates.
20 |
21 | ## Developers
22 | MightyMinerV2 is brought to you by a talented team of developers:
23 | - **Tama**
24 | - **Osama**
25 | - **Nima0908**
26 | - **Mr. Shadow**
27 | - **Nathan**
28 | - **JellyLab** (returned!!!)
29 |
30 | Their combined expertise and passion for Hypixel Skyblock drive the continuous improvement and innovation of MightyMinerV2.
31 |
32 | ## Installation
33 | 1. Download the latest release from the repository.
34 | 2. Follow the setup instructions provided in the `INSTALL.md` file (WIP).
35 | 3. Enjoy effortless mining with MightyMinerV2!
36 |
37 | ## Support
38 | For support, bug reports, or feature requests, feel free to open an issue in the repository or join our [community Discord channel](https://discord.gg/6mSHC2Xd9y).
39 |
40 |
41 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | loom.platform=forge
2 | org.gradle.jvmargs=-Xmx3g
3 | baseGroup=com.jelly.mightyminerv2
4 | modName=MightyMinerV2
5 | modid=mightyminerv2
6 | mcVersion=1.8.9
7 | version=2.7.3-pre1
8 | shouldRelease=true
9 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JellyLabScripts/MightyMiner/62aec611784d81973a9ce9fcba02d659b776d0b8/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%"=="" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%"=="" set DIRNAME=.
29 | @rem This is normally unused
30 | set APP_BASE_NAME=%~n0
31 | set APP_HOME=%DIRNAME%
32 |
33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
35 |
36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
38 |
39 | @rem Find java.exe
40 | if defined JAVA_HOME goto findJavaFromJavaHome
41 |
42 | set JAVA_EXE=java.exe
43 | %JAVA_EXE% -version >NUL 2>&1
44 | if %ERRORLEVEL% equ 0 goto execute
45 |
46 | echo.
47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
48 | echo.
49 | echo Please set the JAVA_HOME variable in your environment to match the
50 | echo location of your Java installation.
51 |
52 | goto fail
53 |
54 | :findJavaFromJavaHome
55 | set JAVA_HOME=%JAVA_HOME:"=%
56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
57 |
58 | if exist "%JAVA_EXE%" goto execute
59 |
60 | echo.
61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
62 | echo.
63 | echo Please set the JAVA_HOME variable in your environment to match the
64 | echo location of your Java installation.
65 |
66 | goto fail
67 |
68 | :execute
69 | @rem Setup the command line
70 |
71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
72 |
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if %ERRORLEVEL% equ 0 goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | set EXIT_CODE=%ERRORLEVEL%
85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
87 | exit /b %EXIT_CODE%
88 |
89 | :mainEnd
90 | if "%OS%"=="Windows_NT" endlocal
91 |
92 | :omega
93 |
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | mavenCentral()
4 | gradlePluginPortal()
5 | maven("https://maven.fabricmc.net")
6 | maven("https://maven.architectury.dev")
7 | maven("https://maven.minecraftforge.net")
8 | maven("https://repo.polyfrost.cc/releases")
9 | }
10 | }
11 |
12 | rootProject.name = "MightyMinerV2"
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/event/BlockChangeEvent.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.event;
2 |
3 | import net.minecraft.block.state.IBlockState;
4 | import net.minecraft.util.BlockPos;
5 | import net.minecraftforge.fml.common.eventhandler.Event;
6 |
7 | public class BlockChangeEvent extends Event {
8 | public BlockPos pos;
9 | public IBlockState old;
10 | public IBlockState update;
11 |
12 | public BlockChangeEvent(BlockPos pos, IBlockState old, IBlockState update) {
13 | this.pos = pos;
14 | this.old = old;
15 | this.update = update;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/event/BlockDestroyEvent.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.event;
2 |
3 | import lombok.Getter;
4 | import net.minecraft.util.BlockPos;
5 | import net.minecraftforge.fml.common.eventhandler.Event;
6 |
7 | @Getter
8 | public class BlockDestroyEvent extends Event {
9 |
10 | private final BlockPos block;
11 | private final float progress;
12 |
13 | public BlockDestroyEvent(final BlockPos block, final float progress) {
14 | this.block = block;
15 | this.progress = progress;
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/event/MotionUpdateEvent.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.event;
2 |
3 | import net.minecraftforge.fml.common.eventhandler.Event;
4 |
5 | public class MotionUpdateEvent extends Event {
6 | public float yaw;
7 | public float pitch;
8 |
9 | public MotionUpdateEvent(float yaw, float pitch) {
10 | this.yaw = yaw;
11 | this.pitch = pitch;
12 | }
13 |
14 | // public static class Pre extends MotionUpdateEvent {
15 | // public Pre(final float yaw, final float pitch) {
16 | // super(yaw, pitch);
17 | // }
18 | // }
19 |
20 | // public static class Post extends MotionUpdateEvent {
21 | // public Post(final float yaw, final float pitch) {
22 | // super(yaw, pitch);
23 | // }
24 | // }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/event/PacketEvent.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.event;
2 |
3 | import net.minecraft.network.Packet;
4 | import net.minecraftforge.fml.common.eventhandler.Cancelable;
5 | import net.minecraftforge.fml.common.eventhandler.Event;
6 |
7 | @Cancelable
8 | public class PacketEvent extends Event {
9 | public final Packet> packet;
10 |
11 | public PacketEvent(Packet> packet) {
12 | this.packet = packet;
13 | }
14 |
15 | @Cancelable
16 | public static class Sent extends PacketEvent {
17 | public Sent(Packet> packet) {
18 | super(packet);
19 | }
20 | }
21 |
22 | @Cancelable
23 | public static class Received extends PacketEvent {
24 | public Received(Packet> packet) {
25 | super(packet);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/event/SpawnParticleEvent.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.event;
2 |
3 | import lombok.Getter;
4 | import net.minecraft.util.EnumParticleTypes;
5 | import net.minecraft.util.Vec3;
6 | import net.minecraftforge.fml.common.eventhandler.Cancelable;
7 | import net.minecraftforge.fml.common.eventhandler.Event;
8 |
9 | @Cancelable
10 | @Getter
11 | public class SpawnParticleEvent extends Event {
12 |
13 | EnumParticleTypes particleTypes;
14 | boolean isLongDistance;
15 | double xCoord;
16 | double yCoord;
17 | double zCoord;
18 | double xOffset;
19 | double yOffset;
20 | double zOffset;
21 | int[] params;
22 |
23 | public SpawnParticleEvent(
24 | EnumParticleTypes particleTypes,
25 | boolean isLongDistance,
26 | double xCoord, double yCoord, double zCoord,
27 | double xOffset, double yOffset, double zOffset,
28 | int[] params
29 | ) {
30 | this.particleTypes = particleTypes;
31 | this.isLongDistance = isLongDistance;
32 | this.xCoord = xCoord;
33 | this.yCoord = yCoord;
34 | this.zCoord = zCoord;
35 | this.xOffset = xOffset;
36 | this.yOffset = yOffset;
37 | this.zOffset = zOffset;
38 | this.params = params;
39 | }
40 |
41 | public Vec3 getPos() {
42 | return new Vec3(xCoord, yCoord, zCoord);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/event/UpdateEntityEvent.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.event;
2 |
3 | import net.minecraft.entity.EntityLivingBase;
4 | import net.minecraftforge.fml.common.eventhandler.Event;
5 |
6 | public class UpdateEntityEvent extends Event {
7 |
8 | public final EntityLivingBase entity;
9 | public final byte updateType; // 0 = entity spawned, 1 = entity despawned, 2 = entity moved
10 | public long newHash; // maybe instead of saving new hash i should just save the coord - but i dont have a use for the coord so L
11 |
12 | public UpdateEntityEvent(EntityLivingBase entity) {
13 | this.entity = entity;
14 | this.updateType = 0;
15 | }
16 |
17 | public UpdateEntityEvent(EntityLivingBase entity, byte updateType) {
18 | this.entity = entity;
19 | this.updateType = updateType;
20 | }
21 |
22 | public UpdateEntityEvent(EntityLivingBase entity, long newHash) {
23 | this.entity = entity;
24 | this.updateType = 2;
25 | this.newHash = newHash;
26 | }
27 | // public Vec3 newPos;
28 | // public UpdateEntityEvent(EntityLivingBase entity, long newHash, Vec3 newPos) {
29 | // this.entity = entity;
30 | // this.updateType = 2;
31 | // this.newHash = newHash;
32 | // this.newPos = newPos;
33 | // }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/event/UpdateScoreboardEvent.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.event;
2 |
3 | import net.minecraftforge.fml.common.eventhandler.Event;
4 |
5 | import java.util.List;
6 |
7 | public class UpdateScoreboardEvent extends Event {
8 | public final List scoreboard;
9 | public final long timestamp;
10 |
11 | public UpdateScoreboardEvent(List scoreboard, long timestamp) {
12 | this.scoreboard = scoreboard;
13 | this.timestamp = timestamp;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/event/UpdateScoreboardLineEvent.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.event;
2 |
3 | import lombok.Getter;
4 | import net.minecraftforge.fml.common.eventhandler.Event;
5 |
6 | @Getter
7 | public class UpdateScoreboardLineEvent extends Event {
8 |
9 | private final String line;
10 |
11 | public UpdateScoreboardLineEvent(String line) {
12 | this.line = line;
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/event/UpdateTablistEvent.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.event;
2 |
3 | import net.minecraftforge.fml.common.eventhandler.Event;
4 |
5 | import java.util.List;
6 |
7 | public class UpdateTablistEvent extends Event {
8 | public final List tablist;
9 | public final long timestamp;
10 |
11 | public UpdateTablistEvent(List tablist, long timestamp) {
12 | this.tablist = tablist;
13 | this.timestamp = timestamp;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/event/UpdateTablistFooterEvent.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.event;
2 |
3 | import net.minecraftforge.fml.common.eventhandler.Event;
4 |
5 | import java.util.List;
6 |
7 | public class UpdateTablistFooterEvent extends Event {
8 | public final List footer;
9 |
10 | public UpdateTablistFooterEvent(List footer) {
11 | this.footer = footer;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/failsafe/AbstractFailsafe.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.failsafe;
2 |
3 | import com.jelly.mightyminerv2.event.BlockChangeEvent;
4 | import com.jelly.mightyminerv2.event.PacketEvent;
5 | import com.jelly.mightyminerv2.util.Logger;
6 | import net.minecraft.client.Minecraft;
7 | import net.minecraftforge.client.event.ClientChatReceivedEvent;
8 | import net.minecraftforge.client.event.GuiOpenEvent;
9 | import net.minecraftforge.event.world.WorldEvent;
10 | import net.minecraftforge.fml.common.gameevent.TickEvent;
11 | import net.minecraftforge.fml.common.network.FMLNetworkEvent;
12 |
13 | public abstract class AbstractFailsafe {
14 |
15 | protected final Minecraft mc = Minecraft.getMinecraft();
16 |
17 | public abstract int getPriority();
18 |
19 | public abstract String getName();
20 |
21 | public abstract Failsafe getFailsafeType();
22 |
23 | public boolean onBlockChange(BlockChangeEvent event) {
24 | return false;
25 | }
26 |
27 | public boolean onPacketReceive(PacketEvent.Received event) {
28 | return false;
29 | }
30 |
31 | public boolean onTick(TickEvent.ClientTickEvent event) {
32 | return false;
33 | }
34 |
35 | public boolean onChat(ClientChatReceivedEvent event) {
36 | return false;
37 | }
38 |
39 | public boolean onGuiOpen(GuiOpenEvent event) { return false; }
40 |
41 | public boolean onWorldUnload(WorldEvent.Unload event) {
42 | return false;
43 | }
44 |
45 | public boolean onDisconnect(FMLNetworkEvent.ClientDisconnectionFromServerEvent event) {
46 | return false;
47 | }
48 |
49 | public abstract boolean react();
50 |
51 | public void resetStates() {}
52 |
53 | protected void log(String message) {
54 | Logger.sendLog(formatMessage(message));
55 | }
56 |
57 | protected void send(String message) {
58 | Logger.sendMessage(formatMessage(message));
59 | }
60 |
61 | protected void error(String message) {
62 | Logger.sendError(formatMessage(message));
63 | }
64 |
65 | protected void warn(String message) {
66 | Logger.sendWarning(formatMessage(message));
67 | }
68 |
69 | protected void note(String message) {
70 | Logger.sendNote(formatMessage(message));
71 | }
72 |
73 | protected String formatMessage(String message) {
74 | return "[" + getName() + "] " + message;
75 | }
76 |
77 | public enum Failsafe {
78 | BAD_EFFECTS,
79 | BLOCK_CHANGE,
80 | DISCONNECT,
81 | ITEM_CHANGE,
82 | KNOCKBACK,
83 | ROTATION,
84 | TELEPORT,
85 | BEDROCK_CHECK,
86 | SLOT_CHANGE,
87 | PLAYER_PROFILE_OPEN,
88 | NAME_MENTION
89 | }
90 | }
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/failsafe/impl/BadEffectFailsafe.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.failsafe.impl;
2 |
3 | import com.google.common.collect.ImmutableSet;
4 | import com.jelly.mightyminerv2.event.PacketEvent;
5 | import com.jelly.mightyminerv2.failsafe.AbstractFailsafe;
6 | import com.jelly.mightyminerv2.macro.MacroManager;
7 | import lombok.Getter;
8 | import net.minecraft.client.entity.EntityPlayerSP;
9 | import net.minecraft.network.play.server.S1DPacketEntityEffect;
10 | import net.minecraft.potion.Potion;
11 | import net.minecraft.potion.PotionEffect;
12 | import net.minecraftforge.fml.common.gameevent.TickEvent;
13 |
14 | import java.util.Set;
15 |
16 | public class BadEffectFailsafe extends AbstractFailsafe {
17 |
18 | @Getter
19 | private static final BadEffectFailsafe instance = new BadEffectFailsafe();
20 | private final Set BAD_EFFECTS = ImmutableSet.of(
21 | Potion.poison.id,
22 | Potion.wither.id,
23 | Potion.weakness.id,
24 | Potion.blindness.id,
25 | Potion.hunger.id,
26 | Potion.moveSlowdown.id,
27 | Potion.digSlowdown.id
28 | );
29 |
30 | @Override
31 | public String getName() {
32 | return "BadEffectFailsafe";
33 | }
34 |
35 | @Override
36 | public Failsafe getFailsafeType() {
37 | return Failsafe.BAD_EFFECTS;
38 | }
39 |
40 | @Override
41 | public int getPriority() {
42 | return 7;
43 | }
44 |
45 | @Override
46 | public boolean onTick(TickEvent.ClientTickEvent event) {
47 | for (PotionEffect effect : mc.thePlayer.getActivePotionEffects()) {
48 | if (BAD_EFFECTS.contains(effect.getPotionID())) return true;
49 | }
50 |
51 | return false;
52 | }
53 |
54 | @Override
55 | public boolean react() {
56 | MacroManager.getInstance().disable();
57 | warn("Bad effect detected! Disabling macro.");
58 | return true;
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/failsafe/impl/BedrockCheckFailsafe.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.failsafe.impl;
2 |
3 | import com.jelly.mightyminerv2.failsafe.AbstractFailsafe;
4 | import com.jelly.mightyminerv2.macro.MacroManager;
5 | import lombok.Getter;
6 | import net.minecraft.block.Block;
7 | import net.minecraft.init.Blocks;
8 | import net.minecraft.util.BlockPos;
9 | import net.minecraft.util.Vec3;
10 |
11 | public class BedrockCheckFailsafe extends AbstractFailsafe {
12 |
13 | @Getter
14 | private static final BedrockCheckFailsafe instance = new BedrockCheckFailsafe();
15 | private static final int CHECK_RADIUS = 5;
16 | private static final int BEDROCK_THRESHOLD = 10;
17 |
18 | @Override
19 | public String getName() {
20 | return "BedrockCheckFailsafe";
21 | }
22 |
23 | @Override
24 | public Failsafe getFailsafeType() {
25 | return Failsafe.BEDROCK_CHECK;
26 | }
27 |
28 | @Override
29 | public int getPriority() {
30 | return 6;
31 | }
32 |
33 |
34 | public boolean checkForBedrock(Vec3 playerPos) {
35 | int bedrockCount = 0;
36 |
37 | for (int x = -CHECK_RADIUS; x <= CHECK_RADIUS; x++) {
38 | for (int y = -CHECK_RADIUS; y <= CHECK_RADIUS; y++) {
39 | for (int z = -CHECK_RADIUS; z <= CHECK_RADIUS; z++) {
40 | BlockPos blockPos = new BlockPos(
41 | playerPos.xCoord + x,
42 | playerPos.yCoord + y,
43 | playerPos.zCoord + z
44 | );
45 | Block block = mc.theWorld.getBlockState(blockPos).getBlock();
46 |
47 | if (block == Blocks.bedrock) {
48 | bedrockCount++;
49 | }
50 |
51 | if (bedrockCount >= BEDROCK_THRESHOLD) {
52 | return true;
53 | }
54 | }
55 | }
56 | }
57 |
58 | return false;
59 | }
60 |
61 | @Override
62 | public boolean react() {
63 | MacroManager.getInstance().disable();
64 | warn("Disabling macro due to bedrock surroundings.");
65 | return true;
66 | }
67 |
68 | }
69 |
70 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/failsafe/impl/DisconnectFailsafe.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.failsafe.impl;
2 |
3 | import com.jelly.mightyminerv2.event.PacketEvent;
4 | import com.jelly.mightyminerv2.failsafe.AbstractFailsafe;
5 | import com.jelly.mightyminerv2.macro.MacroManager;
6 | import lombok.Getter;
7 | import net.minecraft.client.gui.GuiDisconnected;
8 | import net.minecraft.network.play.server.S40PacketDisconnect;
9 |
10 | public class DisconnectFailsafe extends AbstractFailsafe {
11 |
12 | @Getter
13 | private static final DisconnectFailsafe instance = new DisconnectFailsafe();
14 |
15 | @Override
16 | public String getName() {
17 | return "DisconnectFailsafe";
18 | }
19 |
20 | @Override
21 | public Failsafe getFailsafeType() {
22 | return Failsafe.DISCONNECT;
23 | }
24 |
25 | @Override
26 | public int getPriority() {
27 | return 10;
28 | }
29 |
30 | @Override
31 | public boolean onPacketReceive(PacketEvent.Received event) {
32 | return event.packet instanceof S40PacketDisconnect || mc.currentScreen instanceof GuiDisconnected;
33 | }
34 |
35 | @Override
36 | public boolean react() {
37 | warn("Disconnected. Disabling Macro");
38 | MacroManager.getInstance().disable();
39 | return true;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/failsafe/impl/KnockbackFailsafe.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.failsafe.impl;
2 |
3 | import com.jelly.mightyminerv2.config.MightyMinerConfig;
4 | import com.jelly.mightyminerv2.event.PacketEvent;
5 | import com.jelly.mightyminerv2.failsafe.AbstractFailsafe;
6 | import com.jelly.mightyminerv2.macro.MacroManager;
7 | import com.jelly.mightyminerv2.util.Logger;
8 | import lombok.Getter;
9 | import net.minecraft.network.play.server.S12PacketEntityVelocity;
10 |
11 | public class KnockbackFailsafe extends AbstractFailsafe {
12 |
13 | @Getter
14 | private static final KnockbackFailsafe instance = new KnockbackFailsafe();
15 |
16 | public int getPriority() {
17 | return 8;
18 | }
19 |
20 | @Override
21 | public String getName() {
22 | return "";
23 | }
24 |
25 | @Override
26 | public Failsafe getFailsafeType() {
27 | return Failsafe.KNOCKBACK;
28 | }
29 |
30 |
31 | @Override
32 | public boolean onPacketReceive(PacketEvent.Received event) {
33 | if (!(event.packet instanceof S12PacketEntityVelocity)) return false;
34 | if (((S12PacketEntityVelocity) event.packet).getEntityID() != mc.thePlayer.getEntityId()) return false;
35 | return ((S12PacketEntityVelocity) event.packet).getMotionY() >= MightyMinerConfig.verticalKnockbackThreshold;
36 | }
37 |
38 | @Override
39 | public boolean react() {
40 | MacroManager.getInstance().disable();
41 | Logger.sendWarning("Knockback has been detected! Disabling macro.");
42 | return true;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/failsafe/impl/NameMentionFailsafe.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.failsafe.impl;
2 |
3 | import com.jelly.mightyminerv2.config.MightyMinerConfig;
4 | import com.jelly.mightyminerv2.failsafe.AbstractFailsafe;
5 | import com.jelly.mightyminerv2.macro.MacroManager;
6 | import lombok.Getter;
7 | import net.minecraftforge.client.event.ClientChatReceivedEvent;
8 |
9 | import java.util.regex.Matcher;
10 | import java.util.regex.Pattern;
11 |
12 | public class NameMentionFailsafe extends AbstractFailsafe {
13 |
14 | @Getter
15 | private static final NameMentionFailsafe instance = new NameMentionFailsafe();
16 |
17 | private static final Pattern SENDER_NAME_PATTERN = Pattern.compile("^.*?(?[a-zA-Z0-9_]+)§?f?:");
18 |
19 | @Getter
20 | private boolean lobbyChangeRequested = false;
21 |
22 | @Override
23 | public int getPriority() { return 10; }
24 |
25 | @Override
26 | public String getName() { return "NameMentionFailsafe"; }
27 |
28 | @Override
29 | public Failsafe getFailsafeType() { return Failsafe.NAME_MENTION; }
30 |
31 | @Override
32 | public void resetStates() {
33 | this.lobbyChangeRequested = false;
34 | }
35 |
36 | @Override
37 | public boolean onChat(ClientChatReceivedEvent event) {
38 | String playerName = mc.thePlayer.getName();
39 | String unformattedMessage = event.message.getUnformattedText();
40 |
41 | String senderName = null;
42 | Matcher matcher = SENDER_NAME_PATTERN.matcher(unformattedMessage);
43 | if (matcher.find()) { senderName = matcher.group("senderName"); }
44 |
45 | if (senderName != null && senderName.equalsIgnoreCase(playerName)) { return false; }
46 |
47 | if (unformattedMessage.toLowerCase().contains(playerName.toLowerCase() + " invited ")) { return false; }
48 |
49 | //if (unformattedMessage.toLowerCase().contains("has invited you to join their party!")) { notify() }
50 |
51 | Pattern mentionPattern = Pattern.compile("\\b" + Pattern.quote(playerName) + "\\b", Pattern.CASE_INSENSITIVE);
52 | boolean isMentioned = mentionPattern.matcher(unformattedMessage).find();
53 |
54 | if (isMentioned) {
55 | if (MightyMinerConfig.nameMentionFailsafeBehaviour) { // If true, the player wants to warp to a new lobby
56 | warn("Your name was mentioned in chat. Changing lobbies.");
57 | lobbyChangeRequested = true;
58 | return false;
59 | } else { // If false, the player wants to disable the macro
60 | return true;
61 | }
62 | }
63 | return false;
64 | }
65 |
66 | @Override
67 | public boolean react() {
68 | MacroManager.getInstance().disable();
69 | warn("Your name was mentioned in chat. Macro disabled.");
70 | return true;
71 | }
72 | }
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/failsafe/impl/ProfileFailsafe.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.failsafe.impl;
2 |
3 | import com.jelly.mightyminerv2.failsafe.AbstractFailsafe;
4 | import com.jelly.mightyminerv2.macro.MacroManager;
5 | import com.jelly.mightyminerv2.util.Logger;
6 | import lombok.Getter;
7 | import net.minecraft.client.gui.inventory.GuiChest;
8 | import net.minecraft.inventory.ContainerChest;
9 | import net.minecraft.inventory.IInventory;
10 | import net.minecraft.util.StringUtils;
11 | import net.minecraftforge.client.event.GuiOpenEvent;
12 |
13 | public class ProfileFailsafe extends AbstractFailsafe {
14 |
15 | @Getter
16 | private static final ProfileFailsafe instance = new ProfileFailsafe();
17 |
18 | private static final String TRIGGER_PHRASE = "Profile";
19 |
20 | @Override
21 | public String getName() {
22 | return "ProfileFailsafe";
23 | }
24 |
25 | @Override
26 | public Failsafe getFailsafeType() {
27 | return Failsafe.PLAYER_PROFILE_OPEN;
28 | }
29 |
30 | @Override
31 | public int getPriority() { return 2; }
32 |
33 | @Override
34 | public boolean onGuiOpen(GuiOpenEvent event) {
35 | if (event.gui == null) {
36 | return false;
37 | }
38 |
39 | if (event.gui instanceof GuiChest) {
40 | GuiChest guiChest = (GuiChest) event.gui;
41 |
42 | if (guiChest.inventorySlots instanceof ContainerChest) {
43 | ContainerChest container = (ContainerChest) guiChest.inventorySlots;
44 | IInventory chestInventory = container.getLowerChestInventory();
45 |
46 | if (chestInventory != null && chestInventory.hasCustomName()) {
47 | String inventoryName = StringUtils.stripControlCodes(chestInventory.getDisplayName().getUnformattedText());
48 | if (inventoryName.toLowerCase().contains(TRIGGER_PHRASE.toLowerCase())) {
49 | note("Detected inventory open with name containing " + inventoryName);
50 | return true;
51 | }
52 | }
53 | }
54 | }
55 | return false;
56 | }
57 |
58 | @Override
59 | public boolean react() {
60 | if (mc.currentScreen != null && mc.thePlayer != null) {
61 | mc.addScheduledTask(() -> {
62 | if (mc.currentScreen != null && mc.thePlayer != null) {
63 | mc.thePlayer.closeScreen();
64 | note("Closing the menu... continuing");
65 | }
66 | });
67 | } else {
68 | warn("Menu already closed... continuing");
69 | }
70 | return true;
71 | }
72 | }
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/failsafe/impl/RotationFailsafe.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.failsafe.impl;
2 |
3 | import com.jelly.mightyminerv2.event.PacketEvent;
4 | import com.jelly.mightyminerv2.failsafe.AbstractFailsafe;
5 | import com.jelly.mightyminerv2.macro.MacroManager;
6 | import com.jelly.mightyminerv2.util.Logger;
7 | import com.jelly.mightyminerv2.util.helper.Angle;
8 | import com.jelly.mightyminerv2.util.helper.Clock;
9 | import lombok.Getter;
10 | import net.minecraft.network.play.server.S08PacketPlayerPosLook;
11 | import net.minecraftforge.fml.common.gameevent.TickEvent;
12 |
13 | public class RotationFailsafe extends AbstractFailsafe {
14 |
15 | @Getter
16 | private static final RotationFailsafe instance = new RotationFailsafe();
17 |
18 | public int getPriority() {
19 | return 5;
20 | }
21 |
22 | @Override
23 | public String getName() {
24 | return "";
25 | }
26 |
27 | @Override
28 | public Failsafe getFailsafeType() {
29 | return Failsafe.ROTATION;
30 | }
31 |
32 |
33 | private final Clock triggerCheck = new Clock();
34 | private Angle rotationBeforeReacting = null;
35 |
36 | @Override
37 | public boolean onPacketReceive(PacketEvent.Received event) {
38 | if (!MacroManager.getInstance().isEnabled()) return false;
39 |
40 | if (event.packet instanceof S08PacketPlayerPosLook) {
41 | S08PacketPlayerPosLook packet = (S08PacketPlayerPosLook) event.packet;
42 | double packetYaw = packet.getYaw();
43 | double packetPitch = packet.getPitch();
44 | double playerYaw = mc.thePlayer.rotationYaw;
45 | double playerPitch = mc.thePlayer.rotationPitch;
46 |
47 | float yawDifference = Math.abs((mc.thePlayer.rotationYaw - ((S08PacketPlayerPosLook) event.packet).getYaw()));
48 | float pitchDifference = Math.abs((mc.thePlayer.rotationPitch - ((S08PacketPlayerPosLook) event.packet).getPitch()));
49 |
50 | if (yawDifference == 360F && pitchDifference == 0F) return false;
51 |
52 | if (shouldTriggerCheck(packetYaw, packetPitch)) {
53 | if (rotationBeforeReacting == null) rotationBeforeReacting = new Angle((float) playerYaw, (float) playerPitch);
54 | }
55 |
56 | triggerCheck.schedule(500);
57 | }
58 |
59 | return false;
60 | }
61 |
62 | @Override
63 | public boolean onTick(TickEvent.ClientTickEvent event) {
64 | if (!MacroManager.getInstance().isEnabled()) {
65 | rotationBeforeReacting = null;
66 | return false;
67 | }
68 |
69 | if (triggerCheck.passed() && triggerCheck.isScheduled()) {
70 | if (rotationBeforeReacting == null) return false;
71 |
72 | if (shouldTriggerCheck(rotationBeforeReacting.getYaw(), rotationBeforeReacting.getPitch())) {
73 | return true;
74 | }
75 |
76 | rotationBeforeReacting = null;
77 | triggerCheck.reset();
78 | }
79 |
80 | return false;
81 | }
82 |
83 | private boolean shouldTriggerCheck(double newYaw, double newPitch) {
84 | double yawDiff = Math.abs(newYaw - mc.thePlayer.rotationYaw) % 360;
85 | double pitchDiff = Math.abs(newPitch - mc.thePlayer.rotationPitch) % 360;
86 | return yawDiff >= 10 || pitchDiff >= 10;
87 | }
88 |
89 | @Override
90 | public boolean react() {
91 | MacroManager.getInstance().disable();
92 | Logger.sendWarning("You`ve got rotated! Disabeling macro.");
93 | return true;
94 | }
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/failsafe/impl/SlotChangeFailsafe.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.failsafe.impl;
2 |
3 | import com.jelly.mightyminerv2.event.PacketEvent;
4 | import com.jelly.mightyminerv2.failsafe.AbstractFailsafe;
5 | import com.jelly.mightyminerv2.macro.MacroManager;
6 | import com.jelly.mightyminerv2.util.Logger;
7 | import com.jelly.mightyminerv2.util.helper.Clock;
8 | import lombok.Getter;
9 | import net.minecraft.client.Minecraft;
10 | import net.minecraft.network.play.server.S09PacketHeldItemChange;
11 | import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent;
12 |
13 | public class SlotChangeFailsafe extends AbstractFailsafe {
14 |
15 | @Getter
16 | private static final SlotChangeFailsafe instance = new SlotChangeFailsafe();
17 | private final Minecraft mc = Minecraft.getMinecraft();
18 | private final Clock timer = new Clock();
19 | private int lastSelectedSlot;
20 | private boolean slotChanged = false;
21 |
22 | private SlotChangeFailsafe() {
23 | this.lastSelectedSlot = mc.thePlayer != null ? mc.thePlayer.inventory.currentItem : -1;
24 | }
25 |
26 | @Override
27 | public String getName() {
28 | return "SlotChangeFailsafe";
29 | }
30 |
31 | @Override
32 | public Failsafe getFailsafeType() {
33 | return Failsafe.SLOT_CHANGE;
34 | }
35 |
36 | @Override
37 | public int getPriority() {
38 | return 5;
39 | }
40 |
41 | @Override
42 | public boolean onTick(ClientTickEvent event) {
43 | if (slotChanged && timer.passed()) {
44 | Logger.sendLog("Timer passed after slot change");
45 | return true;
46 | }
47 |
48 | return false;
49 | }
50 |
51 | @Override
52 | public boolean onPacketReceive(PacketEvent.Received event) {
53 | if (event.packet instanceof S09PacketHeldItemChange) {
54 | S09PacketHeldItemChange packet = (S09PacketHeldItemChange) event.packet;
55 | int slotIndex = packet.getHeldItemHotbarIndex();
56 |
57 | if (slotIndex != lastSelectedSlot) {
58 | log("Slot changed by S09 packet from " + lastSelectedSlot + " to " + slotIndex);
59 | slotChanged = true;
60 | lastSelectedSlot = slotIndex;
61 |
62 | if (!timer.isScheduled()) {
63 | timer.schedule(2000);
64 | }
65 | }
66 | }
67 |
68 | return false;
69 | }
70 |
71 | @Override
72 | public boolean react() {
73 | if (slotChanged) {
74 | MacroManager.getInstance().disable();
75 | warn("Slot selection changed! Disabling macro.");
76 | slotChanged = false;
77 | return true;
78 | }
79 |
80 | return false;
81 | }
82 |
83 | @Override
84 | public void resetStates() {
85 | timer.reset();
86 | slotChanged = false;
87 | log("SlotChangeFailsafe state reset.");
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/failsafe/impl/WorldChangeFailsafe.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.failsafe.impl;
2 |
3 | import com.jelly.mightyminerv2.failsafe.AbstractFailsafe;
4 | import com.jelly.mightyminerv2.feature.impl.AutoWarp;
5 | import com.jelly.mightyminerv2.macro.MacroManager;
6 | import lombok.Getter;
7 | import net.minecraft.client.Minecraft;
8 | import net.minecraftforge.event.world.WorldEvent;
9 |
10 | public class WorldChangeFailsafe extends AbstractFailsafe {
11 |
12 | @Getter
13 | private static final WorldChangeFailsafe instance = new WorldChangeFailsafe();
14 | private static final Failsafe failsafeType = Failsafe.TELEPORT;
15 |
16 | // Then remove the getFailsafeType() method entirely
17 | // Update any code to access the field directly
18 |
19 | @Override
20 | public String getName() {
21 | return "WorldChangeFailsafe";
22 | }
23 |
24 | @Override
25 | public Failsafe getFailsafeType() {
26 | return failsafeType;
27 | }
28 |
29 | @Override
30 | public int getPriority() {
31 | return 5;
32 | }
33 |
34 | @Override
35 | public boolean react() {
36 | warn("Stopping macro due to world change.");
37 | MacroManager.getInstance().disable();
38 | return true;
39 | }
40 |
41 | @Override
42 | public boolean onWorldUnload(WorldEvent.Unload event) {
43 | if (!MacroManager.getInstance().isEnabled()) return false;
44 | return AutoWarp.getInstance().isDoneWarping();
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/feature/FeatureManager.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.feature;
2 |
3 | import com.jelly.mightyminerv2.failsafe.AbstractFailsafe.Failsafe;
4 | import com.jelly.mightyminerv2.feature.impl.*;
5 | import com.jelly.mightyminerv2.feature.impl.AutoDrillRefuel.AutoDrillRefuel;
6 | import com.jelly.mightyminerv2.feature.impl.AutoGetStats.AutoGetStats;
7 | import com.jelly.mightyminerv2.feature.impl.AutoMobKiller.AutoMobKiller;
8 | import com.jelly.mightyminerv2.feature.impl.BlockMiner.BlockMiner;
9 |
10 | import java.util.Arrays;
11 | import java.util.HashSet;
12 | import java.util.LinkedHashSet;
13 | import java.util.Set;
14 |
15 | // TODO: Finish AutoSell and WorldScanner
16 | public class FeatureManager {
17 |
18 | private static FeatureManager instance;
19 | public final Set allFeatures = new LinkedHashSet<>();
20 |
21 | public FeatureManager() {
22 | this.allFeatures.addAll(Arrays.asList(
23 | AutoCommissionClaim.getInstance(),
24 | AutoGetStats.getInstance(),
25 | AutoMobKiller.getInstance(),
26 | AutoWarp.getInstance(),
27 | BlockMiner.getInstance(),
28 | MouseUngrab.getInstance(),
29 | Pathfinder.getInstance(),
30 | RouteBuilder.getInstance(),
31 | RouteNavigator.getInstance(),
32 | AutoDrillRefuel.getInstance(),
33 | AutoChestUnlocker.instance,
34 | WorldScanner.getInstance(),
35 | AutoSell.getInstance()
36 | ));
37 | }
38 |
39 | public static FeatureManager getInstance() {
40 | if (instance == null) {
41 | instance = new FeatureManager();
42 | }
43 | return instance;
44 | }
45 |
46 | public void enableAll() {
47 | this.allFeatures.forEach(it -> {
48 | if (it.shouldStartAtLaunch()) {
49 | it.start();
50 | }
51 | });
52 | }
53 |
54 | public void disableAll() {
55 | this.allFeatures.forEach(it -> {
56 | if (it.isRunning()) {
57 | it.stop();
58 | }
59 | });
60 | }
61 |
62 | public void pauseAll() {
63 | this.allFeatures.forEach(it -> {
64 | if (it.isRunning()) {
65 | it.pause();
66 | }
67 | });
68 | }
69 |
70 | public void resumeAll() {
71 | this.allFeatures.forEach(it -> {
72 | if (it.isRunning()) {
73 | it.resume();
74 | }
75 | });
76 | }
77 |
78 | public boolean shouldNotCheckForFailsafe() {
79 | return this.allFeatures.stream().filter(AbstractFeature::isRunning).anyMatch(AbstractFeature::shouldNotCheckForFailsafe);
80 | }
81 |
82 | public Set getFailsafesToIgnore() {
83 | Set failsafes = new HashSet<>();
84 | this.allFeatures.forEach(it -> {
85 | if (it.isRunning()) {
86 | failsafes.addAll(it.getFailsafesToIgnore());
87 | }
88 | });
89 | return failsafes;
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/feature/impl/AutoDrillRefuel/AutoDrillRefuel.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.feature.impl.AutoDrillRefuel;
2 |
3 | import com.jelly.mightyminerv2.failsafe.AbstractFailsafe.Failsafe;
4 | import com.jelly.mightyminerv2.feature.AbstractFeature;
5 | import com.jelly.mightyminerv2.feature.impl.AutoDrillRefuel.states.AutoDrillRefuelState;
6 | import com.jelly.mightyminerv2.feature.impl.AutoDrillRefuel.states.StartingState;
7 | import lombok.Getter;
8 | import lombok.Setter;
9 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
10 | import net.minecraftforge.fml.common.gameevent.TickEvent;
11 | import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent;
12 |
13 | public class AutoDrillRefuel extends AbstractFeature {
14 | @Getter
15 | private static final AutoDrillRefuel instance = new AutoDrillRefuel();
16 |
17 | public enum AutoDrillRefuelError {
18 | NONE,
19 | NO_DRILL,
20 | NO_FUEL,
21 | NO_ABIPHONE,
22 | NO_GREATFORGE_CONTACT
23 | }
24 | @Setter
25 | @Getter
26 | private AutoDrillRefuelError error = AutoDrillRefuelError.NONE;
27 |
28 | public enum FuelType{
29 | VOLTA ("Volta"),
30 | OIL_BARREL ("Oil Barrel");
31 |
32 | @Getter
33 | private final String name;
34 |
35 | FuelType(String name) {
36 | this.name = name;
37 | }
38 | }
39 | @Getter
40 | private FuelType fuelType;
41 |
42 | @Getter
43 | private String drillName;
44 |
45 | private AutoDrillRefuelState currentState;
46 |
47 | @Override
48 | public String getName() {
49 | return "AutoDrillRefuel";
50 | }
51 |
52 | @Override
53 | public void resetStatesAfterStop() {
54 | this.failsafesToIgnore.remove(Failsafe.ITEM_CHANGE);
55 | }
56 |
57 | public void start(String drillName, FuelType fuelType) {
58 | this.enabled = true;
59 | this.drillName = drillName;
60 | this.fuelType = fuelType;
61 | this.error = AutoDrillRefuelError.NONE;
62 | currentState = new StartingState();
63 | }
64 |
65 | @Override
66 | public void stop() {
67 | super.stop();
68 | }
69 |
70 | @SubscribeEvent
71 | public void onTick(ClientTickEvent event) {
72 | if (!this.enabled || event.phase == TickEvent.Phase.END) {
73 | return;
74 | }
75 |
76 | if (currentState == null)
77 | return;
78 |
79 | AutoDrillRefuelState nextState = currentState.onTick(this);
80 | transitionTo(nextState);
81 | }
82 |
83 | private void transitionTo(AutoDrillRefuelState nextState){
84 | // Skip if no state change
85 | if (currentState == nextState)
86 | return;
87 |
88 | currentState.onEnd(this);
89 | currentState = nextState;
90 |
91 | if (currentState == null) {
92 | log("null state, returning");
93 | return;
94 | }
95 |
96 | currentState.onStart(this);
97 | }
98 |
99 | }
100 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/feature/impl/AutoDrillRefuel/states/AbiphoneState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.feature.impl.AutoDrillRefuel.states;
2 |
3 | import com.jelly.mightyminerv2.feature.impl.AutoDrillRefuel.AutoDrillRefuel;
4 | import com.jelly.mightyminerv2.util.InventoryUtil;
5 | import com.jelly.mightyminerv2.util.KeyBindUtil;
6 | import net.minecraft.client.Minecraft;
7 |
8 | public class AbiphoneState implements AutoDrillRefuelState{
9 |
10 | private final Minecraft mc = Minecraft.getMinecraft();
11 |
12 | @Override
13 | public void onStart(AutoDrillRefuel refueler) {
14 | int abiphoneSlot = InventoryUtil.getHotbarSlotOfItem("Abiphone");
15 | if (abiphoneSlot == -1) {
16 | logError("No abiphone found!");
17 | refueler.stop();
18 | refueler.setError(AutoDrillRefuel.AutoDrillRefuelError.NO_ABIPHONE);
19 | return;
20 | }
21 |
22 | mc.thePlayer.inventory.currentItem = abiphoneSlot;
23 | KeyBindUtil.rightClick();
24 | log("Entering abiphone state");
25 | }
26 |
27 | @Override
28 | public AutoDrillRefuelState onTick(AutoDrillRefuel refueler) {
29 |
30 | if (InventoryUtil.getInventoryName().contains("Abiphone") && InventoryUtil.isInventoryLoaded()) {
31 | log("Opened Abiphone GUI");
32 | int greatforgeSlot = InventoryUtil.getSlotIdOfItemInContainer("Greatforge");
33 |
34 | if(greatforgeSlot == -1){
35 | logError("No Greatforge contact!");
36 | refueler.stop();
37 | refueler.setError(AutoDrillRefuel.AutoDrillRefuelError.NO_GREATFORGE_CONTACT);
38 | return null;
39 | }
40 |
41 | InventoryUtil.clickContainerSlot(greatforgeSlot, 0, InventoryUtil.ClickMode.PICKUP);
42 | return new GreatforgeState();
43 | }
44 |
45 | return this;
46 | }
47 |
48 | @Override
49 | public void onEnd(AutoDrillRefuel refueler) {
50 | log("Ending abiphone state");
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/feature/impl/AutoDrillRefuel/states/AutoDrillRefuelState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.feature.impl.AutoDrillRefuel.states;
2 |
3 | import com.jelly.mightyminerv2.feature.impl.AutoDrillRefuel.AutoDrillRefuel;
4 |
5 |
6 | public interface AutoDrillRefuelState {
7 |
8 | void onStart(AutoDrillRefuel refueler);
9 | AutoDrillRefuelState onTick(AutoDrillRefuel refueler);
10 | void onEnd(AutoDrillRefuel refueler);
11 |
12 | default void log(String message) {
13 | System.out.println("[" + this.getClass().getSimpleName() + "] " + message);
14 | }
15 |
16 | default void logError(String message) {
17 | System.out.println("[" + this.getClass().getSimpleName() + "] ERROR: " + message);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/feature/impl/AutoDrillRefuel/states/StartingState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.feature.impl.AutoDrillRefuel.states;
2 |
3 | import com.jelly.mightyminerv2.feature.impl.AutoDrillRefuel.AutoDrillRefuel;
4 | import com.jelly.mightyminerv2.util.InventoryUtil;
5 |
6 | public class StartingState implements AutoDrillRefuelState{
7 | @Override
8 | public void onStart(AutoDrillRefuel refueler) {
9 | log("Entering starting state");
10 | }
11 |
12 | @Override
13 | public AutoDrillRefuelState onTick(AutoDrillRefuel refueler) {
14 | if (InventoryUtil.getSlotIdOfItemInContainer(refueler.getDrillName()) == -1) {
15 | logError("No drill found!");
16 | refueler.stop();
17 | refueler.setError(AutoDrillRefuel.AutoDrillRefuelError.NO_DRILL);
18 | return null;
19 | }
20 |
21 | if (InventoryUtil.getSlotIdOfItemInContainer(refueler.getFuelType().getName()) == -1) {
22 | logError("No fuel found!");
23 | refueler.stop();
24 | refueler.setError(AutoDrillRefuel.AutoDrillRefuelError.NO_FUEL);
25 | return null;
26 | }
27 | return new AbiphoneState();
28 | }
29 |
30 | @Override
31 | public void onEnd(AutoDrillRefuel refueler) {
32 | log("Ending starting state");
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/feature/impl/AutoGetStats/AutoGetStats.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.feature.impl.AutoGetStats;
2 |
3 | import com.jelly.mightyminerv2.feature.AbstractFeature;
4 | import com.jelly.mightyminerv2.feature.impl.AutoGetStats.tasks.AbstractInventoryTask;
5 | import com.jelly.mightyminerv2.util.helper.Clock;
6 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
7 | import net.minecraftforge.fml.common.gameevent.TickEvent;
8 |
9 | import java.util.ArrayDeque;
10 | import java.util.Queue;
11 |
12 | /**
13 | * AutoGetStats handles a simple internal queue of AbstractInventoryTask,
14 | * running one at a time in FIFO order. Goes onto the next task (if any) when one fails.
15 | */
16 | public class AutoGetStats extends AbstractFeature {
17 |
18 | private static AutoGetStats instance;
19 |
20 | private final Queue> taskQueue = new ArrayDeque<>();
21 | private AbstractInventoryTask> currentTask;
22 |
23 | private final Clock delay = new Clock();
24 |
25 | public static AutoGetStats getInstance() {
26 | if (instance == null) {
27 | instance = new AutoGetStats();
28 | }
29 | return instance;
30 | }
31 |
32 | @Override
33 | public String getName() {
34 | return "AutoGetStats";
35 | }
36 |
37 | @SubscribeEvent
38 | protected void onTick(TickEvent.ClientTickEvent event) {
39 | if (!enabled || mc.thePlayer == null || mc.theWorld == null || event.phase == TickEvent.Phase.END)
40 | return;
41 |
42 | if (currentTask != null) {
43 | currentTask.onTick();
44 |
45 | if (currentTask.getTaskStatus().isFailure() || currentTask.getTaskStatus().isSuccessful()) {
46 | currentTask.end();
47 | currentTask = null;
48 | delay.schedule(1000); // 1-second delay between each task
49 | }
50 | }
51 | else if (delay.isScheduled() && delay.passed() && !taskQueue.isEmpty()) {
52 | currentTask = taskQueue.poll();
53 | currentTask.init();
54 | }
55 | }
56 |
57 | /**
58 | * Adds a new task to the queue and starts it immediately if idle.
59 | */
60 | public void startTask(AbstractInventoryTask> task) {
61 |
62 | if (task == null) return;
63 | taskQueue.add(task);
64 |
65 | // If no current task running, start this one immediately
66 | if (currentTask == null) {
67 | currentTask = taskQueue.poll();
68 | currentTask.init();
69 | this.enabled = true;
70 | this.start();
71 | }
72 | }
73 |
74 | public boolean hasFinishedAllTasks() {
75 | return currentTask == null && taskQueue.isEmpty();
76 | }
77 | }
78 |
79 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/feature/impl/AutoGetStats/tasks/AbstractInventoryTask.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.feature.impl.AutoGetStats.tasks;
2 |
3 | import lombok.Getter;
4 |
5 | /**
6 | * An abstract task class with a generic type parameter representing the result type.
7 | *
8 | * Each task follows a lifecycle with {@code init()}, {@code onTick()}, and {@code end()} methods.
9 | * The task begins in a {@link TaskStatus#PENDING} state by default
10 | * Subclasses must implement {@code getResult()} to return the final output once the task is complete.
11 | *
12 | * In the subclass, please initialize taskStatus to {@link TaskStatus#RUNNING}. Once the task has successfully finished,
13 | * set it to{@link TaskStatus#SUCCESS}. If the task failed, set taskStatus to {@link TaskStatus#FAILURE}, and attach
14 | * an error.
15 | * @param the type of result this task produces upon successful completion
16 | */
17 | public abstract class AbstractInventoryTask {
18 | @Getter
19 | protected TaskStatus taskStatus = TaskStatus.PENDING;
20 |
21 | @Getter
22 | protected String error;
23 |
24 | abstract public void init();
25 | abstract public void onTick();
26 | abstract public void end();
27 | abstract public T getResult();
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/feature/impl/AutoGetStats/tasks/TaskStatus.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.feature.impl.AutoGetStats.tasks;
2 |
3 | public enum TaskStatus {
4 | PENDING,
5 | RUNNING,
6 | SUCCESS,
7 | FAILURE;
8 |
9 | public boolean isRunning() {
10 | return this == RUNNING;
11 | }
12 |
13 | public boolean isSuccessful() {
14 | return this == SUCCESS;
15 | }
16 |
17 | public boolean isFailure() {
18 | return this == FAILURE;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/feature/impl/AutoGetStats/tasks/impl/MiningBoostRetrievalTask.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.feature.impl.AutoGetStats.tasks.impl;
2 |
3 | import com.jelly.mightyminerv2.config.MightyMinerConfig;
4 | import com.jelly.mightyminerv2.feature.impl.AutoGetStats.tasks.AbstractInventoryTask;
5 | import com.jelly.mightyminerv2.feature.impl.AutoGetStats.tasks.TaskStatus;
6 | import com.jelly.mightyminerv2.util.InventoryUtil;
7 | import com.jelly.mightyminerv2.util.helper.Clock;
8 | import net.minecraft.client.Minecraft;
9 |
10 | import java.util.regex.Matcher;
11 | import java.util.regex.Pattern;
12 |
13 | /**
14 | * A task that retrieves the Mining boost value from the player's HOTM GUI.
15 | */
16 | public class MiningBoostRetrievalTask extends AbstractInventoryTask {
17 |
18 | private final Minecraft mc = Minecraft.getMinecraft();
19 | private final Clock timer = new Clock();
20 | private Integer speedBoost;
21 |
22 | @Override
23 | public void init() {
24 | taskStatus = TaskStatus.RUNNING;
25 |
26 | InventoryUtil.holdItem(MightyMinerConfig.miningTool);
27 |
28 | if (mc.currentScreen != null) {
29 | InventoryUtil.closeScreen();
30 | }
31 |
32 | mc.thePlayer.sendChatMessage("/hotm");
33 | timer.schedule(1000);
34 | }
35 |
36 | @Override
37 | public void onTick() {
38 | if (!timer.passed() && timer.isScheduled()) {
39 | return;
40 | }
41 |
42 | final int speedBoostSlot = InventoryUtil.getSlotIdOfItemInContainer("Mining Speed Boost");
43 | final String speedBoostLore = String.join(" ", InventoryUtil.getLoreOfItemInContainer(speedBoostSlot));
44 |
45 | final Matcher matcher = Pattern.compile("\\+(\\d+)%").matcher(speedBoostLore);
46 | if (matcher.find()) {
47 | speedBoost = Integer.parseInt(matcher.group(1));
48 | taskStatus = TaskStatus.SUCCESS;
49 | return;
50 | }
51 |
52 | taskStatus = TaskStatus.FAILURE;
53 | error = "Cannot parse speed boost. You may have scrolled up in your HOTM GUI.";
54 | }
55 |
56 | @Override
57 | public void end() {
58 | InventoryUtil.closeScreen();
59 | }
60 |
61 | @Override
62 | public Integer getResult() {
63 | return speedBoost;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/feature/impl/AutoGetStats/tasks/impl/MiningSpeedRetrievalTask.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.feature.impl.AutoGetStats.tasks.impl;
2 |
3 | import com.jelly.mightyminerv2.config.MightyMinerConfig;
4 | import com.jelly.mightyminerv2.feature.impl.AutoGetStats.tasks.AbstractInventoryTask;
5 | import com.jelly.mightyminerv2.feature.impl.AutoGetStats.tasks.TaskStatus;
6 | import com.jelly.mightyminerv2.util.InventoryUtil;
7 | import com.jelly.mightyminerv2.util.helper.Clock;
8 | import net.minecraft.client.Minecraft;
9 |
10 | import java.util.List;
11 | import java.util.regex.Matcher;
12 | import java.util.regex.Pattern;
13 |
14 | /**
15 | * A task that retrieves the Mining Speed value from the player's SkyBlock GUI.
16 | */
17 | public class MiningSpeedRetrievalTask extends AbstractInventoryTask {
18 |
19 | private final Minecraft mc = Minecraft.getMinecraft();
20 | private final Clock timer = new Clock();
21 | private Integer miningSpeed;
22 | private static final Pattern MINING_SPEED_PATTERN = Pattern.compile("Mining Speed\\s+([\\d,]+\\.?\\d*)");
23 |
24 | @Override
25 | public void init() {
26 | taskStatus = TaskStatus.RUNNING;
27 |
28 | InventoryUtil.holdItem(MightyMinerConfig.miningTool);
29 |
30 | if(!InventoryUtil.getInventoryName().equals("Your Equipment and Stats")) {
31 | if (mc.currentScreen != null) {
32 | InventoryUtil.closeScreen();
33 | }
34 |
35 | mc.thePlayer.sendChatMessage("/stats");
36 | }
37 |
38 | timer.schedule(1000);
39 | }
40 |
41 | @Override
42 | public void onTick() {
43 | if (!timer.passed() && timer.isScheduled()) {
44 | return;
45 | }
46 |
47 | if (!InventoryUtil.getInventoryName().equals("Your Equipment and Stats")) {
48 | taskStatus = TaskStatus.FAILURE;
49 | error = "Cannot open Stats Menu";
50 | return;
51 | }
52 |
53 | List loreList = InventoryUtil.getItemLoreFromOpenContainer("Mining Stats");
54 | for (String lore : loreList) {
55 | Matcher matcher = MINING_SPEED_PATTERN.matcher(lore);
56 | if (matcher.find()) {
57 | try {
58 | // The number - for example, "2,000" or "123.45" or "1,234.56"
59 | String numberAsString = matcher.group(1);
60 | String cleanNumberString = numberAsString.replace(",", "");
61 |
62 | // Mining speeds from the 'stats menu' can be a decimal
63 | double rawMiningSpeed = Double.parseDouble(cleanNumberString);
64 | miningSpeed = (int) rawMiningSpeed;
65 |
66 | taskStatus = TaskStatus.SUCCESS;
67 | return;
68 | } catch (NumberFormatException e) {
69 | taskStatus = TaskStatus.FAILURE;
70 | error = "Found 'Mining Speed' but failed to parse the number in line: '" + lore + "'. Exiting with error: " + e.getMessage();
71 | return;
72 | }
73 | }
74 | }
75 |
76 | taskStatus = TaskStatus.FAILURE;
77 | error = "Failed to get mining speed in GUI";
78 | }
79 |
80 | @Override
81 | public void end() {
82 | InventoryUtil.closeScreen();
83 | }
84 |
85 | @Override
86 | public Integer getResult() {
87 | return miningSpeed;
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/feature/impl/AutoGetStats/tasks/impl/PickaxeAbilityRetrievalTask.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.feature.impl.AutoGetStats.tasks.impl;
2 |
3 | import com.jelly.mightyminerv2.feature.impl.AutoGetStats.tasks.AbstractInventoryTask;
4 | import com.jelly.mightyminerv2.feature.impl.AutoGetStats.tasks.TaskStatus;
5 | import com.jelly.mightyminerv2.feature.impl.BlockMiner.BlockMiner;
6 | import com.jelly.mightyminerv2.util.InventoryUtil;
7 | import com.jelly.mightyminerv2.util.helper.Clock;
8 | import net.minecraft.block.Block;
9 | import net.minecraft.client.Minecraft;
10 | import net.minecraft.init.Blocks;
11 | import net.minecraft.inventory.Slot;
12 |
13 | /**
14 | * A task that retrieves the players pickaxe ability from the HOTM GUI.
15 | */
16 | public class PickaxeAbilityRetrievalTask extends AbstractInventoryTask {
17 |
18 | private final Minecraft mc = Minecraft.getMinecraft();
19 | private final Clock timer = new Clock();
20 | private BlockMiner.PickaxeAbility pickaxeAbility;
21 |
22 | @Override
23 | public void init() {
24 | pickaxeAbility = BlockMiner.PickaxeAbility.NONE;
25 | taskStatus = TaskStatus.RUNNING;
26 |
27 | // The case that the HOTM menu is already open
28 | if (!InventoryUtil.getInventoryName().equals("Heart of the Mountain")) {
29 | if (mc.currentScreen != null) {
30 | InventoryUtil.closeScreen();
31 | }
32 |
33 | mc.thePlayer.sendChatMessage("/hotm");
34 | }
35 |
36 | timer.schedule(1000);
37 | }
38 |
39 | @Override
40 | public void onTick() {
41 | if (!timer.passed() && timer.isScheduled()) {
42 | return;
43 | }
44 |
45 | if (isSelected("Pickobulus")) {
46 | pickaxeAbility = BlockMiner.PickaxeAbility.PICKOBULUS;
47 | } else {
48 | pickaxeAbility = BlockMiner.PickaxeAbility.MINING_SPEED_BOOST;
49 | }
50 | taskStatus = TaskStatus.SUCCESS;
51 | }
52 |
53 | private boolean isSelected(String name) {
54 | final Slot slot = InventoryUtil.getSlotOfItemInContainer(name);
55 | final Block block = slot != null
56 | ? Block.getBlockFromItem(slot.getStack().getItem())
57 | : null;
58 |
59 | return block != null && block == Blocks.emerald_block;
60 | }
61 |
62 | @Override
63 | public void end() {
64 | InventoryUtil.closeScreen();
65 | }
66 |
67 | @Override
68 | public BlockMiner.PickaxeAbility getResult() {
69 | return pickaxeAbility;
70 | }
71 | }
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/feature/impl/AutoMobKiller/states/AutoMobKillerState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.feature.impl.AutoMobKiller.states;
2 |
3 | import com.jelly.mightyminerv2.feature.impl.AutoMobKiller.AutoMobKiller;
4 |
5 | /**
6 | * AutoMobKillerState
7 | *
8 | * Interface for all states in the AutoMobKiller state machine.
9 | * Implements the State design pattern to encapsulate different behaviors
10 | * for each phase of the mining process.
11 | */
12 | public interface AutoMobKillerState {
13 | /**
14 | * Called when entering this state.
15 | * Use for initialization and setup logic.
16 | *
17 | * @param mobKiller Reference to the AutoMobKiller instance
18 | */
19 | void onStart(AutoMobKiller mobKiller);
20 |
21 | /**
22 | * Called on each game tick while this state is active.
23 | * Contains the main processing logic for the state.
24 | *
25 | * @param mobKiller Reference to the AutoMobKiller instance
26 | * @return The next state to transition to, or this if staying in current state
27 | */
28 | AutoMobKillerState onTick(AutoMobKiller mobKiller);
29 |
30 | /**
31 | * Called when exiting this state.
32 | * Use for cleanup and finalization logic.
33 | *
34 | * @param mobKiller Reference to the AutoMobKiller instance
35 | */
36 | void onEnd(AutoMobKiller mobKiller);
37 |
38 | default void log(String message) {
39 | System.out.println("[" + this.getClass().getSimpleName() + "] " + message);
40 | }
41 |
42 | default void logError(String message) {
43 | System.out.println("[" + this.getClass().getSimpleName() + "] ERROR: " + message);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/feature/impl/AutoMobKiller/states/FindMobState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.feature.impl.AutoMobKiller.states;
2 |
3 | import com.jelly.mightyminerv2.config.MightyMinerConfig;
4 | import com.jelly.mightyminerv2.feature.impl.AutoMobKiller.AutoMobKiller;
5 | import com.jelly.mightyminerv2.feature.impl.Pathfinder;
6 | import com.jelly.mightyminerv2.util.BlockUtil;
7 | import com.jelly.mightyminerv2.util.EntityUtil;
8 | import com.jelly.mightyminerv2.util.PlayerUtil;
9 | import com.jelly.mightyminerv2.util.helper.Clock;
10 | import net.minecraft.client.Minecraft;
11 | import net.minecraft.entity.Entity;
12 | import net.minecraft.entity.EntityLivingBase;
13 | import net.minecraft.entity.player.EntityPlayer;
14 | import net.minecraft.util.BlockPos;
15 |
16 | import java.util.ArrayList;
17 | import java.util.Comparator;
18 | import java.util.List;
19 | import java.util.stream.Collector;
20 | import java.util.stream.Collectors;
21 |
22 | public class FindMobState implements AutoMobKillerState {
23 |
24 | private final Minecraft mc = Minecraft.getMinecraft();
25 | private final Clock waitForMobsToSpawnTimer = new Clock();
26 |
27 | @Override
28 | public void onStart(AutoMobKiller mobKiller) {
29 | log("Entering Find Mob State");
30 | waitForMobsToSpawnTimer.reset();
31 | }
32 |
33 | @Override
34 | public AutoMobKillerState onTick(AutoMobKiller mobKiller) {
35 |
36 | EntityLivingBase mob = findBestMob(mobKiller);
37 |
38 | if (mob == null) {
39 | if (!waitForMobsToSpawnTimer.isScheduled()) {
40 | log("Scheduled a 10-second timer to see if mobs spawn or not");
41 | waitForMobsToSpawnTimer.schedule(10_000);
42 | }
43 |
44 | if (waitForMobsToSpawnTimer.isScheduled() && waitForMobsToSpawnTimer.passed()) {
45 | log("Cannot find a mob to kill!");
46 | mobKiller.setError(AutoMobKiller.MKError.NO_ENTITIES);
47 | mobKiller.stop();
48 | return null;
49 | }
50 |
51 | return this;
52 | }
53 |
54 | mobKiller.setTargetMob(mob);
55 | mobKiller.setTargetMobOriginalPos(mob.getPositionVector());
56 | return new PathfindingState();
57 | }
58 |
59 | private EntityLivingBase findBestMob(AutoMobKiller mobKiller) {
60 | Minecraft mc = Minecraft.getMinecraft();
61 | List playerEntities = new ArrayList<>(Minecraft.getMinecraft().theWorld.playerEntities);
62 | playerEntities.remove(mc.thePlayer);
63 |
64 | List actualPlayers = playerEntities.stream()
65 | .filter(player -> !EntityUtil.isNpc(player))
66 | .collect(Collectors.toList());
67 |
68 | List mobs = EntityUtil.getEntities(mobKiller.getMobsToKill(), mobKiller.getBlacklistedMobs());
69 |
70 | if(mobs.isEmpty())
71 | return null;
72 |
73 | List filteredMobs = mobs.stream()
74 | .filter(mob -> mc.thePlayer.getDistanceSqToEntity(mob) < 1000)
75 | .filter(mob -> actualPlayers.stream()
76 | .noneMatch(player -> player.getDistanceSqToEntity(mob) < 9.0f))
77 | .filter(mob -> BlockUtil.canStandOn(EntityUtil.getBlockStandingOn(mob)))
78 | .collect(Collectors.toList());
79 |
80 | return filteredMobs.stream()
81 | .min(Comparator.comparingDouble(mob -> mc.thePlayer.getDistanceSqToEntity(mob)))
82 | .orElse(null);
83 | }
84 |
85 |
86 | @Override
87 | public void onEnd(AutoMobKiller mobKiller) {
88 | log("Exiting Find Mob State");
89 | }
90 |
91 | }
92 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/feature/impl/AutoMobKiller/states/KillState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.feature.impl.AutoMobKiller.states;
2 |
3 | import com.jelly.mightyminerv2.feature.impl.AutoMobKiller.AutoMobKiller;
4 | import com.jelly.mightyminerv2.feature.impl.Pathfinder;
5 | import com.jelly.mightyminerv2.handler.RotationHandler;
6 | import com.jelly.mightyminerv2.util.KeyBindUtil;
7 | import com.jelly.mightyminerv2.util.helper.RotationConfiguration;
8 | import com.jelly.mightyminerv2.util.helper.Target;
9 | import net.minecraft.client.Minecraft;
10 |
11 | public class KillState implements AutoMobKillerState {
12 |
13 | private final Minecraft mc = Minecraft.getMinecraft();
14 | private boolean hasRotated = false;
15 |
16 | @Override
17 | public void onStart(AutoMobKiller mobKiller) {
18 | log("Entering Kill State");
19 | hasRotated = false;
20 | }
21 |
22 | @Override
23 | public AutoMobKillerState onTick(AutoMobKiller mobKiller) {
24 | // Initial rotation to mob
25 | if (!hasRotated) {
26 | RotationHandler.getInstance().easeTo(new RotationConfiguration(
27 | new Target(mobKiller.getTargetMob()),
28 | 400L,
29 | null
30 | ));
31 |
32 | hasRotated = true;
33 | return this;
34 | }
35 |
36 | // Attack as soon as the player is able to hit the entity
37 | if (mc.objectMouseOver.entityHit != mobKiller.getTargetMob()) {
38 | if (!Pathfinder.getInstance().isRunning() && !RotationHandler.getInstance().isEnabled()) {
39 | return new StartingState();
40 | }
41 |
42 | return this;
43 | }
44 |
45 | KeyBindUtil.leftClick();
46 | RotationHandler.getInstance().stop();
47 | return new StartingState();
48 | }
49 |
50 | @Override
51 | public void onEnd(AutoMobKiller mobKiller) {
52 | log("Exiting Kill State");
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/feature/impl/AutoMobKiller/states/PathfindingState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.feature.impl.AutoMobKiller.states;
2 |
3 | import com.jelly.mightyminerv2.config.MightyMinerConfig;
4 | import com.jelly.mightyminerv2.feature.impl.AutoMobKiller.AutoMobKiller;
5 | import com.jelly.mightyminerv2.feature.impl.Pathfinder;
6 | import com.jelly.mightyminerv2.util.EntityUtil;
7 | import com.jelly.mightyminerv2.util.PlayerUtil;
8 | import com.jelly.mightyminerv2.util.helper.Clock;
9 | import net.minecraft.client.Minecraft;
10 |
11 | public class PathfindingState implements AutoMobKillerState{
12 |
13 | private int pathAttempts = 0;
14 | private final Clock timeout = new Clock();
15 |
16 | @Override
17 | public void onStart(AutoMobKiller mobKiller) {
18 | log("Entering pathfinding state");
19 | pathAttempts = 0;
20 | timeout.reset();
21 | timeout.schedule(10_000);
22 | Pathfinder.getInstance().stopAndRequeue(EntityUtil.nearbyBlock(mobKiller.getTargetMob()));
23 | Pathfinder.getInstance().setSprintState(MightyMinerConfig.mobKillerSprint);
24 | Pathfinder.getInstance().setInterpolationState(MightyMinerConfig.mobKillerInterpolate);
25 | Pathfinder.getInstance().start();
26 | }
27 |
28 | @Override
29 | public AutoMobKillerState onTick(AutoMobKiller mobKiller) {
30 | if (PlayerUtil.getNextTickPosition().squareDistanceTo(mobKiller.getTargetMob().getPositionVector()) < 8
31 | && Minecraft.getMinecraft().thePlayer.canEntityBeSeen(mobKiller.getTargetMob())) {
32 | return new KillState();
33 | }
34 |
35 | if (!mobKiller.getTargetMob().isEntityAlive()) {
36 | Pathfinder.getInstance().stop();
37 | log("Target mob is no longer alive. Re-choosing a mob.");
38 | return new StartingState();
39 | }
40 |
41 | if (mobKiller.getTargetMob().getPositionVector().squareDistanceTo(mobKiller.getTargetMobOriginalPos()) > 9) {
42 | if (++pathAttempts > 3) {
43 | log("Target mob moved away from original location too many times. Re-choosing a mob.");
44 | mobKiller.getBlacklistedMobs().add(mobKiller.getTargetMob());
45 | return new StartingState();
46 | }
47 | mobKiller.setTargetMobOriginalPos(mobKiller.getTargetMob().getPositionVector());
48 | Pathfinder.getInstance().stopAndRequeue(EntityUtil.nearbyBlock(mobKiller.getTargetMob()));
49 | return this;
50 | }
51 |
52 | if (timeout.passed()) {
53 | log("Pathfinding timeout. Re-choosing a mob.");
54 | mobKiller.getBlacklistedMobs().add(mobKiller.getTargetMob());
55 | return new StartingState();
56 | }
57 |
58 | return this;
59 | }
60 |
61 | @Override
62 | public void onEnd(AutoMobKiller mobKiller) {
63 | Pathfinder.getInstance().stop();
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/feature/impl/AutoMobKiller/states/StartingState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.feature.impl.AutoMobKiller.states;
2 |
3 | import com.jelly.mightyminerv2.feature.impl.AutoMobKiller.AutoMobKiller;
4 | import net.minecraft.entity.EntityLivingBase;
5 |
6 | public class StartingState implements AutoMobKillerState {
7 |
8 | @Override
9 | public void onStart(AutoMobKiller mobKiller) {
10 | log("Entering Starting State");
11 | }
12 |
13 | @Override
14 | public AutoMobKillerState onTick(AutoMobKiller mobKiller) {
15 | return new FindMobState();
16 | }
17 |
18 | @Override
19 | public void onEnd(AutoMobKiller mobKiller) {
20 | log("Exiting Starting State");
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/feature/impl/AutoSell.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.feature.impl;
2 |
3 | import com.jelly.mightyminerv2.feature.AbstractFeature;
4 | import lombok.Getter;
5 |
6 | public class AutoSell extends AbstractFeature {
7 |
8 | @Getter
9 | public static AutoSell instance = new AutoSell();
10 |
11 | @Override
12 | public String getName() {
13 | return "AutoSell";
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/feature/impl/BlockMiner/states/BlockMinerState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.feature.impl.BlockMiner.states;
2 |
3 | import com.jelly.mightyminerv2.feature.impl.BlockMiner.BlockMiner;
4 |
5 | /**
6 | * BlockMinerState
7 | *
8 | * Interface for all states in the BlockMiner state machine.
9 | * Implements the State design pattern to encapsulate different behaviors
10 | * for each phase of the mining process.
11 | */
12 | public interface BlockMinerState {
13 | /**
14 | * Called when entering this state.
15 | * Use for initialization and setup logic.
16 | *
17 | * @param miner Reference to the BlockMiner instance
18 | */
19 | void onStart(BlockMiner miner);
20 |
21 | /**
22 | * Called on each game tick while this state is active.
23 | * Contains the main processing logic for the state.
24 | *
25 | * @param miner Reference to the BlockMiner instance
26 | * @return The next state to transition to, or this if staying in current state
27 | */
28 | BlockMinerState onTick(BlockMiner miner);
29 |
30 | /**
31 | * Called when exiting this state.
32 | * Use for cleanup and finalization logic.
33 | *
34 | * @param miner Reference to the BlockMiner instance
35 | */
36 | void onEnd(BlockMiner miner);
37 |
38 | default void log(String message) {
39 | System.out.println("[" + this.getClass().getSimpleName() + "] " + message);
40 | }
41 |
42 | default void logError(String message) {
43 | System.out.println("[" + this.getClass().getSimpleName() + "] ERROR: " + message);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/feature/impl/BlockMiner/states/ChoosingBlockState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.feature.impl.BlockMiner.states;
2 |
3 | import com.jelly.mightyminerv2.feature.impl.BlockMiner.BlockMiner;
4 | import com.jelly.mightyminerv2.util.BlockUtil;
5 | import com.jelly.mightyminerv2.util.helper.Clock;
6 | import net.minecraft.client.Minecraft;
7 | import net.minecraft.util.BlockPos;
8 |
9 | import java.util.List;
10 |
11 | /**
12 | * ChoosingBlockState
13 | *
14 | * State responsible for finding the next block to mine.
15 | * Uses priority settings to determine the best block to target.
16 | * Includes wait logic if no blocks are immediately available.
17 | */
18 | public class ChoosingBlockState implements BlockMinerState {
19 | private final Clock timer = new Clock();
20 |
21 | @Override
22 | public void onStart(BlockMiner blockMiner) {
23 | log("Entering Choosing Block State");
24 | timer.reset();
25 | }
26 |
27 | @Override
28 | public BlockMinerState onTick(BlockMiner blockMiner) {
29 | // Try to find mineable blocks around the player based on priorities
30 | List blocks = BlockUtil.findMineableBlocksFromAccessiblePositions(
31 | blockMiner.getBlockPriority(),
32 | blockMiner.getTargetBlockPos(),
33 | blockMiner.getMiningSpeed()
34 | );
35 |
36 | // Handle case where no blocks are found
37 | if (blocks.isEmpty()) {
38 | if (!timer.isScheduled()) {
39 | log("Scheduled a 2-second timer to see if blocks spawn or not");
40 | timer.schedule(blockMiner.getWaitThreshold());
41 | }
42 |
43 | // If the timer has ended and still no blocks, stop mining
44 | if (timer.isScheduled() && timer.passed()) {
45 | logError("Cannot find enough blocks to mine.");
46 | blockMiner.stop();
47 | blockMiner.setError(BlockMiner.BlockMinerError.NOT_ENOUGH_BLOCKS);
48 | return null;
49 | }
50 |
51 | // Wait for the timer to expire
52 | return this;
53 | }
54 |
55 | // Found blocks - select the best one (first in list) and transition to breaking
56 | blockMiner.setTargetBlockPos(blocks.get(0));
57 | blockMiner.setTargetBlockType(Minecraft.getMinecraft().theWorld.getBlockState(blocks.get(0)).getBlock());
58 | return new BreakingState();
59 | }
60 |
61 | @Override
62 | public void onEnd(BlockMiner blockMiner) {
63 | log("Exiting Choosing Block State");
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/feature/impl/BlockMiner/states/StartingState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.feature.impl.BlockMiner.states;
2 |
3 | import com.jelly.mightyminerv2.feature.impl.BlockMiner.BlockMiner;
4 | import com.jelly.mightyminerv2.config.MightyMinerConfig;
5 |
6 | /**
7 | * StartingState
8 | *
9 | * Initial state in the BlockMiner state machine.
10 | * Acts as an entry point and determines the next appropriate state.
11 | */
12 | public class StartingState implements BlockMinerState {
13 |
14 | @Override
15 | public void onStart(BlockMiner miner) {
16 | log("Entering Starting State");
17 | }
18 |
19 | @Override
20 | public BlockMinerState onTick(BlockMiner miner) {
21 | if (BlockMiner.getInstance().getPickaxeAbility() != BlockMiner.PickaxeAbility.NONE
22 | && miner.getPickaxeAbilityState() == BlockMiner.PickaxeAbilityState.AVAILABLE) {
23 | return new ApplyAbilityState();
24 | } else
25 | return new ChoosingBlockState();
26 | }
27 |
28 | @Override
29 | public void onEnd(BlockMiner miner) {
30 | log("Exiting Starting State");
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/feature/impl/MouseUngrab.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.feature.impl;
2 |
3 | import com.jelly.mightyminerv2.config.MightyMinerConfig;
4 | import com.jelly.mightyminerv2.feature.AbstractFeature;
5 | import net.minecraft.util.MouseHelper;
6 | import org.lwjgl.input.Mouse;
7 |
8 | public class MouseUngrab extends AbstractFeature {
9 |
10 | private static volatile MouseUngrab instance;
11 | private MouseHelper oldMouseHelper;
12 | private boolean mouseUngrabbed = false;
13 |
14 | public static MouseUngrab getInstance() {
15 | if (instance == null) {
16 | synchronized (MouseUngrab.class) {
17 | if (instance == null) {
18 | instance = new MouseUngrab();
19 | }
20 | }
21 | }
22 | return instance;
23 | }
24 |
25 | public void ungrabMouse() {
26 | if (mouseUngrabbed || !Mouse.isGrabbed()) {
27 | return;
28 | }
29 |
30 | oldMouseHelper = mc.mouseHelper;
31 | mc.mouseHelper.ungrabMouseCursor();
32 |
33 | mc.mouseHelper = new MouseHelper() {
34 | @Override
35 | public void mouseXYChange() {
36 | }
37 |
38 | @Override
39 | public void grabMouseCursor() {
40 | }
41 |
42 | @Override
43 | public void ungrabMouseCursor() {
44 | }
45 | };
46 |
47 | mouseUngrabbed = true;
48 | log("Mouse ungrabbed successfully.");
49 | }
50 |
51 | public void regrabMouse() {
52 | if (!mouseUngrabbed || Mouse.isGrabbed()) {
53 | return;
54 | }
55 |
56 | if (oldMouseHelper != null) {
57 | mc.mouseHelper = oldMouseHelper;
58 | oldMouseHelper = null;
59 | }
60 |
61 | if (mc.currentScreen == null) {
62 | mc.mouseHelper.grabMouseCursor();
63 | }
64 |
65 | mouseUngrabbed = false;
66 | log("Mouse regrabbed successfully.");
67 | }
68 |
69 | @Override
70 | public String getName() {
71 | return "Ungrab Mouse";
72 | }
73 |
74 | @Override
75 | public boolean isEnabled() {
76 | return MightyMinerConfig.ungrabMouse;
77 | }
78 |
79 | @Override
80 | public boolean shouldStartAtLaunch() {
81 | return this.isEnabled();
82 | }
83 |
84 | @Override
85 | public void start() {
86 | log("MouseUngrab::start");
87 | try {
88 | ungrabMouse();
89 | } catch (Exception e) {
90 | log("Failed to ungrab mouse: " + e.getMessage());
91 | e.printStackTrace();
92 | }
93 | }
94 |
95 | @Override
96 | public void stop() {
97 | log("MouseUngrab::stop");
98 | try {
99 | regrabMouse();
100 | } catch (Exception e) {
101 | log("Failed to regrab mouse: " + e.getMessage());
102 | e.printStackTrace();
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/feature/impl/RouteBuilder.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.feature.impl;
2 |
3 | import cc.polyfrost.oneconfig.utils.Multithreading;
4 | import com.jelly.mightyminerv2.config.MightyMinerConfig;
5 | import com.jelly.mightyminerv2.feature.AbstractFeature;
6 | import com.jelly.mightyminerv2.handler.RouteHandler;
7 | import com.jelly.mightyminerv2.util.Logger;
8 | import com.jelly.mightyminerv2.util.PlayerUtil;
9 | import com.jelly.mightyminerv2.util.helper.route.Route;
10 | import com.jelly.mightyminerv2.util.helper.route.RouteWaypoint;
11 | import com.jelly.mightyminerv2.util.helper.route.WaypointType;
12 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
13 | import net.minecraftforge.fml.common.gameevent.InputEvent;
14 |
15 | import java.util.concurrent.TimeUnit;
16 |
17 | public class RouteBuilder extends AbstractFeature {
18 |
19 | private static RouteBuilder instance;
20 |
21 | public static RouteBuilder getInstance() {
22 | if (instance == null) {
23 | instance = new RouteBuilder();
24 | }
25 | return instance;
26 | }
27 |
28 | @Override
29 | public String getName() {
30 | return "RouteBuilder";
31 | }
32 |
33 | public void toggle() {
34 | if (!this.enabled) {
35 | this.start();
36 | } else {
37 | this.stop();
38 | }
39 | }
40 |
41 | @Override
42 | public void start() {
43 | this.enabled = true;
44 | Multithreading.schedule(RouteHandler.getInstance()::saveData, 0, TimeUnit.MILLISECONDS);
45 | send("Enabling RouteBuilder.");
46 | }
47 |
48 | @Override
49 | public void stop() {
50 | this.enabled = false;
51 | send("Disabling RouteBuilder.");
52 | }
53 |
54 | @SubscribeEvent
55 | public void onKeyEvent(InputEvent.KeyInputEvent event) {
56 | if (!this.enabled) {
57 | return;
58 | }
59 |
60 | if (MightyMinerConfig.routeBuilderWalkAddKeybind.isActive()) {
61 | this.addToRoute(WaypointType.WALK);
62 | Logger.sendMessage("Added Walk");
63 | }
64 |
65 | if (MightyMinerConfig.routeBuilderEtherwarpAddKeybind.isActive()) {
66 | this.addToRoute(WaypointType.ETHERWARP);
67 | Logger.sendMessage("Added Etherwarp");
68 | }
69 |
70 | if (MightyMinerConfig.routeBuilderRemoveKeybind.isActive()) {
71 | Route selectedRoute = RouteHandler.getInstance().getSelectedRoute();
72 | RouteWaypoint closest = selectedRoute.getClosest(PlayerUtil.getBlockStandingOn()).get();
73 | int index = selectedRoute.indexOf(closest);
74 |
75 | if (index == -1) {
76 | return;
77 | }
78 |
79 | this.removeFromRoute(index);
80 | }
81 | }
82 |
83 | public void addToRoute(final WaypointType method) {
84 | RouteHandler.getInstance().addToCurrentRoute(PlayerUtil.getBlockStandingOn(), method);
85 | }
86 |
87 | public void removeFromRoute(int index) {
88 | RouteHandler.getInstance().removeFromCurrentRoute(index);
89 | }
90 |
91 | public void replaceNode(final int index) {
92 | RouteHandler.getInstance().replaceInCurrentRoute(index, new RouteWaypoint(PlayerUtil.getBlockStandingOn(), WaypointType.ETHERWARP));
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/feature/impl/WorldScanner.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.feature.impl;
2 |
3 | import com.jelly.mightyminerv2.feature.AbstractFeature;
4 | import lombok.Getter;
5 |
6 | public class WorldScanner extends AbstractFeature {
7 |
8 | @Getter
9 | public static WorldScanner instance = new WorldScanner();
10 |
11 | @Override
12 | public String getName() {
13 | return "WorldScanner";
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/hud/DebugHUD.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.hud;
2 |
3 | import cc.polyfrost.oneconfig.config.core.OneColor;
4 | import cc.polyfrost.oneconfig.hud.TextHud;
5 | import com.jelly.mightyminerv2.handler.GameStateHandler;
6 | import com.jelly.mightyminerv2.util.ScoreboardUtil;
7 | import lombok.Getter;
8 | import net.minecraft.client.Minecraft;
9 | import org.lwjgl.opengl.Display;
10 |
11 | import java.util.List;
12 |
13 | public class DebugHUD extends TextHud {
14 |
15 | @Getter
16 | private final static DebugHUD instance = new DebugHUD();
17 | private final transient Minecraft mc = Minecraft.getMinecraft();
18 |
19 | public DebugHUD() {
20 | super(
21 | false,
22 | 1f,
23 | 10f,
24 | 0.8f,
25 | true,
26 | true,
27 | 1,
28 | 5,
29 | 5,
30 | new OneColor(0, 0, 0, 150),
31 | false,
32 | 2,
33 | new OneColor(0, 0, 0, 127)
34 | );
35 | }
36 |
37 | @Override
38 | protected void getLines(List lines, boolean example) {
39 |
40 | lines.add("§6§lScoreboard");
41 | lines.add("§7Title: §f" + ScoreboardUtil.getScoreboardTitle());
42 | lines.addAll(ScoreboardUtil.getScoreboard());
43 | lines.add("Custom Cold: " + ScoreboardUtil.cold);
44 | lines.add("");
45 |
46 | lines.add("§6§lPlayer Location");
47 | lines.add("§7Current Location: §f" + GameStateHandler.getInstance().getCurrentLocation().getName());
48 | lines.add("§7Sub Location: §f" + GameStateHandler.getInstance().getCurrentSubLocation().getName());
49 | lines.add("");
50 |
51 | // Add display and game state information
52 | lines.add("§6§lDisplay & Game State");
53 | lines.add("§7In-Game Focus: §f" + mc.inGameHasFocus);
54 | lines.add("§7Display Active: §f" + Display.isActive());
55 | }
56 |
57 | /*
58 | public void addList(String featureName, DebugList list) {
59 | this.lists.put(featureName, list);
60 | }
61 |
62 | public void clearList() {
63 | this.lists.clear();
64 | }
65 |
66 | public class DebugList implements Iterable {
67 | List debugLines = new ArrayList<>();
68 | int current = 0;
69 |
70 | public DebugList(String... lines) {
71 | debugLines.addAll(Arrays.asList(lines));
72 | }
73 |
74 | public DebugList append(String line) {
75 | debugLines.add(line);
76 | return this;
77 | }
78 |
79 | public DebugList append(int index, String line) {
80 | debugLines.add(index, line);
81 | return this;
82 | }
83 |
84 | public DebugList remove(int index) {
85 | debugLines.remove(index);
86 | return this;
87 | }
88 |
89 | @NotNull
90 | @Override
91 | public Iterator iterator() {
92 | return debugLines.listIterator();
93 | }
94 |
95 | @Override
96 | public void forEach(Consumer super String> action) {
97 | Iterable.super.forEach(action);
98 | }
99 | }
100 | */
101 | }
102 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/macro/impl/CommissionMacro/states/ClaimingCommissionState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.macro.impl.CommissionMacro.states;
2 |
3 | import com.jelly.mightyminerv2.feature.impl.AutoCommissionClaim;
4 | import com.jelly.mightyminerv2.macro.impl.CommissionMacro.Commission;
5 | import com.jelly.mightyminerv2.macro.impl.CommissionMacro.CommissionMacro;
6 |
7 | import java.util.List;
8 |
9 | public class ClaimingCommissionState implements CommissionMacroState{
10 | @Override
11 | public void onStart(CommissionMacro macro) {
12 | log("Starting claiming commission state");
13 | AutoCommissionClaim.getInstance().start();
14 | }
15 |
16 | @Override
17 | public CommissionMacroState onTick(CommissionMacro macro) {
18 |
19 | if (AutoCommissionClaim.getInstance().isRunning()) {
20 | return this;
21 | }
22 |
23 | if (AutoCommissionClaim.getInstance().succeeded()) {
24 | List newCommissions = AutoCommissionClaim.getInstance().getNextComm();
25 |
26 | if (newCommissions != null && !newCommissions.isEmpty()) {
27 | macro.setCurrentCommission(newCommissions.get(0));
28 | log("Claiming successful. Next commission: " + newCommissions.get(0).getName());
29 | } else {
30 | log("Claiming successful, but no new commissions were read. Restarting cycle.");
31 | return new StartingState();
32 | }
33 |
34 | return new PathingState();
35 | }
36 |
37 | switch (AutoCommissionClaim.getInstance().claimError()) {
38 | case NONE:
39 | macro.disable("Auto commission claiming failed, but no error is detected. Please contact the developer.");
40 | break;
41 | case INACCESSIBLE_NPC:
42 | log("The NPC was inaccessible while claiming commission");
43 | return new WarpingState();
44 | case TIMEOUT:
45 | log("Timeout in auto commission claiming");
46 | return new StartingState();
47 | case NO_ITEMS:
48 | macro.disable("No royal pigeons found, but this shouldn't happen. Please contact the developer.");
49 | break;
50 | case NPC_NOT_UNLOCKED:
51 | macro.disable("You have not unlocked Emissaries at Commission Milestone 1. Please post mc logs in #bug-report if this is a mistake.");
52 | break;
53 | }
54 | return null;
55 | }
56 |
57 | @Override
58 | public void onEnd(CommissionMacro macro) {
59 | AutoCommissionClaim.getInstance().stop();
60 | log("Ending claiming commission state");
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/macro/impl/CommissionMacro/states/CommissionMacroState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.macro.impl.CommissionMacro.states;
2 |
3 | import com.jelly.mightyminerv2.macro.impl.CommissionMacro.CommissionMacro;
4 | import com.jelly.mightyminerv2.util.Logger;
5 | import net.minecraft.client.Minecraft;
6 | import net.minecraft.util.ChatComponentText;
7 |
8 | public interface CommissionMacroState {
9 |
10 | void onStart(CommissionMacro macro);
11 |
12 | CommissionMacroState onTick(CommissionMacro macro);
13 |
14 | void onEnd(CommissionMacro macro);
15 |
16 | default void log(String message) {
17 | System.out.println("[" + this.getClass().getSimpleName() + "] " + message);
18 | }
19 |
20 | default void logError(String message) {
21 | System.out.println("[" + this.getClass().getSimpleName() + "] ERROR: " + message);
22 | }
23 |
24 | default void send(String message) {
25 | Logger.addMessage("[" + this.getClass().getSimpleName() + "] " + message);
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/macro/impl/CommissionMacro/states/GettingStatsState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.macro.impl.CommissionMacro.states;
2 |
3 | import com.jelly.mightyminerv2.config.MightyMinerConfig;
4 | import com.jelly.mightyminerv2.feature.impl.AutoGetStats.AutoGetStats;
5 | import com.jelly.mightyminerv2.feature.impl.AutoGetStats.tasks.impl.MiningSpeedRetrievalTask;
6 | import com.jelly.mightyminerv2.feature.impl.AutoGetStats.tasks.impl.PickaxeAbilityRetrievalTask;
7 | import com.jelly.mightyminerv2.feature.impl.BlockMiner.BlockMiner;
8 | import com.jelly.mightyminerv2.macro.impl.CommissionMacro.CommissionMacro;
9 |
10 | public class GettingStatsState implements CommissionMacroState{
11 |
12 | private final AutoGetStats autoInventory = AutoGetStats.getInstance();
13 | private MiningSpeedRetrievalTask miningSpeedRetrievalTask;
14 | private PickaxeAbilityRetrievalTask pickaxeAbilityRetrievalTask;
15 |
16 | @Override
17 | public void onStart(CommissionMacro macro) {
18 | log("Entering getting stats state");
19 | miningSpeedRetrievalTask = new MiningSpeedRetrievalTask();
20 | pickaxeAbilityRetrievalTask = new PickaxeAbilityRetrievalTask();
21 | AutoGetStats.getInstance().startTask(miningSpeedRetrievalTask);
22 | AutoGetStats.getInstance().startTask(pickaxeAbilityRetrievalTask);
23 | }
24 |
25 | @Override
26 | public CommissionMacroState onTick(CommissionMacro macro) {
27 | if (!AutoGetStats.getInstance().hasFinishedAllTasks())
28 | return this;
29 |
30 | if (miningSpeedRetrievalTask.getError() != null) {
31 | macro.disable("Failed to get stats with the following error: " + miningSpeedRetrievalTask.getError());
32 | return null;
33 | }
34 |
35 | if (pickaxeAbilityRetrievalTask.getError() != null) {
36 | macro.disable("Failed to get pickaxe ability with the following error: " + pickaxeAbilityRetrievalTask.getError());
37 | return null;
38 | }
39 |
40 | macro.setMiningSpeed(miningSpeedRetrievalTask.getResult());
41 | macro.setPickaxeAbility(MightyMinerConfig.usePickaxeAbility ? pickaxeAbilityRetrievalTask.getResult() : BlockMiner.PickaxeAbility.NONE);
42 | return new StartingState();
43 | }
44 |
45 | @Override
46 | public void onEnd(CommissionMacro macro) {
47 | autoInventory.stop();
48 | log("Exiting getting stats state");
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/macro/impl/CommissionMacro/states/MobKillingState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.macro.impl.CommissionMacro.states;
2 |
3 | import com.jelly.mightyminerv2.config.MightyMinerConfig;
4 | import com.jelly.mightyminerv2.feature.impl.AutoMobKiller.AutoMobKiller;
5 | import com.jelly.mightyminerv2.macro.impl.CommissionMacro.Commission;
6 | import com.jelly.mightyminerv2.macro.impl.CommissionMacro.CommissionMacro;
7 | import com.jelly.mightyminerv2.util.CommissionUtil;
8 |
9 | import java.util.Set;
10 |
11 | public class MobKillingState implements CommissionMacroState {
12 |
13 | @Override
14 | public void onStart(CommissionMacro macro) {
15 | log("Starting mob killing state");
16 | Set mobName = CommissionUtil.getMobForCommission(macro.getCurrentCommission());
17 |
18 | if (mobName == null) {
19 | logError("Current commission: " + macro.getCurrentCommission());
20 | macro.disable("Mob name not found! Please send the logs to the developer ");
21 | return;
22 | }
23 |
24 | AutoMobKiller.getInstance().start(mobName, macro.getCurrentCommission().getName().startsWith("Glacite") ?
25 | MightyMinerConfig.miningTool : MightyMinerConfig.slayerWeapon);
26 | }
27 |
28 | @Override
29 | public CommissionMacroState onTick(CommissionMacro macro) {
30 | if (macro.getCurrentCommission() == Commission.COMMISSION_CLAIM){
31 | return new PathingState();
32 | }
33 |
34 | if (AutoMobKiller.getInstance().isRunning()) {
35 | return this;
36 | }
37 |
38 | switch (AutoMobKiller.getInstance().getError()) {
39 | case NONE:
40 | return this;
41 | case NO_ENTITIES:
42 | log("No entities found in Mob Killer. Restarting");
43 | return new StartingState();
44 | }
45 |
46 | return null;
47 | }
48 |
49 | @Override
50 | public void onEnd(CommissionMacro macro) {
51 | AutoMobKiller.getInstance().stop();
52 | log("Ending mob killing state");
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/macro/impl/CommissionMacro/states/RefuelState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.macro.impl.CommissionMacro.states;
2 |
3 | import com.jelly.mightyminerv2.config.MightyMinerConfig;
4 | import com.jelly.mightyminerv2.feature.impl.AutoDrillRefuel.AutoDrillRefuel;
5 | import com.jelly.mightyminerv2.macro.impl.CommissionMacro.CommissionMacro;
6 |
7 | public class RefuelState implements CommissionMacroState{
8 |
9 | private final AutoDrillRefuel.FuelType[] fuelTypeMap =
10 | {AutoDrillRefuel.FuelType.VOLTA, AutoDrillRefuel.FuelType.OIL_BARREL};
11 |
12 | @Override
13 | public void onStart(CommissionMacro macro) {
14 | log("Starting refuel state");
15 | AutoDrillRefuel.getInstance().start(MightyMinerConfig.miningTool, fuelTypeMap[MightyMinerConfig.refuelMachineFuel]);
16 | }
17 |
18 | @Override
19 | public CommissionMacroState onTick(CommissionMacro macro) {
20 | if (AutoDrillRefuel.getInstance().isRunning()) {
21 | return this;
22 | }
23 |
24 | switch (AutoDrillRefuel.getInstance().getError()) {
25 | case NONE:
26 | log("Done refilling");
27 | return new StartingState();
28 | case NO_DRILL:
29 | macro.disable("No drill found! This should not happen!");
30 | break;
31 | case NO_ABIPHONE:
32 | macro.disable("No abiphone found! This should not happen!");
33 | break;
34 | case NO_FUEL:
35 | macro.disable("No fuel found! Please put the fuel in the inventory, not mining sacks!");
36 | break;
37 | case NO_GREATFORGE_CONTACT:
38 | macro.disable("No Greatforge contact in abiphone!");
39 | break;
40 | }
41 |
42 | return null;
43 | }
44 |
45 | @Override
46 | public void onEnd(CommissionMacro macro) {
47 | AutoDrillRefuel.getInstance().stop();
48 | log("Ending refuel state");
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/macro/impl/CommissionMacro/states/StartingState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.macro.impl.CommissionMacro.states;
2 |
3 | import com.jelly.mightyminerv2.config.MightyMinerConfig;
4 | import com.jelly.mightyminerv2.macro.impl.CommissionMacro.CommissionMacro;
5 | import com.jelly.mightyminerv2.util.InventoryUtil;
6 |
7 | import java.util.Objects;
8 |
9 | public class StartingState implements CommissionMacroState{
10 |
11 | @Override
12 | public void onStart(CommissionMacro macro) {
13 | log("Entering starting state");
14 | }
15 |
16 | @Override
17 | public CommissionMacroState onTick(CommissionMacro macro) {
18 | if (Objects.equals(MightyMinerConfig.miningTool, "")) {
19 | macro.disable("Please set a Mining Tool in the config");
20 | return null;
21 | }
22 | if (Objects.equals(MightyMinerConfig.slayerWeapon, "")) {
23 | macro.disable("Please set a Slayer Weapon in the config");
24 | return null;
25 | }
26 | if (!InventoryUtil.areItemsInHotbar(macro.getNecessaryItems())) {
27 | macro.disable("Please put the following items in hotbar: " + InventoryUtil.getMissingItemsInHotbar(macro.getNecessaryItems()));
28 | return null;
29 | }
30 | return macro.getMiningSpeed() == 0 ? new GettingStatsState() : new PathingState();
31 | }
32 |
33 | @Override
34 | public void onEnd(CommissionMacro macro) {
35 | log("Exiting starting state");
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/macro/impl/CommissionMacro/states/WarpingState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.macro.impl.CommissionMacro.states;
2 |
3 | import com.jelly.mightyminerv2.feature.impl.AutoWarp;
4 | import com.jelly.mightyminerv2.macro.impl.CommissionMacro.CommissionMacro;
5 | import com.jelly.mightyminerv2.util.helper.location.SubLocation;
6 |
7 | public class WarpingState implements CommissionMacroState{
8 |
9 | AutoWarp autoWarp = AutoWarp.getInstance();
10 |
11 | @Override
12 | public void onStart(CommissionMacro macro) {
13 | log("Starting warping state");
14 | autoWarp.start(null, SubLocation.THE_FORGE);
15 | }
16 |
17 | @Override
18 | public CommissionMacroState onTick(CommissionMacro macro) {
19 |
20 | if (AutoWarp.getInstance().isRunning()) {
21 | return this;
22 | }
23 |
24 | if (AutoWarp.getInstance().hasSucceeded()) {
25 | log("Auto Warp Completed");
26 | return new StartingState();
27 | }
28 |
29 | switch (AutoWarp.getInstance().getFailReason()) {
30 | case NONE:
31 | macro.disable("Auto Warp failed, but no error is detected. Please contact the developer.");
32 | break;
33 | case FAILED_TO_WARP:
34 | log("Retrying Auto Warp");
35 | autoWarp.start(null, SubLocation.THE_FORGE);
36 | break;
37 | case NO_SCROLL:
38 | macro.disable("You don't have the /warp forge scroll!");
39 | break;
40 | }
41 | return null;
42 | }
43 |
44 | @Override
45 | public void onEnd(CommissionMacro macro) {
46 | autoWarp.stop();
47 | log("Ending warping state");
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/macro/impl/GlacialMacro/states/ClaimingCommissionState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.macro.impl.GlacialMacro.states;
2 |
3 | import com.jelly.mightyminerv2.feature.impl.AutoCommissionClaim;
4 | import com.jelly.mightyminerv2.macro.impl.GlacialMacro.GlacialMacro;
5 | import com.jelly.mightyminerv2.util.helper.Clock;
6 |
7 | /**
8 | * State for claiming completed commissions in the Glacial Macro.
9 | * This state handles the claiming process, including retries and timeouts.
10 | */
11 | public class ClaimingCommissionState implements GlacialMacroState {
12 |
13 | private final AutoCommissionClaim claimer = AutoCommissionClaim.getInstance();
14 | private final Clock timeout = new Clock();
15 | private int retries = 0;
16 |
17 | @Override
18 | public void onStart(GlacialMacro macro) {
19 | log("Claiming completed commission.");
20 | claimer.start();
21 | timeout.schedule(10000); // 10s timeout
22 | }
23 |
24 | @Override
25 | public GlacialMacroState onTick(GlacialMacro macro) {
26 | if (claimer.isRunning()) {
27 | if (timeout.passed()) {
28 | logError("Claiming commission timed out.");
29 | return handleFailure(macro);
30 | }
31 | return this;
32 | }
33 |
34 | if (claimer.succeeded()) {
35 | log("Successfully claimed commission.");
36 | macro.incrementCommissionCounter();
37 | macro.updateMiningTasks(); // Update tasks after claiming
38 | return new PathfindingState();
39 | } else {
40 | logError("Failed to claim commission. Reason: " + claimer.claimError());
41 | return handleFailure(macro);
42 | }
43 | }
44 |
45 | private GlacialMacroState handleFailure(GlacialMacro macro) {
46 | if (++retries > 3) {
47 | return new ErrorHandlingState("Failed to claim commission after 3 attempts.");
48 | }
49 | log("Retrying claim... (" + retries + "/3)");
50 | onStart(macro); // Restart the claim process
51 | return this;
52 | }
53 |
54 | @Override
55 | public void onEnd(GlacialMacro macro) {
56 | if (claimer.isRunning()) {
57 | claimer.stop();
58 | }
59 | }
60 | }
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/macro/impl/GlacialMacro/states/ErrorHandlingState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.macro.impl.GlacialMacro.states;
2 |
3 | import com.jelly.mightyminerv2.macro.impl.GlacialMacro.GlacialMacro;
4 |
5 | public class ErrorHandlingState implements GlacialMacroState {
6 | private final String reason;
7 |
8 | public ErrorHandlingState(String reason) {
9 | this.reason = reason;
10 | }
11 |
12 | @Override
13 | public void onStart(GlacialMacro macro) {
14 | logError("Entering Error Handling State");
15 | macro.disable(reason);
16 | }
17 |
18 | @Override
19 | public GlacialMacroState onTick(GlacialMacro macro) {
20 | return this;
21 | }
22 |
23 | @Override
24 | public void onEnd(GlacialMacro macro) {
25 | }
26 | }
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/macro/impl/GlacialMacro/states/GettingStatsState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.macro.impl.GlacialMacro.states;
2 |
3 | import com.jelly.mightyminerv2.config.MightyMinerConfig;
4 | import com.jelly.mightyminerv2.feature.impl.AutoGetStats.AutoGetStats;
5 | import com.jelly.mightyminerv2.feature.impl.AutoGetStats.tasks.impl.MiningSpeedRetrievalTask;
6 | import com.jelly.mightyminerv2.feature.impl.AutoGetStats.tasks.impl.PickaxeAbilityRetrievalTask;
7 | import com.jelly.mightyminerv2.feature.impl.BlockMiner.BlockMiner;
8 | import com.jelly.mightyminerv2.macro.impl.GlacialMacro.GlacialMacro;
9 |
10 | /**
11 | * This state is responsible for retrieving the mining speed and pickaxe ability
12 | * before proceeding to the pathfinding state in the Glacial Macro.
13 | */
14 | public class GettingStatsState implements GlacialMacroState {
15 |
16 | private final AutoGetStats autoInventory = AutoGetStats.getInstance();
17 | private MiningSpeedRetrievalTask miningSpeedTask;
18 | private PickaxeAbilityRetrievalTask pickaxeAbilityTask;
19 |
20 | @Override
21 | public void onStart(GlacialMacro macro) {
22 | log("Entering getting stats state");
23 | miningSpeedTask = new MiningSpeedRetrievalTask();
24 | pickaxeAbilityTask = new PickaxeAbilityRetrievalTask();
25 | AutoGetStats.getInstance().startTask(pickaxeAbilityTask);
26 | AutoGetStats.getInstance().startTask(miningSpeedTask);
27 | }
28 |
29 | @Override
30 | public GlacialMacroState onTick(GlacialMacro macro) {
31 | if (!AutoGetStats.getInstance().hasFinishedAllTasks()) {
32 | return this;
33 | }
34 |
35 | if (miningSpeedTask.getError() != null) {
36 | if (miningSpeedTask.getError().equals("Failed to parse mining speed in GUI")) {
37 | macro.transitionTo(new NewLobbyState());
38 | } else {
39 | macro.disable("Failed to get stats with the following error: "
40 | + miningSpeedTask.getError());
41 | }
42 | return null;
43 | }
44 |
45 | if (pickaxeAbilityTask.getError() != null) {
46 | macro.disable("Failed to get pickaxe ability with the following error: "
47 | + pickaxeAbilityTask.getError());
48 | return null;
49 | }
50 |
51 | macro.setMiningSpeed(miningSpeedTask.getResult());
52 | log("MiningSpeed: " + macro.getMiningSpeed());
53 | macro.setPickaxeAbility(MightyMinerConfig.usePickaxeAbility ?
54 | pickaxeAbilityTask.getResult() : BlockMiner.PickaxeAbility.NONE);
55 | return new PathfindingState();
56 | }
57 |
58 | @Override
59 | public void onEnd(GlacialMacro macro) {
60 | autoInventory.stop();
61 | log("Exiting getting stats state");
62 | }
63 | }
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/macro/impl/GlacialMacro/states/GlacialMacroState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.macro.impl.GlacialMacro.states;
2 |
3 | import com.jelly.mightyminerv2.macro.impl.GlacialMacro.GlacialMacro;
4 | import com.jelly.mightyminerv2.util.Logger;
5 |
6 | /**
7 | * Interface representing the state of the Glacial Macro.
8 | * Each state defines its own behavior for starting, ticking, and ending.
9 | */
10 | public interface GlacialMacroState {
11 |
12 | void onStart(GlacialMacro macro);
13 |
14 | GlacialMacroState onTick(GlacialMacro macro);
15 |
16 | void onEnd(GlacialMacro macro);
17 |
18 | default void log(String message) {
19 | System.out.println("[" + this.getClass().getSimpleName() + "] " + message);
20 | }
21 |
22 | default void logError(String message) {
23 | System.out.println("[" + this.getClass().getSimpleName() + "] ERROR: " + message);
24 | }
25 |
26 | default void send(String message) {
27 | Logger.addMessage("[" + this.getClass().getSimpleName() + "] " + message);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/macro/impl/GlacialMacro/states/NewLobbyState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.macro.impl.GlacialMacro.states;
2 |
3 | import com.jelly.mightyminerv2.feature.impl.AutoWarp;
4 | import com.jelly.mightyminerv2.macro.impl.GlacialMacro.GlacialMacro;
5 | import com.jelly.mightyminerv2.util.helper.location.Location;
6 | import com.jelly.mightyminerv2.util.helper.location.SubLocation;
7 |
8 | public class NewLobbyState implements GlacialMacroState {
9 |
10 | private final AutoWarp autoWarp = AutoWarp.getInstance();
11 | private WarpPhase currentPhase = WarpPhase.TO_HUB;
12 |
13 | @Override
14 | public void onStart(GlacialMacro macro) {
15 | log("Starting NewLobbyState");
16 |
17 | log("Clearing previously visited veins blacklist to prepare for new lobby.");
18 | macro.getPreviousVeins().clear();
19 |
20 | if (currentPhase == WarpPhase.TO_HUB) {
21 | autoWarp.start(Location.HUB, null);
22 | }
23 | }
24 |
25 | @Override
26 | public GlacialMacroState onTick(GlacialMacro macro) {
27 | if (autoWarp.isRunning()) {
28 | return this;
29 | }
30 |
31 | if (autoWarp.hasSucceeded()) {
32 | if (currentPhase == WarpPhase.TO_HUB) {
33 | log("Successfully warped to Hub. Warping back to Dwarven Base Camp.");
34 | currentPhase = WarpPhase.TO_BASE;
35 |
36 | autoWarp.start(null, SubLocation.DWARVEN_BASE_CAMP);
37 | return this;
38 | } else if (currentPhase == WarpPhase.TO_BASE) {
39 | log("Successfully returned to Dwarven Base Camp. Resuming pathfinding.");
40 |
41 | return new GettingStatsState();
42 | }
43 | } else {
44 | logError("AutoWarp failed during NewLobby sequence. Reason: " + autoWarp.getFailReason());
45 | return new ErrorHandlingState("Failed to execute new lobby sequence with reason: " + autoWarp.getFailReason());
46 | }
47 |
48 | return this;
49 | }
50 |
51 | @Override
52 | public void onEnd(GlacialMacro macro) {
53 | if (autoWarp.isRunning()) {
54 | autoWarp.stop();
55 | }
56 | log("Ending NewLobbyState");
57 | }
58 |
59 | private enum WarpPhase {
60 | TO_HUB,
61 | TO_BASE
62 | }
63 | }
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/macro/impl/GlacialMacro/states/StartingState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.macro.impl.GlacialMacro.states;
2 |
3 | import com.jelly.mightyminerv2.config.MightyMinerConfig;
4 | import com.jelly.mightyminerv2.handler.GameStateHandler;
5 | import com.jelly.mightyminerv2.macro.impl.GlacialMacro.GlacialMacro;
6 | import com.jelly.mightyminerv2.util.InventoryUtil;
7 | import com.jelly.mightyminerv2.util.helper.location.SubLocation;
8 |
9 | import java.util.Objects;
10 |
11 | /**
12 | * The initial state of the Glacial Macro.
13 | * This state checks if the player is in the correct location to start the macro.
14 | * If not, it will attempt to teleport the player to the Dwarven Base Camp.
15 | */
16 | public class StartingState implements GlacialMacroState {
17 | @Override
18 | public void onStart(GlacialMacro macro) {
19 | log("Entering starting state");
20 |
21 | }
22 |
23 | @Override
24 | public GlacialMacroState onTick(GlacialMacro macro) {
25 |
26 | if (Objects.equals(MightyMinerConfig.miningTool, "")) {
27 | macro.disable("Mining tool is not set in the Mighty Miner config");
28 | return null;
29 | }
30 |
31 | SubLocation subLocation = GameStateHandler.getInstance().getCurrentSubLocation();
32 | if (subLocation == SubLocation.DWARVEN_BASE_CAMP) {
33 | if (!InventoryUtil.areItemsInHotbar(macro.getNecessaryItems())) {
34 | macro.disable("Please put the following items in hotbar: " + InventoryUtil.getMissingItemsInHotbar(macro.getNecessaryItems()));
35 | return null;
36 | }
37 |
38 | log("Player is in a valid location. Initialising stats");
39 | return new GettingStatsState();
40 | } else {
41 | log("Player is not at Dwarven Base Camp. Teleporting...");
42 | return new TeleportingState(new StartingState());
43 | }
44 | }
45 |
46 | @Override
47 | public void onEnd(GlacialMacro macro) {
48 | log("Exiting starting state");
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/macro/impl/GlacialMacro/states/TeleportingState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.macro.impl.GlacialMacro.states;
2 |
3 | import com.jelly.mightyminerv2.feature.impl.AutoWarp;
4 | import com.jelly.mightyminerv2.macro.impl.GlacialMacro.GlacialMacro;
5 | import com.jelly.mightyminerv2.util.helper.Clock;
6 | import com.jelly.mightyminerv2.util.helper.location.SubLocation;
7 |
8 | public class TeleportingState implements GlacialMacroState {
9 | private final GlacialMacroState nextState;
10 | private int retries = 0;
11 | private final Clock timeout = new Clock();
12 |
13 | // The state to transition to upon successful warp
14 | public TeleportingState(GlacialMacroState nextState) {
15 | this.nextState = nextState;
16 | }
17 |
18 | @Override
19 | public void onStart(GlacialMacro macro) {
20 | log("Attempting to warp to Dwarven Base Camp.");
21 | AutoWarp.getInstance().start(null, SubLocation.DWARVEN_BASE_CAMP);
22 | timeout.schedule(15000); // 15 second timeout for warping
23 | }
24 |
25 | @Override
26 | public GlacialMacroState onTick(GlacialMacro macro) {
27 | if (AutoWarp.getInstance().isRunning()) {
28 | if (timeout.passed()) {
29 | logError("AutoWarp timed out.");
30 | AutoWarp.getInstance().stop();
31 | return handleFailure();
32 | }
33 | return this; // Stay in this state while warping
34 | }
35 |
36 | if (AutoWarp.getInstance().hasSucceeded()) {
37 | log("Successfully warped.");
38 | return nextState;
39 | } else {
40 | logError("AutoWarp failed. Reason: " + AutoWarp.getInstance().getFailReason());
41 | return handleFailure();
42 | }
43 | }
44 |
45 | private GlacialMacroState handleFailure() {
46 | if (++retries > 3) {
47 | return new ErrorHandlingState("Failed to warp to the Glacite Tunnels after 3 attempts.");
48 | }
49 | log("Retrying warp (" + retries + "/3)...");
50 | AutoWarp.getInstance().start(null, SubLocation.DWARVEN_BASE_CAMP);
51 | timeout.schedule(15000);
52 | return this;
53 | }
54 |
55 | @Override
56 | public void onEnd(GlacialMacro macro) {
57 | if (AutoWarp.getInstance().isRunning()) {
58 | AutoWarp.getInstance().stop();
59 | }
60 | }
61 | }
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/macro/impl/RouteMiner/states/GettingStatsState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.macro.impl.RouteMiner.states;
2 |
3 | import com.jelly.mightyminerv2.config.MightyMinerConfig;
4 | import com.jelly.mightyminerv2.feature.impl.AutoGetStats.AutoGetStats;
5 | import com.jelly.mightyminerv2.feature.impl.AutoGetStats.tasks.impl.MiningSpeedRetrievalTask;
6 | import com.jelly.mightyminerv2.feature.impl.AutoGetStats.tasks.impl.PickaxeAbilityRetrievalTask;
7 | import com.jelly.mightyminerv2.feature.impl.BlockMiner.BlockMiner;
8 | import com.jelly.mightyminerv2.macro.impl.GlacialMacro.GlacialMacro;
9 | import com.jelly.mightyminerv2.macro.impl.GlacialMacro.states.GlacialMacroState;
10 | import com.jelly.mightyminerv2.macro.impl.GlacialMacro.states.NewLobbyState;
11 | import com.jelly.mightyminerv2.macro.impl.GlacialMacro.states.PathfindingState;
12 | import com.jelly.mightyminerv2.macro.impl.RouteMiner.RouteMinerMacro;
13 |
14 | /**
15 | * This state is responsible for retrieving the mining speed and pickaxe ability
16 | * before proceeding to the mining state in the Route Miner Macro.
17 | */
18 | public class GettingStatsState implements RouteMinerMacroState {
19 |
20 | private final AutoGetStats autoInventory = AutoGetStats.getInstance();
21 | private MiningSpeedRetrievalTask miningSpeedTask;
22 | private PickaxeAbilityRetrievalTask pickaxeAbilityTask;
23 |
24 | @Override
25 | public void onStart(RouteMinerMacro macro) {
26 | log("Entering getting stats state");
27 | miningSpeedTask = new MiningSpeedRetrievalTask();
28 | pickaxeAbilityTask = new PickaxeAbilityRetrievalTask();
29 | AutoGetStats.getInstance().startTask(pickaxeAbilityTask);
30 | AutoGetStats.getInstance().startTask(miningSpeedTask);
31 | }
32 |
33 | @Override
34 | public RouteMinerMacroState onTick(RouteMinerMacro macro) {
35 | if (AutoGetStats.getInstance().hasFinishedAllTasks()) {
36 | if (miningSpeedTask.getError() != null) {
37 | macro.disable("Failed to get stats with the following error: " + miningSpeedTask.getError());
38 | return null;
39 | }
40 |
41 | if (pickaxeAbilityTask.getError() != null) {
42 | macro.disable("Failed to get pickaxe ability with the following error: " + pickaxeAbilityTask.getError());
43 | return null;
44 | }
45 |
46 | macro.setMiningSpeed(miningSpeedTask.getResult());
47 | macro.setPickaxeAbility(MightyMinerConfig.usePickaxeAbility ? pickaxeAbilityTask.getResult() : BlockMiner.PickaxeAbility.NONE);
48 | return new MovingState();
49 | } else {
50 | return this;
51 | }
52 |
53 | }
54 |
55 | @Override
56 | public void onEnd(RouteMinerMacro macro) {
57 | autoInventory.stop();
58 | log("Exiting getting stats state");
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/macro/impl/RouteMiner/states/MiningState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.macro.impl.RouteMiner.states;
2 |
3 | import com.jelly.mightyminerv2.config.MightyMinerConfig;
4 | import com.jelly.mightyminerv2.feature.impl.BlockMiner.BlockMiner;
5 | import com.jelly.mightyminerv2.macro.impl.GlacialMacro.GlacialMacro;
6 | import com.jelly.mightyminerv2.macro.impl.RouteMiner.RouteMinerMacro;
7 | import com.jelly.mightyminerv2.util.InventoryUtil;
8 | import com.jelly.mightyminerv2.util.helper.MineableBlock;
9 |
10 | /**
11 | * This state is responsible for starting BlockMiner and detecting when to move to next waypoint
12 | * before proceeding to the moving state in the Route Miner Macro.
13 | */
14 | public class MiningState implements RouteMinerMacroState {
15 |
16 | @Override
17 | public void onStart(RouteMinerMacro macro) {
18 | log("Entering Mining State");
19 | InventoryUtil.holdItem(MightyMinerConfig.miningTool);
20 | startMining(macro);
21 | }
22 |
23 | @Override
24 | public RouteMinerMacroState onTick(RouteMinerMacro macro) {
25 | if (BlockMiner.getInstance().getError() == BlockMiner.BlockMinerError.NOT_ENOUGH_BLOCKS) {
26 | BlockMiner.getInstance().stop();
27 | macro.setRouteIndex(macro.getRouteIndex() + 1);
28 | return new MovingState();
29 | }
30 |
31 | return this;
32 | }
33 |
34 | private void startMining(RouteMinerMacro macro) {
35 | MineableBlock[] blocksToMine = macro.getBlocksToMine();
36 |
37 | if (blocksToMine.length == 0) {
38 | macro.disable("No targets provided in configuration.");
39 | return;
40 | }
41 |
42 | BlockMiner.getInstance().start(
43 | blocksToMine,
44 | macro.getMiningSpeed(),
45 | macro.getPickaxeAbility(),
46 | macro.getBlockPriority(),
47 | MightyMinerConfig.miningTool
48 | );
49 | }
50 |
51 | @Override
52 | public void onEnd(RouteMinerMacro macro) {
53 | log("Exiting Mining State");
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/macro/impl/RouteMiner/states/RouteMinerMacroState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.macro.impl.RouteMiner.states;
2 |
3 | import com.jelly.mightyminerv2.macro.impl.RouteMiner.RouteMinerMacro;
4 | import com.jelly.mightyminerv2.util.Logger;
5 | import net.minecraft.client.Minecraft;
6 |
7 | /**
8 | * Interface representing the state of the RouteMiner Macro.
9 | * Each state defines its own behavior for starting, ticking, and ending.
10 | */
11 | public interface RouteMinerMacroState {
12 |
13 | void onStart(RouteMinerMacro macro);
14 |
15 | RouteMinerMacroState onTick(RouteMinerMacro macro);
16 |
17 | void onEnd(RouteMinerMacro macro);
18 |
19 | default void log(String message) {
20 | System.out.println("[" + this.getClass().getSimpleName() + "] " + message);
21 | }
22 |
23 | default void logError(String message) {
24 | System.out.println("[" + this.getClass().getSimpleName() + "] ERROR: " + message);
25 | }
26 |
27 | default void send(String message) {
28 | Logger.addMessage("[" + this.getClass().getSimpleName() + "] " + message);
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/macro/impl/RouteMiner/states/StartingState.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.macro.impl.RouteMiner.states;
2 |
3 | import com.jelly.mightyminerv2.macro.impl.RouteMiner.RouteMinerMacro;
4 | import com.jelly.mightyminerv2.util.InventoryUtil;
5 |
6 | /**
7 | * The initial state of the Route Miner Macro.
8 | * This state checks if the player has the proper items to start macro.
9 | * If not, it will disable itself.
10 | */
11 | public class StartingState implements RouteMinerMacroState {
12 |
13 | @Override
14 | public void onStart(RouteMinerMacro macro) {
15 | log("Entering Starting State");
16 | }
17 |
18 | @Override
19 | public RouteMinerMacroState onTick(RouteMinerMacro macro) {
20 | if (!InventoryUtil.areItemsInHotbar(macro.getNecessaryItems())) {
21 | macro.disable("Please put the following items in hotbar: " + InventoryUtil.getMissingItemsInHotbar(macro.getNecessaryItems()));
22 | return null;
23 | }
24 |
25 | return new GettingStatsState();
26 | }
27 |
28 | @Override
29 | public void onEnd(RouteMinerMacro macro) {
30 | log("Exiting Starting State");
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/mixin/FML/MixinFMLHandshakeMessage.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.mixin.fml;
2 |
3 | import com.jelly.mightyminerv2.MightyMiner;
4 | import net.minecraft.client.Minecraft;
5 | import net.minecraftforge.fml.common.ModContainer;
6 | import net.minecraftforge.fml.common.network.handshake.FMLHandshakeMessage;
7 | import org.spongepowered.asm.mixin.Mixin;
8 | import org.spongepowered.asm.mixin.Shadow;
9 | import org.spongepowered.asm.mixin.injection.At;
10 | import org.spongepowered.asm.mixin.injection.Inject;
11 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
12 |
13 | import java.util.List;
14 | import java.util.Map;
15 |
16 | @Mixin(value = FMLHandshakeMessage.ModList.class, remap = false, priority = Integer.MAX_VALUE)
17 | public abstract class MixinFMLHandshakeMessage {
18 | @Shadow(remap = false)
19 | private Map modTags;
20 |
21 | @Inject(method = "(Ljava/util/List;)V", at = @At("RETURN"), remap = false)
22 | private void init(List modList, CallbackInfo ci) {
23 | if (Minecraft.getMinecraft().isIntegratedServerRunning()) return;
24 | modTags.keySet().removeIf(s -> s.contains(MightyMiner.modid));
25 | }
26 | }
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/mixin/client/EntityPlayerSPAccessor.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.mixin.client;
2 |
3 | import net.minecraft.client.entity.EntityPlayerSP;
4 | import org.spongepowered.asm.mixin.Mixin;
5 | import org.spongepowered.asm.mixin.gen.Accessor;
6 |
7 | @Mixin(EntityPlayerSP.class)
8 | public interface EntityPlayerSPAccessor {
9 | @Accessor
10 | float getLastReportedYaw();
11 |
12 | @Accessor
13 | float getLastReportedPitch();
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/mixin/client/MinecraftAccessor.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.mixin.client;
2 |
3 | import net.minecraft.client.Minecraft;
4 | import net.minecraft.util.Timer;
5 | import org.spongepowered.asm.mixin.Mixin;
6 | import org.spongepowered.asm.mixin.gen.Accessor;
7 | import org.spongepowered.asm.mixin.gen.Invoker;
8 |
9 | @Mixin(Minecraft.class)
10 | public interface MinecraftAccessor {
11 | @Accessor("timer")
12 | Timer getTimer();
13 |
14 | @Accessor("leftClickCounter")
15 | void setLeftClickCounter(int leftClickCounter);
16 |
17 | @Accessor("rightClickDelayTimer")
18 | int getRightClickDelayTimer();
19 |
20 | @Accessor("rightClickDelayTimer")
21 | void setRightClickDelayTimer(int rightClickDelayTimer);
22 |
23 | @Invoker("clickMouse")
24 | void leftClick();
25 |
26 | @Invoker("rightClickMouse")
27 | void rightClick();
28 |
29 | @Invoker("middleClickMouse")
30 | void middleClick();
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/mixin/client/MixinBlockStainedGlassPane.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.mixin.client;
2 |
3 | import com.jelly.mightyminerv2.config.MightyMinerConfig;
4 | import net.minecraft.block.BlockPane;
5 | import net.minecraft.block.BlockStainedGlassPane;
6 | import net.minecraft.block.material.Material;
7 | import net.minecraft.util.BlockPos;
8 | import net.minecraft.world.IBlockAccess;
9 | import org.spongepowered.asm.mixin.Mixin;
10 |
11 | @Mixin({BlockStainedGlassPane.class})
12 | public abstract class MixinBlockStainedGlassPane extends BlockPane {
13 |
14 | protected MixinBlockStainedGlassPane(Material materialIn, boolean canDrop) {
15 | super(materialIn, canDrop);
16 | }
17 |
18 | public void setBlockBoundsBasedOnState(IBlockAccess worldIn, BlockPos pos) {
19 | if (MightyMinerConfig.miscFullBlock) {
20 | this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
21 | } else {
22 | super.setBlockBoundsBasedOnState(worldIn, pos);
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/mixin/client/MixinChunk.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.mixin.client;
2 |
3 | import com.jelly.mightyminerv2.event.BlockChangeEvent;
4 | import net.minecraft.block.state.IBlockState;
5 | import net.minecraft.util.BlockPos;
6 | import net.minecraft.world.chunk.Chunk;
7 | import net.minecraftforge.common.MinecraftForge;
8 | import org.spongepowered.asm.mixin.Mixin;
9 | import org.spongepowered.asm.mixin.injection.At;
10 | import org.spongepowered.asm.mixin.injection.Inject;
11 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
12 |
13 | @Mixin(Chunk.class)
14 | public class MixinChunk {
15 | @Inject(method = "setBlockState", at = @At("RETURN"))
16 | public void setBlockState(BlockPos pos, IBlockState state, CallbackInfoReturnable cir) {
17 | final IBlockState old = cir.getReturnValue();
18 | if (old == null || state == old) return;
19 | MinecraftForge.EVENT_BUS.post(new BlockChangeEvent(pos, old, state));
20 | }
21 | }
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/mixin/client/MixinChunkProviderClient.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.mixin.client;
2 |
3 | import com.jelly.mightyminerv2.util.IChunkProviderClient;
4 | import net.minecraft.client.multiplayer.ChunkProviderClient;
5 | import net.minecraft.util.LongHashMap;
6 | import net.minecraft.world.chunk.Chunk;
7 | import org.spongepowered.asm.mixin.Mixin;
8 | import org.spongepowered.asm.mixin.Shadow;
9 |
10 | import java.util.List;
11 |
12 | @Mixin(ChunkProviderClient.class)
13 | public class MixinChunkProviderClient implements IChunkProviderClient {
14 |
15 | @Shadow
16 | private LongHashMap chunkMapping;
17 |
18 | @Shadow
19 | private List chunkListing;
20 |
21 | @Override
22 | public LongHashMap chunkMapping() {
23 | return chunkMapping;
24 | }
25 |
26 | @Override
27 | public List chunkListing() {
28 | return chunkListing;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/mixin/client/MixinEntityLivingBase.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.mixin.client;
2 |
3 | import com.jelly.mightyminerv2.util.StrafeUtil;
4 | import net.minecraft.client.entity.EntityPlayerSP;
5 | import net.minecraft.entity.Entity;
6 | import net.minecraft.entity.EntityLivingBase;
7 | import net.minecraft.world.World;
8 | import org.spongepowered.asm.mixin.Mixin;
9 | import org.spongepowered.asm.mixin.Shadow;
10 | import org.spongepowered.asm.mixin.injection.At;
11 | import org.spongepowered.asm.mixin.injection.Redirect;
12 |
13 | // From Baritone <3
14 | // Todo: Consider Adding a rotation check To disable omnisprint from within
15 | @Mixin(EntityLivingBase.class)
16 | public abstract class MixinEntityLivingBase extends Entity {
17 |
18 | @Shadow
19 | public float rotationYawHead;
20 |
21 | public MixinEntityLivingBase(World worldIn) {
22 | super(worldIn);
23 | }
24 |
25 | @Redirect(
26 | method = "jump",
27 | at = @At(
28 | value = "FIELD",
29 | target = "net/minecraft/entity/EntityLivingBase.rotationYaw:F"
30 | )
31 | )
32 | private float overrideYaw(EntityLivingBase self) {
33 | if (self instanceof EntityPlayerSP && StrafeUtil.shouldEnable()) {
34 | return StrafeUtil.yaw;
35 | }
36 | return self.rotationYaw;
37 | }
38 |
39 | @Redirect(
40 | method = "moveEntityWithHeading",
41 | at = @At(
42 | value = "INVOKE",
43 | target = "Lnet/minecraft/entity/EntityLivingBase;moveFlying(FFF)V"
44 | )
45 | )
46 | public void moveRelative(EntityLivingBase instance, float s, float f, float fr) {
47 | if (!StrafeUtil.shouldEnable()) {
48 | this.moveFlying(s, f, fr);
49 | return;
50 | }
51 |
52 | final float originalYaw = this.rotationYaw;
53 | this.rotationYaw = StrafeUtil.yaw;
54 |
55 | this.moveFlying(s, f, fr);
56 |
57 | this.rotationYaw = originalYaw;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/mixin/client/MixinEntityPlayerSP.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.mixin.client;
2 |
3 | import com.jelly.mightyminerv2.event.MotionUpdateEvent;
4 | import com.jelly.mightyminerv2.macro.MacroManager;
5 | import com.mojang.authlib.GameProfile;
6 | import net.minecraft.client.entity.AbstractClientPlayer;
7 | import net.minecraft.client.entity.EntityPlayerSP;
8 | import net.minecraft.entity.item.EntityItem;
9 | import net.minecraft.world.World;
10 | import net.minecraftforge.common.MinecraftForge;
11 | import org.objectweb.asm.Opcodes;
12 | import org.spongepowered.asm.mixin.Mixin;
13 | import org.spongepowered.asm.mixin.Unique;
14 | import org.spongepowered.asm.mixin.injection.At;
15 | import org.spongepowered.asm.mixin.injection.Inject;
16 | import org.spongepowered.asm.mixin.injection.Redirect;
17 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
18 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
19 |
20 | @Mixin(value = EntityPlayerSP.class, priority = Integer.MAX_VALUE)
21 | public abstract class MixinEntityPlayerSP extends AbstractClientPlayer {
22 |
23 | @Unique
24 | float mightyMinerv2$serverYaw = 0f;
25 | @Unique
26 | float mightyMinerv2$serverPitch = 0f;
27 | public MixinEntityPlayerSP(World worldIn, GameProfile playerProfile) {
28 | super(worldIn, playerProfile);
29 | }
30 |
31 | @Inject(method = "onUpdateWalkingPlayer", at = @At("HEAD"))
32 | public void onUpdateWalkingPlayerPRE(CallbackInfo ci) {
33 | MotionUpdateEvent event = new MotionUpdateEvent(this.rotationYaw, this.rotationPitch);
34 | MinecraftForge.EVENT_BUS.post(event);
35 | this.mightyMinerv2$serverYaw = event.yaw;
36 | this.mightyMinerv2$serverPitch = event.pitch;
37 | }
38 |
39 | @Redirect(method = "onUpdateWalkingPlayer", at = @At(value = "FIELD", target = "Lnet/minecraft/client/entity/EntityPlayerSP;rotationYaw:F", opcode = Opcodes.GETFIELD))
40 | public float onUpdateWalkingPlayerYaw(EntityPlayerSP instance) {
41 | return this.mightyMinerv2$serverYaw;
42 | }
43 |
44 | @Redirect(method = "onUpdateWalkingPlayer", at = @At(value = "FIELD", target = "Lnet/minecraft/client/entity/EntityPlayerSP;rotationPitch:F", opcode = Opcodes.GETFIELD))
45 | public float onUpdateWalkingPlayerPitch(EntityPlayerSP instance) {
46 | return this.mightyMinerv2$serverPitch;
47 | }
48 |
49 | @Inject(method = "dropOneItem", at = @At("HEAD"), cancellable = true)
50 | public void onDropOneItem(boolean dropAll, CallbackInfoReturnable cir) {
51 | if (MacroManager.getInstance().isRunning()) {
52 | cir.setReturnValue(null);
53 | cir.cancel();
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/mixin/client/MixinMinecraft.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.mixin.client;
2 |
3 | import com.jelly.mightyminerv2.macro.MacroManager;
4 | import net.minecraft.client.Minecraft;
5 | import net.minecraft.client.entity.EntityPlayerSP;
6 | import net.minecraft.client.settings.KeyBinding;
7 | import org.lwjgl.opengl.Display;
8 | import org.spongepowered.asm.mixin.Mixin;
9 | import org.spongepowered.asm.mixin.Shadow;
10 | import org.spongepowered.asm.mixin.injection.At;
11 | import org.spongepowered.asm.mixin.injection.Redirect;
12 |
13 | @Mixin(Minecraft.class)
14 | public class MixinMinecraft {
15 |
16 | @Shadow
17 | public EntityPlayerSP thePlayer;
18 |
19 | @Redirect(method = "runTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/settings/KeyBinding;isPressed()Z", ordinal = 2))
20 | public boolean isPressed(KeyBinding instance) {
21 | return instance.isKeyDown() && !MacroManager.getInstance().isRunning();
22 | }
23 |
24 | @Redirect(method = "setIngameFocus", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/Display;isActive()Z", remap = false))
25 | public boolean isActive() {
26 | if (MacroManager.getInstance().isRunning()) {
27 | return true;
28 | }
29 | return Display.isActive();
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/mixin/client/MixinScoreboard.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.mixin.client;
2 |
3 | import net.minecraft.scoreboard.ScoreObjective;
4 | import net.minecraft.scoreboard.ScorePlayerTeam;
5 | import net.minecraft.scoreboard.Scoreboard;
6 | import org.spongepowered.asm.mixin.Mixin;
7 | import org.spongepowered.asm.mixin.Shadow;
8 | import org.spongepowered.asm.mixin.injection.At;
9 | import org.spongepowered.asm.mixin.injection.Inject;
10 | import org.spongepowered.asm.mixin.injection.Redirect;
11 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
12 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
13 |
14 | import java.util.Map;
15 |
16 | // Patcher's fix for the scoreboard log spam
17 | @Mixin(Scoreboard.class)
18 | public abstract class MixinScoreboard {
19 | @Shadow
20 | public abstract ScorePlayerTeam getTeam(String p_96508_1_);
21 |
22 | @Inject(method = "removeTeam", at = @At("HEAD"), cancellable = true)
23 | private void patcher$checkIfTeamIsNull(ScorePlayerTeam team, CallbackInfo ci) {
24 | if (team == null) ci.cancel();
25 | }
26 |
27 | @Redirect(method = "removeTeam", at = @At(value = "INVOKE", target = "Ljava/util/Map;remove(Ljava/lang/Object;)Ljava/lang/Object;", ordinal = 0, remap = false))
28 | private V patcher$checkIfRegisteredNameIsNull(Map instance, K o) {
29 | if (o != null) return instance.remove(o);
30 | return null;
31 | }
32 |
33 | @Inject(method = "removeObjective", at = @At("HEAD"), cancellable = true)
34 | private void patcher$checkIfObjectiveIsNull(ScoreObjective objective, CallbackInfo ci) {
35 | if (objective == null) ci.cancel();
36 | }
37 |
38 | @Redirect(method = "removeObjective", at = @At(value = "INVOKE", target = "Ljava/util/Map;remove(Ljava/lang/Object;)Ljava/lang/Object;", ordinal = 0, remap = false))
39 | private V patcher$checkIfNameIsNull(Map instance, K o) {
40 | if (o != null) return instance.remove(o);
41 | return null;
42 | }
43 |
44 | @Inject(method = "createTeam", at = @At(value = "CONSTANT", args = "stringValue=A team with the name '"), cancellable = true)
45 | private void patcher$returnExistingTeam(String name, CallbackInfoReturnable cir) {
46 | cir.setReturnValue(this.getTeam(name));
47 | }
48 |
49 | @Inject(method = "removePlayerFromTeam", at = @At(value = "CONSTANT", args = "stringValue=Player is either on another team or not on any team. Cannot remove from team '"), cancellable = true)
50 | private void patcher$silenceException(CallbackInfo ci) {
51 | ci.cancel();
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/mixin/client/MixinSoundManager.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.mixin.client;
2 |
3 | import com.jelly.mightyminerv2.config.MightyMinerConfig;
4 | import com.jelly.mightyminerv2.failsafe.FailsafeManager;
5 | import com.jelly.mightyminerv2.macro.MacroManager;
6 | import net.minecraft.client.audio.ISound;
7 | import net.minecraft.client.audio.SoundCategory;
8 | import net.minecraft.client.audio.SoundManager;
9 | import net.minecraft.client.audio.SoundPoolEntry;
10 | import org.spongepowered.asm.mixin.Mixin;
11 | import org.spongepowered.asm.mixin.injection.At;
12 | import org.spongepowered.asm.mixin.injection.Inject;
13 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
14 |
15 | @Mixin(SoundManager.class)
16 | public class MixinSoundManager {
17 | @Inject(method = "getNormalizedVolume", at = @At("RETURN"), cancellable = true)
18 | private void getNormalizedVolume(ISound sound, SoundPoolEntry entry, SoundCategory category, CallbackInfoReturnable cir) {
19 | if (MacroManager.getInstance().isRunning() && MightyMinerConfig.muteGame && FailsafeManager.getInstance().emergencyQueue.isEmpty() && !FailsafeManager.getInstance().triggeredFailsafe.isPresent()) {
20 | cir.setReturnValue(0f);
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/mixin/gui/MixinGuiContainer.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.mixin.gui;
2 |
3 | import com.jelly.mightyminerv2.macro.MacroManager;
4 | import net.minecraft.client.gui.inventory.GuiContainer;
5 | import net.minecraft.inventory.Slot;
6 | import org.spongepowered.asm.mixin.Mixin;
7 | import org.spongepowered.asm.mixin.injection.At;
8 | import org.spongepowered.asm.mixin.injection.Inject;
9 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
10 |
11 | @Mixin(GuiContainer.class)
12 | public abstract class MixinGuiContainer {
13 |
14 | @Inject(method = "handleMouseClick", at = @At("HEAD"), cancellable = true)
15 | public void handleMouseClick(Slot slotIn, int slotId, int clickedButton, int clickType, CallbackInfo ci) {
16 | if (MacroManager.getInstance().isRunning()) {
17 | ci.cancel();
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/mixin/gui/MixinInventoryPlayer.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.mixin.gui;
2 |
3 | import com.jelly.mightyminerv2.macro.MacroManager;
4 | import net.minecraft.entity.player.InventoryPlayer;
5 | import org.spongepowered.asm.mixin.Mixin;
6 | import org.spongepowered.asm.mixin.injection.At;
7 | import org.spongepowered.asm.mixin.injection.Inject;
8 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
9 |
10 | @Mixin(InventoryPlayer.class)
11 | public abstract class MixinInventoryPlayer {
12 |
13 | @Inject(method = "changeCurrentItem", at = @At("HEAD"), cancellable = true)
14 | public void changeCurrentItem(int direction, CallbackInfo ci) {
15 | if (MacroManager.getInstance().isRunning()) {
16 | ci.cancel();
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/mixin/render/MixinModelBiped.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.mixin.render;
2 |
3 | import com.jelly.mightyminerv2.handler.RotationHandler;
4 | import com.jelly.mightyminerv2.mixin.client.EntityPlayerSPAccessor;
5 | import com.jelly.mightyminerv2.mixin.client.MinecraftAccessor;
6 | import com.jelly.mightyminerv2.util.AngleUtil;
7 | import com.jelly.mightyminerv2.util.helper.RotationConfiguration;
8 | import net.minecraft.client.Minecraft;
9 | import net.minecraft.client.model.ModelBiped;
10 | import net.minecraft.client.model.ModelRenderer;
11 | import net.minecraft.entity.Entity;
12 | import net.minecraft.util.MathHelper;
13 | import org.spongepowered.asm.mixin.Mixin;
14 | import org.spongepowered.asm.mixin.Shadow;
15 | import org.spongepowered.asm.mixin.Unique;
16 | import org.spongepowered.asm.mixin.injection.At;
17 | import org.spongepowered.asm.mixin.injection.Inject;
18 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
19 |
20 | @Mixin(value = ModelBiped.class, priority = Integer.MAX_VALUE)
21 | public class MixinModelBiped {
22 |
23 | @Unique
24 | private final Minecraft mightyMinerV2$mc = Minecraft.getMinecraft();
25 | @Shadow
26 | public ModelRenderer bipedHead;
27 |
28 | @Inject(method = {"setRotationAngles"}, at = {@At(value = "FIELD", target = "Lnet/minecraft/client/model/ModelBiped;swingProgress:F")})
29 | public void onSetRotationAngles(float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch, float scaleFactor, Entity entityIn, CallbackInfo ci) {
30 | if (!RotationHandler.getInstance().isEnabled() || RotationHandler.getInstance().getConfiguration() != null && RotationHandler.getInstance().getConfiguration().rotationType() != RotationConfiguration.RotationType.SERVER || entityIn == null || !entityIn.equals(mightyMinerV2$mc.thePlayer)) {
31 | return;
32 | }
33 |
34 | this.bipedHead.rotateAngleX = ((EntityPlayerSPAccessor) entityIn).getLastReportedPitch() / 57.295776f;
35 | float partialTicks = ((MinecraftAccessor) mightyMinerV2$mc).getTimer().renderPartialTicks;
36 | float yawOffset = mightyMinerV2$mc.thePlayer.renderYawOffset + AngleUtil.normalizeAngle(mightyMinerV2$mc.thePlayer.renderYawOffset - mightyMinerV2$mc.thePlayer.prevRenderYawOffset) * partialTicks;
37 | float calcNetHead = MathHelper.wrapAngleTo180_float(((EntityPlayerSPAccessor) entityIn).getLastReportedYaw() - yawOffset);
38 | this.bipedHead.rotateAngleY = calcNetHead / 57.295776f;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/util/IChunkProviderClient.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.util;
2 |
3 | import net.minecraft.util.LongHashMap;
4 | import net.minecraft.world.chunk.Chunk;
5 |
6 | import java.util.List;
7 |
8 | public interface IChunkProviderClient {
9 | LongHashMap chunkMapping();
10 |
11 | List chunkListing();
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/util/Logger.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.util;
2 |
3 | import cc.polyfrost.oneconfig.utils.Notifications;
4 | import com.jelly.mightyminerv2.config.MightyMinerConfig;
5 | import net.minecraft.client.Minecraft;
6 | import net.minecraft.util.ChatComponentText;
7 | import net.minecraft.util.EnumChatFormatting;
8 | import net.minecraft.util.StringUtils;
9 |
10 | import java.util.HashMap;
11 | import java.util.Map;
12 |
13 | public abstract class Logger {
14 |
15 | protected static final Minecraft mc = Minecraft.getMinecraft();
16 | private static final Map lastMessages = new HashMap<>();
17 |
18 | public static void addMessage(String text) {
19 | if (mc.thePlayer == null || mc.theWorld == null) {
20 | System.out.println("MightyMiner " + StringUtils.stripControlCodes(text));
21 | } else {
22 | mc.thePlayer.addChatMessage(new ChatComponentText(text));
23 | }
24 | }
25 |
26 | public static void sendMessage(final String message) {
27 | addMessage(formatPrefix("§bMighty Miner", message));
28 | }
29 |
30 | public static void sendWarning(final String message) {
31 | addMessage("§c§l[WARNING] §8» §e" + message);
32 | }
33 |
34 | public static void sendError(final String message) {
35 | addMessage("§l§4§kZ§r§l§4[Mighty Miner]§kH§r §8» §c" + message);
36 | }
37 |
38 | public static void sendNote(final String message) {
39 | sendMessage(message);
40 | }
41 |
42 | public static void sendLog(final String message) {
43 | if (isDuplicate("debug", message)) return;
44 |
45 | if (MightyMinerConfig.debugMode && mc.thePlayer != null) {
46 | addMessage("§l§2[Mighty Miner] §8» §7" + message);
47 | } else {
48 | System.out.println("[Mighty Miner] " + message);
49 | }
50 | }
51 |
52 | public static void sendNotification(String title, String message, Long duration) {
53 | if (isDuplicate("notification", message)) return;
54 | Notifications.INSTANCE.send(title, message, duration);
55 | }
56 |
57 | private static boolean isDuplicate(String type, String message) {
58 | if (lastMessages.containsKey(type) && lastMessages.get(type).equals(message)) {
59 | return true;
60 | }
61 | lastMessages.put(type, message);
62 | return false;
63 | }
64 |
65 | private static String formatPrefix(String prefix, String message) {
66 | return EnumChatFormatting.RED + "[" + EnumChatFormatting.BLUE + prefix + EnumChatFormatting.RED + "] §8» §e" + message;
67 | }
68 |
69 | public abstract String getName();
70 |
71 | protected void log(String message) {
72 | sendLog(formatMessage(message));
73 | }
74 |
75 | protected void send(String message) {
76 | sendMessage(formatMessage(message));
77 | }
78 |
79 | protected void error(String message) {
80 | sendError(formatMessage(message));
81 | }
82 |
83 | protected void warn(String message) {
84 | sendWarning(formatMessage(message));
85 | }
86 |
87 | protected void note(String message) {
88 | sendNote(formatMessage(message));
89 | }
90 |
91 | protected String formatMessage(String message) {
92 | return "[" + getName() + "] " + message;
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/util/PlayerUtil.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.util;
2 |
3 | import net.minecraft.client.Minecraft;
4 | import net.minecraft.entity.Entity;
5 | import net.minecraft.util.*;
6 |
7 | import java.util.Collections;
8 | import java.util.Comparator;
9 | import java.util.List;
10 | import java.util.function.Predicate;
11 |
12 | public class PlayerUtil {
13 |
14 | private static final Minecraft mc = Minecraft.getMinecraft();
15 |
16 | // requires more testing
17 | public static BlockPos getBlockStandingOn() {
18 | // 0.25 = 3 layers of snow
19 | // if there is more than 3 layers of snow then i should consider that as a full block i guess
20 | // but there is no snow check in pathfinder so this will probably not work at all in snowy areas
21 | return new BlockPos(mc.thePlayer.posX, Math.ceil(mc.thePlayer.posY - 0.25) - 1, mc.thePlayer.posZ);
22 | }
23 |
24 | public static Vec3 getPlayerEyePos() {
25 | return mc.thePlayer.getPositionEyes(1f);
26 | }
27 |
28 | public static BlockPos getBlockStandingOnFloor() {
29 | return new BlockPos(mc.thePlayer.posX, Math.floor(mc.thePlayer.posY) - 1, mc.thePlayer.posZ);
30 | }
31 |
32 | public static Vec3 getNextTickPosition() {
33 | return mc.thePlayer.getPositionVector().addVector(mc.thePlayer.motionX, 0, mc.thePlayer.motionZ);
34 | }
35 |
36 | public static Vec3 getNextTickPosition(float mult) {
37 | return mc.thePlayer.getPositionVector().addVector(mc.thePlayer.motionX * mult, 0, mc.thePlayer.motionZ * mult);
38 | }
39 |
40 | public static Entity getEntityCuttingOtherEntity(Entity e) {
41 | return getEntityCuttingOtherEntity(e, entity -> true);
42 | }
43 |
44 | public static Entity getEntityCuttingOtherEntity(Entity e, Predicate predicate) {
45 | List possible = mc.theWorld.getEntitiesInAABBexcluding(e, e.getEntityBoundingBox().expand(0.3D, 2.0D, 0.3D), a -> {
46 | boolean flag1 = (!a.isDead && !a.equals(mc.thePlayer));
47 | boolean flag2 = !(a instanceof net.minecraft.entity.projectile.EntityFireball);
48 | boolean flag3 = !(a instanceof net.minecraft.entity.projectile.EntityFishHook);
49 | boolean flag4 = predicate.test(a);
50 | return flag1 && flag2 && flag3 && flag4;
51 | });
52 | if (!possible.isEmpty()) {
53 | return Collections.min(possible, Comparator.comparing(e2 -> e2.getDistanceToEntity(e)));
54 | }
55 | return null;
56 | }
57 |
58 | public static boolean isPlayerSuffocating() {
59 | AxisAlignedBB playerBB = mc.thePlayer.getEntityBoundingBox().expand(-0.15, -0.15, -0.15);
60 | List collidingBoxes = mc.theWorld.getCollidingBoundingBoxes(mc.thePlayer, playerBB);
61 | return !collidingBoxes.isEmpty();
62 | }
63 |
64 | public static EnumFacing getHorizontalFacing(float yaw) {
65 | return EnumFacing.getHorizontal(MathHelper.floor_double((double) (yaw * 4.0F / 360.0F) + 0.5) & 3);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/util/RaytracingUtil.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.util;
2 |
3 | import net.minecraft.client.Minecraft;
4 | import net.minecraft.entity.Entity;
5 | import net.minecraft.util.MovingObjectPosition;
6 | import net.minecraft.util.Vec3;
7 |
8 | import java.util.List;
9 |
10 | public class RaytracingUtil {
11 |
12 | private static final Minecraft mc = Minecraft.getMinecraft();
13 |
14 | public static boolean canSeePoint(Vec3 point) {
15 | return canSeePoint(PlayerUtil.getPlayerEyePos(), point);
16 | }
17 |
18 | public static boolean canSeePoint(Vec3 from, Vec3 point) {
19 | final MovingObjectPosition result = raytrace(from, point);
20 | if (result == null) {
21 | return true;
22 | }
23 |
24 | final Vec3 r = result.hitVec;
25 |
26 | if (r == null) {
27 | return false;
28 | }
29 |
30 | return Math.abs(r.xCoord - point.xCoord) < 0.1f && Math.abs(r.yCoord - point.yCoord) < 0.1f && Math.abs(r.zCoord - point.zCoord) < 0.1f;
31 | }
32 |
33 | public static MovingObjectPosition raytraceTowards(Vec3 v1, Vec3 v2, double distance) {
34 | Vec3 normalized = v2.subtract(v1).normalize();
35 | return raytrace(v1, v1.add(new Vec3(normalized.xCoord * distance, normalized.yCoord * distance, normalized.zCoord * distance)));
36 | }
37 |
38 | public static MovingObjectPosition raytrace(Vec3 v1, Vec3 v2) {
39 | final Vec3 v3 = v2.subtract(v1);
40 | final List entities = mc.theWorld.getEntitiesInAABBexcluding(mc.thePlayer, mc.thePlayer.getEntityBoundingBox().addCoord(v3.xCoord, v3.yCoord, v3.zCoord).expand(1.0, 1.0, 1.0), it -> it.isEntityAlive() && it.canBeCollidedWith());
41 |
42 | for (Entity entity : entities) {
43 | final MovingObjectPosition intercept = entity.getEntityBoundingBox().expand(0.5, 0.5, 0.5).calculateIntercept(v1, v2);
44 | if (intercept != null) {
45 | return new MovingObjectPosition(entity, intercept.hitVec);
46 | }
47 | }
48 |
49 | return mc.theWorld.rayTraceBlocks(v1, v2, false, true, false);
50 | }
51 |
52 | }
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/util/ReflectionUtils.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.util;
2 |
3 | import net.minecraft.client.Minecraft;
4 |
5 | import java.lang.reflect.Field;
6 | import java.lang.reflect.Method;
7 | import java.nio.file.Path;
8 | import java.util.Arrays;
9 |
10 | public class ReflectionUtils {
11 | public static boolean invoke(Object object, String methodName) {
12 | try {
13 | final Method method = object.getClass().getDeclaredMethod(methodName);
14 | method.setAccessible(true);
15 | method.invoke(object);
16 | return true;
17 | } catch (Exception ignored) {
18 | }
19 | return false;
20 | }
21 |
22 | public static Object field(Object object, String name) {
23 | try {
24 | Field field = object.getClass().getDeclaredField(name);
25 | field.setAccessible(true);
26 | return field.get(object);
27 | } catch (Exception ignored) {
28 | }
29 | return null;
30 | }
31 |
32 | public static boolean hasPackageInstalled(String name) {
33 | Package[] packages = Package.getPackages();
34 |
35 | for (Package pack : packages) {
36 | if (pack.getName().contains(name)) {
37 | return true;
38 | }
39 | }
40 | return false;
41 | }
42 |
43 | public static boolean hasModFile(String name) {
44 | Path modsDir = Minecraft.getMinecraft().mcDataDir.toPath().resolve("mods");
45 | String[] modFiles = modsDir.toFile().list();
46 | return modFiles != null && Arrays.stream(modFiles).anyMatch(modFile -> modFile.toLowerCase().contains(name.toLowerCase()) && !modFile.toLowerCase().endsWith(".disabled"));
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/util/ScoreboardUtil.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.util;
2 |
3 | import com.jelly.mightyminerv2.event.UpdateScoreboardLineEvent;
4 | import net.minecraft.client.Minecraft;
5 | import net.minecraft.scoreboard.ScoreObjective;
6 | import net.minecraft.scoreboard.Scoreboard;
7 | import net.minecraft.util.StringUtils;
8 | import net.minecraftforge.client.event.ClientChatReceivedEvent;
9 | import net.minecraftforge.event.world.WorldEvent;
10 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
11 |
12 | import java.util.*;
13 | import java.util.regex.Matcher;
14 | import java.util.regex.Pattern;
15 |
16 | public class ScoreboardUtil {
17 |
18 | private final Pattern coldRegex = Pattern.compile("Cold: -?(\\d{1,3})");
19 | public static int cold = 0;
20 |
21 | private static final Minecraft mc = Minecraft.getMinecraft();
22 | public static Map> scoreboard = new HashMap<>();
23 | public static String[] scoreObjNames = new String[19];
24 |
25 | public static List getScoreboard() {
26 | try {
27 | return new ArrayList<>(scoreboard.get(scoreObjNames[1]).values());
28 | } catch (Exception ignored) {
29 | return Collections.emptyList();
30 | }
31 | }
32 |
33 | public static String getScoreboardTitle() {
34 | if (mc.theWorld == null) {
35 | return "";
36 | }
37 | Scoreboard scoreboard = mc.theWorld.getScoreboard();
38 | if (scoreboard == null) {
39 | return "";
40 | }
41 |
42 | ScoreObjective objective = scoreboard.getObjectiveInDisplaySlot(1);
43 | if (objective == null) {
44 | return "";
45 | }
46 |
47 | return sanitizeString(objective.getDisplayName());
48 | }
49 |
50 | public static String sanitizeString(String scoreboard) {
51 | char[] arr = scoreboard.toCharArray();
52 | StringBuilder cleaned = new StringBuilder();
53 | for (int i = 0; i < arr.length; i++) {
54 | char c = arr[i];
55 | if (c >= 32 && c < 127) {
56 | cleaned.append(c);
57 | }
58 | if (c == 167) {
59 | i++;
60 | }
61 | }
62 | return cleaned.toString();
63 | }
64 |
65 | @SubscribeEvent
66 | public void onWorldChange(WorldEvent.Load event) {
67 | cold = 0;
68 | }
69 |
70 | @SubscribeEvent
71 | public void onScoreboardUpdate(UpdateScoreboardLineEvent event) {
72 | if (event.getLine().contains("Cold:")) {
73 | Matcher coldMatcher = coldRegex.matcher(event.getLine());
74 | if (coldMatcher.find()) cold = Integer.parseInt(coldMatcher.group(1));
75 | else cold = 0;
76 | }
77 |
78 | List scoreboardLines = getScoreboard();
79 | if (scoreboardLines.stream().noneMatch(line -> sanitizeString(line).contains("Cold:"))) cold = 0;
80 | }
81 |
82 | @SubscribeEvent(receiveCanceled = true)
83 | public void onChatDetection(ClientChatReceivedEvent event) {
84 | if (event.type != 0) return;
85 | if (event.message == null) return;
86 |
87 | String message = StringUtils.stripControlCodes(event.message.getUnformattedText());
88 | if (message.contains("The warmth of the campfire reduced your") && message.contains("Cold")) {
89 | cold = 0;
90 | }
91 | }
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/util/StrafeUtil.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.util;
2 |
3 | public final class StrafeUtil {
4 |
5 | public static volatile boolean enabled = false;
6 | public static volatile boolean forceStop = false;
7 | public static volatile float yaw = 0.0f;
8 |
9 | public static boolean shouldEnable() {
10 | return !forceStop && enabled;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/util/helper/Angle.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.util.helper;
2 |
3 | import lombok.Getter;
4 | import lombok.Setter;
5 |
6 | @Getter
7 | @Setter
8 | public class Angle {
9 | public float yaw;
10 | public float pitch;
11 |
12 | public Angle(float yaw, float pitch) {
13 | this.yaw = yaw;
14 | this.pitch = pitch;
15 | }
16 |
17 | public void setRotation(Angle rotation) {
18 | this.yaw = rotation.getYaw();
19 | this.pitch = rotation.getPitch();
20 | }
21 |
22 | public float getValue() {
23 | return Math.abs(this.yaw) + Math.abs(this.pitch);
24 | }
25 |
26 | public float lengthSqrt() {
27 | return (float) Math.sqrt(this.yaw * this.yaw + this.pitch * this.pitch);
28 | }
29 |
30 | @Override
31 | public String toString() {
32 | return "Rotation{" + "yaw=" + yaw + ", pitch=" + pitch + "}";
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/util/helper/Clock.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.util.helper;
2 |
3 | public class Clock {
4 |
5 | private long deltaTime;
6 | private boolean paused;
7 | private boolean scheduled;
8 | private long endTime;
9 | private long startTime;
10 |
11 | // stopwatch
12 |
13 | public void schedule(long milliseconds) {
14 | this.endTime = System.currentTimeMillis() + milliseconds;
15 | this.deltaTime = milliseconds;
16 | this.scheduled = true;
17 | this.paused = false;
18 | }
19 |
20 | public void schedule(double milliseconds) {
21 | this.endTime = (System.currentTimeMillis() + (long) milliseconds);
22 | this.deltaTime = (long) milliseconds;
23 | this.scheduled = true;
24 | this.paused = false;
25 | }
26 |
27 | public boolean passed() {
28 | return System.currentTimeMillis() >= endTime;
29 | }
30 |
31 | public void pause() {
32 | if (scheduled && !paused) {
33 | deltaTime = endTime - System.currentTimeMillis();
34 | paused = true;
35 | }
36 | }
37 |
38 | public void resume() {
39 | if (scheduled && paused) {
40 | endTime = System.currentTimeMillis() + deltaTime;
41 | paused = false;
42 | }
43 | }
44 |
45 | public long getRemainingTime() {
46 | if (this.paused) {
47 | return deltaTime;
48 | }
49 | return Math.max(0, endTime - System.currentTimeMillis());
50 | }
51 |
52 | public void start(boolean reset) {
53 | if (!this.scheduled || reset) {
54 | this.startTime = System.currentTimeMillis();
55 | } else {
56 | this.resumeTimer();
57 | }
58 | this.scheduled = true;
59 | }
60 |
61 | public void stop(boolean reset) {
62 | if (!this.scheduled || reset) {
63 | this.reset();
64 | } else {
65 | this.pauseTimer();
66 | }
67 | }
68 |
69 | public long getTimePassed() {
70 | if (!this.scheduled || this.paused) {
71 | return deltaTime;
72 | }
73 | return System.currentTimeMillis() - startTime;
74 | }
75 |
76 | public void pauseTimer() {
77 | if (scheduled && !paused) {
78 | deltaTime = System.currentTimeMillis() - startTime;
79 | paused = true;
80 | }
81 | }
82 |
83 | public void resumeTimer() {
84 | if (scheduled && paused) {
85 | startTime = System.currentTimeMillis() - deltaTime;
86 | paused = false;
87 | }
88 | }
89 |
90 | public void reset() {
91 | scheduled = false;
92 | paused = false;
93 | endTime = 0;
94 | deltaTime = 0;
95 | }
96 |
97 | public boolean isScheduled() {
98 | return this.scheduled;
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/util/helper/MineableBlock.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.util.helper;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public enum MineableBlock {
7 |
8 | QUARTZ(155, 153),
9 | DIAMOND(57),
10 | EMERALD(133),
11 | REDSTONE( 152),
12 | LAPIS(22),
13 | GOLD(41),
14 | IRON(42),
15 | COAL(173),
16 | SULPHUR(19),
17 | HARDSTONE(1),
18 | TITANIUM(16385),
19 | GRAY_MITHRIL(28707, 37023),
20 | GREEN_MITHRIL(168, 4264, 8360),
21 | BLUE_MITHRIL(12323),
22 | OPAL(95, 160),
23 | JASPER(8287, 8352),
24 | TOPAZ(16544, 16479),
25 | AMBER(4191, 4256),
26 | SAPPHIRE(12383, 12448),
27 | JADE(20575, 20640),
28 | AMETHYST(41055, 41120),
29 | RUBY(57504, 57436),
30 | AQUAMARINE(45151, 45216),
31 | PERIDOT(53343, 53408),
32 | ONYX(61535, 61600),
33 | CITRINE(49247, 49312),
34 | GLACITE(174),
35 | UMBER(172, 32949, 49311),
36 | TUNGSTEN(4193, 82),;
37 |
38 | public final List stateIds;
39 |
40 | MineableBlock(int... values) {
41 | stateIds = new ArrayList<>();
42 | for (int value : values) {
43 | stateIds.add(value);
44 | }
45 | }
46 |
47 | }
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/util/helper/Target.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.util.helper;
2 |
3 | import com.jelly.mightyminerv2.util.AngleUtil;
4 | import lombok.Getter;
5 | import lombok.Setter;
6 | import lombok.experimental.Accessors;
7 | import net.minecraft.entity.Entity;
8 | import net.minecraft.util.BlockPos;
9 | import net.minecraft.util.Vec3;
10 |
11 | public class Target {
12 |
13 | private Vec3 vec;
14 | @Getter
15 | private Entity entity;
16 | @Getter
17 | private BlockPos blockPos;
18 | @Getter
19 | private Angle angle;
20 | @Accessors(fluent = true)
21 | @Setter
22 | @Getter
23 | private float additionalY = (float) (1 + Math.random()) * 0.75f;
24 |
25 | public Target(Vec3 vec) {
26 | this.vec = vec;
27 | }
28 |
29 | public Target(Entity entity) {
30 | this.entity = entity;
31 | }
32 |
33 | public Target(BlockPos blockPos) {
34 | this.blockPos = blockPos;
35 | }
36 |
37 | public Target(Angle angle) {
38 | this.angle = angle;
39 | }
40 |
41 | // Ensures Rotation Always Ends
42 | public Angle getTargetAngle() {
43 | if (blockPos != null) {
44 | return AngleUtil.getRotation(blockPos);
45 | }
46 |
47 | if (vec != null) {
48 | return AngleUtil.getRotation(vec);
49 | }
50 |
51 | if (entity != null) {
52 | return AngleUtil.getRotation(entity.getPositionVector().addVector(0, additionalY, 0));
53 | }
54 |
55 | return angle;
56 | }
57 |
58 | @Override
59 | public String toString() {
60 | return "Vec3: " + this.vec + ", Ent: " + (this.entity != null ? this.entity.getEntityId() : "null") + ", Pos: " + this.blockPos + ", Angle: " + this.angle;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/util/helper/graph/Graph.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.util.helper.graph;
2 |
3 | import com.google.gson.annotations.Expose;
4 |
5 | import java.util.*;
6 |
7 | public class Graph {
8 |
9 | @Expose
10 | public final Map> map = new HashMap<>();
11 |
12 | public void add(T source) {
13 | if (!map.isEmpty()) {
14 | return;
15 | }
16 | map.computeIfAbsent(source, k -> new ArrayList<>());
17 | }
18 |
19 | public void add(T source, T target, boolean bidi) {
20 | map.computeIfAbsent(source, k -> new ArrayList<>()).add(target);
21 | map.computeIfAbsent(target, k -> new ArrayList<>());
22 | if (bidi) {
23 | map.get(target).add(source);
24 | }
25 | }
26 |
27 | public void update(T old, T now) {
28 | if (old == null || now == null) {
29 | throw new IllegalArgumentException("Nodes cannot be null");
30 | }
31 |
32 | List edges = map.remove(old);
33 | if (edges != null) {
34 | map.put(now, edges);
35 | }
36 |
37 | for (Map.Entry> entry : map.entrySet()) {
38 | List updatedEdges = new ArrayList<>();
39 | for (T edge : entry.getValue()) {
40 | if (edge.equals(old)) {
41 | updatedEdges.add(now);
42 | } else {
43 | updatedEdges.add(edge);
44 | }
45 | }
46 | map.put(entry.getKey(), updatedEdges);
47 | }
48 | }
49 |
50 | public void remove(T node) {
51 | if (map.remove(node) == null) {
52 | return;
53 | }
54 |
55 | for (T key : map.keySet()) {
56 | map.get(key).removeIf(edge -> edge.equals(node));
57 | }
58 | }
59 |
60 | // Breadth First Search - Our graph is small enough so it finds path instantly. not worth using a star and wasting so much memory for that
61 | public List findPath(T start, T end) {
62 |
63 | if (start == null || end == null || !map.containsKey(start) || !map.containsKey(end)) {
64 | return new ArrayList<>();
65 | }
66 |
67 | Queue queue = new LinkedList<>();
68 | Set visited = new HashSet<>();
69 | HashMap parent = new HashMap();
70 |
71 | queue.add(start);
72 | visited.add(start);
73 | parent.put(start, null);
74 |
75 | while (!queue.isEmpty()) {
76 | T curr = queue.poll();
77 | if (curr.equals(end)) {
78 | LinkedList path = new LinkedList<>();
79 | for (T at = end; at != null; at = parent.get(at)) {
80 | path.addFirst(at);
81 | }
82 | return path;
83 | }
84 |
85 | for (T neighbour : map.get(curr)) {
86 | if (!visited.contains(neighbour)) {
87 | queue.offer(neighbour);
88 | visited.add(neighbour);
89 | parent.put(neighbour, curr);
90 | }
91 | }
92 | }
93 | return new ArrayList<>();
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/util/helper/graph/GraphSerializer.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.util.helper.graph;
2 |
3 | import com.google.common.reflect.TypeToken;
4 | import com.google.gson.*;
5 | import com.jelly.mightyminerv2.util.helper.route.RouteWaypoint;
6 | import com.jelly.mightyminerv2.util.helper.route.WaypointType;
7 |
8 | import java.lang.reflect.Type;
9 | import java.util.List;
10 | import java.util.Map.Entry;
11 |
12 | public class GraphSerializer implements JsonSerializer>, JsonDeserializer> {
13 |
14 | @Override
15 | public JsonElement serialize(Graph src, Type typeOfSrc, JsonSerializationContext context) {
16 | JsonObject res = new JsonObject();
17 | JsonObject map = new JsonObject();
18 |
19 | for (Entry> entry : src.map.entrySet()) {
20 | RouteWaypoint waypoint = entry.getKey();
21 | String keyString = waypoint.getX() + "," + waypoint.getY() + "," + waypoint.getZ() + "," + waypoint.getTransportMethod().name();
22 |
23 | JsonElement valueElement = context.serialize(entry.getValue());
24 | map.add(keyString, valueElement);
25 | }
26 |
27 | res.add("map", map);
28 | return res;
29 | }
30 |
31 | @Override
32 | @SuppressWarnings("unchecked")
33 | public Graph deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
34 | Graph graph = new Graph<>();
35 | JsonObject map = json.getAsJsonObject().getAsJsonObject("map");
36 |
37 | for (Entry entry : map.entrySet()) {
38 | try {
39 | // The key is a string like "33,119,419,WALK" so we need to manually parse it into RouteWaypoint
40 | String[] keyParts = entry.getKey().split(",");
41 | if (keyParts.length != 4) {
42 | throw new JsonParseException("Invalid RouteWaypoint key format: " + entry.getKey());
43 | }
44 |
45 | int x = Integer.parseInt(keyParts[0]);
46 | int y = Integer.parseInt(keyParts[1]);
47 | int z = Integer.parseInt(keyParts[2]);
48 | WaypointType transportMethod = WaypointType.valueOf(keyParts[3]);
49 | RouteWaypoint key = new RouteWaypoint(x, y, z, transportMethod);
50 |
51 | List value = context.deserialize(entry.getValue(), new TypeToken>() {
52 | }.getType());
53 |
54 | graph.map.put(key, value);
55 | } catch (JsonParseException | NumberFormatException e) {
56 | System.out.println("Error deserializing entry for key: " + entry.getKey());
57 | e.printStackTrace();
58 | }
59 | }
60 |
61 | return graph;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/util/helper/heap/HeapNode.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.util.helper.heap;
2 |
3 | public class HeapNode {
4 | public final T nodeVal;
5 | public final double nodeCost;
6 |
7 | public HeapNode(final T nodeVal, final double nodeCost) {
8 | this.nodeVal = nodeVal;
9 | this.nodeCost = nodeCost;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/util/helper/heap/MinHeap.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.util.helper.heap;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Arrays;
5 | import java.util.List;
6 |
7 | // Starts from 1
8 | public class MinHeap {
9 |
10 | private HeapNode[] items;
11 | private int size;
12 | private int capacity;
13 |
14 | public MinHeap(int capacity) {
15 | this.capacity = capacity;
16 | this.items = new HeapNode[this.capacity];
17 | this.size = 0;
18 | }
19 |
20 | public T poll() {
21 | HeapNode root = items[1];
22 | items[1] = items[size];
23 | items[size] = null;
24 | size--;
25 |
26 | int index = 1;
27 | int small;
28 | while ((small = index << 1) <= size) {
29 | if (small < size && items[small].nodeCost > items[small + 1].nodeCost) {
30 | small++;
31 | }
32 |
33 | if (items[index].nodeCost > items[small].nodeCost) {
34 | HeapNode temp = items[index];
35 | items[index] = items[small];
36 | items[small] = temp;
37 | index = small;
38 | } else {
39 | break;
40 | }
41 | }
42 |
43 | // should throw exception but oh well
44 | return root == null ? null : root.nodeVal;
45 | }
46 |
47 | private void heapDown(int index) {
48 | }
49 |
50 | public void add(T pos, double cost) {
51 | add(new HeapNode<>(pos, cost));
52 | }
53 |
54 | public void add(HeapNode elem) {
55 | if (this.size >= capacity) {
56 | this.capacity *= 2;
57 | this.items = Arrays.copyOf(this.items, this.capacity);
58 | }
59 | this.items[++this.size] = elem;
60 | this.heapUp(this.size - 1);
61 | }
62 |
63 | public void heapUp(int index) {
64 | int parentIndex = index >>> 1;
65 | while (parentIndex > 0 && this.items[index].nodeCost < this.items[parentIndex].nodeCost) {
66 | swap(parentIndex, index);
67 | index = parentIndex;
68 | parentIndex = index >>> 1;
69 | }
70 | }
71 |
72 | public void swap(int i1, int i2) {
73 | HeapNode temp = this.items[i1];
74 | this.items[i1] = this.items[i2];
75 | this.items[i2] = temp;
76 | }
77 |
78 | public List getBlocks() {
79 | final List blocks = new ArrayList<>();
80 | for (int i = 1; i < this.items.length; i++) {
81 | final HeapNode node = this.items[i];
82 | if (node == null) {
83 | break;
84 | }
85 | blocks.add(node.nodeVal);
86 | }
87 | return blocks;
88 | }
89 |
90 | public double getCost(T value) {
91 | for (int i = 1; i <= size; i++) {
92 | HeapNode node = this.items[i];
93 | if (node != null && node.nodeVal.equals(value)) {
94 | return node.nodeCost;
95 | }
96 | }
97 | throw new IllegalArgumentException("Value not found in heap.");
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/util/helper/location/Location.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.util.helper.location;
2 |
3 | import lombok.Getter;
4 |
5 | import java.util.HashMap;
6 | import java.util.Map;
7 |
8 | // DO NOT REARRANGE THE LAST THREE LOCATIONS - ORDINAL USED IN GAMSTATEHANDLER#ISPLAYERINSKYBLOCK TO REDUCE CHECKS
9 | @Getter
10 | public enum Location {
11 | PRIVATE_ISLAND("Private Island"),
12 | HUB("Hub"),
13 | THE_PARK("The Park"),
14 | THE_FARMING_ISLANDS("The Farming Islands"),
15 | SPIDER_DEN("Spider's Den"),
16 | THE_END("The End"),
17 | CRIMSON_ISLE("Crimson Isle"),
18 | GOLD_MINE("Gold Mine"),
19 | DEEP_CAVERNS("Deep Caverns"),
20 | DWARVEN_MINES("Dwarven Mines"),
21 | CRYSTAL_HOLLOWS("Crystal Hollows"),
22 | JERRY_WORKSHOP("Jerry's Workshop"),
23 | DUNGEON_HUB("Dungeon Hub"),
24 | GARDEN("Garden"),
25 | DUNGEON("Dungeon"),
26 | LIMBO("UNKNOWN"),
27 | LOBBY("PROTOTYPE"),
28 | // Knowhere - Avengers: Infinity War
29 | KNOWHERE("Knowhere");
30 |
31 | private static final Map nameToLocationMap = new HashMap<>();
32 |
33 | static {
34 | for (Location location : Location.values()) {
35 | nameToLocationMap.put(location.getName(), location);
36 | }
37 | }
38 |
39 | private final String name;
40 |
41 | Location(String name) {
42 | this.name = name;
43 | }
44 |
45 | public static Location fromName(String name) {
46 | final Location loc = nameToLocationMap.get(name);
47 | if (loc == null) return Location.KNOWHERE;
48 | return loc;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/util/helper/route/Route.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.util.helper.route;
2 |
3 | import com.google.gson.annotations.Expose;
4 | import com.jelly.mightyminerv2.config.MightyMinerConfig;
5 | import com.jelly.mightyminerv2.util.RenderUtil;
6 | import net.minecraft.util.BlockPos;
7 | import net.minecraft.util.Vec3;
8 |
9 | import java.util.ArrayList;
10 | import java.util.Comparator;
11 | import java.util.List;
12 | import java.util.Optional;
13 |
14 | public class Route {
15 |
16 | @Expose
17 | private final List waypoints = new ArrayList<>();
18 |
19 | public Route() {
20 | }
21 |
22 | public Route(List routes) {
23 | this.waypoints.addAll(routes);
24 | }
25 |
26 | public void insert(final RouteWaypoint waypoint) {
27 | this.insert(this.waypoints.size(), waypoint);
28 | }
29 |
30 | public void insert(final int index, final RouteWaypoint waypoint) {
31 | this.waypoints.add(index, waypoint);
32 | }
33 |
34 | public void remove(final RouteWaypoint waypoint) {
35 | final int index = this.waypoints.indexOf(waypoint);
36 | if (index == -1) {
37 | return;
38 | }
39 | this.remove(index);
40 | }
41 |
42 | public void remove(final int index) {
43 | this.waypoints.remove(index);
44 | }
45 |
46 | public RouteWaypoint get(final int index) {
47 | return this.waypoints.get((index + this.waypoints.size()) % this.waypoints.size());
48 | }
49 |
50 | public Optional getClosest(final BlockPos pos) {
51 | return this.waypoints.stream().min(Comparator.comparingDouble(wp -> wp.toVec3().squareDistanceTo(new Vec3(pos))));
52 | }
53 |
54 | public int indexOf(final RouteWaypoint waypoint) {
55 | return this.waypoints.indexOf(waypoint);
56 | }
57 |
58 | public void replace(final int index, final RouteWaypoint waypoint) {
59 | this.waypoints.set(index, waypoint);
60 | }
61 |
62 | public boolean isEnd(final int index) {
63 | return index + 1 == this.waypoints.size();
64 | }
65 |
66 | public boolean isEmpty() {
67 | return this.waypoints.isEmpty();
68 | }
69 |
70 | public void drawRoute() {
71 | for (int i = 0; i < this.waypoints.size(); i++) {
72 | RouteWaypoint currWaypoint = this.get(i);
73 | String name = currWaypoint.getTransportMethod().name();
74 | RenderUtil.drawBlock(currWaypoint.toBlockPos(), MightyMinerConfig.routeBuilderNodeColor.toJavaColor());
75 | RenderUtil.drawText((i + 1) + ". " + name.charAt(0) + name.substring(1).toLowerCase(), currWaypoint.getX() + 0.5, currWaypoint.getY() + 1, currWaypoint.getZ() + 0.5, 0.8F);
76 | if (this.waypoints.size() == 1) {
77 | continue;
78 | }
79 | RouteWaypoint prevWaypoint = this.get(i - 1);
80 | RenderUtil.drawLine(
81 | prevWaypoint.toVec3().addVector(0.5, 0.5, 0.5),
82 | currWaypoint.toVec3().addVector(0.5, 0.5, 0.5),
83 | MightyMinerConfig.routeBuilderTracerColor.toJavaColor()
84 | );
85 | }
86 | }
87 |
88 | public int size() {
89 | return this.waypoints.size();
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/util/helper/route/RouteWaypoint.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.util.helper.route;
2 |
3 | import com.google.gson.annotations.Expose;
4 | import lombok.Data;
5 | import lombok.EqualsAndHashCode;
6 | import net.minecraft.util.BlockPos;
7 | import net.minecraft.util.Vec3;
8 |
9 | @Data
10 | @EqualsAndHashCode(exclude = {"transportMethod"})
11 | public class RouteWaypoint {
12 |
13 | @Expose
14 | private int x;
15 | @Expose
16 | private int y;
17 | @Expose
18 | private int z;
19 | @Expose
20 | private WaypointType transportMethod;
21 |
22 | public RouteWaypoint() {}
23 |
24 | public RouteWaypoint(int x, int y, int z, WaypointType transportMethod) {
25 | this.x = x;
26 | this.y = y;
27 | this.z = z;
28 | this.transportMethod = transportMethod;
29 | }
30 |
31 | public RouteWaypoint(BlockPos pos, WaypointType transportMethod) {
32 | this(pos.getX(), pos.getY(), pos.getZ(), transportMethod);
33 | }
34 |
35 | public boolean isWithinRange(BlockPos pos, int range) {
36 | return Math.abs(pos.getX() - x) <= range && Math.abs(pos.getY() - y) <= range && Math.abs(pos.getZ() - z) <= range;
37 | }
38 |
39 | public int distanceTo(BlockPos pos) {
40 | return (int) Math.sqrt(Math.pow(pos.getX() - x, 2) + Math.pow(pos.getY() - y, 2) + Math.pow(pos.getZ() - z, 2));
41 | }
42 |
43 | public Vec3 toVec3() {
44 | return new Vec3(this.x, this.y, this.z);
45 | }
46 |
47 | public BlockPos toBlockPos() {
48 | return new BlockPos(this.x, this.y, this.z);
49 | }
50 |
51 | @Override
52 | public String toString() {
53 | return x + "," + y + "," + z + "," + transportMethod.name();
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/util/helper/route/TransportMethod.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.util.helper.route;
2 |
3 | // Todo: Rename
4 | public enum TransportMethod {
5 | AOTV, // Right Click Aotv/Aote
6 | ETHERWARP, // Shift + Right Click Aotv/Aote
7 | WALK, // Walks Between Nodes (Add it after pathfinder)
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/jelly/mightyminerv2/util/helper/route/WaypointType.java:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.util.helper.route;
2 |
3 | public enum WaypointType {
4 | AOTV, // Right Click Aotv/Aote
5 | ETHERWARP, // Shift + Right Click Aotv/Aote
6 | WALK, // Walks Between Nodes (Add it after pathfinder)
7 | MINE // User starts mining at this node (needed for RouteMiner)
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/jelly/mightyminerv2/pathfinder/calculate/Path.kt:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.pathfinder.calculate
2 |
3 | import com.jelly.mightyminerv2.pathfinder.goal.Goal
4 | import com.jelly.mightyminerv2.pathfinder.movement.CalculationContext
5 | import com.jelly.mightyminerv2.pathfinder.util.BlockUtil
6 | import com.jelly.mightyminerv2.pathfinder.util.toVec3
7 | import com.jelly.mightyminerv2.pathfinder.util.world
8 | import net.minecraft.init.Blocks
9 | import net.minecraft.util.BlockPos
10 | import java.util.*
11 |
12 | class Path(start: PathNode, end: PathNode, val goal: Goal, val ctx: CalculationContext) {
13 | var start: BlockPos = BlockPos(start.x, start.y, start.z)
14 | var end: BlockPos = BlockPos(end.x, end.y, end.z)
15 | var path: List
16 | var node: List
17 | var smoothPath: List = listOf()
18 |
19 | init {
20 | var temp: PathNode? = end
21 | val listOfBlocks = LinkedList()
22 | val listOfNodes = LinkedList()
23 | while (temp != null) {
24 | listOfNodes.addFirst(temp)
25 | listOfBlocks.addFirst(BlockPos(temp.x, temp.y, temp.z))
26 | temp = temp.parentNode
27 | }
28 | path = listOfBlocks.toList()
29 | node = listOfNodes.toList()
30 | }
31 |
32 | // english is not my strong suit
33 | fun getSmoothedPath(): List {
34 | if (smoothPath.isNotEmpty()) return smoothPath
35 |
36 | val smooth = LinkedList()
37 | if (path.isNotEmpty()) {
38 | smooth.add(path[0])
39 | var currPoint = 0
40 |
41 | while (currPoint + 1 < path.size) {
42 | var nextPos = currPoint + 1
43 |
44 | for (i in (path.size - 1) downTo nextPos) {
45 | if (BlockUtil.bresenham(ctx, path[currPoint], path[i])) {
46 | nextPos = i
47 | break
48 | }
49 | }
50 | smooth.add(path[nextPos])
51 | currPoint = nextPos
52 | }
53 | }
54 | smoothPath = smooth.toList()
55 | return smoothPath
56 | }
57 |
58 | fun reconstructPath(end: PathNode): List {
59 | val path = mutableListOf()
60 | var currentNode: PathNode? = end
61 | while (currentNode != null) {
62 | path.add(0, currentNode.getBlock())
63 | currentNode = currentNode.parentNode
64 | }
65 |
66 | val smooth = mutableListOf()
67 | if (path.isNotEmpty()) {
68 | smooth.add(path[0])
69 | var currPoint = 0
70 | var maxiters = 2000
71 |
72 | while (currPoint + 1 < path.size && maxiters-- > 0) {
73 | var nextPos = currPoint + 1
74 |
75 | for (i in (path.size - 1) downTo nextPos) {
76 | if (BlockUtil.bresenham(ctx, path[currPoint].toVec3(), path[i].toVec3())) {
77 | nextPos = i
78 | break
79 | }
80 | }
81 | smooth.add(path[nextPos])
82 | currPoint = nextPos
83 | }
84 | }
85 | smooth.removeIf { world.getBlockState(it).block == Blocks.air }
86 | return smooth
87 | }
88 |
89 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/jelly/mightyminerv2/pathfinder/calculate/PathNode.kt:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.pathfinder.calculate
2 |
3 | import com.jelly.mightyminerv2.pathfinder.goal.Goal
4 | import net.minecraft.util.BlockPos
5 |
6 | class PathNode(var x: Int, var y: Int, var z: Int, val goal: Goal) {
7 | var costSoFar: Double = 1e6 // gCost - INF_COST
8 | var costToEnd: Double = goal.heuristic(x, y, z) // hCost / Heuristic
9 | var totalCost: Double = 1.0 // INF_COST
10 | var heapPosition = -1 // Smart
11 | var parentNode: PathNode? = null
12 |
13 | override fun equals(other: Any?): Boolean {
14 | val otter =
15 | other as PathNode // otter just means other bt written weird to remove warning
16 | return otter.x == this.x && otter.y == this.y && otter.z == this.z
17 | }
18 |
19 | override fun hashCode(): Int {
20 | return longHash(this.x, this.y, this.z).toInt()
21 | }
22 |
23 | fun getBlock(): BlockPos {
24 | return BlockPos(x, y, z)
25 | }
26 |
27 | override fun toString(): String {
28 | return "PathNode(x: $x, y: $y, z: $z, costSoFar: $costSoFar, costToEnd: $costToEnd totalCost: $totalCost)"
29 | }
30 |
31 | companion object {
32 | fun longHash(x: Int, y: Int, z: Int): Long {
33 | var hash = 3241L
34 | hash = 3457689L * hash + x
35 | hash = 8734625L * hash + y
36 | hash = 2873465L * hash + z
37 | return hash
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/jelly/mightyminerv2/pathfinder/calculate/openset/BinaryHeapOpenSet.kt:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.pathfinder.calculate.openset
2 |
3 | import com.jelly.mightyminerv2.pathfinder.calculate.PathNode
4 | import java.util.*
5 |
6 | class BinaryHeapOpenSet(initialSize: Int = 1024) {
7 | var items = arrayOfNulls(initialSize)
8 | var size = 0
9 |
10 | fun add(node: PathNode) {
11 | if (size >= items.size - 1) {
12 | items = Arrays.copyOf(items, items.size shl 1)
13 | }
14 | node.heapPosition = ++size
15 | items[size] = node
16 | relocate(node)
17 | }
18 |
19 | fun relocate(node: PathNode) {
20 | var parent = node.heapPosition ushr 1
21 | var parentNode = items[parent]
22 | while (node.heapPosition > 1 && node.totalCost < parentNode!!.totalCost) {
23 | items[node.heapPosition] = parentNode
24 | items[parent] = node
25 | node.heapPosition = parent
26 | parent = parent ushr 1
27 | parentNode = items[parent]
28 | }
29 | }
30 |
31 | fun poll(): PathNode {
32 | val itemToPoll = items[1]
33 | itemToPoll!!.heapPosition = -1
34 | val itemToSwap = items[size--]
35 | itemToSwap!!.heapPosition = 1
36 | items[1] = itemToSwap
37 | val itemToSwapCost = itemToSwap.totalCost
38 |
39 | if (size <= 1) return itemToPoll
40 |
41 | var parentIndex = 1
42 | var smallestChildIndex = 2
43 | while (smallestChildIndex <= size) {
44 | val rightChildIndex = smallestChildIndex + 1
45 | if (rightChildIndex < size && items[rightChildIndex]!!.totalCost < items[smallestChildIndex]!!.totalCost) {
46 | smallestChildIndex = rightChildIndex
47 | }
48 |
49 | if (items[smallestChildIndex]!!.totalCost >= itemToSwapCost) {
50 | break
51 | }
52 |
53 | val swapTemp = items[smallestChildIndex]
54 | swapTemp!!.heapPosition = parentIndex
55 | items[parentIndex] = swapTemp
56 | itemToSwap.heapPosition = smallestChildIndex
57 | items[smallestChildIndex] = itemToSwap
58 |
59 | parentIndex = smallestChildIndex
60 | smallestChildIndex = parentIndex shl 1
61 | }
62 | return itemToPoll
63 | }
64 |
65 | fun isEmpty() = size <= 0
66 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/jelly/mightyminerv2/pathfinder/calculate/path/AStarPathFinder.kt:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.pathfinder.calculate.path
2 |
3 | import com.jelly.mightyminerv2.pathfinder.calculate.Path
4 | import com.jelly.mightyminerv2.pathfinder.calculate.PathNode
5 | import com.jelly.mightyminerv2.pathfinder.calculate.openset.BinaryHeapOpenSet
6 | import com.jelly.mightyminerv2.pathfinder.goal.Goal
7 | import com.jelly.mightyminerv2.pathfinder.movement.CalculationContext
8 | import com.jelly.mightyminerv2.pathfinder.movement.MovementResult
9 | import com.jelly.mightyminerv2.pathfinder.movement.Moves
10 | import it.unimi.dsi.fastutil.longs.Long2ObjectMap
11 | import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap
12 |
13 | class AStarPathFinder(val startX: Int, val startY: Int, val startZ: Int, val goal: Goal, val ctx: CalculationContext) {
14 | private val closedSet: Long2ObjectMap = Long2ObjectOpenHashMap()
15 | private var calculating = false
16 |
17 | fun calculatePath(): Path? {
18 | calculating = true
19 | val openSet = BinaryHeapOpenSet()
20 | val startNode = PathNode(startX, startY, startZ, goal)
21 | val res = MovementResult()
22 | val moves = Moves.values()
23 | startNode.costSoFar = 0.0
24 | startNode.totalCost = startNode.costToEnd
25 | openSet.add(startNode)
26 |
27 | while (!openSet.isEmpty() && calculating) {
28 | val currentNode = openSet.poll()
29 |
30 | if (goal.isAtGoal(currentNode.x, currentNode.y, currentNode.z)) {
31 | return Path(startNode, currentNode, goal, ctx)
32 | }
33 |
34 | for (move in moves) {
35 | res.reset()
36 | move.calculate(ctx, currentNode.x, currentNode.y, currentNode.z, res)
37 | val cost = res.cost
38 | if (cost >= ctx.cost.INF_COST) continue
39 | val neighbourNode =
40 | getNode(res.x, res.y, res.z, PathNode.longHash(res.x, res.y, res.z))
41 | val neighbourCostSoFar = currentNode.costSoFar + cost
42 |
43 | if (neighbourNode.costSoFar > neighbourCostSoFar) {
44 | neighbourNode.parentNode = currentNode
45 | neighbourNode.costSoFar = neighbourCostSoFar
46 | neighbourNode.totalCost = neighbourCostSoFar + neighbourNode.costToEnd
47 |
48 | if (neighbourNode.heapPosition == -1) {
49 | openSet.add(neighbourNode)
50 | } else {
51 | openSet.relocate(neighbourNode)
52 | }
53 | }
54 | }
55 | }
56 | calculating = false
57 | return null
58 | }
59 |
60 | fun getNode(x: Int, y: Int, z: Int, hash: Long): PathNode {
61 | var n: PathNode? = closedSet.get(hash)
62 | if (n == null) {
63 | n = PathNode(x, y, z, goal)
64 | closedSet.put(hash, n)
65 | }
66 | return n
67 | }
68 |
69 | fun requestStop() {
70 | if (!calculating) return
71 | calculating = false
72 | }
73 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/jelly/mightyminerv2/pathfinder/goal/Goal.kt:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.pathfinder.goal
2 |
3 | import com.jelly.mightyminerv2.pathfinder.movement.CalculationContext
4 | import kotlin.math.abs
5 | import kotlin.math.min
6 | import kotlin.math.sqrt
7 |
8 | class Goal(val goalX: Int, val goalY: Int, val goalZ: Int, val ctx: CalculationContext) : IGoal {
9 | private val SQRT_2 = sqrt(2.0)
10 |
11 | override fun isAtGoal(x: Int, y: Int, z: Int): Boolean {
12 | return goalX == x && goalY == y && goalZ == z
13 | }
14 |
15 | override fun heuristic(x: Int, y: Int, z: Int): Double {
16 | val dx = abs(goalX - x)
17 | val dz = abs(goalZ - z)
18 | val straight = abs(dx - dz).toDouble()
19 | var vertical = abs(goalY - y).toDouble()
20 | val diagonal = min(dx, dz).toDouble()
21 |
22 | if (goalY > y) {
23 | vertical *= 6.234399666206506
24 | // vertical *= ctx.cost.JUMP_ONE_BLOCK_COST
25 | } else {
26 | vertical *= ctx.cost.N_BLOCK_FALL_COST[2] / 2.0
27 | }
28 |
29 | return (straight + diagonal * SQRT_2) * ctx.cost.ONE_BLOCK_SPRINT_COST + vertical
30 | }
31 |
32 | override fun toString(): String {
33 | return "x: $goalX, y: $goalY, z: $goalZ"
34 | }
35 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/jelly/mightyminerv2/pathfinder/goal/IGoal.kt:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.pathfinder.goal
2 |
3 | interface IGoal {
4 | fun isAtGoal(x: Int, y: Int, z: Int): Boolean
5 | fun heuristic(x: Int, y: Int, z: Int): Double
6 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/jelly/mightyminerv2/pathfinder/helper/BlockStateAccessor.kt:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.pathfinder.helper
2 |
3 | import com.jelly.mightyminerv2.util.IChunkProviderClient
4 | import it.unimi.dsi.fastutil.longs.Long2ObjectMap
5 | import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap
6 | import net.minecraft.block.state.IBlockState
7 | import net.minecraft.init.Blocks
8 | import net.minecraft.util.BlockPos
9 | import net.minecraft.world.IBlockAccess
10 | import net.minecraft.world.World
11 | import net.minecraft.world.chunk.Chunk
12 |
13 | class BlockStateAccessor(private val world: World) {
14 | private val loadedChunks: Long2ObjectMap = Long2ObjectOpenHashMap()
15 | private var cached: Chunk? = null
16 | var access: IBlockAccess
17 | val isPassableBlockPos: BlockPos.MutableBlockPos
18 |
19 | init {
20 | val loadedWorld: List = (this.world.chunkProvider as IChunkProviderClient).chunkListing()
21 |
22 | for (chunk in loadedWorld) {
23 | this.loadedChunks[this.getKey(chunk.xPosition, chunk.zPosition)] = chunk
24 | }
25 |
26 | isPassableBlockPos = BlockPos.MutableBlockPos()
27 | access = BlockStateInterfaceAccessWrapper(this, world)
28 | }
29 |
30 | fun get(x: Int, y: Int, z: Int): IBlockState {
31 | var current = this.cached
32 | if (current != null && current.xPosition == x shr 4 && current.zPosition == z shr 4) {
33 | return current.getBlockState(BlockPos(x, y, z))
34 | }
35 |
36 | current = this.loadedChunks[this.getKey(x shr 4, z shr 4)]
37 |
38 | if (current != null && current.isLoaded) {
39 | this.cached = current
40 | return current.getBlockState(BlockPos(x, y, z))
41 | }
42 | return Blocks.air.defaultState
43 | }
44 |
45 | fun isBlockInLoadedChunks(blockX: Int, blockZ: Int): Boolean {
46 | return this.loadedChunks.containsKey(getKey(blockX shr 4, blockZ shr 4))
47 | }
48 |
49 | private fun getKey(x: Int, z: Int): Long {
50 | return (x.toLong() and 4294967295L) or ((z.toLong() and 4294967295L) shl 32)
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/jelly/mightyminerv2/pathfinder/helper/BlockStateInterfaceAccessWrapper.kt:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.pathfinder.helper
2 |
3 | import net.minecraft.block.state.IBlockState
4 | import net.minecraft.init.Blocks
5 | import net.minecraft.tileentity.TileEntity
6 | import net.minecraft.util.BlockPos
7 | import net.minecraft.util.EnumFacing
8 | import net.minecraft.world.IBlockAccess
9 | import net.minecraft.world.WorldType
10 | import net.minecraft.world.biome.BiomeGenBase
11 |
12 | class BlockStateInterfaceAccessWrapper(private val bsi: BlockStateAccessor, private val world: IBlockAccess) :
13 | IBlockAccess {
14 |
15 | override fun getTileEntity(pos: BlockPos): TileEntity? {
16 | return null
17 | }
18 |
19 | override fun getCombinedLight(pos: BlockPos, lightValue: Int): Int {
20 | return 0
21 | }
22 |
23 | override fun getBlockState(pos: BlockPos): IBlockState {
24 | // BlockStateInterface#get0(BlockPos) btfo!
25 | return bsi.get(pos.x, pos.y, pos.z)
26 | }
27 |
28 | override fun isAirBlock(pos: BlockPos): Boolean {
29 | return bsi.get(pos.x, pos.y, pos.z).block == Blocks.air
30 | }
31 |
32 | override fun getBiomeGenForCoords(pos: BlockPos): BiomeGenBase? {
33 | return null
34 | }
35 |
36 | override fun extendedLevelsInChunkCache(): Boolean {
37 | return false
38 | }
39 |
40 | // Uncomment and implement if needed
41 | // override fun getBiome(pos: BlockPos): Biome {
42 | // return Biomes.FOREST
43 | // }
44 |
45 | override fun getStrongPower(pos: BlockPos, direction: EnumFacing): Int {
46 | return 0
47 | }
48 |
49 | override fun getWorldType(): WorldType {
50 | return world.worldType
51 | }
52 |
53 | override fun isSideSolid(pos: BlockPos, side: EnumFacing, _default: Boolean): Boolean {
54 | return false
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/jelly/mightyminerv2/pathfinder/helper/player/IPlayerContext.kt:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.pathfinder.helper.player
2 |
3 | import net.minecraft.client.Minecraft
4 | import net.minecraft.client.entity.EntityPlayerSP
5 | import net.minecraft.client.multiplayer.PlayerControllerMP
6 | import net.minecraft.util.BlockPos
7 | import net.minecraft.world.World
8 |
9 | interface IPlayerContext {
10 | val mc: Minecraft
11 | val player: EntityPlayerSP
12 | val playerController: PlayerControllerMP
13 | val world: World
14 | val playerPosition: BlockPos
15 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/jelly/mightyminerv2/pathfinder/helper/player/PlayerContext.kt:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.pathfinder.helper.player
2 |
3 | import net.minecraft.client.Minecraft
4 | import net.minecraft.util.BlockPos
5 | import kotlin.math.ceil
6 |
7 | class PlayerContext(override val mc: Minecraft) : IPlayerContext {
8 | override val player get() = mc.thePlayer
9 | override val playerController get() = mc.playerController
10 | override val world get() = mc.theWorld
11 |
12 | // Block player is standing on
13 | // Todo: Change name
14 | override val playerPosition get() = BlockPos(player.posX, ceil(player.posY) - 1, player.posZ)
15 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/jelly/mightyminerv2/pathfinder/movement/CalculationContext.kt:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.pathfinder.movement
2 |
3 | import com.jelly.mightyminerv2.pathfinder.costs.ActionCosts
4 | import com.jelly.mightyminerv2.pathfinder.helper.BlockStateAccessor
5 | import com.jelly.mightyminerv2.pathfinder.helper.player.PlayerContext
6 | import net.minecraft.block.state.IBlockState
7 | import net.minecraft.client.Minecraft
8 | import net.minecraft.potion.Potion
9 |
10 | class CalculationContext(sprintFactor: Double = 0.13, walkFactor: Double = 0.1, sneakFactor: Double = 0.03) {
11 | val playerContext = PlayerContext(Minecraft.getMinecraft())
12 | val world = playerContext.world
13 | val player = playerContext.player
14 | val bsa = BlockStateAccessor(world)
15 | val jumpBoostAmplifier = player.getActivePotionEffect(Potion.jump)?.amplifier ?: -1
16 | val cost = ActionCosts(sprintFactor, walkFactor, sneakFactor, jumpBoostAmplifier)
17 | val maxFallHeight = 20
18 |
19 | fun get(x: Int, y: Int, z: Int): IBlockState {
20 | return bsa.get(x, y, z)
21 | }
22 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/jelly/mightyminerv2/pathfinder/movement/IMovement.kt:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.pathfinder.movement
2 |
3 | import com.jelly.mightyminerv2.MightyMiner
4 | import net.minecraft.util.BlockPos
5 |
6 | interface IMovement {
7 | val mm: MightyMiner
8 | val source: BlockPos
9 | val dest: BlockPos
10 | val costs: Double // plural cuz kotlin gae
11 |
12 | fun getCost(): Double
13 | fun calculateCost(ctx: CalculationContext, res: MovementResult)
14 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/jelly/mightyminerv2/pathfinder/movement/Movement.kt:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.pathfinder.movement
2 |
3 | import com.jelly.mightyminerv2.MightyMiner
4 | import net.minecraft.util.BlockPos
5 |
6 | abstract class Movement(override val mm: MightyMiner, override val source: BlockPos, override val dest: BlockPos) :
7 | IMovement {
8 |
9 | override var costs: Double = 1e6
10 | override fun getCost() = costs
11 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/jelly/mightyminerv2/pathfinder/movement/MovementResult.kt:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.pathfinder.movement
2 |
3 | import net.minecraft.util.BlockPos
4 |
5 | class MovementResult {
6 | var x: Int = 0
7 | var y: Int = 0
8 | var z: Int = 0
9 | var cost: Double = 1e6
10 |
11 | fun set(x: Int, y: Int, z: Int) {
12 | this.x = x
13 | this.y = y
14 | this.z = z
15 | }
16 |
17 | fun reset() {
18 | x = 0
19 | y = 0
20 | z = 0
21 | cost = 1e6
22 | }
23 |
24 | fun getDest(): BlockPos {
25 | return BlockPos(x, y, z)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/jelly/mightyminerv2/pathfinder/movement/movements/MovementAscend.kt:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.pathfinder.movement.movements
2 |
3 | import com.jelly.mightyminerv2.MightyMiner
4 | import com.jelly.mightyminerv2.pathfinder.movement.CalculationContext
5 | import com.jelly.mightyminerv2.pathfinder.movement.Movement
6 | import com.jelly.mightyminerv2.pathfinder.movement.MovementHelper
7 | import com.jelly.mightyminerv2.pathfinder.movement.MovementResult
8 | import net.minecraft.util.BlockPos
9 |
10 | class MovementAscend(mm: MightyMiner, from: BlockPos, to: BlockPos) : Movement(mm, from, to) {
11 | override fun calculateCost(ctx: CalculationContext, res: MovementResult) {
12 | calculateCost(ctx, source.x, source.y, source.z, dest.x, dest.z, res)
13 | costs = res.cost
14 | }
15 |
16 | companion object {
17 | fun calculateCost(
18 | ctx: CalculationContext,
19 | x: Int,
20 | y: Int,
21 | z: Int,
22 | destX: Int,
23 | destZ: Int,
24 | res: MovementResult
25 | ) {
26 | res.set(destX, y + 1, destZ)
27 | cost(ctx, x, y, z, destX, destZ, res)
28 | }
29 |
30 | private fun cost(
31 | ctx: CalculationContext,
32 | x: Int,
33 | y: Int,
34 | z: Int,
35 | destX: Int,
36 | destZ: Int,
37 | res: MovementResult
38 | ) {
39 | val destState = ctx.get(destX, y + 1, destZ)
40 | if (!MovementHelper.canStandOn(ctx.bsa, destX, y + 1, destZ, destState)) return
41 | if (!MovementHelper.canWalkThrough(ctx.bsa, destX, y + 3, destZ)) return
42 | if (!MovementHelper.canWalkThrough(ctx.bsa, destX, y + 2, destZ)) return
43 | if (!MovementHelper.canWalkThrough(ctx.bsa, x, y + 3, z)) return
44 |
45 | val sourceState = ctx.get(x, y, z)
46 | if (MovementHelper.isLadder(sourceState)) return
47 | if (MovementHelper.isLadder(destState) && !MovementHelper.canWalkIntoLadder(
48 | destState,
49 | destX - x,
50 | destZ - z
51 | )
52 | ) return
53 |
54 | // small = half block / stair - in this case it doesnt matter which way the source stair(if it is a stair) is facing
55 | // big = fill block
56 | // this logic is actually fucking sick ngl
57 |
58 | val sourceHeight =
59 | sourceState.block.getCollisionBoundingBox(ctx.world, BlockPos(x, y, z), sourceState)?.maxY ?: return
60 | val destHeight =
61 | destState.block.getCollisionBoundingBox(ctx.world, BlockPos(destX, y + 1, destZ), destState)?.maxY
62 | ?: return
63 | // if (!snow) {
64 | // val srcSmall = MovementHelper.isBottomSlab(sourceState);
65 | // val destSmall = MovementHelper.isBottomSlab(destState);
66 | //
67 | // val destSmallStair = MovementHelper.isValidStair(destState, destX - x, destZ - z);
68 | //
69 | // if (!srcSmall == !(destSmall || destSmallStair)) {
70 | // res.cost = ctx.cost.JUMP_ONE_BLOCK_COST
71 | // } else if (!srcSmall) {
72 | // res.cost = ctx.cost.ONE_BLOCK_SPRINT_COST;
73 | // }
74 | // } else {
75 | val diff = destHeight - sourceHeight
76 | // println("SourceHeight: $sourceHeight, DestHeight: $destHeight, Diff: $diff")
77 | res.cost = when {
78 | diff <= 0.5 -> ctx.cost.ONE_BLOCK_SPRINT_COST
79 | diff <= 1.125 -> ctx.cost.JUMP_ONE_BLOCK_COST
80 | else -> ctx.cost.INF_COST
81 | }
82 | }
83 | // }
84 | }
85 | }
--------------------------------------------------------------------------------
/src/main/kotlin/com/jelly/mightyminerv2/pathfinder/movement/movements/MovementFall.kt:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.pathfinder.movement.movements
2 |
3 | import com.jelly.mightyminerv2.MightyMiner
4 | import com.jelly.mightyminerv2.pathfinder.movement.CalculationContext
5 | import com.jelly.mightyminerv2.pathfinder.movement.Movement
6 | import com.jelly.mightyminerv2.pathfinder.movement.MovementResult
7 | import net.minecraft.util.BlockPos
8 |
9 | class MovementFall(mm: MightyMiner, source: BlockPos, dest: BlockPos) : Movement(mm, source, dest) {
10 | override fun calculateCost(ctx: CalculationContext, res: MovementResult) {
11 | calculateCost(ctx, source.x, source.y, source.z, dest.x, dest.z, res)
12 | costs = res.cost
13 | }
14 |
15 | companion object {
16 | fun calculateCost(
17 | ctx: CalculationContext,
18 | x: Int,
19 | y: Int,
20 | z: Int,
21 | destX: Int,
22 | destZ: Int,
23 | res: MovementResult
24 | ) {
25 | res.set(destX, y - 1, destZ)
26 | MovementDescend.calculateCost(ctx, x, y, z, destX, destZ, res)
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/jelly/mightyminerv2/pathfinder/util/Extension.kt:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.pathfinder.util
2 |
3 | import net.minecraft.client.settings.KeyBinding
4 | import net.minecraft.entity.EntityLivingBase
5 | import net.minecraft.util.BlockPos
6 | import net.minecraft.util.Vec3
7 | import kotlin.math.ceil
8 | import kotlin.math.floor
9 |
10 | fun EntityLivingBase.getStandingOnCeil() = BlockPos(posX, ceil(posY) - 1, posZ)
11 | fun EntityLivingBase.getStandingOnFloor() = BlockPos(posX, floor(posY) - 1, posZ)
12 | fun KeyBinding.setPressed(pressed: Boolean) = KeyBinding.setKeyBindState(keyCode, pressed)
13 | fun BlockPos.toVec3() = Vec3(x.toDouble() + 0.5, y.toDouble() + 0.5, z.toDouble() + 0.5)
14 | fun BlockPos.toVec3Top(): Vec3 = toVec3().addVector(0.0, 0.5, 0.0)
15 | fun Vec3.toBlockPos(): BlockPos = BlockPos(xCoord, yCoord, zCoord)
16 |
17 | fun EntityLivingBase.lastTickPositionCeil() = BlockPos(lastTickPosX, ceil(lastTickPosY) - 1, lastTickPosZ)
--------------------------------------------------------------------------------
/src/main/kotlin/com/jelly/mightyminerv2/pathfinder/util/Ref.kt:
--------------------------------------------------------------------------------
1 | package com.jelly.mightyminerv2.pathfinder.util
2 |
3 | import net.minecraft.client.Minecraft
4 | import net.minecraft.client.renderer.Tessellator
5 |
6 | val mc
7 | get() = Minecraft.getMinecraft()
8 | val player
9 | get() = mc.thePlayer
10 | val world
11 | get() = mc.theWorld
12 | val tessellator
13 | get() = Tessellator.getInstance()
14 | val gameSettings
15 | get() = mc.gameSettings
--------------------------------------------------------------------------------
/src/main/resources/mcmod.info:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "modid": "mightyminerv2",
4 | "name": "MightyMiner V2",
5 | "description": "Best miner ever!!",
6 | "version": "${version}",
7 | "mcversion": "1.8.9",
8 | "url": "",
9 | "updateUrl": "",
10 | "authorList": [
11 | "Me"
12 | ],
13 | "credits": "",
14 | "logoFile": "",
15 | "screenshots": [],
16 | "dependencies": []
17 | }
18 | ]
--------------------------------------------------------------------------------
/src/main/resources/mightyminer/sounds/AAAAAAAAAA.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JellyLabScripts/MightyMiner/62aec611784d81973a9ce9fcba02d659b776d0b8/src/main/resources/mightyminer/sounds/AAAAAAAAAA.wav
--------------------------------------------------------------------------------
/src/main/resources/mightyminer/sounds/loud_buzz.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JellyLabScripts/MightyMiner/62aec611784d81973a9ce9fcba02d659b776d0b8/src/main/resources/mightyminer/sounds/loud_buzz.wav
--------------------------------------------------------------------------------
/src/main/resources/mightyminer/sounds/metal_pipe.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JellyLabScripts/MightyMiner/62aec611784d81973a9ce9fcba02d659b776d0b8/src/main/resources/mightyminer/sounds/metal_pipe.wav
--------------------------------------------------------------------------------
/src/main/resources/mightyminer/sounds/staff_check_voice_notification.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JellyLabScripts/MightyMiner/62aec611784d81973a9ce9fcba02d659b776d0b8/src/main/resources/mightyminer/sounds/staff_check_voice_notification.wav
--------------------------------------------------------------------------------
/src/main/resources/mixins.mightyminerv2.json:
--------------------------------------------------------------------------------
1 | {
2 | "package": "com.jelly.mightyminerv2.mixin",
3 | "refmap": "mixins.mightyminerv2.refmap.json",
4 | "minVersion": "0.7",
5 | "compatibilityLevel": "JAVA_8",
6 | "mixins": [
7 | "client.MixinBlockStainedGlassPane",
8 | "client.MixinChunk",
9 | "client.MixinEntityLivingBase",
10 | "client.MixinMinecraft",
11 | "client.MixinScoreboard",
12 | "client.MixinSoundManager",
13 | "fml.MixinFMLHandshakeMessage",
14 | "gui.MixinGuiContainer",
15 | "gui.MixinInventoryPlayer",
16 | "network.MixinNetworkManager"
17 | ],
18 | "client": [
19 | "client.EntityPlayerSPAccessor",
20 | "client.MinecraftAccessor",
21 | "client.MixinChunkProviderClient",
22 | "client.MixinEntityPlayerSP",
23 | "network.MixinNetHandlerPlayClient",
24 | "render.MixinModelBiped"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------