├── .gitignore
├── LICENSE.md
├── README.md
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── move.bat
├── settings.gradle
└── src
└── main
├── java
└── com
│ └── jorianwoltjer
│ └── liveoverflowmod
│ ├── LiveOverflowMod.java
│ ├── client
│ ├── ClientEntrypoint.java
│ └── Gui.java
│ ├── command
│ ├── ClipCommand.java
│ └── GetCodeCommand.java
│ ├── hacks
│ ├── ClipReach.java
│ ├── FastMiner.java
│ ├── PanicMode.java
│ ├── PassiveMods.java
│ ├── Reach.java
│ ├── ToggledHack.java
│ └── WorldGuardBypass.java
│ ├── helper
│ └── Utils.java
│ └── mixin
│ ├── AbstractBlockMixin.java
│ ├── ClientConnectionInvoker.java
│ ├── ClientConnectionMixin.java
│ ├── ClientPlayNetworkHandlerMixin.java
│ ├── ClientPlayerInteractionManagerMixin.java
│ ├── GameStateChangeS2CPacketAccessor.java
│ ├── InGameHudAccessor.java
│ ├── InGameHudMixin.java
│ ├── LivingEntityMixin.java
│ ├── MinecraftClientMixin.java
│ ├── PlayerPositionFullPacketMixin.java
│ ├── PlayerPositionPacketMixin.java
│ ├── SessionMixin.java
│ └── VehicleMovePacketMixin.java
└── resources
├── assets
└── liveoverflowmod
│ ├── icon.png
│ └── lang
│ └── en_us.json
├── fabric.mod.json
└── liveoverflowmod.mixins.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # User-specific stuff
2 | .idea/
3 |
4 | *.iml
5 | *.ipr
6 | *.iws
7 |
8 | # IntelliJ
9 | out/
10 | # mpeltonen/sbt-idea plugin
11 | .idea_modules/
12 |
13 | # JIRA plugin
14 | atlassian-ide-plugin.xml
15 |
16 | # Compiled class file
17 | *.class
18 |
19 | # Log file
20 | *.log
21 |
22 | # BlueJ files
23 | *.ctxt
24 |
25 | # Package Files #
26 | *.jar
27 | *.war
28 | *.nar
29 | *.ear
30 | *.zip
31 | *.tar.gz
32 | *.rar
33 |
34 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
35 | hs_err_pid*
36 |
37 | *~
38 |
39 | # temporary files which can be created if a process still has a handle open of a deleted file
40 | .fuse_hidden*
41 |
42 | # KDE directory preferences
43 | .directory
44 |
45 | # Linux trash folder which might appear on any partition or disk
46 | .Trash-*
47 |
48 | # .nfs files are created when an open file is removed but is still being accessed
49 | .nfs*
50 |
51 | # General
52 | .DS_Store
53 | .AppleDouble
54 | .LSOverride
55 |
56 | # Icon must end with two \r
57 | Icon
58 |
59 | # Thumbnails
60 | ._*
61 |
62 | # Files that might appear in the root of a volume
63 | .DocumentRevisions-V100
64 | .fseventsd
65 | .Spotlight-V100
66 | .TemporaryItems
67 | .Trashes
68 | .VolumeIcon.icns
69 | .com.apple.timemachine.donotpresent
70 |
71 | # Directories potentially created on remote AFP share
72 | .AppleDB
73 | .AppleDesktop
74 | Network Trash Folder
75 | Temporary Items
76 | .apdisk
77 |
78 | # Windows thumbnail cache files
79 | Thumbs.db
80 | Thumbs.db:encryptable
81 | ehthumbs.db
82 | ehthumbs_vista.db
83 |
84 | # Dump file
85 | *.stackdump
86 |
87 | # Folder config file
88 | [Dd]esktop.ini
89 |
90 | # Recycle Bin used on file shares
91 | $RECYCLE.BIN/
92 |
93 | # Windows Installer files
94 | *.cab
95 | *.msi
96 | *.msix
97 | *.msm
98 | *.msp
99 |
100 | # Windows shortcuts
101 | *.lnk
102 |
103 | .gradle
104 | build/
105 |
106 | # Ignore Gradle GUI config
107 | gradle-app.setting
108 |
109 | # Cache of project
110 | .gradletasknamecache
111 |
112 | **/build/
113 |
114 | # Common working directory
115 | run/
116 |
117 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
118 | !gradle-wrapper.jar
119 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 JorianWoltjer
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # LiveOverflowMod
2 |
3 | A Minecraft hacked-client for the LiveOverflow Server. Contains various hacks for the challenges on the server,
4 | and some utilities.
5 |
6 | **Read all about it in my [blog post](https://jorianwoltjer.com/blog/post/hacking/playing-on-the-liveoverflow-minecraft-hacking-server)**, and now also [**Part 2**](https://jorianwoltjer.com/blog/post/hacking/part-2-the-new-liveoverflow-minecraft-hacking-server)!
7 |
8 | ## Hacks
9 |
10 | 
11 |
12 | ### WorldGuard Bypass ;
13 |
14 | WorldGuard was used to deny "entry" to a protected area, in which the player had to die in the lava to complete the challenge.
15 | WorldGuard works using `PlayerMoveEvent`s and this bypass works by moving without triggering this event.
16 |
17 | Only when movement is large enough, an event is sent. So we can move a small amount, and then save the position by "moving too quickly!".
18 | This means it can only move `0.06` blocks per tick, and then has to send a position packet far away to trigger the warning and reset your position
19 | for the next repeat. However, this can be improved because WorldGuard only checks regions when you cross a block boundary.
20 | So when we can move almost a full block while not crossing the boundary, and then only move a small amount to cross the boundary.
21 |
22 | When this hack is activated using the default ; (semicolon) keybind, it will allow you to move in this way with your `WASD` keys.
23 |
24 | [**YouTube Video - Showcase**](https://www.youtube.com/watch?v=hYA1cTUOXgA)
25 |
26 | * [WorldGuardBypass.java](src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/WorldGuardBypass.java):
27 | When activated, it performs the bypass explained above until it is deactivated again
28 | * [LivingEntityMixin.java](src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/LivingEntityMixin.java):
29 | Redirect the `isImmobile()` method to return true when the hack is enabled, so the normal player movement is disabled
30 |
31 | ### Reach ]
32 |
33 | While reading the movement code, I found that it is possible to send a position packet a maximum of 10 blocks away from the current position.
34 | But also that you can send 5 packets per tick, so you can move 50 blocks in a single tick. This gave me the idea of making
35 | a reach hack that uses this by sending multiple position packets going towards a player, hit them, and then move back.
36 | That is exactly what this hack does when you toggle the default ] (right bracket) keybind, and then click on a far away entity as
37 | if you were hitting them.
38 |
39 | > **Warning**:
40 | > This hack is not perfect. It only works when there is a clear line of sight to the player, and sometimes gets
41 | > stuck while moving meaning you end up somewhere along traveled path. But it's good enough for a proof of concept!
42 | > See [Clip Reach](#clip-reach-) for a better version of this hack that teleports through blocks.
43 |
44 | [**YouTube Video - Showcase**](https://www.youtube.com/watch?v=Hio_iDnnJ5c)
45 |
46 | * [Reach.java](src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/Reach.java):
47 | When enabled, you will teleport to every entity you click from a distance, and then teleported back to your original position
48 | * [ClientPlayerInteractionManagerMixin.java](src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerMixin.java):
49 | Detect clicking on entities and forward it to the teleport function
50 | * [MinecraftClientMixin.java](src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java):
51 | When enabled, the client will think it can hit entities from far away to make the Minecraft UI work correctly and detect hit attempts
52 |
53 | ### Clip Reach [
54 |
55 | There is a trick to clip huge distances by sending many movement packets in a single tick, and then doing one big jump.
56 | This is implemented into the Clip Reach hack which when enabled using the default [ (left bracket) keybind, will
57 | use this to teleport upwards, then above the target, and finally down to the target. Afterward it goes back up, to your
58 | original position, and back down. This all happens without seeing any teleports on screen, for a clean Reach feeling.
59 |
60 | > **Warning**:
61 | > Due to the required number of packets needed to be sent in a single tick, it may fail sometimes and get you stuck somewhere
62 | > in the middle, often in the air. Because of this it is recommended to use a NoFall hack when trying to use this hack so you
63 | > don't die :)
64 |
65 | [**YouTube Video - Showcase**](https://www.youtube.com/watch?v=_eBEtPoCuj0)
66 |
67 | * [ClipReach.java](src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ClipReach.java):
68 | When enabled, you will teleport to every entity you click from a distance, through walls, and then teleported back to your original position
69 | * [ClientPlayerInteractionManagerMixin.java](src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerMixin.java):
70 | Detect clicking on entities and forward it to the teleport function
71 | * [MinecraftClientMixin.java](src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java):
72 | When enabled, the client will think it can hit entities from far away to make the Minecraft UI work correctly and detect hit attempts
73 |
74 | ### Panic Mode ,
75 |
76 | When you want to AFK, you can enable this mode with the , (comma) keybind to make sure nothing happens to you. It detects players entering your render
77 | distance, and receiving any form of damage. When it detects any of these, it sends 5 packets per tick each moving you up 10 blocks.
78 | It does so 1 full second meaning you end up traveling precisely 1000 blocks straight up. Afterward it instantly disconnects you from the server.
79 |
80 | * [PanicMode.java](src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PanicMode.java)
81 | Handles detecting players entering your render distance, and the teleportation with disconnecting itself
82 | * [ClientPlayNetworkHandlerMixin.java](src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayNetworkHandlerMixin.java#L50-L55):
83 | When you take any damage, also trigger
84 |
85 | ### Passive Mods -
86 |
87 | Passive Mods are enabled by default, and are expected to always be used. They are utility mods that don't really have a downside.
88 |
89 | You can toggle all passive mods at once using the default - (minus) keybind.
90 |
91 | * [PassiveMods.java](src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PassiveMods.java)
92 |
93 | #### Anti-Human Bypass
94 |
95 | All movement packets need to be rounded to the 100ths. This is done using a simple `Math.round()` function,
96 | and to fix floating point errors the `Math.nextAfter()` function is used.
97 |
98 | * [Utils.java](src/main/java/com/jorianwoltjer/liveoverflowmod/helper/Utils.java):
99 | Does the rounding calculations
100 | * [PlayerPositionFullPacketMixin.java](src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/PlayerPositionFullPacketMixin.java):
101 | Intercept the `PlayerMoveC2SPacket.Full` and round the position when sending it to the server
102 | * [PlayerPositionPacketMixin.java](src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/PlayerPositionPacketMixin.java):
103 | Same as above, but for the `PlayerMoveC2SPacket.PositionAndOnGround` packet
104 | * [VehicleMovePacketMixin.java](src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/VehicleMovePacketMixin.java):
105 | Same as above, but for riding a vehicle like a boat
106 |
107 | #### Disable Weird Packets
108 |
109 | There are a few packets that the server tries to send to you that are actually fake, namely World Border, Creative Mode, Demo Mode and End Credits.
110 | These packets are not actually enforced by the server, only to mess with your client. This mod ignores them.
111 |
112 | > **Warning**:
113 | > The mod does not differentiate between the server sending a fake gamemode change, or you actually changing gamemode. Therefore,
114 | > if you want to change gamemode, you need to disable this mod first.
115 |
116 | * [ClientPlayNetworkHandlerMixin.java](src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayNetworkHandlerMixin.java):
117 | Ignore or change packets as they come in
118 |
119 | #### Insta-Mine
120 |
121 | This hack is a simple one useful in some situations. When you try to break a block, it will send `START_DESTROY_BLOCK` action to the server.
122 | When you as the client are done breaking the block, it will send `STOP_DESTROY_BLOCK` to the server, and it will verify
123 | if you have been breaking the block for long enough. It turns out that the server only checks if you have broken the block
124 | 70% of the way, so you can send `STOP_DESTROY_BLOCK` a bit faster than normal. (see `ServerPlayerGameMode.java` in the Paper-Server source code)
125 |
126 | ```Java
127 | public void handleBlockBreakAction(BlockPos pos, ServerboundPlayerActionPacket.Action action, Direction direction, int worldHeight, int sequence) {
128 | ...
129 | float f1 = iblockdata.getDestroyProgress(this.player, this.player.level,pos) * (float) (l+1);
130 |
131 | if(f1 >= 0.7F) { // <--- This check is abused
132 | this.isDestroyingBlock = false;
133 | this.level.destroyBlockProgress(this.player.getId(), pos, -1);
134 | this.destroyAndAck(pos, sequence, "destroyed"); // Count as destroyed
135 | return;
136 | }
137 | ...
138 | }
139 | ```
140 |
141 | This allows you to insta-mine some blocks, that were previously really close to being insta-minable. You can for example insta-mine
142 | stone and cobblestone with an Efficiency 5 Netherite Pickaxe using this hack.
143 |
144 | * [ClientPlayerInteractionMixin.java](src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionMixin.java):
145 | Send the `STOP_DESTROY_BLOCK` action packet right after starting to break a block if it is close enough to be insta-mined
146 |
147 | #### Random Texture Rotations
148 |
149 | This hack changed the random texture rotation code to use a completely random number every time, so it is not reversible from a screenshot.
150 | This was to be able to take screenshots and videos, while not revealing the texture rotations that can be brute-forced easily for coordinates.
151 | The same type of mod was used by LiveOverflow himself to make the challenge of finding his base harder.
152 |
153 | * [AbstractBlockMixin.java](src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/AbstractBlockMixin.java):
154 | Use a randomized hash function to generate block rotations, making it unpredictable
155 |
156 | ### Commands
157 |
158 | #### Clipping
159 |
160 | A lot can be done with the ability to clip through walls. There are a few commands that do useful things like flipping
161 | vertically and horizontally. There are 4 common-use commands, and 2 specific ones for challenges:
162 |
163 | * `/vclip`: Vertical clip, through ceilings and floors, up to around 180 blocks (always straight up)
164 | * `/hclip`: Horizontal clip, through walls by teleporting up, forward and then down. Up to around 150 blocks (always flat)
165 | * `/dclip`: Directional clip, into the exact direction you are looking. Up to around 150 blocks
166 | * `/autoclip [up|down]`: Automatically clip through the nearest floor or ceiling, placing you at the first open air gap the player fits
167 |
168 | * `/vault`: Complete the Vault challenge by clipping through the 50 blocks of bedrock. Start from the button and it will
169 | automatically start the challenge, teleport and finish the challenge giving you a mask
170 | * `/clubmate`: This trick also works on the original Club Mate challenge, it will simply teleport to the chest and open it in one tick
171 |
172 | * [ClipCommand.java](src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java):
173 | Includes all the logic for clipping through walls, as well as the registered commands
174 |
175 | #### Bedrock Cracking
176 |
177 | I made a few commands to aid in cracking the bedrock formation in order to find LiveOverflow's base:
178 | *
179 | * `/bedrock`: Simply tell if a certain coordinate should be bedrock or not (in The Nether). It calculates this itself,
180 | not by looking at the block data in chunks. This command was useful because you can set a breakpoint in the code to see exactly
181 | what the algorithm is doing, while comparing it to your own code.
182 | * `/getcode [from] [to]`: Select an area from two coordinates, and get the Rust code of the offsets from
183 | a recreation of bedrock copied to your clipboard. Simply recreate some formation with *bedrock* and *glass*, and run the command
184 | over the area to get the code. It is meant to be used with my [BedrockFinder](https://github.com/JorianWoltjer/BedrockFinder) tool,
185 | which will then find the coordinates of that bedrock formation in a specific seed.
186 |
187 | * [GetCodeCommand.java](src/main/java/com/jorianwoltjer/liveoverflowmod/command/GetCodeCommand.java):
188 | `/getcode` command and `/bedrock` command implementations
189 |
190 | ## Development
191 |
192 | ### Building to JAR (IntelliJ)
193 |
194 | 1. Select `liveoverflowmod build` task and click green arrow in
195 | 2. JAR in [build/libs](build/libs)
196 |
197 | ### Building and running Minecraft (IntelliJ)
198 |
199 | 1. Select `Minecraft Client` task and click green arrow
200 | 2. Minecraft will start, with logs in IntelliJ
201 |
202 | > **Note**:
203 | > Use the [ViaFabric](https://www.curseforge.com/minecraft/mc-mods/viafabric) mod to connect to any lower version server
204 |
205 | ## Resources
206 |
207 | * An example of a simple fabric mod with a Mixin: https://github.com/FabricMC/fabric-example-mod
208 | * Getting the Paper-Server source code: https://github.com/PaperMC/Paper/blob/master/CONTRIBUTING.md
209 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'fabric-loom' version '1.0-SNAPSHOT'
3 | id 'maven-publish'
4 | }
5 |
6 | version = project.mod_version
7 | group = project.maven_group
8 |
9 | repositories {
10 | // Add repositories to retrieve artifacts from in here.
11 | // You should only use this when depending on other mods because
12 | // Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
13 | // See https://docs.gradle.org/current/userguide/declaring_repositories.html
14 | // for more information about repositories.
15 | }
16 |
17 | dependencies {
18 | // To change the versions see the gradle.properties file
19 | minecraft "com.mojang:minecraft:${project.minecraft_version}"
20 | mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
21 | modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
22 |
23 | // Fabric API. This is technically optional, but you probably want it anyway.
24 | modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
25 | }
26 |
27 | processResources {
28 | inputs.property "version", project.version
29 | filteringCharset "UTF-8"
30 |
31 | filesMatching("fabric.mod.json") {
32 | expand "version": project.version
33 | }
34 | }
35 |
36 | def targetJavaVersion = 17
37 | tasks.withType(JavaCompile).configureEach {
38 | // ensure that the encoding is set to UTF-8, no matter what the system default is
39 | // this fixes some edge cases with special characters not displaying correctly
40 | // see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
41 | // If Javadoc is generated, this must be specified in that task too.
42 | it.options.encoding = "UTF-8"
43 | if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) {
44 | it.options.release = targetJavaVersion
45 | }
46 | }
47 |
48 | java {
49 | def javaVersion = JavaVersion.toVersion(targetJavaVersion)
50 | if (JavaVersion.current() < javaVersion) {
51 | toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion)
52 | }
53 | archivesBaseName = project.archives_base_name
54 | // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
55 | // if it is present.
56 | // If you remove this line, sources will not be generated.
57 | withSourcesJar()
58 | }
59 |
60 | jar {
61 | from("LICENSE") {
62 | rename { "${it}_${project.archivesBaseName}" }
63 | }
64 | }
65 |
66 | // configure the maven publication
67 | publishing {
68 | publications {
69 | mavenJava(MavenPublication) {
70 | from components.java
71 | }
72 | }
73 |
74 | // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
75 | repositories {
76 | // Add repositories to publish to here.
77 | // Notice: This block does NOT have the same function as the block in the top level.
78 | // The repositories here will be used for publishing your artifact, not for
79 | // retrieving dependencies.
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Done to increase the memory available to gradle.
2 | org.gradle.jvmargs=-Xmx1G
3 | # Fabric Properties
4 | # check these on https://modmuss50.me/fabric.html
5 | minecraft_version=1.19.4
6 | yarn_mappings=1.19.4+build.1
7 | loader_version=0.14.17
8 | # Mod Properties
9 | mod_version=1.0
10 | maven_group=com.jorianwoltjer
11 | archives_base_name=liveoverflowmod
12 | # Dependencies
13 | # check this on https://modmuss50.me/fabric.html
14 | fabric_version=0.75.3+1.19.4
15 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JorianWoltjer/LiveOverflowMod/4743836cb37689fd0e3d46c7f8552bcdc5823cea/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | #
21 | # Gradle start up script for POSIX generated by Gradle.
22 | #
23 | # Important for running:
24 | #
25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
26 | # noncompliant, but you have some other compliant shell such as ksh or
27 | # bash, then to run this script, type that shell name before the whole
28 | # command line, like:
29 | #
30 | # ksh Gradle
31 | #
32 | # Busybox and similar reduced shells will NOT work, because this script
33 | # requires all of these POSIX shell features:
34 | # * functions;
35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
37 | # * compound commands having a testable exit status, especially «case»;
38 | # * various built-in commands including «command», «set», and «ulimit».
39 | #
40 | # Important for patching:
41 | #
42 | # (2) This script targets any POSIX shell, so it avoids extensions provided
43 | # by Bash, Ksh, etc; in particular arrays are avoided.
44 | #
45 | # The "traditional" practice of packing multiple parameters into a
46 | # space-separated string is a well documented source of bugs and security
47 | # problems, so this is (mostly) avoided, by progressively accumulating
48 | # options in "$@", and eventually passing that to Java.
49 | #
50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
52 | # see the in-line comments for details.
53 | #
54 | # There are tweaks for specific operating systems such as AIX, CygWin,
55 | # Darwin, MinGW, and NonStop.
56 | #
57 | # (3) This script is generated from the Groovy template
58 | # https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
59 | # within the Gradle project.
60 | #
61 | # You can find Gradle at https://github.com/gradle/gradle/.
62 | #
63 | ##############################################################################
64 |
65 | # Attempt to set APP_HOME
66 |
67 | # Resolve links: $0 may be a link
68 | app_path=$0
69 |
70 | # Need this for daisy-chained symlinks.
71 | while
72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
73 | [ -h "$app_path" ]
74 | do
75 | ls=$( ls -ld "$app_path" )
76 | link=${ls#*' -> '}
77 | case $link in #(
78 | /*) app_path=$link ;; #(
79 | *) app_path=$APP_HOME$link ;;
80 | esac
81 | done
82 |
83 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
84 |
85 | APP_NAME="Gradle"
86 | APP_BASE_NAME=${0##*/}
87 |
88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
90 |
91 | # Use the maximum available, or set MAX_FD != -1 to use that value.
92 | MAX_FD=maximum
93 |
94 | warn () {
95 | echo "$*"
96 | } >&2
97 |
98 | die () {
99 | echo
100 | echo "$*"
101 | echo
102 | exit 1
103 | } >&2
104 |
105 | # OS specific support (must be 'true' or 'false').
106 | cygwin=false
107 | msys=false
108 | darwin=false
109 | nonstop=false
110 | case "$( uname )" in #(
111 | CYGWIN* ) cygwin=true ;; #(
112 | Darwin* ) darwin=true ;; #(
113 | MSYS* | MINGW* ) msys=true ;; #(
114 | NONSTOP* ) nonstop=true ;;
115 | esac
116 |
117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
118 |
119 |
120 | # Determine the Java command to use to start the JVM.
121 | if [ -n "$JAVA_HOME" ] ; then
122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
123 | # IBM's JDK on AIX uses strange locations for the executables
124 | JAVACMD=$JAVA_HOME/jre/sh/java
125 | else
126 | JAVACMD=$JAVA_HOME/bin/java
127 | fi
128 | if [ ! -x "$JAVACMD" ] ; then
129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
130 |
131 | Please set the JAVA_HOME variable in your environment to match the
132 | location of your Java installation."
133 | fi
134 | else
135 | JAVACMD=java
136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
137 |
138 | Please set the JAVA_HOME variable in your environment to match the
139 | location of your Java installation."
140 | fi
141 |
142 | # Increase the maximum file descriptors if we can.
143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
144 | case $MAX_FD in #(
145 | max*)
146 | MAX_FD=$( ulimit -H -n ) ||
147 | warn "Could not query maximum file descriptor limit"
148 | esac
149 | case $MAX_FD in #(
150 | '' | soft) :;; #(
151 | *)
152 | ulimit -n "$MAX_FD" ||
153 | warn "Could not set maximum file descriptor limit to $MAX_FD"
154 | esac
155 | fi
156 |
157 | # Collect all arguments for the java command, stacking in reverse order:
158 | # * args from the command line
159 | # * the main class name
160 | # * -classpath
161 | # * -D...appname settings
162 | # * --module-path (only if needed)
163 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
164 |
165 | # For Cygwin or MSYS, switch paths to Windows format before running java
166 | if "$cygwin" || "$msys" ; then
167 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
168 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
169 |
170 | JAVACMD=$( cygpath --unix "$JAVACMD" )
171 |
172 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
173 | for arg do
174 | if
175 | case $arg in #(
176 | -*) false ;; # don't mess with options #(
177 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
178 | [ -e "$t" ] ;; #(
179 | *) false ;;
180 | esac
181 | then
182 | arg=$( cygpath --path --ignore --mixed "$arg" )
183 | fi
184 | # Roll the args list around exactly as many times as the number of
185 | # args, so each arg winds up back in the position where it started, but
186 | # possibly modified.
187 | #
188 | # NB: a `for` loop captures its iteration list before it begins, so
189 | # changing the positional parameters here affects neither the number of
190 | # iterations, nor the values presented in `arg`.
191 | shift # remove old arg
192 | set -- "$@" "$arg" # push replacement arg
193 | done
194 | fi
195 |
196 | # Collect all arguments for the java command;
197 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
198 | # shell script including quotes and variable substitutions, so put them in
199 | # double quotes to make sure that they get re-expanded; and
200 | # * put everything else in single quotes, so that it's not re-expanded.
201 |
202 | set -- \
203 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
204 | -classpath "$CLASSPATH" \
205 | org.gradle.wrapper.GradleWrapperMain \
206 | "$@"
207 |
208 | # Use "xargs" to parse quoted args.
209 | #
210 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
211 | #
212 | # In Bash we could simply go:
213 | #
214 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
215 | # set -- "${ARGS[@]}" "$@"
216 | #
217 | # but POSIX shell has neither arrays nor command substitution, so instead we
218 | # post-process each arg (as a line of input to sed) to backslash-escape any
219 | # character that might be a shell metacharacter, then use eval to reverse
220 | # that process (while maintaining the separation between arguments), and wrap
221 | # the whole thing up as a single "set" statement.
222 | #
223 | # This will of course break if any of these variables contains a newline or
224 | # an unmatched quote.
225 | #
226 |
227 | eval "set -- $(
228 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
229 | xargs -n1 |
230 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
231 | tr '\n' ' '
232 | )" '"$@"'
233 |
234 | exec "$JAVACMD" "$@"
235 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/move.bat:
--------------------------------------------------------------------------------
1 | :: Copy the build into your minecraft mods for convenience
2 | copy build\libs\liveoverflowmod-1.0.jar %APPDATA%\.minecraft\mods
3 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | maven {
4 | name = 'Fabric'
5 | url = 'https://maven.fabricmc.net/'
6 | }
7 | gradlePluginPortal()
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/com/jorianwoltjer/liveoverflowmod/LiveOverflowMod.java:
--------------------------------------------------------------------------------
1 | package com.jorianwoltjer.liveoverflowmod;
2 |
3 | import net.fabricmc.api.ModInitializer;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 |
7 | public class LiveOverflowMod implements ModInitializer {
8 | public static final Logger LOGGER = LoggerFactory.getLogger("liveoverflowmod");
9 | public static final String PREFIX = "§8[§c⬤§7 §7LiveOverflowMod§8] §r";
10 |
11 | @Override
12 | public void onInitialize() {
13 | LOGGER.info("Successfully loaded LiveOverflowMod");
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java:
--------------------------------------------------------------------------------
1 | package com.jorianwoltjer.liveoverflowmod.client;
2 |
3 | import com.jorianwoltjer.liveoverflowmod.command.*;
4 | import com.jorianwoltjer.liveoverflowmod.hacks.*;
5 | import com.jorianwoltjer.liveoverflowmod.mixin.ClientConnectionInvoker;
6 | import com.mojang.brigadier.CommandDispatcher;
7 | import net.fabricmc.api.ClientModInitializer;
8 | import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
9 | import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
10 | import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
11 | import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
12 | import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
13 | import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
14 | import net.minecraft.client.MinecraftClient;
15 | import net.minecraft.client.network.ClientPlayNetworkHandler;
16 | import net.minecraft.network.packet.Packet;
17 | import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket;
18 | import net.minecraft.network.packet.c2s.play.VehicleMoveC2SPacket;
19 | import net.minecraft.server.command.ServerCommandSource;
20 |
21 | import java.util.LinkedList;
22 |
23 | public class ClientEntrypoint implements ClientModInitializer {
24 | public static final PassiveMods passiveMods = new PassiveMods();
25 | public static final WorldGuardBypass worldGuardBypassHack = new WorldGuardBypass();
26 | public static final Reach reachHack = new Reach();
27 | public static final ClipReach clipReachHack = new ClipReach();
28 | public static final PanicMode panicModeHack = new PanicMode();
29 | public static final FastMiner fastMinerHack = new FastMiner();
30 | public static final ToggledHack[] toggledHacks = new ToggledHack[] {
31 | passiveMods,
32 | worldGuardBypassHack,
33 | reachHack,
34 | clipReachHack,
35 | panicModeHack,
36 | fastMinerHack
37 | };
38 | public static final MinecraftClient client = MinecraftClient.getInstance();
39 | public static ClientPlayNetworkHandler networkHandler;
40 | public static int globalTimer = 0;
41 | public static final LinkedList> packetQueue = new LinkedList<>(); // Max 5 per tick
42 |
43 | @Override
44 | public void onInitializeClient() {
45 | // Register functions for hacks
46 | for (ToggledHack hack : toggledHacks) {
47 | KeyBindingHelper.registerKeyBinding(hack.keybind); // Keybinds
48 | ClientTickEvents.END_CLIENT_TICK.register(hack::tick); // Every tick
49 | }
50 |
51 | ClientTickEvents.END_CLIENT_TICK.register(ClientEntrypoint::tickEnd); // End of every tick
52 | ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> registerClientCommands(dispatcher)); // Client Commands
53 | CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> registerServerCommands(dispatcher)); // Server Commands
54 |
55 | HudRenderCallback.EVENT.register(Gui::render); // Render GUI
56 | }
57 |
58 | public static void tickEnd(MinecraftClient client) {
59 | // Update variables
60 | networkHandler = client.getNetworkHandler();
61 | globalTimer++;
62 |
63 | // Send packets from queue (max 5)
64 | int movementPacketsLeft = 5;
65 | while (packetQueue.size() > 0 && movementPacketsLeft > 0) {
66 | Packet> packet = packetQueue.remove(0);
67 | if (packet instanceof PlayerMoveC2SPacket || packet instanceof VehicleMoveC2SPacket) {
68 | movementPacketsLeft--;
69 | }
70 | ((ClientConnectionInvoker) networkHandler.getConnection())._sendImmediately(packet, null);
71 | }
72 | }
73 |
74 | public static void registerClientCommands(CommandDispatcher dispatcher) {
75 | ClipCommand.register(dispatcher);
76 | }
77 |
78 | public static void registerServerCommands(CommandDispatcher dispatcher) {
79 | GetCodeCommand.register(dispatcher);
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/main/java/com/jorianwoltjer/liveoverflowmod/client/Gui.java:
--------------------------------------------------------------------------------
1 | package com.jorianwoltjer.liveoverflowmod.client;
2 |
3 | import com.jorianwoltjer.liveoverflowmod.hacks.ToggledHack;
4 | import net.minecraft.client.util.math.MatrixStack;
5 |
6 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.client;
7 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.toggledHacks;
8 |
9 | public class Gui {
10 |
11 | public static void render(MatrixStack matrixStack, float tickDelta) {
12 | // Show all hacks in the bottom right corner
13 | for (int i = 0; i < toggledHacks.length; i++) {
14 | ToggledHack hack = toggledHacks[toggledHacks.length - i - 1];
15 | String text = String.format("§8[§7%s§8] §r%s§7:§r %s",
16 | hack.keybind.getBoundKeyLocalizedText().getString(),
17 | hack.name,
18 | hack.isEnabled() ? "§aON" : "§cOFF"
19 | );
20 | renderTextShadow(matrixStack, text, i);
21 | }
22 | // Show title
23 | renderTextShadow(matrixStack, "§8[§7LiveOverflowMod §c⬤§8]", toggledHacks.length);
24 | }
25 |
26 | private static void renderTextShadow(MatrixStack matrixStack, String text, float index) {
27 | int x = client.getWindow().getScaledWidth() - client.textRenderer.getWidth(text) - 2;
28 | int y = client.getWindow().getScaledHeight() - 12 - (int)(index * 11);
29 |
30 | client.textRenderer.drawWithShadow(matrixStack, text, x, y, 0xFFFFFF);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java:
--------------------------------------------------------------------------------
1 | package com.jorianwoltjer.liveoverflowmod.command;
2 |
3 | import com.mojang.brigadier.CommandDispatcher;
4 | import com.mojang.brigadier.context.CommandContext;
5 | import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
6 | import net.minecraft.entity.player.PlayerEntity;
7 | import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket;
8 | import net.minecraft.network.packet.c2s.play.VehicleMoveC2SPacket;
9 | import net.minecraft.text.Text;
10 | import net.minecraft.util.Hand;
11 | import net.minecraft.util.hit.BlockHitResult;
12 | import net.minecraft.util.math.BlockPos;
13 | import net.minecraft.util.math.Direction;
14 | import net.minecraft.util.math.Vec3d;
15 |
16 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*;
17 | import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
18 | import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.*;
19 |
20 | public class ClipCommand {
21 | private static void interactAt(BlockPos pos) {
22 | if (client.interactionManager == null) return;
23 |
24 | client.interactionManager.interactBlock(client.player, Hand.MAIN_HAND, new BlockHitResult(
25 | new Vec3d(pos.getX(), pos.getY(), pos.getZ()),
26 | Direction.DOWN,
27 | pos,
28 | false
29 | ));
30 | }
31 |
32 | public static void register(CommandDispatcher dispatcher) {
33 | dispatcher.register(literal("vault")
34 | .executes(context -> {
35 | PlayerEntity player = context.getSource().getPlayer();
36 | Vec3d pos = player.getPos();
37 |
38 | interactAt(new BlockPos(4729, 125, 1337)); // Start button
39 |
40 | // y += 53.0
41 | for (int i = 0; i < 5; i++) {
42 | pos = pos.add(0, 9.9, 0);
43 | networkHandler.sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true));
44 | }
45 | pos = pos.add(0, 3.5, 0);
46 | networkHandler.sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true));
47 |
48 | // x += 53.0
49 | for (int i = 0; i < 5; i++) {
50 | pos = pos.add(9.9, 0, 0);
51 | networkHandler.sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true));
52 | }
53 | pos = pos.add(3.0, 0, 0);
54 | networkHandler.sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true));
55 |
56 | // y -= 53.0 (through box)
57 | pos = pos.add(0, -53, 0);
58 | networkHandler.sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true));
59 | player.setPosition(pos);
60 |
61 | interactAt(new BlockPos(4780, 125, 1336)); // End button
62 |
63 | return 1;
64 | })
65 | );
66 |
67 | dispatcher.register(literal("vclip") // Vertical clip
68 | .then(argument("distance", integer())
69 | .executes(context -> {
70 | int distance = context.getArgument("distance", Integer.class);
71 | PlayerEntity player = context.getSource().getPlayer();
72 |
73 | Vec3d pos = player.getPos();
74 | Vec3d targetPos = pos.add(0, distance, 0);
75 |
76 | clipStraight(targetPos);
77 |
78 | return 1;
79 | })
80 | )
81 | );
82 |
83 | dispatcher.register(literal("hclip") // Horizontal clip (up -> horizontal -> down: to go through walls)
84 | .then(argument("distance", integer())
85 | .executes(context -> {
86 | int distance = context.getArgument("distance", Integer.class);
87 |
88 | assert client.player != null;
89 |
90 | // Move `direction` blocks into viewing direction
91 | Vec3d targetPos = client.player.getPos().add(
92 | client.player.getRotationVector().multiply(1, 0, 1).normalize().multiply(distance)
93 | );
94 | clipUpDown(targetPos);
95 |
96 | return 1;
97 | })
98 | )
99 | );
100 |
101 | dispatcher.register(literal("dclip") // Directional clip
102 | .then(argument("distance", integer())
103 | .executes(context -> {
104 | int distance = context.getArgument("distance", Integer.class);
105 | PlayerEntity player = context.getSource().getPlayer();
106 |
107 | Vec3d pos = player.getPos();
108 | // Move into players viewing direction
109 | Vec3d targetPos = pos.add(player.getRotationVector().normalize().multiply(distance));
110 |
111 | clipStraight(targetPos);
112 |
113 | return 1;
114 | })
115 | )
116 | );
117 |
118 | dispatcher.register(literal("autoclip")
119 | .then(literal("up")
120 | .executes(context -> executeAutoClip(context, 1))
121 | )
122 | .then(literal("down")
123 | .executes(context -> executeAutoClip(context, -1))
124 | )
125 | );
126 |
127 | dispatcher.register(literal("clubmate")
128 | .executes(context -> {
129 | clipStraight(new Vec3d(1331, 89, 1330)); // Next to chest
130 |
131 | assert client.player != null;
132 | interactAt(new BlockPos(1331, 89, 1331)); // Chest
133 |
134 | return 1;
135 | })
136 | );
137 | }
138 |
139 | public static void moveTo(Vec3d pos) {
140 | if (client.player == null) return;
141 |
142 | if (client.player.getVehicle() != null) {
143 | client.player.getVehicle().setPosition(pos);
144 | networkHandler.sendPacket(new VehicleMoveC2SPacket(client.player.getVehicle()));
145 | } else {
146 | client.player.setPosition(pos);
147 | networkHandler.sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true));
148 | }
149 | }
150 | public static void moveTo(Vec3d pos, float yaw, float pitch) {
151 | if (client.player == null) return;
152 |
153 | if (client.player.getVehicle() != null) {
154 | client.player.getVehicle().setPosition(pos);
155 | networkHandler.sendPacket(new VehicleMoveC2SPacket(client.player.getVehicle()));
156 | } else {
157 | client.player.setPosition(pos);
158 | networkHandler.sendPacket(new PlayerMoveC2SPacket.Full(
159 | pos.x, pos.y, pos.z,
160 | yaw, pitch,
161 | client.player.isOnGround()));
162 | }
163 | }
164 |
165 | public static void clipStraight(Vec3d targetPos) {
166 | if (client.player == null) return;
167 |
168 | Vec3d pos = client.player.getPos();
169 |
170 | for (int i = 0; i < 18; i++) { // Send a lot of the same movement packets to increase max travel distance
171 | moveTo(pos);
172 | }
173 | // Send one big movement packet to actually move the player
174 | moveTo(targetPos);
175 | }
176 |
177 | // TODO: maybe refactor this to be the same as ClipReach#hitEntity
178 | public static void clipUpDown(Vec3d targetPos) {
179 | if (client.player == null) return;
180 |
181 | Vec3d pos = client.player.getPos();
182 |
183 | for (int i = 0; i < 15; i++) { // Send a lot of the same movement packets to increase max travel distance
184 | moveTo(pos);
185 | }
186 |
187 | pos = pos.add(0, 100, 0); // Up
188 | moveTo(pos);
189 |
190 | pos = new Vec3d(targetPos.x, pos.y, targetPos.z); // Horizontal
191 | moveTo(pos);
192 |
193 | moveTo(targetPos); // Down
194 | }
195 |
196 | public static int executeAutoClip(CommandContext context, int direction) {
197 | if (client.player == null) return 0;
198 |
199 | Vec3d pos = getAutoClipPos(direction);
200 | if (pos == null) {
201 | context.getSource().sendFeedback(Text.of("§cNo valid position found within 150 blocks"));
202 | return 0;
203 | } else {
204 | context.getSource().sendFeedback(Text.of(String.format("§7Clipping §a%.0f§7 blocks", pos.y - (int) client.player.getPos().y)));
205 | clipStraight(pos);
206 | return 1;
207 | }
208 | }
209 |
210 | /**
211 | * Automatically go through the nearest blocks in the given direction.
212 | * Credits to @EnderKill98 for the original code.
213 | */
214 | public static Vec3d getAutoClipPos(int direction) {
215 | if (client.player == null || client.world == null) return null;
216 |
217 | boolean inside = false;
218 | for (float i = 0; i < 150; i += 0.25) {
219 | Vec3d pos = client.player.getPos();
220 | Vec3d targetPos = pos.add(0, direction * i, 0);
221 |
222 | boolean collides = !client.world.isSpaceEmpty(client.player, client.player.getBoundingBox().offset(targetPos.subtract(pos)));
223 |
224 | if (!inside && collides) { // Step 1: Into the blocks
225 | inside = true;
226 | } else if (inside && !collides) { // Step 2: Out of the blocks
227 | return targetPos;
228 | }
229 | }
230 |
231 | return null; // Nothing found
232 | }
233 | }
234 |
--------------------------------------------------------------------------------
/src/main/java/com/jorianwoltjer/liveoverflowmod/command/GetCodeCommand.java:
--------------------------------------------------------------------------------
1 | package com.jorianwoltjer.liveoverflowmod.command;
2 |
3 | import com.mojang.brigadier.CommandDispatcher;
4 | import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType;
5 | import net.minecraft.block.Block;
6 | import net.minecraft.block.Blocks;
7 | import net.minecraft.command.argument.BlockPosArgumentType;
8 | import net.minecraft.server.command.ServerCommandSource;
9 | import net.minecraft.server.world.ServerWorld;
10 | import net.minecraft.text.Text;
11 | import net.minecraft.util.Formatting;
12 | import net.minecraft.util.Identifier;
13 | import net.minecraft.util.math.*;
14 | import net.minecraft.util.math.random.Random;
15 | import net.minecraft.util.math.random.RandomSplitter;
16 |
17 | import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.LOGGER;
18 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*;
19 |
20 | import static net.minecraft.client.util.SelectionManager.setClipboard;
21 | import static net.minecraft.server.command.CommandManager.argument;
22 | import static net.minecraft.server.command.CommandManager.literal;
23 |
24 | public class GetCodeCommand {
25 | private static final Dynamic2CommandExceptionType TOO_BIG_EXCEPTION = new Dynamic2CommandExceptionType((maxCount, count) -> Text.translatable("commands.fill.toobig", maxCount, count));
26 |
27 | public static void register(CommandDispatcher dispatcher) {
28 | // Checks to see if bedrock is at a certain position (for tracing in debugger)
29 | dispatcher.register(literal("bedrock")
30 | .then(argument("pos", BlockPosArgumentType.blockPos())
31 | .executes(context -> {
32 | BlockPos pos = BlockPosArgumentType.getBlockPos(context, "pos");
33 | ServerWorld world = context.getSource().getWorld();
34 |
35 | boolean result = checkBedrock(world, pos); // <--- Try setting a breakpoint here
36 |
37 | context.getSource().sendFeedback(Text.of("Bedrock at " + pos.getX() + " " + pos.getY() + " " + pos.getZ() +
38 | ": " + (result ? "§atrue" : "§cfalse")), false);
39 |
40 | return 1;
41 | })
42 | )
43 | );
44 |
45 | // Generate the checks for the Rust code to brute-force a recreated bedrock formation
46 | dispatcher.register(literal("getcode")
47 | .then(argument("from", BlockPosArgumentType.blockPos())
48 | .then(argument("to", BlockPosArgumentType.blockPos())
49 | .executes(context -> {
50 | BlockBox area = BlockBox.create(BlockPosArgumentType.getLoadedBlockPos(context, "from"), BlockPosArgumentType.getLoadedBlockPos(context, "to"));
51 | ChunkPos centerChunk = new ChunkPos(area.getCenter());
52 | BlockPos start = new BlockPos(centerChunk.getStartX(), area.getMaxY(), centerChunk.getStartZ());
53 |
54 | int i = area.getBlockCountX() * area.getBlockCountY() * area.getBlockCountZ();
55 | if (i > 32768) {
56 | throw TOO_BIG_EXCEPTION.create(32768, i);
57 | }
58 |
59 | ServerWorld world = context.getSource().getWorld();
60 | StringBuilder code = new StringBuilder();
61 |
62 | for (BlockPos blockPos : BlockPos.iterate(area.getMinX(), area.getMinY(), area.getMinZ(), area.getMaxX(), area.getMaxY(), area.getMaxZ())) {
63 | Block block = world.getBlockState(blockPos).getBlock();
64 | if (block == Blocks.BEDROCK) {
65 | BlockPos pos = blockPos.subtract(start);
66 | code.append(String.format(" generator.is_bedrock(chunk_x + %d, y + %d, chunk_z + %d) &&\n", pos.getX(), pos.getY(), pos.getZ()));
67 | } else if (block == Blocks.GLASS) {
68 | BlockPos pos = blockPos.subtract(start);
69 | code.append(String.format("!generator.is_bedrock(chunk_x + %d, y + %d, chunk_z + %d) &&\n", pos.getX(), pos.getY(), pos.getZ()));
70 | } else if (block == Blocks.REDSTONE_BLOCK) {
71 | BlockPos pos = blockPos.subtract(start);
72 | code.append(String.format("// generator.is_bedrock(chunk_x + %d, y + %d, chunk_z + %d) &&\n", pos.getX(), pos.getY(), pos.getZ()));
73 | } else if (block == Blocks.RED_STAINED_GLASS) {
74 | BlockPos pos = blockPos.subtract(start);
75 | code.append(String.format("// !generator.is_bedrock(chunk_x + %d, y + %d, chunk_z + %d) &&\n", pos.getX(), pos.getY(), pos.getZ()));
76 | }
77 | }
78 |
79 | setClipboard(client, code.toString());
80 |
81 | int lineCount = code.toString().split("\n").length;
82 | context.getSource().sendFeedback(Text.literal("Copied ")
83 | .append(Text.literal(String.valueOf(lineCount)).formatted(Formatting.GREEN))
84 | .append(Text.literal(" lines to clipboard")), false);
85 |
86 | return 1;
87 | })
88 | )
89 | )
90 | );
91 | }
92 |
93 | private static boolean checkBedrock(ServerWorld world, BlockPos pos) {
94 | RandomSplitter randomSplitter = world.getChunkManager().getNoiseConfig().getOrCreateRandomDeriver(new Identifier("bedrock_floor"));
95 |
96 | int i = 0;
97 | int j = 5;
98 |
99 | int i2 = pos.getY();
100 | if (i2 <= i) {
101 | return true;
102 | }
103 | if (i2 >= j) {
104 | return false;
105 | }
106 | double d = MathHelper.map(i2, i, j, 1.0, 0.0);
107 | LOGGER.info("d: " + d);
108 |
109 | Random random = randomSplitter.split(pos.getX(), i, pos.getZ());
110 |
111 | return (double)random.nextFloat() < d;
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ClipReach.java:
--------------------------------------------------------------------------------
1 | package com.jorianwoltjer.liveoverflowmod.hacks;
2 |
3 | import com.jorianwoltjer.liveoverflowmod.mixin.ClientPlayerInteractionManagerMixin;
4 | import com.jorianwoltjer.liveoverflowmod.mixin.MinecraftClientMixin;
5 | import net.minecraft.entity.Entity;
6 | import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket;
7 | import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket;
8 | import net.minecraft.network.packet.c2s.play.PlayerInteractItemC2SPacket;
9 | import net.minecraft.util.Hand;
10 | import net.minecraft.util.math.Vec3d;
11 | import org.lwjgl.glfw.GLFW;
12 |
13 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*;
14 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.client;
15 | import static com.jorianwoltjer.liveoverflowmod.command.ClipCommand.moveTo;
16 |
17 | public class ClipReach extends ToggledHack {
18 | /**
19 | * Hit enitities from far away *through blocks* by vclipping.
20 | * Not compatible with Meteor Client's:
21 | * - Anti-Hunger: will set onGound to false making you take fall damage
22 | * - Criticals: will send an extra move packet going over the limit
23 | *
24 | * @see MinecraftClientMixin
25 | * @see ClientPlayerInteractionManagerMixin
26 | */
27 | public ClipReach() {
28 | super("Clip Reach", GLFW.GLFW_KEY_LEFT_BRACKET);
29 | }
30 |
31 | @Override
32 | public void onEnable() {
33 | reachHack.enabled = false; // Disable normal reach
34 | }
35 |
36 | public void hitEntity(Entity target) {
37 | if (client.player == null) return;
38 |
39 | Vec3d pos = client.player.getPos();
40 | Vec3d targetPos = target.getPos();
41 |
42 | double maxDistance = 99.0D;
43 | Vec3d diff = pos.subtract(targetPos);
44 | double flatUp = Math.sqrt(maxDistance * maxDistance - (diff.x * diff.x + diff.z * diff.z));
45 | double targetUp = flatUp + diff.y;
46 |
47 | for (int i = 0; i < 9; i++) { // Build up TP range
48 | moveTo(pos);
49 | }
50 | moveTo(pos.add(0, maxDistance, 0)); // V-Clip up
51 | moveTo(targetPos.add(0, targetUp, 0)); // Can now move freely
52 | moveTo(targetPos); // V-Clip down to target
53 |
54 | networkHandler.sendPacket(PlayerInteractEntityC2SPacket.attack(target, client.player.isSneaking())); // Hit packet
55 | networkHandler.sendPacket(new HandSwingC2SPacket(client.player.getActiveHand())); // Serverside animation
56 |
57 | moveTo(targetPos.add(0, targetUp + 0.01, 0)); // V-Clip up
58 | moveTo(pos.add(0, maxDistance + 0.01, 0)); // Can now move freely
59 | moveTo(pos); // V-Clip down to original position
60 | client.player.setPosition(pos); // Set position on client-side
61 | }
62 |
63 | public void interactAtEntity(Entity target) {
64 | if (client.player == null) return;
65 |
66 | Vec3d pos = client.player.getPos();
67 | Vec3d targetPos = target.getPos();
68 |
69 | double maxDistance = 99.0D;
70 | Vec3d diff = pos.subtract(targetPos);
71 | double flatUp = Math.sqrt(maxDistance * maxDistance - (diff.x * diff.x + diff.z * diff.z));
72 | double targetUp = flatUp + diff.y;
73 |
74 | for (int i = 0; i < 9; i++) { // Build up TP range
75 | moveTo(pos);
76 | }
77 | moveTo(pos.add(0, maxDistance, 0)); // V-Clip up
78 | moveTo(targetPos.add(0, targetUp, 0)); // Can now move freely
79 | moveTo(targetPos, client.player.getYaw(), 90); // V-Clip down to target (looking down)
80 |
81 | networkHandler.sendPacket(new PlayerInteractItemC2SPacket(Hand.MAIN_HAND, 0)); // Interact item packet
82 | networkHandler.sendPacket(PlayerInteractEntityC2SPacket.interact(target, client.player.isSneaking(), Hand.MAIN_HAND)); // Interact entity packet
83 | networkHandler.sendPacket(new HandSwingC2SPacket(client.player.getActiveHand())); // Serverside animation
84 |
85 | moveTo(targetPos.add(0, targetUp + 0.01, 0), client.player.getYaw(), client.player.getPitch()); // V-Clip up (looking normal)
86 | moveTo(pos.add(0, maxDistance + 0.01, 0)); // Can now move freely
87 | moveTo(pos); // V-Clip down to original position
88 | client.player.setPosition(pos); // Set position on client-side
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/FastMiner.java:
--------------------------------------------------------------------------------
1 | package com.jorianwoltjer.liveoverflowmod.hacks;
2 |
3 | import com.jorianwoltjer.liveoverflowmod.mixin.ClientConnectionMixin;
4 | import net.minecraft.item.Item;
5 | import net.minecraft.item.ItemStack;
6 | import net.minecraft.item.Items;
7 | import net.minecraft.item.MiningToolItem;
8 | import net.minecraft.network.packet.c2s.play.ClientStatusC2SPacket;
9 | import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket;
10 | import net.minecraft.network.packet.c2s.play.PlayerInteractBlockC2SPacket;
11 | import net.minecraft.screen.slot.SlotActionType;
12 | import net.minecraft.text.Text;
13 | import net.minecraft.util.Hand;
14 | import net.minecraft.util.hit.BlockHitResult;
15 | import net.minecraft.util.math.BlockPos;
16 | import net.minecraft.util.math.Direction;
17 | import net.minecraft.util.math.Vec3d;
18 | import org.lwjgl.glfw.GLFW;
19 |
20 | import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.PREFIX;
21 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.client;
22 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.networkHandler;
23 |
24 | public class FastMiner extends ToggledHack {
25 | BlockPos targetPos;
26 | int timer;
27 | public Item itemToPlace;
28 |
29 | int statsValue = -1;
30 | int statsTimer = 0;
31 |
32 | /**
33 | * Breaks and places blocks *really* fast.
34 | * Hold a block in your offhand, and the best tool in your main hand. This hack will automatically fill the offhand with
35 | * more blocks of that type from your inventory if it runs out.
36 | * @see ClientConnectionMixin
37 | */
38 | public FastMiner() {
39 | super("Fast Miner", GLFW.GLFW_KEY_BACKSLASH);
40 | }
41 |
42 | @Override
43 | public void tickEnabled() {
44 | if (client.player == null || client.interactionManager == null) return;
45 |
46 | if (++statsTimer > 20*60) { // 1 minute
47 | statsTimer = 0;
48 | networkHandler.sendPacket(new ClientStatusC2SPacket(ClientStatusC2SPacket.Mode.REQUEST_STATS));
49 | }
50 |
51 | if (++timer % 2 != 0) return; // Only run every few ticks
52 | if (!(client.player.getMainHandStack().getItem() instanceof MiningToolItem)) return; // Stop if not holding a tool
53 |
54 | for (int i = 0; i < 9; i++) {
55 | if (client.player.getOffHandStack().getCount() == 0) {
56 | int slot = findItemSlot(itemToPlace);
57 | if (slot == -1) {
58 | message("§cNo cobblestone in inventory");
59 | return;
60 | }
61 | client.interactionManager.clickSlot(client.player.currentScreenHandler.syncId, slot, 40, SlotActionType.SWAP, client.player);
62 | }
63 |
64 | placeOffhandAt(targetPos);
65 | networkHandler.sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.START_DESTROY_BLOCK, targetPos, Direction.UP));
66 | networkHandler.sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK, targetPos, Direction.UP));
67 | }
68 | }
69 |
70 | @Override
71 | public void onEnable() {
72 | if (client.player == null) return;
73 |
74 | timer = 0;
75 | statsTimer = 0;
76 | statsValue = -1;
77 | itemToPlace = client.player.getOffHandStack().getItem();
78 |
79 | if (itemToPlace == Items.AIR) {
80 | message("§cNo block in offhand");
81 | enabled = false;
82 | return;
83 | }
84 |
85 | networkHandler.sendPacket(new ClientStatusC2SPacket(ClientStatusC2SPacket.Mode.REQUEST_STATS)); // Send initial
86 |
87 | switch (client.player.getHorizontalFacing()) {
88 | case NORTH -> targetPos = client.player.getBlockPos().add(0, 0, -1);
89 | case SOUTH -> targetPos = client.player.getBlockPos().add(0, 0, 1);
90 | case WEST -> targetPos = client.player.getBlockPos().add(-1, 0, 0);
91 | case EAST -> targetPos = client.player.getBlockPos().add(1, 0, 0);
92 | default -> targetPos = client.player.getBlockPos();
93 | }
94 | }
95 |
96 | public void onStatResponse(Integer newValue) { // Will get a callback from ClientConnectionMixin
97 | if (!enabled || client.player == null) return;
98 |
99 | if (newValue == null) { // If not updated, value will be null
100 | newValue = statsValue;
101 | }
102 | if (statsValue == -1) { // Initial value
103 | statsValue = newValue;
104 | }
105 |
106 | client.player.sendMessage(Text.of(String.format(PREFIX + "%s: §b%d§r/min (§a%s§r total)",
107 | itemToPlace.getName().getString(),
108 | newValue - statsValue,
109 | newValue == -1 ? "?" : newValue
110 | )), false);
111 |
112 | statsValue = newValue;
113 | }
114 |
115 | public int findItemSlot(Item item) {
116 | if (client.player == null) return -1;
117 |
118 | for (int i = 9; i < 36; i++) { // Inventory slots
119 | ItemStack stack = client.player.getInventory().getStack(i);
120 | if (stack.getItem() == item) {
121 | return i;
122 | }
123 | }
124 | return -1; // Not found
125 | }
126 |
127 | public static void placeOffhandAt(BlockPos pos) {
128 | BlockHitResult hitResult = new BlockHitResult(
129 | new Vec3d(pos.getX(), pos.getY(), pos.getZ()),
130 | Direction.UP,
131 | pos,
132 | false
133 | );
134 | networkHandler.sendPacket(new PlayerInteractBlockC2SPacket(Hand.OFF_HAND, hitResult, 0));
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PanicMode.java:
--------------------------------------------------------------------------------
1 | package com.jorianwoltjer.liveoverflowmod.hacks;
2 |
3 | import com.jorianwoltjer.liveoverflowmod.command.ClipCommand;
4 | import com.jorianwoltjer.liveoverflowmod.mixin.ClientPlayNetworkHandlerMixin;
5 | import net.minecraft.client.MinecraftClient;
6 | import net.minecraft.client.gui.screen.DisconnectedScreen;
7 | import net.minecraft.client.network.AbstractClientPlayerEntity;
8 | import net.minecraft.entity.Entity;
9 | import net.minecraft.entity.player.PlayerEntity;
10 | import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket;
11 | import net.minecraft.network.packet.c2s.play.VehicleMoveC2SPacket;
12 | import net.minecraft.text.Text;
13 | import net.minecraft.util.math.Vec3d;
14 | import org.lwjgl.glfw.GLFW;
15 |
16 | import java.util.List;
17 |
18 | import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.PREFIX;
19 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*;
20 |
21 | public class PanicMode extends ToggledHack {
22 | final double MAX_DELTA = 10;
23 | boolean panicActive = false;
24 | PanicReason reason;
25 |
26 | /**
27 | * Fly up and disconnect if the player is in a dangerous situation.
28 | * - If another player is in render distance
29 | * - If health goes down
30 | * @see ClientPlayNetworkHandlerMixin
31 | */
32 | public PanicMode() {
33 | super("Panic", GLFW.GLFW_KEY_COMMA);
34 | }
35 |
36 | @Override
37 | public void tick(MinecraftClient client) {
38 | super.tick(client);
39 | if (client.world == null) return;
40 |
41 | if (panicActive && packetQueue.size() == 0) { // If ended, disconnect
42 | panicActive = false; // Disable for next join
43 |
44 | StringBuilder message = new StringBuilder("Panic Mode: §cTriggered§r\n");
45 | switch (reason.reason) {
46 | case PLAYER_NEARBY -> message.append(String.format("§7Player §a%s §7was nearby", reason.player.getName().getString()));
47 | case DAMAGE -> message.append("§7You took damage");
48 | }
49 |
50 | client.world.disconnect();
51 | client.disconnect(new DisconnectedScreen(null, Text.of(PREFIX), Text.of(message.toString())));
52 | }
53 | }
54 |
55 | @Override
56 | public void tickEnabled() {
57 | if (client.world == null) return;
58 |
59 | List players = client.world.getPlayers();
60 | if (players.size() > 1) {
61 | AbstractClientPlayerEntity nearby = players.get(1);
62 | triggerPanic(new PanicReason(PanicReason.Reason.PLAYER_NEARBY, nearby, (double) nearby.distanceTo(client.player)));
63 | }
64 | }
65 |
66 | public void triggerPanic(PanicReason reason) {
67 | if (client.player == null) return;
68 |
69 | this.reason = reason;
70 | this.enabled = false; // Don't trigger repeatedly
71 | panicActive = true;
72 | message("§cTriggered§r, flying up...");
73 |
74 | // Fly up 1000 blocks
75 | for (int i = 0; i < 1000/MAX_DELTA; i++) {
76 | Vec3d pos = client.player.getPos().add(0, MAX_DELTA, 0); // Max 10 blocks per packet
77 |
78 | if (client.player.getVehicle() != null) { // If in boat
79 | moveVehicleTo(client.player.getVehicle(), pos);
80 | } else {
81 | client.player.setPosition(pos);
82 | packetQueue.add(new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true));
83 | }
84 | }
85 |
86 | }
87 |
88 | public static class PanicReason {
89 | public Reason reason;
90 | public Double distance;
91 | public PlayerEntity player;
92 |
93 | public PanicReason(Reason reason, PlayerEntity nearbyPlayer, Double distance) {
94 | this.reason = reason;
95 | this.distance = distance;
96 | this.player = nearbyPlayer;
97 | }
98 |
99 | public enum Reason {
100 | PLAYER_NEARBY,
101 | DAMAGE
102 | }
103 | }
104 |
105 | public static void moveVehicleTo(Entity vehicle, Vec3d pos) {
106 | vehicle.updatePosition(pos.x, pos.y, pos.z);
107 | packetQueue.add(new VehicleMoveC2SPacket(vehicle));
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PassiveMods.java:
--------------------------------------------------------------------------------
1 | package com.jorianwoltjer.liveoverflowmod.hacks;
2 |
3 | import com.jorianwoltjer.liveoverflowmod.mixin.*;
4 | import net.minecraft.entity.Entity;
5 |
6 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.client;
7 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.globalTimer;
8 | import static org.lwjgl.glfw.GLFW.GLFW_KEY_MINUS;
9 |
10 | public class PassiveMods extends ToggledHack {
11 | /**
12 | * Passive mods that should always be on.
13 | * - Randomize Texture Rotations
14 | * - Disable Weird Packets: World Border, Creative Mode, Demo Mode, End Credits
15 | * - Insta-Mine
16 | * - Anti-Human Bypass (round coordinates)
17 | * - Find Herobrine
18 | * @see AbstractBlockMixin
19 | * @see ClientPlayNetworkHandlerMixin
20 | * @see ClientPlayerInteractionManagerMixin
21 | * @see PlayerPositionFullPacketMixin
22 | * @see PlayerPositionPacketMixin
23 | * @see VehicleMovePacketMixin
24 | */
25 | public PassiveMods() {
26 | super("Passive Mods", GLFW_KEY_MINUS);
27 | this.defaultEnabled = true;
28 | this.enabled = defaultEnabled;
29 | }
30 |
31 | @Override
32 | public void tickEnabled() {
33 | if (client.world == null) return;
34 |
35 | // Find Herobrine
36 | for (Entity entity : client.world.getEntities()) {
37 | if (entity.getName().getString().equals("Herobrine")) {
38 | message(String.format(
39 | "%sFound %s §r(%.1f, %.1f, %.1f)",
40 | globalTimer % 8 > 4 ? "" : "§a", // Blinking
41 | entity.getName().getString(),
42 | entity.getX(), entity.getY(), entity.getZ()
43 | ));
44 | break;
45 | }
46 | }
47 | }
48 |
49 | @Override
50 | public void onEnable() {
51 | client.worldRenderer.reload(); // Reload chunks (for Texture Rotations)
52 | }
53 |
54 | @Override
55 | public void onDisable() {
56 | if (client.world != null) {
57 | client.worldRenderer.reload(); // Reload chunks (for Texture Rotations)
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/Reach.java:
--------------------------------------------------------------------------------
1 | package com.jorianwoltjer.liveoverflowmod.hacks;
2 |
3 | import com.jorianwoltjer.liveoverflowmod.mixin.ClientPlayerInteractionManagerMixin;
4 | import com.jorianwoltjer.liveoverflowmod.mixin.MinecraftClientMixin;
5 | import net.minecraft.entity.Entity;
6 | import net.minecraft.entity.EntityType;
7 | import net.minecraft.entity.player.PlayerEntity;
8 | import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket;
9 | import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket;
10 | import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket;
11 | import net.minecraft.util.math.MathHelper;
12 | import net.minecraft.util.math.Vec3d;
13 | import org.lwjgl.glfw.GLFW;
14 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
15 |
16 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*;
17 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.client;
18 | import static com.jorianwoltjer.liveoverflowmod.helper.Utils.insertToCenter;
19 |
20 | public class Reach extends ToggledHack {
21 | /**
22 | * Hit enitities from far away
23 | * @see MinecraftClientMixin
24 | * @see ClientPlayerInteractionManagerMixin
25 | */
26 | public Reach() {
27 | super("Reach", GLFW.GLFW_KEY_RIGHT_BRACKET);
28 | }
29 |
30 | @Override
31 | public void onEnable() {
32 | clipReachHack.enabled = false; // Disable clip reach
33 | }
34 |
35 | public void hitEntity(Entity target) {
36 | if (client.player == null) return;
37 |
38 | if (packetQueue.size() > 0) {
39 | return; // Already running (may take multiple ticks)
40 | }
41 |
42 | Vec3d pos = client.player.getPos();
43 | Vec3d targetPos = target.getPos().subtract( // Subtract a bit from the end
44 | target.getPos().subtract(pos).normalize().multiply(2)
45 | );
46 | // If player is still too far away, move closer
47 | while (target.squaredDistanceTo(pos.add(0, client.player.getStandingEyeHeight(), 0)) >= MathHelper.square(6.0)) {
48 | Vec3d movement = targetPos.subtract(pos);
49 |
50 | boolean lastPacket = false;
51 | if (movement.lengthSquared() >= 100) { // Length squared is max 100 (otherwise "moved too quickly")
52 | // Normalize to length 10
53 | movement = movement.normalize().multiply(9.9);
54 | } else { // If short enough, this is last packet
55 | lastPacket = true;
56 | }
57 | pos = pos.add(movement);
58 |
59 | // Add forward and backwards packets
60 | insertToCenter(packetQueue, new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true));
61 | if (!lastPacket) { // If not the last packet, add a backwards packet (only need one at the sheep)
62 | insertToCenter(packetQueue, new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true));
63 | }
64 | }
65 | // Add hit packet in the middle and original position at the end
66 | insertToCenter(packetQueue, PlayerInteractEntityC2SPacket.attack(target, client.player.isSneaking()));
67 | packetQueue.add(new PlayerMoveC2SPacket.PositionAndOnGround(client.player.getX(), client.player.getY(), client.player.getZ(), true));
68 | packetQueue.add(new HandSwingC2SPacket(client.player.getActiveHand())); // Serverside animation
69 | client.player.resetLastAttackedTicks(); // Reset attack cooldown
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java:
--------------------------------------------------------------------------------
1 | package com.jorianwoltjer.liveoverflowmod.hacks;
2 |
3 | import net.minecraft.client.MinecraftClient;
4 | import net.minecraft.client.option.KeyBinding;
5 | import net.minecraft.text.Text;
6 |
7 | import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.PREFIX;
8 | import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.LOGGER;
9 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.client;
10 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.networkHandler;
11 |
12 | public abstract class ToggledHack {
13 | public static final String LIVEOVERFLOW_CATEGORY = "category.liveoverflowmod";
14 |
15 | public final KeyBinding keybind;
16 | public final String name;
17 | public boolean defaultEnabled = false;
18 | public boolean enabled = defaultEnabled;
19 |
20 | /**
21 | * A hack that can be toggled on/off
22 | * @param name Display name of the hack
23 | * @param key The GLFW key code of the keybind
24 | */
25 | ToggledHack(String name, int key) {
26 | keybind = new KeyBinding("key.liveoverflowmod." + this.getClass().getSimpleName().toLowerCase() + "_toggle",
27 | key, LIVEOVERFLOW_CATEGORY);
28 | this.name = name;
29 | }
30 |
31 | /**
32 | * Called every tick
33 | */
34 | public void tick(MinecraftClient client) { // Called every tick
35 | if (keybind.wasPressed()) {
36 | toggle();
37 | }
38 | if (enabled && networkHandler != null) { // networkHandler = Safety check
39 | tickEnabled();
40 | }
41 | }
42 |
43 | /**
44 | * Toggle the hack on/off
45 | */
46 | public void toggle() {
47 | if (enabled) {
48 | disable();
49 | } else {
50 | enable();
51 | }
52 | }
53 |
54 | /**
55 | * Called every tick, but only when the hack is enabled
56 | */
57 | void tickEnabled() {}
58 |
59 | /**
60 | * Called when the hack is enabled
61 | */
62 | public void enable() {
63 | enabled = true;
64 | message("§aON");
65 | LOGGER.info("Enabled " + name);
66 | onEnable();
67 | }
68 | /**
69 | * Overridable method to add extra functionality when the hack is enabled
70 | */
71 | void onEnable() {}
72 |
73 | /**
74 | * Called when the hack is disabled
75 | */
76 | public void disable() {
77 | enabled = false;
78 | message("§cOFF");
79 | LOGGER.info("Disabled " + name);
80 | onDisable();
81 | }
82 | /**
83 | * Overridable method to add extra functionality when the hack is disabled
84 | */
85 | void onDisable() {}
86 |
87 | /**
88 | * Send a message via the action bar with the prefix
89 | * @param message The message to send
90 | */
91 | public void message(String message) {
92 | if (client.player == null) return;
93 |
94 | message = "§7" + message.replace("§r", "§7"); // Make white text gray
95 |
96 | client.player.sendMessage(Text.of(PREFIX + name + ": " + message), true);
97 | }
98 |
99 | public boolean isEnabled() {
100 | return enabled;
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/WorldGuardBypass.java:
--------------------------------------------------------------------------------
1 | package com.jorianwoltjer.liveoverflowmod.hacks;
2 |
3 | import com.jorianwoltjer.liveoverflowmod.mixin.LivingEntityMixin;
4 | import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket;
5 | import net.minecraft.util.math.Vec3d;
6 | import org.lwjgl.glfw.GLFW;
7 |
8 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.client;
9 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.networkHandler;
10 |
11 | public class WorldGuardBypass extends ToggledHack {
12 | final double MAX_DELTA = 0.05001; // Absolute maximum is sqrt(1/256) = 0.0625
13 | int flyingTimer = 0;
14 |
15 | /**
16 | * Walk through a WorldGuard protected region (with entry: deny) by avoiding `PlayerMoveEvent`s
17 | * @see LivingEntityMixin
18 | */
19 | public WorldGuardBypass() {
20 | super("WorldGuard Bypass", GLFW.GLFW_KEY_SEMICOLON);
21 | }
22 |
23 | @Override
24 | public void tickEnabled() {
25 | if (client.player == null || client.world == null) return;
26 |
27 | client.player.setVelocity(0, 0, 0);
28 |
29 | if (++flyingTimer > 20) { // Max 80, to bypass "Flying is not enabled"
30 | Vec3d pos = client.player.getPos();
31 | pos = pos.add(0, -MAX_DELTA, 0); // Small down position
32 |
33 | client.player.setPosition(pos.x, pos.y, pos.z);
34 | networkHandler.sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true));
35 | networkHandler.sendPacket(new PlayerMoveC2SPacket.Full(pos.x + 1337.0, pos.y + 1337.0, // Far packet again to keep bypassing
36 | pos.z + 1337.0, client.player.getYaw(), client.player.getPitch(), true));
37 |
38 | flyingTimer = 0; // Reset
39 | } else {
40 | Vec3d vec = getMovementVec();
41 | assert vec != null;
42 |
43 | if (vec.length() > 0) {
44 | if (!(vec.x == 0 && vec.z == 0)) { // Rotate by looking yaw (won't change length)
45 | double moveAngle = Math.atan2(vec.x, vec.z) + Math.toRadians(client.player.getYaw() + 90);
46 | double x = Math.cos(moveAngle);
47 | double z = Math.sin(moveAngle);
48 | vec = new Vec3d(x, vec.y, z);
49 | }
50 |
51 | vec = vec.multiply(MAX_DELTA); // Scale to maxDelta
52 |
53 | Vec3d newPos = new Vec3d(client.player.getX() + vec.x, client.player.getY() + vec.y, client.player.getZ() + vec.z);
54 | if (collides(newPos)) return; // Don't move if it would collide
55 |
56 | // If able to add more without going over a block boundary, add more
57 | boolean extra = false;
58 | if (client.options.sprintKey.isPressed()) { // Trigger by sprinting
59 | // If doesn't cross block boundary, and doesn't collide with anything, add more
60 | while (inSameBlock(newPos.add(vec.multiply(1.5)), new Vec3d(client.player.prevX, client.player.prevY, client.player.prevZ)) &&
61 | !collides(newPos.add(vec.multiply(1.5)))) {
62 | newPos = newPos.add(vec);
63 | extra = true;
64 | }
65 | }
66 |
67 | client.player.setPosition(newPos);
68 |
69 | // Send tiny movement so delta is small enough
70 | PlayerMoveC2SPacket.Full smallMovePacket = new PlayerMoveC2SPacket.Full(client.player.getX(), client.player.getY(),
71 | client.player.getZ(), client.player.getYaw(), client.player.getPitch(), true);
72 | networkHandler.sendPacket(smallMovePacket);
73 |
74 | // Send far away packet for "moving too quickly!" to reset position
75 | if (!extra) {
76 | PlayerMoveC2SPacket.Full farPacket = new PlayerMoveC2SPacket.Full(client.player.getX() + 1337.0, client.player.getY() + 1337.0,
77 | client.player.getZ() + 1337.0, client.player.getYaw(), client.player.getPitch(), true);
78 | networkHandler.sendPacket(farPacket);
79 | }
80 | }
81 | }
82 | }
83 |
84 | @Override
85 | public void onDisable() {
86 | flyingTimer = 0;
87 | }
88 |
89 |
90 | public static boolean inSameBlock(Vec3d vector, Vec3d other) {
91 | return other.x >= Math.floor(vector.x) && other.x <= Math.ceil(vector.x) &&
92 | other.y >= Math.floor(vector.y) && other.y <= Math.ceil(vector.y) &&
93 | other.z >= Math.floor(vector.z) && other.z <= Math.ceil(vector.z);
94 | }
95 |
96 | public static boolean collides(Vec3d pos) {
97 | if (client.player == null || client.world == null) return false;
98 |
99 | return !client.world.isSpaceEmpty(client.player, client.player.getBoundingBox().offset(pos.subtract(client.player.getPos())));
100 | }
101 |
102 | public static Vec3d getMovementVec() {
103 | if (client.player == null) return null;
104 |
105 | Vec3d vec = new Vec3d(0, 0, 0);
106 |
107 | // Key presses changing position
108 | if (client.player.input.jumping) { // Move up
109 | vec = vec.add(new Vec3d(0, 1, 0));
110 | } else if (client.player.input.sneaking) { // Move down
111 | vec = vec.add(new Vec3d(0, -1, 0));
112 | } else {
113 | // Horizontal movement (not at the same time as vertical)
114 | if (client.player.input.pressingForward) {
115 | vec = vec.add(new Vec3d(0, 0, 1));
116 | }
117 | if (client.player.input.pressingRight) {
118 | vec = vec.add(new Vec3d(1, 0, 0));
119 | }
120 | if (client.player.input.pressingBack) {
121 | vec = vec.add(new Vec3d(0, 0, -1));
122 | }
123 | if (client.player.input.pressingLeft) {
124 | vec = vec.add(new Vec3d(-1, 0, 0));
125 | }
126 | }
127 |
128 | return vec.normalize();
129 | }
130 |
131 | }
132 |
--------------------------------------------------------------------------------
/src/main/java/com/jorianwoltjer/liveoverflowmod/helper/Utils.java:
--------------------------------------------------------------------------------
1 | package com.jorianwoltjer.liveoverflowmod.helper;
2 |
3 | import org.spongepowered.asm.mixin.injection.invoke.arg.Args;
4 |
5 | import java.util.LinkedList;
6 |
7 | public class Utils {
8 |
9 | public static double roundCoordinate(double n) {
10 | n = Math.round(n * 100) / 100d; // Round to 1/100th
11 | return Math.nextAfter(n, n + Math.signum(n)); // Fix floating point errors
12 | }
13 |
14 | public static void onPositionPacket(Args args) {
15 | double x = args.get(0);
16 | double y = args.get(1);
17 | double z = args.get(2);
18 |
19 | // Round to 100ths for Anti-Human check
20 | x = roundCoordinate(x);
21 | z = roundCoordinate(z);
22 |
23 | args.set(0, x);
24 | args.set(1, y);
25 | args.set(2, z);
26 | }
27 |
28 | @SuppressWarnings("SameParameterValue")
29 | public static void insertToCenter(LinkedList list, T object) {
30 | int middle = (list.size() + 1) / 2; // Rounded up
31 | list.add(middle, object);
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/AbstractBlockMixin.java:
--------------------------------------------------------------------------------
1 | package com.jorianwoltjer.liveoverflowmod.mixin;
2 |
3 | import net.minecraft.block.AbstractBlock;
4 | import net.minecraft.util.math.MathHelper;
5 | import net.minecraft.util.math.Vec3i;
6 | import org.spongepowered.asm.mixin.Mixin;
7 | import org.spongepowered.asm.mixin.injection.At;
8 | import org.spongepowered.asm.mixin.injection.Redirect;
9 |
10 | import java.util.Objects;
11 | import java.util.Random;
12 |
13 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.passiveMods;
14 |
15 | @Mixin(AbstractBlock.class)
16 | public class AbstractBlockMixin {
17 | private static final long xFactor = new Random().nextLong();
18 | private static final long yFactor = new Random().nextLong();
19 | private static final long zFactor = new Random().nextLong();
20 |
21 | // Randomize texture rotations (prevent leaks)
22 | @Redirect(method="getRenderingSeed", at=@At(value="INVOKE", target="Lnet/minecraft/util/math/MathHelper;hashCode(Lnet/minecraft/util/math/Vec3i;)J"))
23 | private long getSeed(Vec3i vec) {
24 | if (passiveMods.enabled) {
25 | return Objects.hash(vec.getX() * xFactor, vec.getY() * yFactor, vec.getZ() * zFactor);
26 | } else {
27 | return MathHelper.hashCode(vec);
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionInvoker.java:
--------------------------------------------------------------------------------
1 | package com.jorianwoltjer.liveoverflowmod.mixin;
2 |
3 | import net.minecraft.network.ClientConnection;
4 | import net.minecraft.network.packet.Packet;
5 | import net.minecraft.network.PacketCallbacks;
6 | import org.spongepowered.asm.mixin.Mixin;
7 | import org.spongepowered.asm.mixin.gen.Invoker;
8 |
9 | @Mixin(ClientConnection.class)
10 | public interface ClientConnectionInvoker {
11 | @Invoker("sendImmediately")
12 | void _sendImmediately(Packet> packet, PacketCallbacks callbacks);
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java:
--------------------------------------------------------------------------------
1 | package com.jorianwoltjer.liveoverflowmod.mixin;
2 |
3 | import com.jorianwoltjer.liveoverflowmod.hacks.ToggledHack;
4 | import net.minecraft.block.Block;
5 | import net.minecraft.network.ClientConnection;
6 | import net.minecraft.network.packet.Packet;
7 | import net.minecraft.network.PacketCallbacks;
8 | import net.minecraft.network.listener.PacketListener;
9 | import net.minecraft.network.packet.s2c.play.StatisticsS2CPacket;
10 | import net.minecraft.stat.Stats;
11 | import net.minecraft.text.Text;
12 | import org.jetbrains.annotations.Nullable;
13 | import org.spongepowered.asm.mixin.Mixin;
14 | import org.spongepowered.asm.mixin.injection.At;
15 | import org.spongepowered.asm.mixin.injection.Inject;
16 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
17 |
18 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*;
19 |
20 | @Mixin(ClientConnection.class)
21 | public class ClientConnectionMixin {
22 | // Log outgoing packets (for debugging)
23 | @SuppressWarnings({"EmptyMethod", "CommentedOutCode"})
24 | @Inject(method = "sendImmediately", at = @At("HEAD"))
25 | void onSendImmediately(Packet> packet, @Nullable PacketCallbacks callbacks, CallbackInfo ci) {
26 | // LOGGER.info(String.format("---> [%04d] %s", ZonedDateTime.now().toInstant().toEpochMilli() % 1000, packet.getClass().getSimpleName()));
27 |
28 | // if (packet instanceof PlayerMoveC2SPacket _packet) {
29 | // LOGGER.info(String.format(" PlayerMoveC2SPacket(%.2f, %.2f, %.2f)", _packet.getX(0), _packet.getY(0), _packet.getZ(0)));
30 | // }
31 | }
32 |
33 | // Log incoming packets (for debugging)
34 | @Inject(method = "handlePacket", at = @At("HEAD"))
35 | private static void onHandlePacket(Packet packet, PacketListener listener, CallbackInfo ci) {
36 | // LOGGER.info(String.format("<--- [%04d] %s", ZonedDateTime.now().toInstant().toEpochMilli() % 1000, packet.getClass().getSimpleName()));
37 |
38 | // Save statistics response
39 | if (packet instanceof StatisticsS2CPacket statsPacket) {
40 | // Get mined stat for FastBreak
41 | Integer statsValue = statsPacket.getStatMap().get(Stats.MINED.getOrCreateStat(Block.getBlockFromItem(fastMinerHack.itemToPlace)));
42 | fastMinerHack.onStatResponse(statsValue);
43 | }
44 |
45 | // if (packet instanceof PlayerPositionLookS2CPacket _packet) {
46 | // LOGGER.info(String.format(" PlayerPositionLookS2CPacket(%.2f, %.2f, %.2f)", _packet.getX(), _packet.getY(), _packet.getZ()));
47 | // }
48 | }
49 |
50 | // Delay other packets while any packets in packetQueue
51 | @Inject(method = "send*", at = @At("HEAD"), cancellable = true)
52 | private void normalSend(Packet> packet, CallbackInfo ci) {
53 | if (packetQueue.size() > 0 || worldGuardBypassHack.enabled) { // WorldGuard Bypass also needs it for anti-flykick to work
54 | packetQueue.add(packet); // Do send them later
55 | ci.cancel();
56 | }
57 | }
58 |
59 | // Clear packet queue
60 | @Inject(method = "disconnect", at = @At("HEAD"))
61 | void onDisconnect(Text reason, CallbackInfo ci) {
62 | packetQueue.clear();
63 | for (ToggledHack hack : toggledHacks) {
64 | if (hack.enabled != hack.defaultEnabled) {
65 | hack.toggle();
66 | }
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayNetworkHandlerMixin.java:
--------------------------------------------------------------------------------
1 | package com.jorianwoltjer.liveoverflowmod.mixin;
2 |
3 | import com.jorianwoltjer.liveoverflowmod.hacks.PanicMode;
4 | import net.minecraft.client.network.ClientPlayNetworkHandler;
5 | import net.minecraft.network.packet.c2s.play.ClientStatusC2SPacket;
6 | import net.minecraft.network.packet.s2c.play.GameStateChangeS2CPacket;
7 | import net.minecraft.network.packet.s2c.play.HealthUpdateS2CPacket;
8 | import org.spongepowered.asm.mixin.Mixin;
9 | import org.spongepowered.asm.mixin.injection.*;
10 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
11 | import org.spongepowered.asm.mixin.injection.invoke.arg.Args;
12 |
13 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*;
14 |
15 | @Mixin(ClientPlayNetworkHandler.class)
16 | public class ClientPlayNetworkHandlerMixin {
17 | // Normalize WorldBorder
18 | @ModifyArgs(method = "onWorldBorderInitialize", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/border/WorldBorder;setSize(D)V"))
19 | private void setSize(Args args) { // Set radius to default 30 million
20 | if (passiveMods.enabled) {
21 | args.set(0, 30000000.0D); // radius
22 | }
23 | }
24 | @ModifyArgs(method = "onWorldBorderInitialize", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/border/WorldBorder;setCenter(DD)V"))
25 | private void setCenter(Args args) { // Set center to 0 0
26 | if (passiveMods.enabled) {
27 | args.set(0, 0.0D); // x
28 | args.set(1, 0.0D); // z
29 | }
30 | }
31 |
32 | // Disable demo popup, end credits and creative mode
33 | @Redirect(method = "onGameStateChange", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/packet/s2c/play/GameStateChangeS2CPacket;getReason()Lnet/minecraft/network/packet/s2c/play/GameStateChangeS2CPacket$Reason;"))
34 | private GameStateChangeS2CPacket.Reason getReason(GameStateChangeS2CPacket instance) {
35 | GameStateChangeS2CPacket.Reason reason = ((GameStateChangeS2CPacketAccessor) instance)._reason();
36 | if (passiveMods.enabled) {
37 | if (reason.equals(GameStateChangeS2CPacket.DEMO_MESSAGE_SHOWN) || // Demo popup
38 | reason.equals(GameStateChangeS2CPacket.GAME_MODE_CHANGED)) { // Creative mode
39 | // Completely ignore packets
40 | return null;
41 | } else if (reason.equals(GameStateChangeS2CPacket.GAME_WON)) { // End credits (still send respawn packet)
42 | networkHandler.sendPacket(new ClientStatusC2SPacket(ClientStatusC2SPacket.Mode.PERFORM_RESPAWN));
43 | return null;
44 | }
45 | }
46 | return reason;
47 | }
48 |
49 | // Panic if hit
50 | @Inject(method = "onHealthUpdate", at = @At("HEAD"))
51 | void onHealthUpdate(HealthUpdateS2CPacket packet, CallbackInfo ci) {
52 | if (panicModeHack.enabled && packet.getHealth() < 20.0F) {
53 | panicModeHack.triggerPanic(new PanicMode.PanicReason(PanicMode.PanicReason.Reason.DAMAGE, null, null));
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerMixin.java:
--------------------------------------------------------------------------------
1 | package com.jorianwoltjer.liveoverflowmod.mixin;
2 |
3 | import net.minecraft.block.BlockState;
4 | import net.minecraft.client.network.ClientPlayerInteractionManager;
5 | import net.minecraft.entity.Entity;
6 | import net.minecraft.entity.EntityType;
7 | import net.minecraft.entity.player.PlayerEntity;
8 | import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket;
9 | import net.minecraft.util.ActionResult;
10 | import net.minecraft.util.Hand;
11 | import net.minecraft.util.hit.EntityHitResult;
12 | import net.minecraft.util.math.BlockPos;
13 | import net.minecraft.util.math.Direction;
14 | import net.minecraft.util.math.MathHelper;
15 | import net.minecraft.util.math.Vec3d;
16 | import org.spongepowered.asm.mixin.Mixin;
17 | import org.spongepowered.asm.mixin.injection.At;
18 | import org.spongepowered.asm.mixin.injection.Inject;
19 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
20 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
21 |
22 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*;
23 |
24 | @Mixin(ClientPlayerInteractionManager.class)
25 | public class ClientPlayerInteractionManagerMixin {
26 |
27 | // Insta-Mine
28 | @Inject(method = "attackBlock", at = @At(value = "HEAD"), cancellable = true)
29 | private void attackBlock(BlockPos pos, Direction direction, CallbackInfoReturnable cir) {
30 | if (client.world == null || client.player == null) return;
31 |
32 | if (passiveMods.enabled) {
33 | BlockState blockState = client.world.getBlockState(pos);
34 | double speed = blockState.calcBlockBreakingDelta(client.player, client.world, pos);
35 | if (!blockState.isAir() && speed > 0.5F) { // If you can break the block fast enough, break it instantly
36 | client.world.breakBlock(pos, true, client.player);
37 | networkHandler.sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.START_DESTROY_BLOCK, pos, direction));
38 | networkHandler.sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK, pos, direction));
39 | cir.setReturnValue(true); // Return true to break the block on the client-side
40 | }
41 | }
42 | }
43 |
44 | // On attack, use Reach
45 | @Inject(method = "attackEntity", at = @At(value = "HEAD"), cancellable = true)
46 | private void attackEntity(PlayerEntity player, Entity target, CallbackInfo ci) {
47 | if (client.player == null) return;
48 |
49 | if (reachHack.enabled || clipReachHack.enabled) {
50 | Vec3d pos = client.player.getPos();
51 |
52 | // If player is too far away, needs reach
53 | if (target.squaredDistanceTo(pos.add(0, client.player.getStandingEyeHeight(), 0)) >= MathHelper.square(6.0)) {
54 | String targetName;
55 | if (target.getType().equals(EntityType.PLAYER)) {
56 | targetName = target.getName().getString();
57 | } else {
58 | targetName = target.getType().getName().getString();
59 | }
60 |
61 | if (reachHack.enabled) {
62 | reachHack.message(String.format("Hit §a%s §r(§b%.0fm§r)", targetName, target.distanceTo(client.player)));
63 | reachHack.hitEntity(target);
64 | } else if (clipReachHack.enabled) {
65 | clipReachHack.message(String.format("Hit §a%s §r(§b%.0fm§r)", targetName, target.distanceTo(client.player)));
66 | clipReachHack.hitEntity(target);
67 | }
68 |
69 | ci.cancel();
70 | }
71 | }
72 | }
73 |
74 | // On interact, use Reach
75 | @Inject(method = "interactEntityAtLocation", at = @At(value = "HEAD"), cancellable = true)
76 | private void interactEntityAtLocation(PlayerEntity player, Entity entity, EntityHitResult hitResult, Hand hand, CallbackInfoReturnable cir) {
77 | if (client.player == null) return;
78 |
79 | if (clipReachHack.enabled && hand.equals(Hand.MAIN_HAND)) {
80 | Vec3d pos = client.player.getPos();
81 |
82 | // If player is too far away, needs reach
83 | if (entity.squaredDistanceTo(pos.add(0, client.player.getStandingEyeHeight(), 0)) >= MathHelper.square(6.0)) {
84 | String targetName;
85 | if (entity.getType().equals(EntityType.PLAYER)) {
86 | targetName = entity.getName().getString();
87 | } else {
88 | targetName = entity.getType().getName().getString();
89 | }
90 |
91 | clipReachHack.message(String.format("Interacted with §a%s §r(§b%.0fm§r)", targetName, entity.distanceTo(client.player)));
92 | clipReachHack.interactAtEntity(entity);
93 |
94 | cir.setReturnValue(ActionResult.SUCCESS);
95 | }
96 | }
97 | }
98 |
99 | }
100 |
--------------------------------------------------------------------------------
/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/GameStateChangeS2CPacketAccessor.java:
--------------------------------------------------------------------------------
1 | package com.jorianwoltjer.liveoverflowmod.mixin;
2 |
3 | import net.minecraft.network.packet.s2c.play.GameStateChangeS2CPacket;
4 | import org.spongepowered.asm.mixin.Mixin;
5 | import org.spongepowered.asm.mixin.gen.Accessor;
6 |
7 | @Mixin(GameStateChangeS2CPacket.class)
8 | public interface GameStateChangeS2CPacketAccessor {
9 | @Accessor("reason")
10 | GameStateChangeS2CPacket.Reason _reason();
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/InGameHudAccessor.java:
--------------------------------------------------------------------------------
1 | package com.jorianwoltjer.liveoverflowmod.mixin;
2 |
3 | import net.minecraft.client.gui.hud.InGameHud;
4 | import net.minecraft.text.Text;
5 | import org.spongepowered.asm.mixin.Mixin;
6 | import org.spongepowered.asm.mixin.gen.Accessor;
7 |
8 | @Mixin(InGameHud.class)
9 | public interface InGameHudAccessor {
10 | @Accessor("overlayMessage")
11 | Text _overlayMessage();
12 |
13 | @Accessor("overlayRemaining")
14 | int _overlayRemaining();
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/InGameHudMixin.java:
--------------------------------------------------------------------------------
1 | package com.jorianwoltjer.liveoverflowmod.mixin;
2 |
3 | import net.minecraft.client.gui.hud.InGameHud;
4 | import net.minecraft.text.Text;
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 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.client;
11 |
12 | @Mixin(InGameHud.class)
13 | public class InGameHudMixin {
14 |
15 | // Don't overwrite the overlay message if it contains "LiveOverflow"
16 | @Inject(method = "setOverlayMessage", at = @At("HEAD"), cancellable = true)
17 | private void setOverlayMessage(Text message, boolean tinted, CallbackInfo ci) {
18 | Text currentMessage = ((InGameHudAccessor) client.inGameHud)._overlayMessage();
19 | int remaining = ((InGameHudAccessor) client.inGameHud)._overlayRemaining();
20 | if (currentMessage == null || message == null) return;
21 |
22 | if (currentMessage.getString().contains("LiveOverflow") && !message.getString().contains("LiveOverflow") && remaining > 20) {
23 | ci.cancel();
24 | }
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/LivingEntityMixin.java:
--------------------------------------------------------------------------------
1 | package com.jorianwoltjer.liveoverflowmod.mixin;
2 |
3 | import org.spongepowered.asm.mixin.Mixin;
4 | import org.spongepowered.asm.mixin.injection.At;
5 | import org.spongepowered.asm.mixin.injection.Redirect;
6 |
7 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.worldGuardBypassHack;
8 |
9 | @Mixin(net.minecraft.entity.LivingEntity.class)
10 | public class LivingEntityMixin {
11 | // Disable regular movement when WorldGuard Bypass is enabled
12 | @Redirect(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;isImmobile()Z"))
13 | private boolean isImmobile(net.minecraft.entity.LivingEntity livingEntity) {
14 | return worldGuardBypassHack.enabled;
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java:
--------------------------------------------------------------------------------
1 | package com.jorianwoltjer.liveoverflowmod.mixin;
2 |
3 | import net.minecraft.client.MinecraftClient;
4 | import net.minecraft.client.render.debug.DebugRenderer;
5 | import net.minecraft.entity.Entity;
6 | import net.minecraft.util.hit.EntityHitResult;
7 | import org.spongepowered.asm.mixin.Mixin;
8 | import org.spongepowered.asm.mixin.injection.At;
9 | import org.spongepowered.asm.mixin.injection.Inject;
10 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
11 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
12 |
13 | import java.util.Optional;
14 |
15 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.clipReachHack;
16 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.reachHack;
17 |
18 | @Mixin(MinecraftClient.class)
19 | public class MinecraftClientMixin {
20 |
21 | private void updateCrossairTarget() {
22 | if (reachHack.enabled || clipReachHack.enabled) {
23 | MinecraftClient client = MinecraftClient.getInstance();
24 | Optional entity = DebugRenderer.getTargetedEntity(client.player, 100);
25 | entity.ifPresent(e -> client.crosshairTarget = new EntityHitResult(e));
26 | }
27 | }
28 |
29 | // Extend reach for attack
30 | @Inject(method = "doAttack", at = @At(value = "HEAD"))
31 | private void doAttack(CallbackInfoReturnable cir) {
32 | updateCrossairTarget();
33 | }
34 |
35 | // Extend reach for interact
36 | @Inject(method = "doItemUse", at = @At(value = "HEAD"))
37 | private void doItemUse(CallbackInfo ci) {
38 | updateCrossairTarget();
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/PlayerPositionFullPacketMixin.java:
--------------------------------------------------------------------------------
1 | package com.jorianwoltjer.liveoverflowmod.mixin;
2 |
3 | import com.jorianwoltjer.liveoverflowmod.helper.Utils;
4 | import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket;
5 | import org.spongepowered.asm.mixin.Mixin;
6 | import org.spongepowered.asm.mixin.injection.At;
7 | import org.spongepowered.asm.mixin.injection.ModifyArgs;
8 | import org.spongepowered.asm.mixin.injection.invoke.arg.Args;
9 |
10 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.passiveMods;
11 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.worldGuardBypassHack;
12 |
13 | @Mixin(PlayerMoveC2SPacket.Full.class)
14 | public abstract class PlayerPositionFullPacketMixin {
15 | // Anti-human bypass
16 | @ModifyArgs(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/packet/c2s/play/PlayerMoveC2SPacket;(DDDFFZZZ)V"))
17 | private static void init(Args args) {
18 | if (passiveMods.enabled) {
19 | Utils.onPositionPacket(args);
20 | }
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/PlayerPositionPacketMixin.java:
--------------------------------------------------------------------------------
1 | package com.jorianwoltjer.liveoverflowmod.mixin;
2 |
3 | import com.jorianwoltjer.liveoverflowmod.helper.Utils;
4 | import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket;
5 | import org.spongepowered.asm.mixin.Mixin;
6 | import org.spongepowered.asm.mixin.injection.At;
7 | import org.spongepowered.asm.mixin.injection.ModifyArgs;
8 | import org.spongepowered.asm.mixin.injection.invoke.arg.Args;
9 |
10 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.passiveMods;
11 |
12 | @Mixin(PlayerMoveC2SPacket.PositionAndOnGround.class)
13 | public class PlayerPositionPacketMixin {
14 | // Anti-human bypass
15 | @ModifyArgs(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/packet/c2s/play/PlayerMoveC2SPacket;(DDDFFZZZ)V"))
16 | private static void init(Args args) {
17 | if (passiveMods.enabled) {
18 | Utils.onPositionPacket(args);
19 | }
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/SessionMixin.java:
--------------------------------------------------------------------------------
1 | package com.jorianwoltjer.liveoverflowmod.mixin;
2 |
3 | import net.minecraft.client.util.Session;
4 | import org.spongepowered.asm.mixin.Mixin;
5 | import org.spongepowered.asm.mixin.injection.At;
6 | import org.spongepowered.asm.mixin.injection.Inject;
7 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
8 |
9 | import java.util.HashMap;
10 | import java.util.HashSet;
11 | import java.util.List;
12 |
13 | @Mixin(Session.class)
14 | public class SessionMixin {
15 | private final HashMap> names = new HashMap<>() {{
16 | put("Hackende", new HashSet<>(List.of("Hackende", "HACKENDE", "hackende", "HACKende", "hackENDe", "HaCkEnDe", "hAcKeNdE", "HackendE", "HackEnde")));
17 | // Put your own fun name in here :)
18 | }};
19 |
20 | @Inject(method = "getUsername", at = @At("RETURN"), cancellable = true)
21 | private void getUsername(CallbackInfoReturnable cir) {
22 | String name = cir.getReturnValue();
23 | if (name != null && names.containsKey(name)) {
24 | String random = (String) names.get(name).toArray()[(int) (Math.random() * names.get(name).size())];
25 | cir.setReturnValue(random);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/VehicleMovePacketMixin.java:
--------------------------------------------------------------------------------
1 | package com.jorianwoltjer.liveoverflowmod.mixin;
2 |
3 | import com.jorianwoltjer.liveoverflowmod.helper.Utils;
4 | import net.minecraft.entity.Entity;
5 | import net.minecraft.network.packet.c2s.play.VehicleMoveC2SPacket;
6 | import org.spongepowered.asm.mixin.Mixin;
7 | import org.spongepowered.asm.mixin.injection.At;
8 | import org.spongepowered.asm.mixin.injection.Redirect;
9 |
10 | import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.passiveMods;
11 |
12 | @Mixin(VehicleMoveC2SPacket.class)
13 | public class VehicleMovePacketMixin {
14 | // Anti-human bypass for X
15 | @Redirect(method = "(Lnet/minecraft/entity/Entity;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getX()D"))
16 | public double getX(Entity instance){
17 | if (passiveMods.enabled) {
18 | return Utils.roundCoordinate(instance.getX());
19 | } else {
20 | return instance.getX();
21 | }
22 | }
23 | // Anti-human bypass for Z
24 | @Redirect(method = "(Lnet/minecraft/entity/Entity;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getZ()D"))
25 | public double getZ(Entity instance) {
26 | if (passiveMods.enabled) {
27 | return Utils.roundCoordinate(instance.getZ());
28 | } else {
29 | return instance.getZ();
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/resources/assets/liveoverflowmod/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JorianWoltjer/LiveOverflowMod/4743836cb37689fd0e3d46c7f8552bcdc5823cea/src/main/resources/assets/liveoverflowmod/icon.png
--------------------------------------------------------------------------------
/src/main/resources/assets/liveoverflowmod/lang/en_us.json:
--------------------------------------------------------------------------------
1 | {
2 | "category.liveoverflowmod": "LiveOverflowMod",
3 | "key.liveoverflowmod.worldguardbypass_toggle": "Toggle WorldGuard Bypass",
4 | "key.liveoverflowmod.reach_toggle": "Toggle Reach",
5 | "key.liveoverflowmod.autoplace_toggle": "Toggle Auto Place",
6 | "key.liveoverflowmod.panicmode_toggle": "Toggle Panic Mode",
7 | "key.liveoverflowmod.fastbreak_toggle": "Toggle Fast Break",
8 | "key.liveoverflowmod.passivemods_toggle": "Toggle Passive Mods"
9 | }
--------------------------------------------------------------------------------
/src/main/resources/fabric.mod.json:
--------------------------------------------------------------------------------
1 | {
2 | "schemaVersion": 1,
3 | "id": "liveoverflowmod",
4 | "version": "${version}",
5 | "name": "LiveOverflowMod",
6 | "description": "A Hacked Client for the LiveOverflow Server",
7 | "authors": ["J0R1AN"],
8 | "contact": {},
9 | "license": "MIT",
10 | "icon": "assets/liveoverflowmod/icon.png",
11 | "environment": "*",
12 | "entrypoints": {
13 | "main": [
14 | "com.jorianwoltjer.liveoverflowmod.LiveOverflowMod"
15 | ],
16 | "client": [
17 | "com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint"
18 | ]
19 | },
20 | "mixins": [
21 | "liveoverflowmod.mixins.json"
22 | ],
23 | "depends": {
24 | "fabricloader": ">=0.14.17",
25 | "fabric": "*",
26 | "minecraft": "1.19.4"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/resources/liveoverflowmod.mixins.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": true,
3 | "minVersion": "0.8",
4 | "package": "com.jorianwoltjer.liveoverflowmod.mixin",
5 | "compatibilityLevel": "JAVA_17",
6 | "mixins": [
7 | "AbstractBlockMixin",
8 | "ClientConnectionInvoker",
9 | "ClientConnectionMixin",
10 | "ClientPlayerInteractionManagerMixin",
11 | "LivingEntityMixin",
12 | "PlayerPositionFullPacketMixin",
13 | "PlayerPositionPacketMixin",
14 | "VehicleMovePacketMixin"
15 | ],
16 | "injectors": {
17 | "defaultRequire": 1
18 | },
19 | "client": [
20 | "ClientPlayNetworkHandlerMixin",
21 | "GameStateChangeS2CPacketAccessor",
22 | "InGameHudAccessor",
23 | "InGameHudMixin",
24 | "MinecraftClientMixin",
25 | "SessionMixin"
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------