Skip to content

Commit

Permalink
Merge branch 'new-server'
Browse files Browse the repository at this point in the history
# Conflicts:
#	README.md
#	src/main/java/com/jorianwoltjer/liveoverflowmod/client/Keybinds.java
#	src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java
#	src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionMixin.java
#	src/main/resources/liveoverflowmod.mixins.json
  • Loading branch information
JorianWoltjer committed May 20, 2023
2 parents bccb1bc + 3ca3be4 commit 5e9f853
Show file tree
Hide file tree
Showing 34 changed files with 1,669 additions and 272 deletions.
83 changes: 73 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
# LiveOverflowMod

A Minecraft hacked-client for the LiveOverflow Server. Contains various hacks specifically for the challenges on the server,
A Minecraft hacked-client for the LiveOverflow Server. Contains various hacks for the challenges on the server,
and some utilities.

**Read all about it in my [blog post](https://jorianwoltjer.com/blog/post/hacking/playing-on-the-liveoverflow-minecraft-hacking-server)**.
**Read all about it in my [blog post](https://jorianwoltjer.com/blog/post/hacking/playing-on-the-liveoverflow-minecraft-hacking-server)**.

## Hacks

### Anti-Human Bypass <kbd>-</kbd>
### Anti-Human Bypass

All movement packets need to be rounded to the 100ths. This is done using a simple `Math.round()` function,
and to fix floating point errors the `Math.nextAfter()` function is used.

This is a **passive** mod. You can toggle all passive mods using the default `-` (minus) keybind.

* [RoundPosition.java](src/main/java/com/jorianwoltjer/liveoverflowmod/helper/RoundPosition.java):
Does the rounding calculations
* [PlayerPositionFullPacketMixin.java](src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/PlayerPositionFullPacketMixin.java):
Expand All @@ -21,7 +23,7 @@ Same as above, but for the `PlayerMoveC2SPacket.PositionAndOnGround` packet
* [VehicleMovePacketMixin.java](src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/VehicleMovePacketMixin.java):
Same as above, but for riding a vehicle like a boat

### WorldGuard Bypass <kbd>;</kbd>
### WorldGuard Bypass

WorldGuard was used to deny `entry` to a protected area, in which the player had to die in the lava to complete the challenge.
WorldGuard works using `PlayerMoveEvent`s and this bypass works by moving without triggering this event.
Expand All @@ -31,17 +33,53 @@ This means it can only move `0.06` blocks per tick, and then has to send a posit
for the next repeat. However, this can be improved because WorldGuard only checks regions when you cross a block boundary.
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.

When this hack is activated using the default <kbd>;</kbd> (semicolon) keybind, it will allow you to move in this way with your `WASD` keys.
To activate the **faster** movement mode, you can press your **sprint** key (or toggle). This will enable the trick to
move faster by moving almost a full block without crossing the boundary, but won't always work in some other plugins that detect `PlayerMoveEvent`s
without taking this shortcut.
When this hack is activated using the default `;` (semicolon) keybind, it will allow you to move in this way with your `WASD` keys.

##### YouTube Video

[![Video showcasing the WorldGuard Bypass and completing the challenge](https://img.youtube.com/vi/hYA1cTUOXgA/maxresdefault.jpg)](https://www.youtube.com/watch?v=hYA1cTUOXgA)

* [Keybinds.java](src/main/java/com/jorianwoltjer/liveoverflowmod/client/Keybinds.java):
* [Keybinds.java](src/main/java/com/jorianwoltjer/liveoverflowmod/client/Keybinds.java#L82-L151):
When the keybind is pressed, `worldGuardBypassEnabled` is activated and `WASD` keys send the required packets to bypass WorldGuard
* [LivingEntityMixin.java](src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/LivingEntityMixin.java):
Redirect the `isImmobile()` method to return true when the hack is enabled, so the normal player movement is disabled

### Insta-Mine <kbd>-</kbd>
### Reach

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.
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
a reach hack that uses this by sending multiple position packets going towards a player, hit them, and then move back.
That is exactly what this hack does when you toggle the default `\​` (backslash) keybind, and then click on a far away entity as
if you were hitting them.

> **Note**
> This hack is not perfect. It only works when there is a clear line of sight to the player, and sometimes gets
> stuck while moving meaning you end up somewhere along traveled path. But it's good enough for a proof of concept!
##### YouTube Video

[![Video showcasing the Reach hack and completing the challenge](https://img.youtube.com/vi/Hio_iDnnJ5c/maxresdefault.jpg)](https://www.youtube.com/watch?v=Hio_iDnnJ5c)

* [Keybinds.java](src/main/java/com/jorianwoltjer/liveoverflowmod/client/Keybinds.java#L153-L171):
When the keybind is pressed, it will toggle reach on. Sending the packets
may take multiple ticks, so these are remembered and sent from the queue when the next tick happens.
* [MinecraftClientMixin.java](src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java):
When the hack is toggled on, you can click on an entity to hit them. This will send the packets to move towards the entity,
and then move back to the original position.
* [ClientPlayerEntityMixin.java](src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerEntityMixin.java):
Cancel the `sendMovementPackets()` method when this hack is traveling, so the client doesn't send any wrong packets by itself

### Panic

This hack is more of a test to see what is possible with movement. It sends 5 packets per tick each moving you up 10 blocks.
It does so 1 full second meaning you end up traveling precisely 1000 blocks straight up. This is useful if there is some danger,
like someone trying to kill you. You can then press the default `,` (comma) keybind to go up 1000 blocks and get out of the danger,
maybe even logging off at that high position because you cannot be trapped with blocks up there.

* [Keybinds.java](src/main/java/com/jorianwoltjer/liveoverflowmod/client/Keybinds.java#L173-L189):
When the keybind is pressed, it will send 5 packets going up 10 blocks each time for 20 ticks in total

### Insta-Mine

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.
When you as the client are done breaking the block, it will send `STOP_DESTROY_BLOCK` to the server, and it will verify
Expand All @@ -66,9 +104,34 @@ public void handleBlockBreakAction(BlockPos pos, ServerboundPlayerActionPacket.A
This allows you to insta-mine some blocks, that were previously really close to being insta-minable. You can for example insta-mine
stone and cobblestone with an Efficiency 5 Netherite Pickaxe using this hack.

This is a **passive** mod. You can toggle all passive mods using the default `-` (minus) keybind.

* [ClientPlayerInteractionMixin.java](src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionMixin.java):
Send the `STOP_DESTROY_BLOCK` action packet right after starting to break a block if it is close enough to be insta-mined

### Random Texture Rotations

This hack changed the random texture rotation code to use a completely random number every time, so it is not reversible from a screenshot.
This was to be able to take screenshots and videos, while not revealing the texture rotations that can be brute-forced easily for coordinates.
The same hack was used by LiveOverflow himself to make the challenge of finding his base harder.

This is a **passive** mod. You can toggle all passive mods using the default `-` (minus) keybind.

* [AbstractBlockMixin.java](src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/AbstractBlockMixin.java):

### Bedrock Cracking

I made a few commands to aid in cracking the bedrock formation in order to find LiveOverflow's base.
The first is `/bedrock`, which simply tells you if a certain coordinate should be bedrock or not (in The Nether). It calculates this itself,
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
what the algorithm is doing, while comparing it to your own code.
The second is `/getcode`, with which you can select an area from two coordinates, and get the Rust code of the offsets from
a recreation of bedrock. Simply build some formation with *bedrock* and *glass*, and run the command over the area to get the code.
It is meant to be used with my [BedrockFinder](https://github.com/JorianWoltjer/BedrockFinder) tool, which will then find the
coordinates of that bedrock formation in a specific seed.

* [LiveOverflowMod.java](src/main/java/com/jorianwoltjer/liveoverflowmod/LiveOverflowMod.java#L32-L86):

## Development

### Building to JAR (IntelliJ)
Expand Down
8 changes: 4 additions & 4 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
org.gradle.jvmargs=-Xmx1G
# Fabric Properties
# check these on https://modmuss50.me/fabric.html
minecraft_version=1.19.2
yarn_mappings=1.19.2+build.9
loader_version=0.14.9
minecraft_version=1.19.4
yarn_mappings=1.19.4+build.1
loader_version=0.14.17
# Mod Properties
mod_version=1.0
maven_group=com.jorianwoltjer
archives_base_name=liveoverflowmod
# Dependencies
# check this on https://modmuss50.me/fabric.html
fabric_version=0.60.0+1.19.2
fabric_version=0.75.3+1.19.4
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@

public class LiveOverflowMod implements ModInitializer {
public static final Logger LOGGER = LoggerFactory.getLogger("liveoverflowmod");
public static final String PREFIX = "§8[§c⬤§7 §7LiveOverflowMod§8] §r";

@Override
public void onInitialize() {
LOGGER.info("Successfully loaded LiveOverflowMod");
}

}
Original file line number Diff line number Diff line change
@@ -1,12 +1,81 @@
package com.jorianwoltjer.liveoverflowmod.client;

import com.jorianwoltjer.liveoverflowmod.command.*;
import com.jorianwoltjer.liveoverflowmod.hacks.*;
import com.jorianwoltjer.liveoverflowmod.mixin.ClientConnectionInvoker;
import com.mojang.brigadier.CommandDispatcher;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket;
import net.minecraft.network.packet.c2s.play.VehicleMoveC2SPacket;
import net.minecraft.server.command.ServerCommandSource;

import java.util.LinkedList;

public class ClientEntrypoint implements ClientModInitializer {
public static final PassiveMods passiveMods = new PassiveMods();
public static final WorldGuardBypass worldGuardBypassHack = new WorldGuardBypass();
public static final Reach reachHack = new Reach();
public static final ClipReach clipReachHack = new ClipReach();
public static final PanicMode panicModeHack = new PanicMode();
public static final FastMiner fastMinerHack = new FastMiner();
public static final ToggledHack[] toggledHacks = new ToggledHack[] {
passiveMods,
worldGuardBypassHack,
reachHack,
clipReachHack,
panicModeHack,
fastMinerHack
};
public static final MinecraftClient client = MinecraftClient.getInstance();
public static ClientPlayNetworkHandler networkHandler;
public static int globalTimer = 0;
public static final LinkedList<Packet<?>> packetQueue = new LinkedList<>(); // Max 5 per tick

@Override
public void onInitializeClient() {
Keybinds.registerKeybinds(); // Register keybinds
ClientTickEvents.END_CLIENT_TICK.register(Keybinds::checkKeybinds); // Register a callback to be called every tick
// Register functions for hacks
for (ToggledHack hack : toggledHacks) {
KeyBindingHelper.registerKeyBinding(hack.keybind); // Keybinds
ClientTickEvents.END_CLIENT_TICK.register(hack::tick); // Every tick
}

ClientTickEvents.END_CLIENT_TICK.register(ClientEntrypoint::tickEnd); // End of every tick
ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> registerClientCommands(dispatcher)); // Client Commands
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> registerServerCommands(dispatcher)); // Server Commands

HudRenderCallback.EVENT.register(Gui::render); // Render GUI
}

public static void tickEnd(MinecraftClient client) {
// Update variables
networkHandler = client.getNetworkHandler();
globalTimer++;

// Send packets from queue (max 5)
int movementPacketsLeft = 5;
while (packetQueue.size() > 0 && movementPacketsLeft > 0) {
Packet<?> packet = packetQueue.remove(0);
if (packet instanceof PlayerMoveC2SPacket || packet instanceof VehicleMoveC2SPacket) {
movementPacketsLeft--;
}
((ClientConnectionInvoker) networkHandler.getConnection())._sendImmediately(packet, null);
}
}

public static void registerClientCommands(CommandDispatcher<FabricClientCommandSource> dispatcher) {
ClipCommand.register(dispatcher);
}

public static void registerServerCommands(CommandDispatcher<ServerCommandSource> dispatcher) {
GetCodeCommand.register(dispatcher);
}
}
32 changes: 32 additions & 0 deletions src/main/java/com/jorianwoltjer/liveoverflowmod/client/Gui.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.jorianwoltjer.liveoverflowmod.client;

import com.jorianwoltjer.liveoverflowmod.hacks.ToggledHack;
import net.minecraft.client.util.math.MatrixStack;

import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.client;
import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.toggledHacks;

public class Gui {

public static void render(MatrixStack matrixStack, float tickDelta) {
// Show all hacks in the bottom right corner
for (int i = 0; i < toggledHacks.length; i++) {
ToggledHack hack = toggledHacks[toggledHacks.length - i - 1];
String text = String.format("§8[§7%s§8] §r%s§7:§r %s",
hack.keybind.getBoundKeyLocalizedText().getString(),
hack.name,
hack.isEnabled() ? "§aON" : "§cOFF"
);
renderTextShadow(matrixStack, text, i);
}
// Show title
renderTextShadow(matrixStack, "§8[§7LiveOverflowMod §c⬤§8]", toggledHacks.length);
}

private static void renderTextShadow(MatrixStack matrixStack, String text, float index) {
int x = client.getWindow().getScaledWidth() - client.textRenderer.getWidth(text) - 2;
int y = client.getWindow().getScaledHeight() - 12 - (int)(index * 11);

client.textRenderer.drawWithShadow(matrixStack, text, x, y, 0xFFFFFF);
}
}
Loading

0 comments on commit 5e9f853

Please sign in to comment.