├── .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 | ![Screenshot of the Text UI in the bottom right corner](https://github.com/JorianWoltjer/LiveOverflowMod/assets/26067369/6202a614-5915-49ed-96c6-a6f188a31039) 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 | --------------------------------------------------------------------------------