From 539227984e780cfd708802256dc830c88bacc560 Mon Sep 17 00:00:00 2001 From: Jorian Woltjer Date: Thu, 17 Nov 2022 18:49:37 +0100 Subject: [PATCH 01/20] Add features for new server --- README.md | 77 +++++++++++-- .../liveoverflowmod/LiveOverflowMod.java | 96 ++++++++++++++++ .../liveoverflowmod/client/Keybinds.java | 69 ++++++++++-- .../mixin/AbstractBlockMixin.java | 29 +++++ .../mixin/ClientConnectionInvoker.java | 14 +++ .../mixin/ClientPlayNetworkHandlerMixin.java | 45 ++++++++ .../mixin/ClientPlayerEntityAccessor.java | 13 +++ .../mixin/ClientPlayerEntityMixin.java | 22 ++++ ...lientPlayerInteractionManagerAccessor.java | 21 ++++ ... ClientPlayerInteractionManagerMixin.java} | 12 +- .../GameStateChangeS2CPacketAccessor.java | 12 ++ .../mixin/MinecraftClientMixin.java | 104 ++++++++++++++++++ .../mixin/VehicleMovePacketMixin.java | 2 +- .../assets/liveoverflowmod/lang/en_us.json | 4 +- .../resources/liveoverflowmod.mixins.json | 10 +- 15 files changed, 511 insertions(+), 19 deletions(-) create mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/AbstractBlockMixin.java create mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionInvoker.java create mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayNetworkHandlerMixin.java create mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerEntityAccessor.java create mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerEntityMixin.java create mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerAccessor.java rename src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/{ClientPlayerInteractionMixin.java => ClientPlayerInteractionManagerMixin.java} (79%) create mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/GameStateChangeS2CPacketAccessor.java create mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java diff --git a/README.md b/README.md index a307496..5b11752 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # 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 @@ -12,6 +12,8 @@ and some utilities. 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): @@ -31,16 +33,52 @@ 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 `;` (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 +### 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. @@ -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) diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/LiveOverflowMod.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/LiveOverflowMod.java index 444450f..b7e55af 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/LiveOverflowMod.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/LiveOverflowMod.java @@ -1,15 +1,111 @@ package com.jorianwoltjer.liveoverflowmod; +import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType; import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; +import net.minecraft.block.Blocks; +import net.minecraft.command.argument.BlockPosArgumentType; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockBox; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.random.Random; +import net.minecraft.util.math.random.RandomSplitter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; + public class LiveOverflowMod implements ModInitializer { public static final Logger LOGGER = LoggerFactory.getLogger("liveoverflowmod"); + public static final String PREFIX = "§8[§c⬤§7 §7LiveOverflowMod§8] §r"; + private static final Dynamic2CommandExceptionType TOO_BIG_EXCEPTION = new Dynamic2CommandExceptionType((maxCount, count) -> Text.translatable("commands.fill.toobig", maxCount, count)); @Override public void onInitialize() { LOGGER.info("Successfully loaded LiveOverflowMod"); + + // Checks to see if bedrock is at a certain position + CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> dispatcher.register(literal("bedrock") + .then(argument("pos", BlockPosArgumentType.blockPos()) + .executes(context -> { + BlockPos pos = BlockPosArgumentType.getBlockPos(context, "pos"); + ServerWorld world = context.getSource().getWorld(); + + boolean result = checkBedrock(world, pos); // <--- Try setting a breakpoint here + + context.getSource().sendFeedback(Text.of("Bedrock at " + pos.getX() + " " + pos.getY() + " " + pos.getZ() + + ": " + (result ? "§atrue" : "§cfalse")), false); + + return 1; + })) + )); + + // Generate the checks for the Rust code to brute-force a recreated bedrock formation + CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> dispatcher.register(literal("getcode") + .then(argument("from", BlockPosArgumentType.blockPos()) + .then(argument("to", BlockPosArgumentType.blockPos()) + .executes(context -> { + BlockBox area = BlockBox.create(BlockPosArgumentType.getLoadedBlockPos(context, "from"), BlockPosArgumentType.getLoadedBlockPos(context, "to")); + ChunkPos centerChunk = new ChunkPos(area.getCenter()); + BlockPos start = new BlockPos(centerChunk.getStartX(), area.getMaxY(), centerChunk.getStartZ()); + + int i = area.getBlockCountX() * area.getBlockCountY() * area.getBlockCountZ(); + if (i > 32768) { + throw TOO_BIG_EXCEPTION.create(32768, i); + } + + ServerWorld world = context.getSource().getWorld(); + + for (BlockPos blockPos : BlockPos.iterate(area.getMinX(), area.getMinY(), area.getMinZ(), area.getMaxX(), area.getMaxY(), area.getMaxZ())) { + String code = ""; + if (world.getBlockState(blockPos).getBlock() == Blocks.BEDROCK) { // Is bedrock + BlockPos pos = blockPos.subtract(start); + code = String.format("generator.is_bedrock(chunk_x + %d, y + %d, chunk_z + %d) == true", pos.getX(), pos.getY(), pos.getZ()); + } else if (world.getBlockState(blockPos).getBlock() == Blocks.GLASS) { // Is empty + BlockPos pos = blockPos.subtract(start); + code = String.format("generator.is_bedrock(chunk_x + %d, y + %d, chunk_z + %d) == false", pos.getX(), pos.getY(), pos.getZ()); + } else if (world.getBlockState(blockPos).getBlock() == Blocks.REDSTONE_BLOCK) { // Is unused bedrock + BlockPos pos = blockPos.subtract(start); + code = String.format("// generator.is_bedrock(chunk_x + %d, y + %d, chunk_z + %d) == true", pos.getX(), pos.getY(), pos.getZ()); + } else if (world.getBlockState(blockPos).getBlock() == Blocks.RED_STAINED_GLASS) { // Is unused empty + BlockPos pos = blockPos.subtract(start); + code = String.format("// generator.is_bedrock(chunk_x + %d, y + %d, chunk_z + %d) == false", pos.getX(), pos.getY(), pos.getZ()); + } + if (!code.isEmpty()) { + context.getSource().sendFeedback(Text.of(code), false); + } + } + + return 1; + })) + ))); + + } + + private static boolean checkBedrock(ServerWorld world, BlockPos pos) { + RandomSplitter randomSplitter = world.getChunkManager().getNoiseConfig().getOrCreateRandomDeriver(new Identifier("bedrock_floor")); + + int i = 0; + int j = 5; + + int i2 = pos.getY(); + if (i2 <= i) { + return true; + } + if (i2 >= j) { + return false; + } + double d = MathHelper.map(i2, i, j, 1.0, 0.0); + LOGGER.info("d: " + d); + + Random random = randomSplitter.split(pos.getX(), i, pos.getZ()); + + return (double)random.nextFloat() < d; } } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/client/Keybinds.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/client/Keybinds.java index 6e848e8..3c33f8d 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/client/Keybinds.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/client/Keybinds.java @@ -1,14 +1,19 @@ package com.jorianwoltjer.liveoverflowmod.client; +import com.jorianwoltjer.liveoverflowmod.mixin.ClientConnectionInvoker; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.option.KeyBinding; +import net.minecraft.network.Packet; import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; import net.minecraft.text.Text; import net.minecraft.util.math.Vec3d; import org.lwjgl.glfw.GLFW; +import java.util.LinkedList; + +import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.PREFIX; public class Keybinds { @@ -20,15 +25,25 @@ public class Keybinds { private static final KeyBinding worldGuardBypassToggle = new KeyBinding("key.liveoverflowmod.worldguardbypass_toggle", GLFW.GLFW_KEY_SEMICOLON, LIVEOVERFLOW_CATEGORY); // Bypass WorldGuard region protection + private static final KeyBinding reachKeybind = new KeyBinding("key.liveoverflowmod.reach", + GLFW.GLFW_KEY_BACKSLASH, LIVEOVERFLOW_CATEGORY); // Extend reach to infinity + private static final KeyBinding panicKeybind = new KeyBinding("key.liveoverflowmod.panic", + GLFW.GLFW_KEY_COMMA, LIVEOVERFLOW_CATEGORY); // Fly up as fast as possible private static final KeyBinding modToggle = new KeyBinding("key.liveoverflowmod.passive_toggle", GLFW.GLFW_KEY_MINUS, LIVEOVERFLOW_CATEGORY); // Toggle passive mods on/off + // packetQueue: [1, 2, 3, 4, 5, A, 4, 3, 2, 1, 0] + public static LinkedList> packetQueue = new LinkedList<>(); public static boolean worldGuardBypassEnabled = false; + public static boolean reachEnabled = false; public static boolean passiveModsEnabled = true; public static int flyingTimer = 0; + public static int panicTimer = 0; public static void registerKeybinds() { KeyBindingHelper.registerKeyBinding(worldGuardBypassToggle); + KeyBindingHelper.registerKeyBinding(reachKeybind); + KeyBindingHelper.registerKeyBinding(panicKeybind); KeyBindingHelper.registerKeyBinding(modToggle); } @@ -44,10 +59,12 @@ public static void checkKeybinds(MinecraftClient client) { while (modToggle.wasPressed()) { // Toggle whole mod passiveModsEnabled = !passiveModsEnabled; if (passiveModsEnabled) { - client.player.sendMessage(Text.of("§7[LiveOverflowMod] §aEnabled"), false); + client.player.sendMessage(Text.of(PREFIX + "Passive Mods: §aEnabled"), true); } else { - client.player.sendMessage(Text.of("§7[LiveOverflowMod] §cDisabled"), false); + client.player.sendMessage(Text.of(PREFIX + "Passive Mods: §cDisabled"), true); } + // Reload chunks + client.worldRenderer.reload(); } // Toggle WorldGuard Bypass @@ -55,18 +72,18 @@ public static void checkKeybinds(MinecraftClient client) { flyingTimer = 0; if (worldGuardBypassEnabled) { worldGuardBypassEnabled = false; - client.player.sendMessage(Text.of("§7[LiveOverflowMod] §rWorldGuard Bypass: §cDisabled"), false); + client.player.sendMessage(Text.of(PREFIX + "WorldGuard Bypass: §cDisabled"), true); } else { worldGuardBypassEnabled = true; - client.player.sendMessage(Text.of("§7[LiveOverflowMod] §rWorldGuard Bypass: §aEnabled"), false); + client.player.sendMessage(Text.of(PREFIX + "WorldGuard Bypass: §aEnabled"), true); } } // WorldGuard bypass if (worldGuardBypassEnabled) { - if (++flyingTimer > 30) { // Max 80, to bypass "Flying is not enabled" - networkHandler.sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround(client.player.getX(), - client.player.getY() - 0.04, client.player.getZ(), client.player.isOnGround())); + if (++flyingTimer > 20) { // Max 80, to bypass "Flying is not enabled" + ((ClientConnectionInvoker)networkHandler.getConnection())._sendImmediately(new PlayerMoveC2SPacket.PositionAndOnGround(client.player.getX(), + client.player.getY() - 0.04, client.player.getZ(), client.player.isOnGround()), null); flyingTimer = 0; // Reset } else { client.player.setVelocity(0, 0, 0); @@ -132,6 +149,44 @@ public static void checkKeybinds(MinecraftClient client) { } } } + + // Reach + while (reachKeybind.wasPressed()) { + reachEnabled = !reachEnabled; + if (reachEnabled) { + client.player.sendMessage(Text.of(PREFIX + "Reach: §aEnabled"), true); + } else { + client.player.sendMessage(Text.of(PREFIX + "Reach: §cDisabled"), true); + } + } + + // Send packets from reach queue (max 5) + int movementPacketsLeft = 5; + while (packetQueue.size() != 0 && movementPacketsLeft != 0) { + Packet packet = packetQueue.remove(0); + if (packet instanceof PlayerMoveC2SPacket) { + movementPacketsLeft--; + } + ((ClientConnectionInvoker) networkHandler.getConnection())._sendImmediately(packet, null); + } + + // Panic + if (panicKeybind.wasPressed()) { + client.player.sendMessage(Text.of(PREFIX + "Panic: §aFlying up 1000 blocks"), true); + panicTimer = 20; + } + if (panicTimer > 0) { + panicTimer--; + for (int i = 0; i < 5; i++) { // Max 5 packets per tick + Vec3d pos = client.player.getPos().add(0, 10, 0); // Max 10 blocks per packet + client.player.setPosition(pos); + client.player.setVelocity(0, 0, 0); + networkHandler.sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true)); + } + if (panicTimer == 0) { // If end + client.player.sendMessage(Text.of(PREFIX + "Panic: §cFinished"), true); + } + } } } } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/AbstractBlockMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/AbstractBlockMixin.java new file mode 100644 index 0000000..5d1ddc1 --- /dev/null +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/AbstractBlockMixin.java @@ -0,0 +1,29 @@ +package com.jorianwoltjer.liveoverflowmod.mixin; + +import com.jorianwoltjer.liveoverflowmod.client.Keybinds; +import net.minecraft.block.AbstractBlock; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3i; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import java.util.Objects; +import java.util.Random; + +@Mixin(AbstractBlock.class) +public class AbstractBlockMixin { + private static final long xFactor = new Random().nextLong(); + private static final long yFactor = new Random().nextLong(); + private static final long zFactor = new Random().nextLong(); + + // Randomize texture rotations (prevent leaks) + @Redirect(method="getRenderingSeed", at=@At(value="INVOKE", target="Lnet/minecraft/util/math/MathHelper;hashCode(Lnet/minecraft/util/math/Vec3i;)J")) + private long getSeed(Vec3i vec) { + if (Keybinds.passiveModsEnabled) { + return Objects.hash(vec.getX() * xFactor, vec.getY() * yFactor, vec.getZ() * zFactor); + } else { + return MathHelper.hashCode(vec); + } + } +} diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionInvoker.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionInvoker.java new file mode 100644 index 0000000..d0b77b7 --- /dev/null +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionInvoker.java @@ -0,0 +1,14 @@ +package com.jorianwoltjer.liveoverflowmod.mixin; + +import net.minecraft.network.ClientConnection; +import net.minecraft.network.Packet; +import net.minecraft.network.PacketCallbacks; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(ClientConnection.class) +public interface ClientConnectionInvoker { + @Invoker("sendImmediately") + void _sendImmediately(Packet packet, PacketCallbacks callbacks); + +} diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayNetworkHandlerMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayNetworkHandlerMixin.java new file mode 100644 index 0000000..86b44ed --- /dev/null +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayNetworkHandlerMixin.java @@ -0,0 +1,45 @@ +package com.jorianwoltjer.liveoverflowmod.mixin; + +import com.jorianwoltjer.liveoverflowmod.client.Keybinds; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.network.packet.c2s.play.ClientStatusC2SPacket; +import net.minecraft.network.packet.s2c.play.GameStateChangeS2CPacket; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.*; +import org.spongepowered.asm.mixin.injection.invoke.arg.Args; + +@Mixin(ClientPlayNetworkHandler.class) +public class ClientPlayNetworkHandlerMixin { + // Normalize WorldBorder + @ModifyArgs(method = "onWorldBorderInitialize", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/border/WorldBorder;setSize(D)V")) + private void setSize(Args args) { // Set radius to default 30 million + if (Keybinds.passiveModsEnabled) { + args.set(0, 30000000.0D); // radius + } + } + @ModifyArgs(method = "onWorldBorderInitialize", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/border/WorldBorder;setCenter(DD)V")) + private void setCenter(Args args) { // Set center to 0 0 + if (Keybinds.passiveModsEnabled) { + args.set(0, 0.0D); // x + args.set(1, 0.0D); // z + } + } + + // Disable demo popup, end credits and creative mode + @Redirect(method = "onGameStateChange", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/packet/s2c/play/GameStateChangeS2CPacket;getReason()Lnet/minecraft/network/packet/s2c/play/GameStateChangeS2CPacket$Reason;")) + private GameStateChangeS2CPacket.Reason getReason(GameStateChangeS2CPacket instance) { + GameStateChangeS2CPacket.Reason reason = ((GameStateChangeS2CPacketAccessor) instance)._reason(); + if (Keybinds.passiveModsEnabled) { + if (reason.equals(GameStateChangeS2CPacket.DEMO_MESSAGE_SHOWN) || // Demo popup + reason.equals(GameStateChangeS2CPacket.GAME_MODE_CHANGED)) { // Creative mode + // Completely ignore packets + return null; + } else if (reason.equals(GameStateChangeS2CPacket.GAME_WON)) { // End credits (still send respawn packet) + MinecraftClient.getInstance().getNetworkHandler().sendPacket(new ClientStatusC2SPacket(ClientStatusC2SPacket.Mode.PERFORM_RESPAWN)); + return null; + } + } + return reason; + } +} diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerEntityAccessor.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerEntityAccessor.java new file mode 100644 index 0000000..d05c7cc --- /dev/null +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerEntityAccessor.java @@ -0,0 +1,13 @@ +package com.jorianwoltjer.liveoverflowmod.mixin; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(ClientPlayerEntity.class) +public interface ClientPlayerEntityAccessor { + @Accessor("client") + MinecraftClient _client(); + +} diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerEntityMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerEntityMixin.java new file mode 100644 index 0000000..5fec973 --- /dev/null +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerEntityMixin.java @@ -0,0 +1,22 @@ +package com.jorianwoltjer.liveoverflowmod.mixin; + +import com.jorianwoltjer.liveoverflowmod.client.Keybinds; +import net.minecraft.client.network.ClientPlayerEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ClientPlayerEntity.class) +public class ClientPlayerEntityMixin { + + // If this is false, no movement packets will be sent + @Redirect(method = "sendMovementPackets", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isCamera()Z")) + private boolean isCamera(ClientPlayerEntity instance) { + return ((ClientPlayerEntityAccessor)instance)._client().getCameraEntity() == instance && + Keybinds.packetQueue.size() == 0; + } + +} diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerAccessor.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerAccessor.java new file mode 100644 index 0000000..a6614aa --- /dev/null +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerAccessor.java @@ -0,0 +1,21 @@ +package com.jorianwoltjer.liveoverflowmod.mixin; + +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.network.ClientPlayerInteractionManager; +import net.minecraft.world.GameMode; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(ClientPlayerInteractionManager.class) +public interface ClientPlayerInteractionManagerAccessor { + @Invoker("syncSelectedSlot") + void _syncSelectedSlot(); + + @Accessor("networkHandler") + ClientPlayNetworkHandler _networkHandler(); + + @Accessor("gameMode") + GameMode _gameMode(); + +} diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerMixin.java similarity index 79% rename from src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionMixin.java rename to src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerMixin.java index 8688229..8ecafad 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerMixin.java @@ -1,18 +1,25 @@ package com.jorianwoltjer.liveoverflowmod.mixin; import net.minecraft.block.BlockState; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerInteractionManager; import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; +import org.slf4j.Logger; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import static com.jorianwoltjer.liveoverflowmod.client.Keybinds.*; -@Mixin(net.minecraft.client.network.ClientPlayerInteractionManager.class) -public class ClientPlayerInteractionMixin { +@Mixin(ClientPlayerInteractionManager.class) +public class ClientPlayerInteractionManagerMixin { + // Insta-Mine hack @Inject(method = "attackBlock", at = @At(value = "HEAD"), cancellable = true) private void attackBlock(BlockPos pos, Direction direction, CallbackInfoReturnable cir) { @@ -29,4 +36,5 @@ private void attackBlock(BlockPos pos, Direction direction, CallbackInfoReturnab } } } + } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/GameStateChangeS2CPacketAccessor.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/GameStateChangeS2CPacketAccessor.java new file mode 100644 index 0000000..73ac582 --- /dev/null +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/GameStateChangeS2CPacketAccessor.java @@ -0,0 +1,12 @@ +package com.jorianwoltjer.liveoverflowmod.mixin; + +import net.minecraft.network.packet.s2c.play.GameStateChangeS2CPacket; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(GameStateChangeS2CPacket.class) +public interface GameStateChangeS2CPacketAccessor { + @Accessor("reason") + GameStateChangeS2CPacket.Reason _reason(); + +} diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java new file mode 100644 index 0000000..febf181 --- /dev/null +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java @@ -0,0 +1,104 @@ +package com.jorianwoltjer.liveoverflowmod.mixin; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerInteractionManager; +import net.minecraft.client.render.debug.DebugRenderer; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket; +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; +import net.minecraft.text.Text; +import net.minecraft.util.hit.EntityHitResult; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.GameMode; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.LinkedList; +import java.util.Optional; + +import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.PREFIX; +import static com.jorianwoltjer.liveoverflowmod.client.Keybinds.packetQueue; +import static com.jorianwoltjer.liveoverflowmod.client.Keybinds.reachEnabled; + +@Mixin(MinecraftClient.class) +public class MinecraftClientMixin { + + private static void addToMiddle(LinkedList list, T object) { + int middle = (list.size() + 1) / 2; // Rounded up + list.add(middle, object); + } + + @Inject(method = "doAttack", at = @At(value = "HEAD")) + private void doAttack(CallbackInfoReturnable cir) { + if (reachEnabled) { + MinecraftClient client = MinecraftClient.getInstance(); + Optional entity = DebugRenderer.getTargetedEntity(client.player, 100); + entity.ifPresent(e -> { + client.crosshairTarget = new EntityHitResult(e); + }); + } + } + + @Redirect(method = "doAttack", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerInteractionManager;attackEntity(Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/entity/Entity;)V")) + private void attackEntity(ClientPlayerInteractionManager instance, PlayerEntity player, Entity target) { + MinecraftClient client = MinecraftClient.getInstance(); + if (reachEnabled) { + if (packetQueue.size() > 0) { + return; // Already running + } + String targetName; + if (target.getType().equals(EntityType.PLAYER)) { + targetName = target.getName().getString(); + } else { + targetName = target.getType().getName().getString(); + } + client.player.sendMessage(Text.of(String.format(PREFIX + "Reach: Hit §a%s §r(%.1f blocks)", + targetName, client.player.distanceTo(target))), true); + + Vec3d virtualPosition = client.player.getPos(); + // Move close enough to target + while (true) { + // If player is too far away, move closer + if (target.squaredDistanceTo(virtualPosition.add(0, client.player.getStandingEyeHeight(), 0)) >= MathHelper.square(6.0)) { + Vec3d movement = target.getPos().subtract(virtualPosition); + double length = movement.lengthSquared(); + + boolean lastPacket = false; + if (length >= 100) { // Length squared is max 100 + // Normalize to length 10 + movement = movement.multiply(9.9 / Math.sqrt(length)); + } else { // If short enough, this is last packet + movement = movement.multiply(Math.max(0, Math.sqrt(length) - 2) / 10); // Reduce length by 2 blocks + lastPacket = true; + } + virtualPosition = virtualPosition.add(movement); + // Add forward and backwards packets + addToMiddle(packetQueue, new PlayerMoveC2SPacket.PositionAndOnGround(virtualPosition.x, virtualPosition.y, virtualPosition.z, true)); + if (!lastPacket) { // If not the last packet, add a backwards packet (only need one at the sheep) + addToMiddle(packetQueue, new PlayerMoveC2SPacket.PositionAndOnGround(virtualPosition.x, virtualPosition.y, virtualPosition.z, true)); + } + } else { + break; + } + } + // Add hit packet in the middle and original position at the end + addToMiddle(packetQueue, PlayerInteractEntityC2SPacket.attack(target, client.player.isSneaking())); + packetQueue.add(new PlayerMoveC2SPacket.PositionAndOnGround(client.player.getX(), client.player.getY(), client.player.getZ(), true)); + + } else { // Orignal code if not enabled + ClientPlayerInteractionManagerAccessor _instance = (ClientPlayerInteractionManagerAccessor) instance; + _instance._syncSelectedSlot(); + _instance._networkHandler().sendPacket(PlayerInteractEntityC2SPacket.attack(target, player.isSneaking())); + if (_instance._gameMode() != GameMode.SPECTATOR) { + player.attack(target); + player.resetLastAttackedTicks(); + } + } + } +} diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/VehicleMovePacketMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/VehicleMovePacketMixin.java index 60decc3..7cb177b 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/VehicleMovePacketMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/VehicleMovePacketMixin.java @@ -30,4 +30,4 @@ public double getZ(Entity instance) { return instance.getX(); } } -} \ No newline at end of file +} diff --git a/src/main/resources/assets/liveoverflowmod/lang/en_us.json b/src/main/resources/assets/liveoverflowmod/lang/en_us.json index 5c28814..66eb7a0 100644 --- a/src/main/resources/assets/liveoverflowmod/lang/en_us.json +++ b/src/main/resources/assets/liveoverflowmod/lang/en_us.json @@ -1,5 +1,7 @@ { "category.liveoverflowmod": "LiveOverflowMod", - "key.liveoverflowmod.worldguardbypass_toggle": "WorldGuard Bypass", + "key.liveoverflowmod.worldguardbypass_toggle": "Toggle WorldGuard Bypass", + "key.liveoverflowmod.reach": "Reach", + "key.liveoverflowmod.panic": "Panic", "key.liveoverflowmod.passive_toggle": "Toggle Passive Mods" } \ No newline at end of file diff --git a/src/main/resources/liveoverflowmod.mixins.json b/src/main/resources/liveoverflowmod.mixins.json index 6323742..cf6660e 100644 --- a/src/main/resources/liveoverflowmod.mixins.json +++ b/src/main/resources/liveoverflowmod.mixins.json @@ -4,7 +4,9 @@ "package": "com.jorianwoltjer.liveoverflowmod.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ - "ClientPlayerInteractionMixin", + "AbstractBlockMixin", + "ClientConnectionInvoker", + "ClientPlayerInteractionManagerMixin", "LivingEntityMixin", "PlayerPositionFullPacketMixin", "PlayerPositionPacketMixin", @@ -14,5 +16,11 @@ "defaultRequire": 1 }, "client": [ + "ClientPlayerEntityAccessor", + "ClientPlayerEntityMixin", + "ClientPlayNetworkHandlerMixin", + "GameStateChangeS2CPacketAccessor", + "ClientPlayerInteractionManagerAccessor", + "MinecraftClientMixin" ] } From b406d5c18b0e3166228d1091f9ff55d6d91d4a6f Mon Sep 17 00:00:00 2001 From: Jorian Woltjer Date: Thu, 24 Nov 2022 17:16:35 +0100 Subject: [PATCH 02/20] Add clip commands, auto-place and fix reach damage --- .../client/ClientEntrypoint.java | 11 ++ .../liveoverflowmod/client/Keybinds.java | 70 ++++++++- .../liveoverflowmod/command/ClipCommand.java | 136 ++++++++++++++++++ .../mixin/ClientConnectionMixin.java | 36 +++++ .../mixin/ClientPlayerEntityMixin.java | 21 +++ .../mixin/MinecraftClientMixin.java | 3 + .../assets/liveoverflowmod/lang/en_us.json | 3 +- .../resources/liveoverflowmod.mixins.json | 3 +- 8 files changed, 276 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java create mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java index c351f7b..b579ff0 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java @@ -1,12 +1,23 @@ package com.jorianwoltjer.liveoverflowmod.client; +import com.jorianwoltjer.liveoverflowmod.command.*; +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.minecraft.command.CommandRegistryAccess; public class ClientEntrypoint implements ClientModInitializer { @Override public void onInitializeClient() { Keybinds.registerKeybinds(); // Register keybinds ClientTickEvents.END_CLIENT_TICK.register(Keybinds::checkKeybinds); // Register a callback to be called every tick + + ClientCommandRegistrationCallback.EVENT.register(ClientEntrypoint::registerCommands); + } + + public static void registerCommands(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess) { + ClipCommand.register(dispatcher); } } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/client/Keybinds.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/client/Keybinds.java index 3c33f8d..c0775ca 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/client/Keybinds.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/client/Keybinds.java @@ -5,20 +5,27 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.option.KeyBinding; +import net.minecraft.item.Items; import net.minecraft.network.Packet; -import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; +import net.minecraft.network.packet.c2s.play.*; import net.minecraft.text.Text; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import org.lwjgl.glfw.GLFW; import java.util.LinkedList; +import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.LOGGER; import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.PREFIX; public class Keybinds { public static final String LIVEOVERFLOW_CATEGORY = "category.liveoverflowmod"; - public static double MAX_DELTA = 0.05; + public static final double MAX_DELTA = 0.05; + public static final int OFFHAND = 45; public static MinecraftClient mc = MinecraftClient.getInstance(); public static ClientPlayNetworkHandler networkHandler; @@ -31,11 +38,14 @@ public class Keybinds { GLFW.GLFW_KEY_COMMA, LIVEOVERFLOW_CATEGORY); // Fly up as fast as possible private static final KeyBinding modToggle = new KeyBinding("key.liveoverflowmod.passive_toggle", GLFW.GLFW_KEY_MINUS, LIVEOVERFLOW_CATEGORY); // Toggle passive mods on/off + private static final KeyBinding placeKeybind = new KeyBinding("key.liveoverflowmod.place", + GLFW.GLFW_KEY_RIGHT_BRACKET, LIVEOVERFLOW_CATEGORY); // Place blocks around you // packetQueue: [1, 2, 3, 4, 5, A, 4, 3, 2, 1, 0] public static LinkedList> packetQueue = new LinkedList<>(); public static boolean worldGuardBypassEnabled = false; public static boolean reachEnabled = false; + public static boolean placeEnabled = false; public static boolean passiveModsEnabled = true; public static int flyingTimer = 0; public static int panicTimer = 0; @@ -45,6 +55,7 @@ public static void registerKeybinds() { KeyBindingHelper.registerKeyBinding(reachKeybind); KeyBindingHelper.registerKeyBinding(panicKeybind); KeyBindingHelper.registerKeyBinding(modToggle); + KeyBindingHelper.registerKeyBinding(placeKeybind); } public static boolean inSameBlock(Vec3d vector, Vec3d other) { @@ -82,7 +93,7 @@ public static void checkKeybinds(MinecraftClient client) { // WorldGuard bypass if (worldGuardBypassEnabled) { if (++flyingTimer > 20) { // Max 80, to bypass "Flying is not enabled" - ((ClientConnectionInvoker)networkHandler.getConnection())._sendImmediately(new PlayerMoveC2SPacket.PositionAndOnGround(client.player.getX(), + ((ClientConnectionInvoker) networkHandler.getConnection())._sendImmediately(new PlayerMoveC2SPacket.PositionAndOnGround(client.player.getX(), client.player.getY() - 0.04, client.player.getZ(), client.player.isOnGround()), null); flyingTimer = 0; // Reset } else { @@ -162,11 +173,15 @@ public static void checkKeybinds(MinecraftClient client) { // Send packets from reach queue (max 5) int movementPacketsLeft = 5; - while (packetQueue.size() != 0 && movementPacketsLeft != 0) { + int blockBreakPacketsLeft = 1; + while (packetQueue.size() > 0 && movementPacketsLeft > 0 && blockBreakPacketsLeft > 0) { Packet packet = packetQueue.remove(0); - if (packet instanceof PlayerMoveC2SPacket) { + if (packet instanceof PlayerMoveC2SPacket || packet instanceof VehicleMoveC2SPacket) { movementPacketsLeft--; } + if (packet instanceof PlayerActionC2SPacket breakPacket && breakPacket.getAction() == PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK) { + blockBreakPacketsLeft--; + } ((ClientConnectionInvoker) networkHandler.getConnection())._sendImmediately(packet, null); } @@ -187,6 +202,51 @@ public static void checkKeybinds(MinecraftClient client) { client.player.sendMessage(Text.of(PREFIX + "Panic: §cFinished"), true); } } + + while (placeKeybind.wasPressed()) { + placeEnabled = !placeEnabled; + if (placeEnabled) { + client.player.sendMessage(Text.of(PREFIX + "Place: §aEnabled"), true); + } else { + client.player.sendMessage(Text.of(PREFIX + "Place: §cDisabled"), true); + } + } + if (placeEnabled) { + BlockPos[] positions = { + client.player.getBlockPos().add(0, 2, 0), + client.player.getBlockPos().add(1, 1, 0), + client.player.getBlockPos().add(0, 1, 1), + client.player.getBlockPos().add(-1, 1, 0), + client.player.getBlockPos().add(0, 1, -1), + client.player.getBlockPos().add(1, 0, 0), + client.player.getBlockPos().add(0, 0, 1), + client.player.getBlockPos().add(-1, 0, 0), + client.player.getBlockPos().add(0, 0, -1), + }; + // Check if enough blocks in offhand + if (client.player.getOffHandStack().getItem() == Items.COBBLESTONE && client.player.getOffHandStack().getCount() > positions.length) { + for (BlockPos pos : positions) { + if (client.world.getBlockState(pos).isAir()) { // Only place if empty + placeAt(pos); + } + } + } + } } } + + public static void placeAt(BlockPos pos) { + networkHandler.sendPacket( + new PlayerInteractBlockC2SPacket( + Hand.OFF_HAND, + new BlockHitResult( + new Vec3d(pos.getX(), pos.getY(), pos.getZ()), + Direction.DOWN, + pos, + false + ), + 0 + ) + ); + } } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java new file mode 100644 index 0000000..a6ca9d3 --- /dev/null +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java @@ -0,0 +1,136 @@ +package com.jorianwoltjer.liveoverflowmod.command; + +import com.mojang.brigadier.CommandDispatcher; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.client.MinecraftClient; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.network.packet.c2s.play.PlayerInteractBlockC2SPacket; +import net.minecraft.network.packet.c2s.play.VehicleMoveC2SPacket; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3d; + +import static com.jorianwoltjer.liveoverflowmod.client.Keybinds.packetQueue; +import static com.mojang.brigadier.arguments.IntegerArgumentType.integer; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.*; +import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.LOGGER; + +public class ClipCommand { + private static void clipVehicleTo(Entity vehicle, Vec3d pos) { + packetQueue.add(new VehicleMoveC2SPacket(vehicle)); // Queue packet +// networkHandler.sendPacket(new VehicleMoveC2SPacket(vehicle)); // First packet (original position) + vehicle.updatePosition(pos.x, pos.y, pos.z); + packetQueue.add(new VehicleMoveC2SPacket(vehicle)); // Queue packet +// networkHandler.sendPacket(new VehicleMoveC2SPacket(vehicle)); // Far packet + } + + private static void moveVehicleTo(Entity vehicle, Vec3d pos) { + vehicle.updatePosition(pos.x, pos.y, pos.z); + packetQueue.add(new VehicleMoveC2SPacket(vehicle)); // Queue packet +// networkHandler.sendPacket(new VehicleMoveC2SPacket(vehicle)); // Far packet + } + + private static void pressButtonAt(PlayerEntity player, BlockPos pos) { + packetQueue.add( + new PlayerInteractBlockC2SPacket( + player.preferredHand, + new BlockHitResult( + new Vec3d(pos.getX(), pos.getY(), pos.getZ()), + Direction.DOWN, + pos, + false + ), + 0 + ) + ); + } + + public static void register(CommandDispatcher dispatcher) { + dispatcher.register(literal("vault") + .executes(context -> { + PlayerEntity player = context.getSource().getPlayer(); + assert player != null; + Entity vehicle = player.getVehicle(); + assert vehicle != null; + + LOGGER.info("Pressing start button"); + pressButtonAt(player, new BlockPos(4729, 125, 1337)); // Start button + + // y += 53.0 + LOGGER.info("Moving to ceiling right above end button"); + moveVehicleTo(vehicle, vehicle.getPos().add(0, 9.9, 0)); + moveVehicleTo(vehicle, vehicle.getPos().add(0, 9.9, 0)); + moveVehicleTo(vehicle, vehicle.getPos().add(0, 9.9, 0)); + moveVehicleTo(vehicle, vehicle.getPos().add(0, 9.9, 0)); + moveVehicleTo(vehicle, vehicle.getPos().add(0, 9.9, 0)); + moveVehicleTo(vehicle, vehicle.getPos().add(0, 3.5, 0)); + + // x += 53.0 + moveVehicleTo(vehicle, vehicle.getPos().add(9.9, 0, 0)); + moveVehicleTo(vehicle, vehicle.getPos().add(9.9, 0, 0)); + moveVehicleTo(vehicle, vehicle.getPos().add(9.9, 0, 0)); + moveVehicleTo(vehicle, vehicle.getPos().add(9.9, 0, 0)); + moveVehicleTo(vehicle, vehicle.getPos().add(9.9, 0, 0)); + moveVehicleTo(vehicle, vehicle.getPos().add(3.0, 0, 0)); + + // y -= 53.0 (through box) + LOGGER.info("Clipping down through box"); + clipVehicleTo(vehicle, vehicle.getPos().add(0, -53, 0)); + + LOGGER.info("Pressing end button"); + pressButtonAt(player, new BlockPos(4780, 125, 1336)); // End button + + return 1; + }) + ); + + dispatcher.register(literal("vclip") + .then(argument("distance", integer()) + .executes(context -> { + int distance = context.getArgument("distance", Integer.class); + + PlayerEntity player = context.getSource().getPlayer(); + assert player != null; + Entity vehicle = player.getVehicle(); + assert vehicle != null; + clipVehicleTo(vehicle, vehicle.getPos().add(0, distance, 0)); + + return 1; + }) + )); + + // Clip into viewing direction + dispatcher.register(literal("hclip") + .then(argument("distance", integer()) + .executes(context -> { + int distance = context.getArgument("distance", Integer.class); + + PlayerEntity player = context.getSource().getPlayer(); + assert player != null; + Entity vehicle = player.getVehicle(); + assert vehicle != null; + + double yaw = floatMod(player.getYaw(), 360); + + if (yaw < 270+45 && yaw > 270-45) { + clipVehicleTo(vehicle, vehicle.getPos().add(distance, 0, 0)); + } else if (yaw < 180+45 && yaw > 180-45) { + clipVehicleTo(vehicle, vehicle.getPos().add(0, 0, -distance)); + } else if (yaw < 90+45 && yaw > 90-45) { + clipVehicleTo(vehicle, vehicle.getPos().add(-distance, 0, 0)); + } else { + clipVehicleTo(vehicle, vehicle.getPos().add(0, 0, distance)); + } + + return 1; + }) + )); + } + + private static double floatMod(double x, double y) { + // x mod y behaving the same way as Math.floorMod but with doubles + return (x - Math.floor(x/y) * y); + } +} diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java new file mode 100644 index 0000000..246292e --- /dev/null +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java @@ -0,0 +1,36 @@ +package com.jorianwoltjer.liveoverflowmod.mixin; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import net.minecraft.item.ItemStack; +import net.minecraft.network.ClientConnection; +import net.minecraft.network.Packet; +import net.minecraft.network.PacketCallbacks; +import net.minecraft.network.packet.c2s.play.*; +import net.minecraft.screen.slot.SlotActionType; +import net.minecraft.util.hit.BlockHitResult; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.LOGGER; + +@Mixin(ClientConnection.class) +public class ClientConnectionMixin { + // Log packets + @Inject(method = "sendImmediately", at = @At("HEAD")) + void onSendImmediately(Packet packet, @Nullable PacketCallbacks callbacks, CallbackInfo ci) { +// if (packet instanceof PlayerInteractBlockC2SPacket interactPacket) { +// BlockHitResult blockHitResult = interactPacket.getBlockHitResult(); +// LOGGER.info("PlayerInteractBlockC2SPacket: " + blockHitResult.getBlockPos() + " " + blockHitResult.getSide() +// + " " + blockHitResult.getPos() + " " + blockHitResult.isInsideBlock()); +// +// } + +// LOGGER.info("Sending packet: " + packet.getClass().getSimpleName()); +// if (packet instanceof PlayerInteractEntityC2SPacket interactPacket) { +//// LOGGER.info("PlayerInteractEntityC2SPacket: " + interactPacket.getT + " " + interactPacket.()); +// } + } +} diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerEntityMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerEntityMixin.java index 5fec973..f79aee4 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerEntityMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerEntityMixin.java @@ -1,8 +1,12 @@ package com.jorianwoltjer.liveoverflowmod.mixin; import com.jorianwoltjer.liveoverflowmod.client.Keybinds; +import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.network.Packet; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -12,6 +16,8 @@ @Mixin(ClientPlayerEntity.class) public class ClientPlayerEntityMixin { + @Shadow @Final public ClientPlayNetworkHandler networkHandler; + // If this is false, no movement packets will be sent @Redirect(method = "sendMovementPackets", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isCamera()Z")) private boolean isCamera(ClientPlayerEntity instance) { @@ -19,4 +25,19 @@ private boolean isCamera(ClientPlayerEntity instance) { Keybinds.packetQueue.size() == 0; } + // No boat movement packets + @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;hasVehicle()Z")) + private boolean hasVehicle(ClientPlayerEntity instance) { + return instance.getVehicle() != null && + Keybinds.packetQueue.size() == 0; + } + + // No hand swing before attack (will reset the attack cooldown otherwise) + @Redirect(method = "swingHand", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendPacket(Lnet/minecraft/network/Packet;)V")) + private void swingHand(ClientPlayNetworkHandler instance, Packet packet) { + if (Keybinds.packetQueue.size() == 0) { + instance.getConnection().send(packet); + } + } + } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java index febf181..bf140d9 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java @@ -6,6 +6,7 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket; import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket; import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; import net.minecraft.text.Text; @@ -90,6 +91,8 @@ private void attackEntity(ClientPlayerInteractionManager instance, PlayerEntity // Add hit packet in the middle and original position at the end addToMiddle(packetQueue, PlayerInteractEntityC2SPacket.attack(target, client.player.isSneaking())); packetQueue.add(new PlayerMoveC2SPacket.PositionAndOnGround(client.player.getX(), client.player.getY(), client.player.getZ(), true)); + packetQueue.add(new HandSwingC2SPacket(client.player.getActiveHand())); // Serverside animation + client.player.resetLastAttackedTicks(); // Reset attack cooldown } else { // Orignal code if not enabled ClientPlayerInteractionManagerAccessor _instance = (ClientPlayerInteractionManagerAccessor) instance; diff --git a/src/main/resources/assets/liveoverflowmod/lang/en_us.json b/src/main/resources/assets/liveoverflowmod/lang/en_us.json index 66eb7a0..9e1dc6e 100644 --- a/src/main/resources/assets/liveoverflowmod/lang/en_us.json +++ b/src/main/resources/assets/liveoverflowmod/lang/en_us.json @@ -3,5 +3,6 @@ "key.liveoverflowmod.worldguardbypass_toggle": "Toggle WorldGuard Bypass", "key.liveoverflowmod.reach": "Reach", "key.liveoverflowmod.panic": "Panic", - "key.liveoverflowmod.passive_toggle": "Toggle Passive Mods" + "key.liveoverflowmod.passive_toggle": "Toggle Passive Mods", + "key.liveoverflowmod.place": "Place" } \ No newline at end of file diff --git a/src/main/resources/liveoverflowmod.mixins.json b/src/main/resources/liveoverflowmod.mixins.json index cf6660e..1cc2f24 100644 --- a/src/main/resources/liveoverflowmod.mixins.json +++ b/src/main/resources/liveoverflowmod.mixins.json @@ -6,6 +6,7 @@ "mixins": [ "AbstractBlockMixin", "ClientConnectionInvoker", + "ClientConnectionMixin", "ClientPlayerInteractionManagerMixin", "LivingEntityMixin", "PlayerPositionFullPacketMixin", @@ -18,9 +19,9 @@ "client": [ "ClientPlayerEntityAccessor", "ClientPlayerEntityMixin", + "ClientPlayerInteractionManagerAccessor", "ClientPlayNetworkHandlerMixin", "GameStateChangeS2CPacketAccessor", - "ClientPlayerInteractionManagerAccessor", "MinecraftClientMixin" ] } From 993026c552941fde9e6507f9e52de3960ae848e3 Mon Sep 17 00:00:00 2001 From: Jorian Woltjer Date: Fri, 25 Nov 2022 15:14:31 +0100 Subject: [PATCH 03/20] Add panic mode to leave automatically in danger --- .../liveoverflowmod/client/Keybinds.java | 66 +++++++++++++++---- .../liveoverflowmod/command/ClipCommand.java | 48 ++------------ .../mixin/ClientConnectionMixin.java | 14 ++-- .../mixin/ClientPlayNetworkHandlerMixin.java | 14 ++++ .../assets/liveoverflowmod/lang/en_us.json | 8 +-- 5 files changed, 84 insertions(+), 66 deletions(-) diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/client/Keybinds.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/client/Keybinds.java index c0775ca..68cdadb 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/client/Keybinds.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/client/Keybinds.java @@ -1,10 +1,13 @@ package com.jorianwoltjer.liveoverflowmod.client; +import com.jorianwoltjer.liveoverflowmod.command.ClipCommand; import com.jorianwoltjer.liveoverflowmod.mixin.ClientConnectionInvoker; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.DisconnectedScreen; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.option.KeyBinding; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Items; import net.minecraft.network.Packet; import net.minecraft.network.packet.c2s.play.*; @@ -25,7 +28,6 @@ public class Keybinds { public static final String LIVEOVERFLOW_CATEGORY = "category.liveoverflowmod"; public static final double MAX_DELTA = 0.05; - public static final int OFFHAND = 45; public static MinecraftClient mc = MinecraftClient.getInstance(); public static ClientPlayNetworkHandler networkHandler; @@ -34,7 +36,7 @@ public class Keybinds { GLFW.GLFW_KEY_SEMICOLON, LIVEOVERFLOW_CATEGORY); // Bypass WorldGuard region protection private static final KeyBinding reachKeybind = new KeyBinding("key.liveoverflowmod.reach", GLFW.GLFW_KEY_BACKSLASH, LIVEOVERFLOW_CATEGORY); // Extend reach to infinity - private static final KeyBinding panicKeybind = new KeyBinding("key.liveoverflowmod.panic", + private static final KeyBinding panicModeKeybind = new KeyBinding("key.liveoverflowmod.panic", GLFW.GLFW_KEY_COMMA, LIVEOVERFLOW_CATEGORY); // Fly up as fast as possible private static final KeyBinding modToggle = new KeyBinding("key.liveoverflowmod.passive_toggle", GLFW.GLFW_KEY_MINUS, LIVEOVERFLOW_CATEGORY); // Toggle passive mods on/off @@ -46,14 +48,16 @@ public class Keybinds { public static boolean worldGuardBypassEnabled = false; public static boolean reachEnabled = false; public static boolean placeEnabled = false; + public static boolean panicModeEnabled = false; public static boolean passiveModsEnabled = true; public static int flyingTimer = 0; - public static int panicTimer = 0; + public static int panicFlyingTimer = 0; + public static int globalTimer = 0; public static void registerKeybinds() { KeyBindingHelper.registerKeyBinding(worldGuardBypassToggle); KeyBindingHelper.registerKeyBinding(reachKeybind); - KeyBindingHelper.registerKeyBinding(panicKeybind); + KeyBindingHelper.registerKeyBinding(panicModeKeybind); KeyBindingHelper.registerKeyBinding(modToggle); KeyBindingHelper.registerKeyBinding(placeKeybind); } @@ -65,6 +69,8 @@ public static boolean inSameBlock(Vec3d vector, Vec3d other) { } public static void checkKeybinds(MinecraftClient client) { + globalTimer++; + networkHandler = client.getNetworkHandler(); if (client.player != null && client.world != null && networkHandler != null && client.interactionManager != null) { while (modToggle.wasPressed()) { // Toggle whole mod @@ -185,24 +191,40 @@ public static void checkKeybinds(MinecraftClient client) { ((ClientConnectionInvoker) networkHandler.getConnection())._sendImmediately(packet, null); } - // Panic - if (panicKeybind.wasPressed()) { - client.player.sendMessage(Text.of(PREFIX + "Panic: §aFlying up 1000 blocks"), true); - panicTimer = 20; + // Panic Mode + while (panicModeKeybind.wasPressed()) { + panicModeEnabled = !panicModeEnabled; + if (panicModeEnabled) { + client.player.sendMessage(Text.of(PREFIX + "Panic Mode: §aEnabled"), true); + } else { + client.player.sendMessage(Text.of(PREFIX + "Panic Mode: §cDisabled"), true); + } } - if (panicTimer > 0) { - panicTimer--; + if (panicModeEnabled) { + if (client.world.getPlayers().size() > 1) { + triggerPanic(); + } + } + if (panicFlyingTimer > 0) { + panicFlyingTimer--; for (int i = 0; i < 5; i++) { // Max 5 packets per tick Vec3d pos = client.player.getPos().add(0, 10, 0); // Max 10 blocks per packet - client.player.setPosition(pos); client.player.setVelocity(0, 0, 0); - networkHandler.sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true)); + if (client.player.getVehicle() != null) { + ClipCommand.moveVehicleTo(client.player.getVehicle(), pos); + } else { + client.player.setPosition(pos); + networkHandler.sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true)); + } } - if (panicTimer == 0) { // If end - client.player.sendMessage(Text.of(PREFIX + "Panic: §cFinished"), true); + if (panicFlyingTimer == 0) { // If end, disconnect + client.world.disconnect(); + client.disconnect(new DisconnectedScreen(null, Text.of(PREFIX), Text.of("Panic Mode: §cTriggered"))); + return; } } + // Auto-place while (placeKeybind.wasPressed()) { placeEnabled = !placeEnabled; if (placeEnabled) { @@ -232,6 +254,17 @@ public static void checkKeybinds(MinecraftClient client) { } } } + + // Find Herobrine + for (PlayerEntity player : client.world.getPlayers()) { + if (player.getName().getString().equals("Herobrine")) { + client.player.sendMessage(Text.of(String.format(PREFIX + "%s%s Found §r(%.2f, %.2f, %.2f)", + player.getName(), + globalTimer % 10 > 5 ? "" : "§a", + player.getX(), player.getY(), player.getZ())), true); + break; + } + } } } @@ -249,4 +282,9 @@ public static void placeAt(BlockPos pos) { ) ); } + + public static void triggerPanic() { + panicModeEnabled = false; + panicFlyingTimer = 20; // 20 ticks = 1 second + } } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java index a6ca9d3..25756ff 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java @@ -18,18 +18,15 @@ import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.LOGGER; public class ClipCommand { - private static void clipVehicleTo(Entity vehicle, Vec3d pos) { - packetQueue.add(new VehicleMoveC2SPacket(vehicle)); // Queue packet -// networkHandler.sendPacket(new VehicleMoveC2SPacket(vehicle)); // First packet (original position) + public static void clipVehicleTo(Entity vehicle, Vec3d pos) { + packetQueue.add(new VehicleMoveC2SPacket(vehicle)); vehicle.updatePosition(pos.x, pos.y, pos.z); - packetQueue.add(new VehicleMoveC2SPacket(vehicle)); // Queue packet -// networkHandler.sendPacket(new VehicleMoveC2SPacket(vehicle)); // Far packet + packetQueue.add(new VehicleMoveC2SPacket(vehicle)); } - private static void moveVehicleTo(Entity vehicle, Vec3d pos) { + public static void moveVehicleTo(Entity vehicle, Vec3d pos) { vehicle.updatePosition(pos.x, pos.y, pos.z); - packetQueue.add(new VehicleMoveC2SPacket(vehicle)); // Queue packet -// networkHandler.sendPacket(new VehicleMoveC2SPacket(vehicle)); // Far packet + packetQueue.add(new VehicleMoveC2SPacket(vehicle)); } private static void pressButtonAt(PlayerEntity player, BlockPos pos) { @@ -99,38 +96,7 @@ public static void register(CommandDispatcher dispatc return 1; }) - )); - - // Clip into viewing direction - dispatcher.register(literal("hclip") - .then(argument("distance", integer()) - .executes(context -> { - int distance = context.getArgument("distance", Integer.class); - - PlayerEntity player = context.getSource().getPlayer(); - assert player != null; - Entity vehicle = player.getVehicle(); - assert vehicle != null; - - double yaw = floatMod(player.getYaw(), 360); - - if (yaw < 270+45 && yaw > 270-45) { - clipVehicleTo(vehicle, vehicle.getPos().add(distance, 0, 0)); - } else if (yaw < 180+45 && yaw > 180-45) { - clipVehicleTo(vehicle, vehicle.getPos().add(0, 0, -distance)); - } else if (yaw < 90+45 && yaw > 90-45) { - clipVehicleTo(vehicle, vehicle.getPos().add(-distance, 0, 0)); - } else { - clipVehicleTo(vehicle, vehicle.getPos().add(0, 0, distance)); - } - - return 1; - }) - )); - } - - private static double floatMod(double x, double y) { - // x mod y behaving the same way as Math.floorMod but with doubles - return (x - Math.floor(x/y) * y); + ) + ); } } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java index 246292e..c2156de 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java @@ -5,6 +5,7 @@ import net.minecraft.network.ClientConnection; import net.minecraft.network.Packet; import net.minecraft.network.PacketCallbacks; +import net.minecraft.network.listener.PacketListener; import net.minecraft.network.packet.c2s.play.*; import net.minecraft.screen.slot.SlotActionType; import net.minecraft.util.hit.BlockHitResult; @@ -21,16 +22,15 @@ public class ClientConnectionMixin { // Log packets @Inject(method = "sendImmediately", at = @At("HEAD")) void onSendImmediately(Packet packet, @Nullable PacketCallbacks callbacks, CallbackInfo ci) { -// if (packet instanceof PlayerInteractBlockC2SPacket interactPacket) { -// BlockHitResult blockHitResult = interactPacket.getBlockHitResult(); -// LOGGER.info("PlayerInteractBlockC2SPacket: " + blockHitResult.getBlockPos() + " " + blockHitResult.getSide() -// + " " + blockHitResult.getPos() + " " + blockHitResult.isInsideBlock()); -// -// } +// LOGGER.info("---> " + packet.getClass().getSimpleName()); -// LOGGER.info("Sending packet: " + packet.getClass().getSimpleName()); // if (packet instanceof PlayerInteractEntityC2SPacket interactPacket) { //// LOGGER.info("PlayerInteractEntityC2SPacket: " + interactPacket.getT + " " + interactPacket.()); // } } + + @Inject(method = "handlePacket", at = @At("HEAD")) + private static void onHandlePacket(Packet packet, PacketListener listener, CallbackInfo ci) { +// LOGGER.info("<--- " + packet.getClass().getSimpleName()); + } } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayNetworkHandlerMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayNetworkHandlerMixin.java index 86b44ed..417a39d 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayNetworkHandlerMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayNetworkHandlerMixin.java @@ -5,10 +5,16 @@ import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.network.packet.c2s.play.ClientStatusC2SPacket; import net.minecraft.network.packet.s2c.play.GameStateChangeS2CPacket; +import net.minecraft.network.packet.s2c.play.HealthUpdateS2CPacket; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.*; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.invoke.arg.Args; +import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.LOGGER; +import static com.jorianwoltjer.liveoverflowmod.client.Keybinds.panicModeEnabled; +import static com.jorianwoltjer.liveoverflowmod.client.Keybinds.triggerPanic; + @Mixin(ClientPlayNetworkHandler.class) public class ClientPlayNetworkHandlerMixin { // Normalize WorldBorder @@ -42,4 +48,12 @@ private GameStateChangeS2CPacket.Reason getReason(GameStateChangeS2CPacket insta } return reason; } + + // Panic if hit + @Inject(method = "onHealthUpdate", at = @At("HEAD")) + void onHealthUpdate(HealthUpdateS2CPacket packet, CallbackInfo ci) { + if (panicModeEnabled && packet.getHealth() < 20.0F) { + triggerPanic(); + } + } } diff --git a/src/main/resources/assets/liveoverflowmod/lang/en_us.json b/src/main/resources/assets/liveoverflowmod/lang/en_us.json index 9e1dc6e..02579a0 100644 --- a/src/main/resources/assets/liveoverflowmod/lang/en_us.json +++ b/src/main/resources/assets/liveoverflowmod/lang/en_us.json @@ -1,8 +1,8 @@ { "category.liveoverflowmod": "LiveOverflowMod", "key.liveoverflowmod.worldguardbypass_toggle": "Toggle WorldGuard Bypass", - "key.liveoverflowmod.reach": "Reach", - "key.liveoverflowmod.panic": "Panic", - "key.liveoverflowmod.passive_toggle": "Toggle Passive Mods", - "key.liveoverflowmod.place": "Place" + "key.liveoverflowmod.reach": "Toggle Reach", + "key.liveoverflowmod.place": "Toggle Auto Place", + "key.liveoverflowmod.panic": "Toggle Panic Mode", + "key.liveoverflowmod.passive_toggle": "Toggle Passive Mods" } \ No newline at end of file From 9a97c14b0684ea9a049f05363dbb75373a028640 Mon Sep 17 00:00:00 2001 From: Jorian Woltjer Date: Fri, 25 Nov 2022 18:52:42 +0100 Subject: [PATCH 04/20] Refactor code to be in separate files and extended from ToggledHack --- .../client/ClientEntrypoint.java | 56 +++- .../liveoverflowmod/client/Keybinds.java | 290 ------------------ .../liveoverflowmod/command/ClipCommand.java | 13 +- .../liveoverflowmod/hacks/AutoPlace.java | 57 ++++ .../liveoverflowmod/hacks/PanicMode.java | 67 ++++ .../liveoverflowmod/hacks/PassiveMods.java | 60 ++++ .../liveoverflowmod/hacks/Reach.java | 14 + .../liveoverflowmod/hacks/ToggledHack.java | 73 +++++ .../hacks/WorldGuardBypass.java | 110 +++++++ .../helper/{RoundPosition.java => Utils.java} | 52 ++-- .../mixin/AbstractBlockMixin.java | 5 +- .../mixin/ClientConnectionMixin.java | 16 +- .../mixin/ClientPlayNetworkHandlerMixin.java | 18 +- .../mixin/ClientPlayerEntityMixin.java | 17 +- .../ClientPlayerInteractionManagerMixin.java | 21 +- .../mixin/LivingEntityMixin.java | 5 +- .../mixin/MinecraftClientMixin.java | 40 +-- .../mixin/PlayerPositionFullPacketMixin.java | 8 +- .../mixin/PlayerPositionPacketMixin.java | 8 +- .../mixin/VehicleMovePacketMixin.java | 15 +- .../assets/liveoverflowmod/lang/en_us.json | 8 +- 21 files changed, 541 insertions(+), 412 deletions(-) delete mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/client/Keybinds.java create mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/AutoPlace.java create mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PanicMode.java create mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PassiveMods.java create mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/Reach.java create mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java create mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/WorldGuardBypass.java rename src/main/java/com/jorianwoltjer/liveoverflowmod/helper/{RoundPosition.java => Utils.java} (85%) diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java index b579ff0..a980b0a 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java @@ -1,23 +1,69 @@ 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.minecraft.command.CommandRegistryAccess; +import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.network.Packet; +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; +import net.minecraft.network.packet.c2s.play.VehicleMoveC2SPacket; + +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 PanicMode panicModeHack = new PanicMode(); + public static final AutoPlace autoPlaceHack = new AutoPlace(); + final ToggledHack[] toggledHacks = new ToggledHack[] { + passiveMods, + worldGuardBypassHack, + reachHack, + panicModeHack, + autoPlaceHack, + }; + public static final MinecraftClient client = MinecraftClient.getInstance(); + public static ClientPlayNetworkHandler networkHandler; + public static int globalTimer = 0; + public static final LinkedList> packetQueue = new LinkedList<>(); + @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::tick); // Every tick + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> registerCommands(dispatcher)); // Commands + } + + public static void tick(MinecraftClient client) { + // Update variables + networkHandler = client.getNetworkHandler(); + globalTimer++; - ClientCommandRegistrationCallback.EVENT.register(ClientEntrypoint::registerCommands); + // Send packets from reach 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 registerCommands(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess) { + public static void registerCommands(CommandDispatcher dispatcher) { ClipCommand.register(dispatcher); } } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/client/Keybinds.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/client/Keybinds.java deleted file mode 100644 index 68cdadb..0000000 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/client/Keybinds.java +++ /dev/null @@ -1,290 +0,0 @@ -package com.jorianwoltjer.liveoverflowmod.client; - -import com.jorianwoltjer.liveoverflowmod.command.ClipCommand; -import com.jorianwoltjer.liveoverflowmod.mixin.ClientConnectionInvoker; -import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.DisconnectedScreen; -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.client.option.KeyBinding; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.Items; -import net.minecraft.network.Packet; -import net.minecraft.network.packet.c2s.play.*; -import net.minecraft.text.Text; -import net.minecraft.util.Hand; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.Vec3d; -import org.lwjgl.glfw.GLFW; - -import java.util.LinkedList; - -import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.LOGGER; -import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.PREFIX; - - -public class Keybinds { - public static final String LIVEOVERFLOW_CATEGORY = "category.liveoverflowmod"; - public static final double MAX_DELTA = 0.05; - - public static MinecraftClient mc = MinecraftClient.getInstance(); - public static ClientPlayNetworkHandler networkHandler; - - private static final KeyBinding worldGuardBypassToggle = new KeyBinding("key.liveoverflowmod.worldguardbypass_toggle", - GLFW.GLFW_KEY_SEMICOLON, LIVEOVERFLOW_CATEGORY); // Bypass WorldGuard region protection - private static final KeyBinding reachKeybind = new KeyBinding("key.liveoverflowmod.reach", - GLFW.GLFW_KEY_BACKSLASH, LIVEOVERFLOW_CATEGORY); // Extend reach to infinity - private static final KeyBinding panicModeKeybind = new KeyBinding("key.liveoverflowmod.panic", - GLFW.GLFW_KEY_COMMA, LIVEOVERFLOW_CATEGORY); // Fly up as fast as possible - private static final KeyBinding modToggle = new KeyBinding("key.liveoverflowmod.passive_toggle", - GLFW.GLFW_KEY_MINUS, LIVEOVERFLOW_CATEGORY); // Toggle passive mods on/off - private static final KeyBinding placeKeybind = new KeyBinding("key.liveoverflowmod.place", - GLFW.GLFW_KEY_RIGHT_BRACKET, LIVEOVERFLOW_CATEGORY); // Place blocks around you - - // packetQueue: [1, 2, 3, 4, 5, A, 4, 3, 2, 1, 0] - public static LinkedList> packetQueue = new LinkedList<>(); - public static boolean worldGuardBypassEnabled = false; - public static boolean reachEnabled = false; - public static boolean placeEnabled = false; - public static boolean panicModeEnabled = false; - public static boolean passiveModsEnabled = true; - public static int flyingTimer = 0; - public static int panicFlyingTimer = 0; - public static int globalTimer = 0; - - public static void registerKeybinds() { - KeyBindingHelper.registerKeyBinding(worldGuardBypassToggle); - KeyBindingHelper.registerKeyBinding(reachKeybind); - KeyBindingHelper.registerKeyBinding(panicModeKeybind); - KeyBindingHelper.registerKeyBinding(modToggle); - KeyBindingHelper.registerKeyBinding(placeKeybind); - } - - public static boolean inSameBlock(Vec3d vector, Vec3d other) { - return other.x >= Math.floor(vector.x) && other.x <= Math.ceil(vector.x) && - other.y >= Math.floor(vector.y) && other.y <= Math.ceil(vector.y) && - other.z >= Math.floor(vector.z) && other.z <= Math.ceil(vector.z); - } - - public static void checkKeybinds(MinecraftClient client) { - globalTimer++; - - networkHandler = client.getNetworkHandler(); - if (client.player != null && client.world != null && networkHandler != null && client.interactionManager != null) { - while (modToggle.wasPressed()) { // Toggle whole mod - passiveModsEnabled = !passiveModsEnabled; - if (passiveModsEnabled) { - client.player.sendMessage(Text.of(PREFIX + "Passive Mods: §aEnabled"), true); - } else { - client.player.sendMessage(Text.of(PREFIX + "Passive Mods: §cDisabled"), true); - } - // Reload chunks - client.worldRenderer.reload(); - } - - // Toggle WorldGuard Bypass - while (worldGuardBypassToggle.wasPressed()) { - flyingTimer = 0; - if (worldGuardBypassEnabled) { - worldGuardBypassEnabled = false; - client.player.sendMessage(Text.of(PREFIX + "WorldGuard Bypass: §cDisabled"), true); - } else { - worldGuardBypassEnabled = true; - client.player.sendMessage(Text.of(PREFIX + "WorldGuard Bypass: §aEnabled"), true); - } - } - - // WorldGuard bypass - if (worldGuardBypassEnabled) { - if (++flyingTimer > 20) { // Max 80, to bypass "Flying is not enabled" - ((ClientConnectionInvoker) networkHandler.getConnection())._sendImmediately(new PlayerMoveC2SPacket.PositionAndOnGround(client.player.getX(), - client.player.getY() - 0.04, client.player.getZ(), client.player.isOnGround()), null); - flyingTimer = 0; // Reset - } else { - client.player.setVelocity(0, 0, 0); - - Vec3d vec = new Vec3d(0, 0, 0); - - // Key presses changing position - if (client.player.input.jumping) { // Move up - vec = vec.add(new Vec3d(0, 1, 0)); - } else if (client.player.input.sneaking) { // Move down - vec = vec.add(new Vec3d(0, -1, 0)); - } else { - // Horizontal movement (not at the same time as vertical) - if (client.player.input.pressingForward) { - vec = vec.add(new Vec3d(0, 0, 1)); - } - if (client.player.input.pressingRight) { - vec = vec.add(new Vec3d(1, 0, 0)); - } - if (client.player.input.pressingBack) { - vec = vec.add(new Vec3d(0, 0, -1)); - } - if (client.player.input.pressingLeft) { - vec = vec.add(new Vec3d(-1, 0, 0)); - } - } - - if (vec.length() > 0) { - vec = vec.normalize(); // Normalize to length 1 - - if (!(vec.x == 0 && vec.z == 0)) { // Rotate by looking yaw (won't change length) - double moveAngle = Math.atan2(vec.x, vec.z) + Math.toRadians(client.player.getYaw() + 90); - double x = Math.cos(moveAngle); - double z = Math.sin(moveAngle); - vec = new Vec3d(x, vec.y, z); - } - - vec = vec.multiply(MAX_DELTA); // Scale to maxDelta - - Vec3d newPos = new Vec3d(client.player.getX() + vec.x, client.player.getY() + vec.y, client.player.getZ() + vec.z); - // If able to add more without going over a block boundary, add more - boolean extra = false; - if (client.options.sprintKey.isPressed()) { // Trigger by sprinting - while (inSameBlock(newPos.add(vec.multiply(1.5)), new Vec3d(client.player.prevX, client.player.prevY, client.player.prevZ))) { - newPos = newPos.add(vec); - extra = true; - } - } - - client.player.setPosition(newPos); - - // Send tiny movement so delta is small enough - PlayerMoveC2SPacket.Full smallMovePacket = new PlayerMoveC2SPacket.Full(client.player.getX(), client.player.getY(), - client.player.getZ(), client.player.getYaw(), client.player.getPitch(), client.player.isOnGround()); - networkHandler.getConnection().send(smallMovePacket); - - // Send far away packet for "moving too quickly!" to reset position - if (!extra) { - PlayerMoveC2SPacket.Full farPacket = new PlayerMoveC2SPacket.Full(client.player.getX() + 1337.0, client.player.getY() + 1337.0, - client.player.getZ() + 1337.0, client.player.getYaw(), client.player.getPitch(), client.player.isOnGround()); - networkHandler.getConnection().send(farPacket); - } - } - } - } - - // Reach - while (reachKeybind.wasPressed()) { - reachEnabled = !reachEnabled; - if (reachEnabled) { - client.player.sendMessage(Text.of(PREFIX + "Reach: §aEnabled"), true); - } else { - client.player.sendMessage(Text.of(PREFIX + "Reach: §cDisabled"), true); - } - } - - // Send packets from reach queue (max 5) - int movementPacketsLeft = 5; - int blockBreakPacketsLeft = 1; - while (packetQueue.size() > 0 && movementPacketsLeft > 0 && blockBreakPacketsLeft > 0) { - Packet packet = packetQueue.remove(0); - if (packet instanceof PlayerMoveC2SPacket || packet instanceof VehicleMoveC2SPacket) { - movementPacketsLeft--; - } - if (packet instanceof PlayerActionC2SPacket breakPacket && breakPacket.getAction() == PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK) { - blockBreakPacketsLeft--; - } - ((ClientConnectionInvoker) networkHandler.getConnection())._sendImmediately(packet, null); - } - - // Panic Mode - while (panicModeKeybind.wasPressed()) { - panicModeEnabled = !panicModeEnabled; - if (panicModeEnabled) { - client.player.sendMessage(Text.of(PREFIX + "Panic Mode: §aEnabled"), true); - } else { - client.player.sendMessage(Text.of(PREFIX + "Panic Mode: §cDisabled"), true); - } - } - if (panicModeEnabled) { - if (client.world.getPlayers().size() > 1) { - triggerPanic(); - } - } - if (panicFlyingTimer > 0) { - panicFlyingTimer--; - for (int i = 0; i < 5; i++) { // Max 5 packets per tick - Vec3d pos = client.player.getPos().add(0, 10, 0); // Max 10 blocks per packet - client.player.setVelocity(0, 0, 0); - if (client.player.getVehicle() != null) { - ClipCommand.moveVehicleTo(client.player.getVehicle(), pos); - } else { - client.player.setPosition(pos); - networkHandler.sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true)); - } - } - if (panicFlyingTimer == 0) { // If end, disconnect - client.world.disconnect(); - client.disconnect(new DisconnectedScreen(null, Text.of(PREFIX), Text.of("Panic Mode: §cTriggered"))); - return; - } - } - - // Auto-place - while (placeKeybind.wasPressed()) { - placeEnabled = !placeEnabled; - if (placeEnabled) { - client.player.sendMessage(Text.of(PREFIX + "Place: §aEnabled"), true); - } else { - client.player.sendMessage(Text.of(PREFIX + "Place: §cDisabled"), true); - } - } - if (placeEnabled) { - BlockPos[] positions = { - client.player.getBlockPos().add(0, 2, 0), - client.player.getBlockPos().add(1, 1, 0), - client.player.getBlockPos().add(0, 1, 1), - client.player.getBlockPos().add(-1, 1, 0), - client.player.getBlockPos().add(0, 1, -1), - client.player.getBlockPos().add(1, 0, 0), - client.player.getBlockPos().add(0, 0, 1), - client.player.getBlockPos().add(-1, 0, 0), - client.player.getBlockPos().add(0, 0, -1), - }; - // Check if enough blocks in offhand - if (client.player.getOffHandStack().getItem() == Items.COBBLESTONE && client.player.getOffHandStack().getCount() > positions.length) { - for (BlockPos pos : positions) { - if (client.world.getBlockState(pos).isAir()) { // Only place if empty - placeAt(pos); - } - } - } - } - - // Find Herobrine - for (PlayerEntity player : client.world.getPlayers()) { - if (player.getName().getString().equals("Herobrine")) { - client.player.sendMessage(Text.of(String.format(PREFIX + "%s%s Found §r(%.2f, %.2f, %.2f)", - player.getName(), - globalTimer % 10 > 5 ? "" : "§a", - player.getX(), player.getY(), player.getZ())), true); - break; - } - } - } - } - - public static void placeAt(BlockPos pos) { - networkHandler.sendPacket( - new PlayerInteractBlockC2SPacket( - Hand.OFF_HAND, - new BlockHitResult( - new Vec3d(pos.getX(), pos.getY(), pos.getZ()), - Direction.DOWN, - pos, - false - ), - 0 - ) - ); - } - - public static void triggerPanic() { - panicModeEnabled = false; - panicFlyingTimer = 20; // 20 ticks = 1 second - } -} diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java index 25756ff..9ca5b5c 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java @@ -2,7 +2,6 @@ import com.mojang.brigadier.CommandDispatcher; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.client.MinecraftClient; import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.packet.c2s.play.PlayerInteractBlockC2SPacket; @@ -12,7 +11,7 @@ import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; -import static com.jorianwoltjer.liveoverflowmod.client.Keybinds.packetQueue; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.packetQueue; import static com.mojang.brigadier.arguments.IntegerArgumentType.integer; import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.*; import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.LOGGER; @@ -48,9 +47,9 @@ public static void register(CommandDispatcher dispatc dispatcher.register(literal("vault") .executes(context -> { PlayerEntity player = context.getSource().getPlayer(); - assert player != null; Entity vehicle = player.getVehicle(); - assert vehicle != null; + + if (vehicle == null) return 0; LOGGER.info("Pressing start button"); pressButtonAt(player, new BlockPos(4729, 125, 1337)); // Start button @@ -87,11 +86,11 @@ public static void register(CommandDispatcher dispatc .then(argument("distance", integer()) .executes(context -> { int distance = context.getArgument("distance", Integer.class); - PlayerEntity player = context.getSource().getPlayer(); - assert player != null; Entity vehicle = player.getVehicle(); - assert vehicle != null; + + if (vehicle == null) return 0; + clipVehicleTo(vehicle, vehicle.getPos().add(0, distance, 0)); return 1; diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/AutoPlace.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/AutoPlace.java new file mode 100644 index 0000000..029f685 --- /dev/null +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/AutoPlace.java @@ -0,0 +1,57 @@ +package com.jorianwoltjer.liveoverflowmod.hacks; + +import net.minecraft.network.packet.c2s.play.PlayerInteractBlockC2SPacket; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3d; +import org.lwjgl.glfw.GLFW; + +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.client; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.networkHandler; + +public class AutoPlace extends ToggledHack { + /** + * Automatically place blocks around you. + * Uses the item in your *offhand* and makes sure to wait if you run out of blocks. + */ + public AutoPlace() { + super("Auto Place", GLFW.GLFW_KEY_RIGHT_BRACKET); + } + + @Override + public void tickEnabled() { + if (client.player == null || client.world == null) return; + + BlockPos[] positions = { // All positions around you (except floor) + client.player.getBlockPos().add(0, 2, 0), + client.player.getBlockPos().add(1, 1, 0), + client.player.getBlockPos().add(0, 1, 1), + client.player.getBlockPos().add(-1, 1, 0), + client.player.getBlockPos().add(0, 1, -1), + client.player.getBlockPos().add(1, 0, 0), + client.player.getBlockPos().add(0, 0, 1), + client.player.getBlockPos().add(-1, 0, 0), + client.player.getBlockPos().add(0, 0, -1), + }; + // Enough blocks in offhand + if (client.player.getOffHandStack().getCount() > positions.length) { + for (BlockPos pos : positions) { + if (client.world.getBlockState(pos).isAir()) { // Only place if empty + placeAt(pos); + } + } + } + } + + public static void placeAt(BlockPos pos) { + BlockHitResult hitResult = new BlockHitResult( + new Vec3d(pos.getX(), pos.getY(), pos.getZ()), + Direction.UP, + pos, + false + ); + networkHandler.sendPacket(new PlayerInteractBlockC2SPacket(Hand.OFF_HAND, hitResult, 0)); + } +} diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PanicMode.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PanicMode.java new file mode 100644 index 0000000..38d348f --- /dev/null +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PanicMode.java @@ -0,0 +1,67 @@ +package com.jorianwoltjer.liveoverflowmod.hacks; + +import com.jorianwoltjer.liveoverflowmod.command.ClipCommand; +import com.jorianwoltjer.liveoverflowmod.mixin.ClientPlayNetworkHandlerMixin; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.DisconnectedScreen; +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; +import net.minecraft.text.Text; +import net.minecraft.util.math.Vec3d; +import org.lwjgl.glfw.GLFW; + +import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.PREFIX; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.client; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.networkHandler; + +public class PanicMode extends ToggledHack { + int panicFlyingTimer = 0; + + /** + * Fly up and disconnect if the player is in a dangerous situation. + * - If another player is in render distance + * - If health goes down + * @see ClientPlayNetworkHandlerMixin + */ + public PanicMode() { + super("Panic", GLFW.GLFW_KEY_M); + } + + @Override + public void tick(MinecraftClient client) { + super.tick(client); + if (client.player == null || client.world == null) return; + + if (panicFlyingTimer > 0) { // TODO: make this code simpler + panicFlyingTimer--; + for (int i = 0; i < 5; i++) { // Max 5 packets per tick + Vec3d pos = client.player.getPos().add(0, 10, 0); // Max 10 blocks per packet + client.player.setVelocity(0, 0, 0); + if (client.player.getVehicle() != null) { + ClipCommand.moveVehicleTo(client.player.getVehicle(), pos); + } else { + client.player.setPosition(pos); + networkHandler.sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true)); + } + } + if (panicFlyingTimer == 0) { // If end, disconnect + client.world.disconnect(); + client.disconnect(new DisconnectedScreen(null, Text.of(PREFIX), Text.of("Panic Mode: §cTriggered"))); + } + } + } + + @Override + public void tickEnabled() { + if (client.world == null) return; + + if (client.world.getPlayers().size() > 1) { + triggerPanic(); + } + } + + public void triggerPanic() { + this.enabled = false; + panicFlyingTimer = 20; // 20 ticks = 1 second + message("§cTriggered§r, flying up..."); + } +} diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PassiveMods.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PassiveMods.java new file mode 100644 index 0000000..84f4fc5 --- /dev/null +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PassiveMods.java @@ -0,0 +1,60 @@ +package com.jorianwoltjer.liveoverflowmod.hacks; + +import com.jorianwoltjer.liveoverflowmod.mixin.*; +import net.minecraft.entity.player.PlayerEntity; + +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.client; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.globalTimer; +import static org.lwjgl.glfw.GLFW.GLFW_KEY_MINUS; + +public class PassiveMods extends ToggledHack { + /** + * Passive mods that should always be on. + * - Randomize Texture Rotations + * - Disable Weird Packets: World Border, Creative Mode, Demo Mode, End Credits + * - Insta-Mine + * - Anti-Human Bypass (round coordinates) + * @see AbstractBlockMixin + * @see ClientPlayNetworkHandlerMixin + * @see ClientPlayerInteractionManagerMixin + * @see PlayerPositionFullPacketMixin + * @see PlayerPositionPacketMixin + * @see VehicleMovePacketMixin + */ + public PassiveMods() { + super("Passive Mods", GLFW_KEY_MINUS); + this.enabled = true; // Default on + } + + @Override + public void tickEnabled() { + if (client.world == null) return; + + // Find Herobrine + for (PlayerEntity player : client.world.getPlayers()) { + if (player.getName().getString().equals("Herobrine")) { + message(String.format( + "%sFound %s §r(%.1f, %.1f, %.1f)", + globalTimer % 8 > 4 ? "" : "§a", // Blinking + player.getName().getString(), + player.getX(), player.getY(), player.getZ() + )); + break; + } + } + } + + @Override + public void onEnable() { + super.onEnable(); + + client.worldRenderer.reload(); // Reload chunks (for Texture Rotations) + } + + @Override + public void onDisable() { + super.onDisable(); + + client.worldRenderer.reload(); // Reload chunks (for Texture Rotations) + } +} diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/Reach.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/Reach.java new file mode 100644 index 0000000..bf16df3 --- /dev/null +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/Reach.java @@ -0,0 +1,14 @@ +package com.jorianwoltjer.liveoverflowmod.hacks; + +import com.jorianwoltjer.liveoverflowmod.mixin.MinecraftClientMixin; +import org.lwjgl.glfw.GLFW; + +public class Reach extends ToggledHack { + /** + * Hit enitities from far away + * @see MinecraftClientMixin + */ + public Reach() { + super("Reach", GLFW.GLFW_KEY_BACKSLASH); + } +} diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java new file mode 100644 index 0000000..6a24b53 --- /dev/null +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java @@ -0,0 +1,73 @@ +package com.jorianwoltjer.liveoverflowmod.hacks; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.text.Text; + +import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.PREFIX; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.client; + +public abstract class ToggledHack { + public static final String LIVEOVERFLOW_CATEGORY = "category.liveoverflowmod"; + + public final KeyBinding keybind; + public final String name; + public boolean enabled = false; + + /** + * A hack that can be toggled on/off + * @param name Display name of the hack + * @param key The GLFW key code of the keybind + */ + ToggledHack(String name, int key) { + keybind = new KeyBinding("key.liveoverflowmod." + this.getClass().getSimpleName().toLowerCase() + "_toggle", + key, LIVEOVERFLOW_CATEGORY); + this.name = name; + } + + /** + * Called every tick + */ + public void tick(MinecraftClient client) { // Called every tick + if (keybind.wasPressed()) { + enabled = !enabled; + if (enabled) { + onEnable(); + } else { + onDisable(); + } + } + if (enabled) { + tickEnabled(); + } + } + + /** + * Called every tick, but only when the hack is enabled + */ + public void tickEnabled() {} + + /** + * Called when the hack is enabled + */ + void onEnable() { + message("§aEnabled"); + } + + /** + * Called when the hack is disabled + */ + void onDisable() { + message("§cDisabled"); + } + + /** + * Send a message via the action bar with the prefix + * @param message The message to send + */ + public void message(String message) { + if (client.player == null) return; + + client.player.sendMessage(Text.of(PREFIX + name + ": " + message), true); + } +} diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/WorldGuardBypass.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/WorldGuardBypass.java new file mode 100644 index 0000000..2f30ed3 --- /dev/null +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/WorldGuardBypass.java @@ -0,0 +1,110 @@ +package com.jorianwoltjer.liveoverflowmod.hacks; + +import com.jorianwoltjer.liveoverflowmod.mixin.ClientConnectionInvoker; +import com.jorianwoltjer.liveoverflowmod.mixin.LivingEntityMixin; +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; +import net.minecraft.util.math.Vec3d; +import org.lwjgl.glfw.GLFW; + +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.client; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.networkHandler; + +public class WorldGuardBypass extends ToggledHack { + final double MAX_DELTA = 0.05; // Absolute maximum is sqrt(1/256) = 0.0625 + int flyingTimer = 0; + + /** + * Walk through a WorldGuard protected region (with entry: deny) by avoiding `PlayerMoveEvent`s + * @see LivingEntityMixin + */ + public WorldGuardBypass() { + super("WorldGuard Bypass", GLFW.GLFW_KEY_SEMICOLON); + } + + @Override + public void tickEnabled() { + if (client.player == null) return; + + if (++flyingTimer > 20) { // Max 80, to bypass "Flying is not enabled" + ((ClientConnectionInvoker) networkHandler.getConnection())._sendImmediately(new PlayerMoveC2SPacket.PositionAndOnGround(client.player.getX(), + client.player.getY() - 0.04, client.player.getZ(), client.player.isOnGround()), null); + flyingTimer = 0; // Reset + } else { + client.player.setVelocity(0, 0, 0); + + Vec3d vec = new Vec3d(0, 0, 0); + + // Key presses changing position + if (client.player.input.jumping) { // Move up + vec = vec.add(new Vec3d(0, 1, 0)); + } else if (client.player.input.sneaking) { // Move down + vec = vec.add(new Vec3d(0, -1, 0)); + } else { + // Horizontal movement (not at the same time as vertical) + if (client.player.input.pressingForward) { + vec = vec.add(new Vec3d(0, 0, 1)); + } + if (client.player.input.pressingRight) { + vec = vec.add(new Vec3d(1, 0, 0)); + } + if (client.player.input.pressingBack) { + vec = vec.add(new Vec3d(0, 0, -1)); + } + if (client.player.input.pressingLeft) { + vec = vec.add(new Vec3d(-1, 0, 0)); + } + } + + if (vec.length() > 0) { + vec = vec.normalize(); // Normalize to length 1 + + if (!(vec.x == 0 && vec.z == 0)) { // Rotate by looking yaw (won't change length) + double moveAngle = Math.atan2(vec.x, vec.z) + Math.toRadians(client.player.getYaw() + 90); + double x = Math.cos(moveAngle); + double z = Math.sin(moveAngle); + vec = new Vec3d(x, vec.y, z); + } + + vec = vec.multiply(MAX_DELTA); // Scale to maxDelta + + Vec3d newPos = new Vec3d(client.player.getX() + vec.x, client.player.getY() + vec.y, client.player.getZ() + vec.z); + // If able to add more without going over a block boundary, add more + boolean extra = false; + if (client.options.sprintKey.isPressed()) { // Trigger by sprinting + while (inSameBlock(newPos.add(vec.multiply(1.5)), new Vec3d(client.player.prevX, client.player.prevY, client.player.prevZ))) { + newPos = newPos.add(vec); + extra = true; + } + } + + client.player.setPosition(newPos); + + // Send tiny movement so delta is small enough + PlayerMoveC2SPacket.Full smallMovePacket = new PlayerMoveC2SPacket.Full(client.player.getX(), client.player.getY(), + client.player.getZ(), client.player.getYaw(), client.player.getPitch(), client.player.isOnGround()); + networkHandler.getConnection().send(smallMovePacket); + + // Send far away packet for "moving too quickly!" to reset position + if (!extra) { + PlayerMoveC2SPacket.Full farPacket = new PlayerMoveC2SPacket.Full(client.player.getX() + 1337.0, client.player.getY() + 1337.0, + client.player.getZ() + 1337.0, client.player.getYaw(), client.player.getPitch(), client.player.isOnGround()); + networkHandler.getConnection().send(farPacket); + } + } + } + } + + @Override + public void onDisable() { + super.onDisable(); + + flyingTimer = 0; + } + + public static boolean inSameBlock(Vec3d vector, Vec3d other) { + return other.x >= Math.floor(vector.x) && other.x <= Math.ceil(vector.x) && + other.y >= Math.floor(vector.y) && other.y <= Math.ceil(vector.y) && + other.z >= Math.floor(vector.z) && other.z <= Math.ceil(vector.z); + } + +} diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/helper/RoundPosition.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/helper/Utils.java similarity index 85% rename from src/main/java/com/jorianwoltjer/liveoverflowmod/helper/RoundPosition.java rename to src/main/java/com/jorianwoltjer/liveoverflowmod/helper/Utils.java index efea851..137fe9e 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/helper/RoundPosition.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/helper/Utils.java @@ -1,25 +1,27 @@ -package com.jorianwoltjer.liveoverflowmod.helper; - -import org.spongepowered.asm.mixin.injection.invoke.arg.Args; - -public class RoundPosition { - - public static double roundCoordinate(double n) { - n = Math.round(n * 100) / 100d; // Round to 1/100th - return Math.nextAfter(n, n + Math.signum(n)); // Fix floating point errors - } - - public static void onPositionPacket(Args args) { - double x = args.get(0); - double y = args.get(1); - double z = args.get(2); - - // Round to 100ths for "Anti-Human" check - x = roundCoordinate(x); - z = roundCoordinate(z); - - args.set(0, x); - args.set(1, y); - args.set(2, z); - } -} +package com.jorianwoltjer.liveoverflowmod.helper; + +import org.spongepowered.asm.mixin.injection.invoke.arg.Args; + +public class Utils { + + public static double roundCoordinate(double n) { + n = Math.round(n * 100) / 100d; // Round to 1/100th + return Math.nextAfter(n, n + Math.signum(n)); // Fix floating point errors + } + + public static void onPositionPacket(Args args) { + double x = args.get(0); + double y = args.get(1); + double z = args.get(2); + + // Round to 100ths for Anti-Human check + x = roundCoordinate(x); + z = roundCoordinate(z); + + args.set(0, x); + args.set(1, y); + args.set(2, z); + } + + +} diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/AbstractBlockMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/AbstractBlockMixin.java index 5d1ddc1..7409ee2 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/AbstractBlockMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/AbstractBlockMixin.java @@ -1,6 +1,5 @@ package com.jorianwoltjer.liveoverflowmod.mixin; -import com.jorianwoltjer.liveoverflowmod.client.Keybinds; import net.minecraft.block.AbstractBlock; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3i; @@ -11,6 +10,8 @@ import java.util.Objects; import java.util.Random; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.passiveMods; + @Mixin(AbstractBlock.class) public class AbstractBlockMixin { private static final long xFactor = new Random().nextLong(); @@ -20,7 +21,7 @@ public class AbstractBlockMixin { // Randomize texture rotations (prevent leaks) @Redirect(method="getRenderingSeed", at=@At(value="INVOKE", target="Lnet/minecraft/util/math/MathHelper;hashCode(Lnet/minecraft/util/math/Vec3i;)J")) private long getSeed(Vec3i vec) { - if (Keybinds.passiveModsEnabled) { + if (passiveMods.enabled) { return Objects.hash(vec.getX() * xFactor, vec.getY() * yFactor, vec.getZ() * zFactor); } else { return MathHelper.hashCode(vec); diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java index c2156de..419da3e 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java @@ -1,14 +1,10 @@ package com.jorianwoltjer.liveoverflowmod.mixin; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import net.minecraft.item.ItemStack; import net.minecraft.network.ClientConnection; import net.minecraft.network.Packet; import net.minecraft.network.PacketCallbacks; import net.minecraft.network.listener.PacketListener; -import net.minecraft.network.packet.c2s.play.*; -import net.minecraft.screen.slot.SlotActionType; -import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -20,15 +16,21 @@ @Mixin(ClientConnection.class) public class ClientConnectionMixin { // Log packets + @SuppressWarnings({"EmptyMethod", "CommentedOutCode"}) @Inject(method = "sendImmediately", at = @At("HEAD")) void onSendImmediately(Packet packet, @Nullable PacketCallbacks callbacks, CallbackInfo ci) { // LOGGER.info("---> " + packet.getClass().getSimpleName()); -// if (packet instanceof PlayerInteractEntityC2SPacket interactPacket) { -//// LOGGER.info("PlayerInteractEntityC2SPacket: " + interactPacket.getT + " " + interactPacket.()); +// if (packet instanceof PlayerMoveC2SPacket _packet) { +// LOGGER.info(String.format("PlayerMoveC2SPacket(%.3f, %.3f, %.3f)", +// _packet.getX(0), +// _packet.getY(0), +// _packet.getZ(0) +// )); // } } + @SuppressWarnings({"EmptyMethod"}) @Inject(method = "handlePacket", at = @At("HEAD")) private static void onHandlePacket(Packet packet, PacketListener listener, CallbackInfo ci) { // LOGGER.info("<--- " + packet.getClass().getSimpleName()); diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayNetworkHandlerMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayNetworkHandlerMixin.java index 417a39d..5e62aa0 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayNetworkHandlerMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayNetworkHandlerMixin.java @@ -1,7 +1,5 @@ package com.jorianwoltjer.liveoverflowmod.mixin; -import com.jorianwoltjer.liveoverflowmod.client.Keybinds; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.network.packet.c2s.play.ClientStatusC2SPacket; import net.minecraft.network.packet.s2c.play.GameStateChangeS2CPacket; @@ -11,22 +9,20 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.invoke.arg.Args; -import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.LOGGER; -import static com.jorianwoltjer.liveoverflowmod.client.Keybinds.panicModeEnabled; -import static com.jorianwoltjer.liveoverflowmod.client.Keybinds.triggerPanic; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*; @Mixin(ClientPlayNetworkHandler.class) public class ClientPlayNetworkHandlerMixin { // Normalize WorldBorder @ModifyArgs(method = "onWorldBorderInitialize", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/border/WorldBorder;setSize(D)V")) private void setSize(Args args) { // Set radius to default 30 million - if (Keybinds.passiveModsEnabled) { + if (passiveMods.enabled) { args.set(0, 30000000.0D); // radius } } @ModifyArgs(method = "onWorldBorderInitialize", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/border/WorldBorder;setCenter(DD)V")) private void setCenter(Args args) { // Set center to 0 0 - if (Keybinds.passiveModsEnabled) { + if (passiveMods.enabled) { args.set(0, 0.0D); // x args.set(1, 0.0D); // z } @@ -36,13 +32,13 @@ private void setCenter(Args args) { // Set center to 0 0 @Redirect(method = "onGameStateChange", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/packet/s2c/play/GameStateChangeS2CPacket;getReason()Lnet/minecraft/network/packet/s2c/play/GameStateChangeS2CPacket$Reason;")) private GameStateChangeS2CPacket.Reason getReason(GameStateChangeS2CPacket instance) { GameStateChangeS2CPacket.Reason reason = ((GameStateChangeS2CPacketAccessor) instance)._reason(); - if (Keybinds.passiveModsEnabled) { + if (passiveMods.enabled) { if (reason.equals(GameStateChangeS2CPacket.DEMO_MESSAGE_SHOWN) || // Demo popup reason.equals(GameStateChangeS2CPacket.GAME_MODE_CHANGED)) { // Creative mode // Completely ignore packets return null; } else if (reason.equals(GameStateChangeS2CPacket.GAME_WON)) { // End credits (still send respawn packet) - MinecraftClient.getInstance().getNetworkHandler().sendPacket(new ClientStatusC2SPacket(ClientStatusC2SPacket.Mode.PERFORM_RESPAWN)); + networkHandler.sendPacket(new ClientStatusC2SPacket(ClientStatusC2SPacket.Mode.PERFORM_RESPAWN)); return null; } } @@ -52,8 +48,8 @@ private GameStateChangeS2CPacket.Reason getReason(GameStateChangeS2CPacket insta // Panic if hit @Inject(method = "onHealthUpdate", at = @At("HEAD")) void onHealthUpdate(HealthUpdateS2CPacket packet, CallbackInfo ci) { - if (panicModeEnabled && packet.getHealth() < 20.0F) { - triggerPanic(); + if (panicModeHack.enabled && packet.getHealth() < 20.0F) { + panicModeHack.triggerPanic(); } } } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerEntityMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerEntityMixin.java index f79aee4..74422ee 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerEntityMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerEntityMixin.java @@ -1,41 +1,34 @@ package com.jorianwoltjer.liveoverflowmod.mixin; -import com.jorianwoltjer.liveoverflowmod.client.Keybinds; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.network.Packet; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.packetQueue; @Mixin(ClientPlayerEntity.class) public class ClientPlayerEntityMixin { - - @Shadow @Final public ClientPlayNetworkHandler networkHandler; - // If this is false, no movement packets will be sent @Redirect(method = "sendMovementPackets", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isCamera()Z")) private boolean isCamera(ClientPlayerEntity instance) { return ((ClientPlayerEntityAccessor)instance)._client().getCameraEntity() == instance && - Keybinds.packetQueue.size() == 0; + packetQueue.size() == 0; } // No boat movement packets @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;hasVehicle()Z")) private boolean hasVehicle(ClientPlayerEntity instance) { return instance.getVehicle() != null && - Keybinds.packetQueue.size() == 0; + packetQueue.size() == 0; } // No hand swing before attack (will reset the attack cooldown otherwise) @Redirect(method = "swingHand", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendPacket(Lnet/minecraft/network/Packet;)V")) private void swingHand(ClientPlayNetworkHandler instance, Packet packet) { - if (Keybinds.packetQueue.size() == 0) { + if (packetQueue.size() == 0) { instance.getConnection().send(packet); } } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerMixin.java index 8ecafad..71408e8 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerMixin.java @@ -1,35 +1,30 @@ package com.jorianwoltjer.liveoverflowmod.mixin; import net.minecraft.block.BlockState; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerInteractionManager; import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; -import org.slf4j.Logger; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import static com.jorianwoltjer.liveoverflowmod.client.Keybinds.*; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*; @Mixin(ClientPlayerInteractionManager.class) public class ClientPlayerInteractionManagerMixin { - // Insta-Mine hack + // Insta-Mine @Inject(method = "attackBlock", at = @At(value = "HEAD"), cancellable = true) private void attackBlock(BlockPos pos, Direction direction, CallbackInfoReturnable cir) { - if (passiveModsEnabled) { - assert mc.world != null; - assert mc.player != null; - BlockState blockState = mc.world.getBlockState(pos); - double speed = blockState.calcBlockBreakingDelta(mc.player, mc.world, pos); + if (client.world == null || client.player == null) return; + + if (passiveMods.enabled) { + BlockState blockState = client.world.getBlockState(pos); + double speed = blockState.calcBlockBreakingDelta(client.player, client.world, pos); if (!blockState.isAir() && speed > 0.5F) { // If you can break the block fast enough, break it instantly - mc.world.breakBlock(pos, true, mc.player); + client.world.breakBlock(pos, true, client.player); networkHandler.sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.START_DESTROY_BLOCK, pos, direction)); networkHandler.sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK, pos, direction)); cir.setReturnValue(true); // Return true to break the block on the client-side diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/LivingEntityMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/LivingEntityMixin.java index 715bc82..b041805 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/LivingEntityMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/LivingEntityMixin.java @@ -1,15 +1,16 @@ package com.jorianwoltjer.liveoverflowmod.mixin; -import com.jorianwoltjer.liveoverflowmod.client.Keybinds; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.worldGuardBypassHack; + @Mixin(net.minecraft.entity.LivingEntity.class) public class LivingEntityMixin { // Disable regular movement when WorldGuard Bypass is enabled @Redirect(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;isImmobile()Z")) private boolean isImmobile(net.minecraft.entity.LivingEntity livingEntity) { - return Keybinds.worldGuardBypassEnabled; + return worldGuardBypassHack.enabled; } } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java index bf140d9..0249eae 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java @@ -9,7 +9,6 @@ import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket; import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket; import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; -import net.minecraft.text.Text; import net.minecraft.util.hit.EntityHitResult; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; @@ -23,33 +22,39 @@ import java.util.LinkedList; import java.util.Optional; -import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.PREFIX; -import static com.jorianwoltjer.liveoverflowmod.client.Keybinds.packetQueue; -import static com.jorianwoltjer.liveoverflowmod.client.Keybinds.reachEnabled; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.client; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.packetQueue; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.reachHack; @Mixin(MinecraftClient.class) public class MinecraftClientMixin { - private static void addToMiddle(LinkedList list, T object) { + @SuppressWarnings("SameParameterValue") + private static void insertToCenter(LinkedList list, T object) { int middle = (list.size() + 1) / 2; // Rounded up list.add(middle, object); } + // Extend reach @Inject(method = "doAttack", at = @At(value = "HEAD")) private void doAttack(CallbackInfoReturnable cir) { - if (reachEnabled) { + if (reachHack.enabled) { MinecraftClient client = MinecraftClient.getInstance(); Optional entity = DebugRenderer.getTargetedEntity(client.player, 100); - entity.ifPresent(e -> { - client.crosshairTarget = new EntityHitResult(e); - }); + entity.ifPresent(e -> client.crosshairTarget = new EntityHitResult(e)); } } + // On attack @Redirect(method = "doAttack", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerInteractionManager;attackEntity(Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/entity/Entity;)V")) private void attackEntity(ClientPlayerInteractionManager instance, PlayerEntity player, Entity target) { - MinecraftClient client = MinecraftClient.getInstance(); - if (reachEnabled) { + // packetQueue: [1, 2, 3, 4, 5, A, 4, 3, 2, 1, 0] + // A = attack packet + // 0 = starting position + // 1-5 = path + if (client.player == null) return; + + if (reachHack.enabled) { if (packetQueue.size() > 0) { return; // Already running } @@ -59,8 +64,7 @@ private void attackEntity(ClientPlayerInteractionManager instance, PlayerEntity } else { targetName = target.getType().getName().getString(); } - client.player.sendMessage(Text.of(String.format(PREFIX + "Reach: Hit §a%s §r(%.1f blocks)", - targetName, client.player.distanceTo(target))), true); + reachHack.message(String.format("Hit §a%s §r(%.1fm)", targetName, target.distanceTo(client.player))); Vec3d virtualPosition = client.player.getPos(); // Move close enough to target @@ -75,26 +79,26 @@ private void attackEntity(ClientPlayerInteractionManager instance, PlayerEntity // Normalize to length 10 movement = movement.multiply(9.9 / Math.sqrt(length)); } else { // If short enough, this is last packet - movement = movement.multiply(Math.max(0, Math.sqrt(length) - 2) / 10); // Reduce length by 2 blocks + movement = movement.multiply(Math.max(0, Math.sqrt(length) - 2) / 10); // Reduce length by 2 blocks to prevent collision lastPacket = true; } virtualPosition = virtualPosition.add(movement); // Add forward and backwards packets - addToMiddle(packetQueue, new PlayerMoveC2SPacket.PositionAndOnGround(virtualPosition.x, virtualPosition.y, virtualPosition.z, true)); + insertToCenter(packetQueue, new PlayerMoveC2SPacket.PositionAndOnGround(virtualPosition.x, virtualPosition.y, virtualPosition.z, true)); if (!lastPacket) { // If not the last packet, add a backwards packet (only need one at the sheep) - addToMiddle(packetQueue, new PlayerMoveC2SPacket.PositionAndOnGround(virtualPosition.x, virtualPosition.y, virtualPosition.z, true)); + insertToCenter(packetQueue, new PlayerMoveC2SPacket.PositionAndOnGround(virtualPosition.x, virtualPosition.y, virtualPosition.z, true)); } } else { break; } } // Add hit packet in the middle and original position at the end - addToMiddle(packetQueue, PlayerInteractEntityC2SPacket.attack(target, client.player.isSneaking())); + insertToCenter(packetQueue, PlayerInteractEntityC2SPacket.attack(target, client.player.isSneaking())); packetQueue.add(new PlayerMoveC2SPacket.PositionAndOnGround(client.player.getX(), client.player.getY(), client.player.getZ(), true)); packetQueue.add(new HandSwingC2SPacket(client.player.getActiveHand())); // Serverside animation client.player.resetLastAttackedTicks(); // Reset attack cooldown - } else { // Orignal code if not enabled + } else { // Orignal `attackEntity()` code if not enabled ClientPlayerInteractionManagerAccessor _instance = (ClientPlayerInteractionManagerAccessor) instance; _instance._syncSelectedSlot(); _instance._networkHandler().sendPacket(PlayerInteractEntityC2SPacket.attack(target, player.isSneaking())); diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/PlayerPositionFullPacketMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/PlayerPositionFullPacketMixin.java index ff0aa4d..611d72d 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/PlayerPositionFullPacketMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/PlayerPositionFullPacketMixin.java @@ -1,21 +1,21 @@ package com.jorianwoltjer.liveoverflowmod.mixin; -import com.jorianwoltjer.liveoverflowmod.helper.RoundPosition; +import com.jorianwoltjer.liveoverflowmod.helper.Utils; import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.ModifyArgs; import org.spongepowered.asm.mixin.injection.invoke.arg.Args; -import static com.jorianwoltjer.liveoverflowmod.client.Keybinds.passiveModsEnabled; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.passiveMods; @Mixin(PlayerMoveC2SPacket.Full.class) public abstract class PlayerPositionFullPacketMixin { // Anti-human bypass @ModifyArgs(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/packet/c2s/play/PlayerMoveC2SPacket;(DDDFFZZZ)V")) private static void init(Args args) { - if (passiveModsEnabled) { - RoundPosition.onPositionPacket(args); + if (passiveMods.enabled) { + Utils.onPositionPacket(args); } } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/PlayerPositionPacketMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/PlayerPositionPacketMixin.java index 3621a7c..7c8c937 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/PlayerPositionPacketMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/PlayerPositionPacketMixin.java @@ -1,21 +1,21 @@ package com.jorianwoltjer.liveoverflowmod.mixin; -import com.jorianwoltjer.liveoverflowmod.helper.RoundPosition; +import com.jorianwoltjer.liveoverflowmod.helper.Utils; import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.ModifyArgs; import org.spongepowered.asm.mixin.injection.invoke.arg.Args; -import static com.jorianwoltjer.liveoverflowmod.client.Keybinds.passiveModsEnabled; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.passiveMods; @Mixin(PlayerMoveC2SPacket.PositionAndOnGround.class) public class PlayerPositionPacketMixin { // Anti-human bypass @ModifyArgs(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/packet/c2s/play/PlayerMoveC2SPacket;(DDDFFZZZ)V")) private static void init(Args args) { - if (passiveModsEnabled) { - RoundPosition.onPositionPacket(args); + if (passiveMods.enabled) { + Utils.onPositionPacket(args); } } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/VehicleMovePacketMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/VehicleMovePacketMixin.java index 7cb177b..309f3b4 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/VehicleMovePacketMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/VehicleMovePacketMixin.java @@ -1,22 +1,21 @@ package com.jorianwoltjer.liveoverflowmod.mixin; -import com.jorianwoltjer.liveoverflowmod.helper.RoundPosition; +import com.jorianwoltjer.liveoverflowmod.helper.Utils; import net.minecraft.entity.Entity; import net.minecraft.network.packet.c2s.play.VehicleMoveC2SPacket; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import static com.jorianwoltjer.liveoverflowmod.client.Keybinds.passiveModsEnabled; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.passiveMods; @Mixin(VehicleMoveC2SPacket.class) public class VehicleMovePacketMixin { // Anti-human bypass for X @Redirect(method = "(Lnet/minecraft/entity/Entity;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getX()D")) - public double getX(Entity instance) - { - if (passiveModsEnabled) { - return RoundPosition.roundCoordinate(instance.getX()); + public double getX(Entity instance){ + if (passiveMods.enabled) { + return Utils.roundCoordinate(instance.getX()); } else { return instance.getX(); } @@ -24,8 +23,8 @@ public double getX(Entity instance) // Anti-human bypass for Z @Redirect(method = "(Lnet/minecraft/entity/Entity;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getZ()D")) public double getZ(Entity instance) { - if (passiveModsEnabled) { - return RoundPosition.roundCoordinate(instance.getZ()); + if (passiveMods.enabled) { + return Utils.roundCoordinate(instance.getZ()); } else { return instance.getX(); } diff --git a/src/main/resources/assets/liveoverflowmod/lang/en_us.json b/src/main/resources/assets/liveoverflowmod/lang/en_us.json index 02579a0..4af39bd 100644 --- a/src/main/resources/assets/liveoverflowmod/lang/en_us.json +++ b/src/main/resources/assets/liveoverflowmod/lang/en_us.json @@ -1,8 +1,8 @@ { "category.liveoverflowmod": "LiveOverflowMod", "key.liveoverflowmod.worldguardbypass_toggle": "Toggle WorldGuard Bypass", - "key.liveoverflowmod.reach": "Toggle Reach", - "key.liveoverflowmod.place": "Toggle Auto Place", - "key.liveoverflowmod.panic": "Toggle Panic Mode", - "key.liveoverflowmod.passive_toggle": "Toggle Passive Mods" + "key.liveoverflowmod.reach_toggle": "Toggle Reach", + "key.liveoverflowmod.autoplace_toggle": "Toggle Auto Place", + "key.liveoverflowmod.panicmode_toggle": "Toggle Panic Mode", + "key.liveoverflowmod.passivemods_toggle": "Toggle Passive Mods" } \ No newline at end of file From 032372a272d0d861066bd3e86326481d2f206197 Mon Sep 17 00:00:00 2001 From: Jorian Woltjer Date: Fri, 25 Nov 2022 19:27:15 +0100 Subject: [PATCH 05/20] Simplify Panic Mode --- .../liveoverflowmod/command/ClipCommand.java | 2 +- .../liveoverflowmod/hacks/PanicMode.java | 47 ++++++++++--------- .../liveoverflowmod/hacks/ToggledHack.java | 3 +- .../mixin/ClientConnectionMixin.java | 4 +- 4 files changed, 30 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java index 9ca5b5c..b365195 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java @@ -82,7 +82,7 @@ public static void register(CommandDispatcher dispatc }) ); - dispatcher.register(literal("vclip") + dispatcher.register(literal("boatclip") .then(argument("distance", integer()) .executes(context -> { int distance = context.getArgument("distance", Integer.class); diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PanicMode.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PanicMode.java index 38d348f..d05652e 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PanicMode.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PanicMode.java @@ -10,11 +10,11 @@ import org.lwjgl.glfw.GLFW; import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.PREFIX; -import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.client; -import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.networkHandler; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*; public class PanicMode extends ToggledHack { - int panicFlyingTimer = 0; + final double MAX_DELTA = 10; + boolean panicActive = false; /** * Fly up and disconnect if the player is in a dangerous situation. @@ -29,24 +29,12 @@ public PanicMode() { @Override public void tick(MinecraftClient client) { super.tick(client); - if (client.player == null || client.world == null) return; + if (client.world == null) return; - if (panicFlyingTimer > 0) { // TODO: make this code simpler - panicFlyingTimer--; - for (int i = 0; i < 5; i++) { // Max 5 packets per tick - Vec3d pos = client.player.getPos().add(0, 10, 0); // Max 10 blocks per packet - client.player.setVelocity(0, 0, 0); - if (client.player.getVehicle() != null) { - ClipCommand.moveVehicleTo(client.player.getVehicle(), pos); - } else { - client.player.setPosition(pos); - networkHandler.sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true)); - } - } - if (panicFlyingTimer == 0) { // If end, disconnect - client.world.disconnect(); - client.disconnect(new DisconnectedScreen(null, Text.of(PREFIX), Text.of("Panic Mode: §cTriggered"))); - } + if (panicActive && packetQueue.size() == 0) { // If ended, disconnect + panicActive = false; // Disable for next join + client.world.disconnect(); + client.disconnect(new DisconnectedScreen(null, Text.of(PREFIX), Text.of("Panic Mode: §cTriggered"))); } } @@ -60,8 +48,23 @@ public void tickEnabled() { } public void triggerPanic() { - this.enabled = false; - panicFlyingTimer = 20; // 20 ticks = 1 second + if (client.player == null) return; + + this.enabled = false; // Don't trigger repeatedly + panicActive = true; message("§cTriggered§r, flying up..."); + + // Fly up 1000 blocks + for (int i = 0; i < 1000/MAX_DELTA; i++) { + Vec3d pos = client.player.getPos().add(0, MAX_DELTA, 0); // Max 10 blocks per packet + + if (client.player.getVehicle() != null) { // If in boat + ClipCommand.moveVehicleTo(client.player.getVehicle(), pos); + } else { + client.player.setPosition(pos); + packetQueue.add(new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true)); + } + } + } } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java index 6a24b53..ab75691 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java @@ -6,6 +6,7 @@ import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.PREFIX; import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.client; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.networkHandler; public abstract class ToggledHack { public static final String LIVEOVERFLOW_CATEGORY = "category.liveoverflowmod"; @@ -37,7 +38,7 @@ public void tick(MinecraftClient client) { // Called every tick onDisable(); } } - if (enabled) { + if (enabled && networkHandler != null) { // networkHandler = Safety check tickEnabled(); } } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java index 419da3e..a349aa4 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java @@ -15,12 +15,12 @@ @Mixin(ClientConnection.class) public class ClientConnectionMixin { - // Log packets + // Log packets (for debugging) @SuppressWarnings({"EmptyMethod", "CommentedOutCode"}) @Inject(method = "sendImmediately", at = @At("HEAD")) void onSendImmediately(Packet packet, @Nullable PacketCallbacks callbacks, CallbackInfo ci) { // LOGGER.info("---> " + packet.getClass().getSimpleName()); - +// // if (packet instanceof PlayerMoveC2SPacket _packet) { // LOGGER.info(String.format("PlayerMoveC2SPacket(%.3f, %.3f, %.3f)", // _packet.getX(0), From 6e4479aea62f6a9e83919b287e42821d420544cc Mon Sep 17 00:00:00 2001 From: Jorian Woltjer Date: Wed, 30 Nov 2022 20:23:39 +0100 Subject: [PATCH 06/20] Add panic reason and create FastBreak --- .../client/ClientEntrypoint.java | 4 +- .../liveoverflowmod/hacks/AutoPlace.java | 57 -------- .../liveoverflowmod/hacks/FastBreak.java | 129 ++++++++++++++++++ .../liveoverflowmod/hacks/PanicMode.java | 43 +++++- .../liveoverflowmod/hacks/PassiveMods.java | 11 +- .../hacks/WorldGuardBypass.java | 2 +- .../mixin/ClientConnectionMixin.java | 31 ++++- .../mixin/ClientPlayNetworkHandlerMixin.java | 3 +- .../mixin/ClientPlayerEntityMixin.java | 36 ----- .../mixin/MinecraftClientMixin.java | 38 +++--- .../resources/liveoverflowmod.mixins.json | 1 - 11 files changed, 225 insertions(+), 130 deletions(-) delete mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/AutoPlace.java create mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/FastBreak.java delete mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerEntityMixin.java diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java index a980b0a..cf5190c 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java @@ -22,13 +22,13 @@ public class ClientEntrypoint implements ClientModInitializer { public static final WorldGuardBypass worldGuardBypassHack = new WorldGuardBypass(); public static final Reach reachHack = new Reach(); public static final PanicMode panicModeHack = new PanicMode(); - public static final AutoPlace autoPlaceHack = new AutoPlace(); + public static final FastBreak fastBreakHack = new FastBreak(); final ToggledHack[] toggledHacks = new ToggledHack[] { passiveMods, worldGuardBypassHack, reachHack, panicModeHack, - autoPlaceHack, + fastBreakHack }; public static final MinecraftClient client = MinecraftClient.getInstance(); public static ClientPlayNetworkHandler networkHandler; diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/AutoPlace.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/AutoPlace.java deleted file mode 100644 index 029f685..0000000 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/AutoPlace.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.jorianwoltjer.liveoverflowmod.hacks; - -import net.minecraft.network.packet.c2s.play.PlayerInteractBlockC2SPacket; -import net.minecraft.util.Hand; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.Vec3d; -import org.lwjgl.glfw.GLFW; - -import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.client; -import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.networkHandler; - -public class AutoPlace extends ToggledHack { - /** - * Automatically place blocks around you. - * Uses the item in your *offhand* and makes sure to wait if you run out of blocks. - */ - public AutoPlace() { - super("Auto Place", GLFW.GLFW_KEY_RIGHT_BRACKET); - } - - @Override - public void tickEnabled() { - if (client.player == null || client.world == null) return; - - BlockPos[] positions = { // All positions around you (except floor) - client.player.getBlockPos().add(0, 2, 0), - client.player.getBlockPos().add(1, 1, 0), - client.player.getBlockPos().add(0, 1, 1), - client.player.getBlockPos().add(-1, 1, 0), - client.player.getBlockPos().add(0, 1, -1), - client.player.getBlockPos().add(1, 0, 0), - client.player.getBlockPos().add(0, 0, 1), - client.player.getBlockPos().add(-1, 0, 0), - client.player.getBlockPos().add(0, 0, -1), - }; - // Enough blocks in offhand - if (client.player.getOffHandStack().getCount() > positions.length) { - for (BlockPos pos : positions) { - if (client.world.getBlockState(pos).isAir()) { // Only place if empty - placeAt(pos); - } - } - } - } - - public static void placeAt(BlockPos pos) { - BlockHitResult hitResult = new BlockHitResult( - new Vec3d(pos.getX(), pos.getY(), pos.getZ()), - Direction.UP, - pos, - false - ); - networkHandler.sendPacket(new PlayerInteractBlockC2SPacket(Hand.OFF_HAND, hitResult, 0)); - } -} diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/FastBreak.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/FastBreak.java new file mode 100644 index 0000000..bf06623 --- /dev/null +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/FastBreak.java @@ -0,0 +1,129 @@ +package com.jorianwoltjer.liveoverflowmod.hacks; + +import com.jorianwoltjer.liveoverflowmod.mixin.ClientConnectionMixin; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.MiningToolItem; +import net.minecraft.network.packet.c2s.play.ClientStatusC2SPacket; +import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket; +import net.minecraft.network.packet.c2s.play.PlayerInteractBlockC2SPacket; +import net.minecraft.screen.slot.SlotActionType; +import net.minecraft.text.Text; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3d; +import org.lwjgl.glfw.GLFW; + +import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.PREFIX; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.client; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.networkHandler; + +public class FastBreak extends ToggledHack { + BlockPos targetPos; + int timer; + public Item itemToPlace; + + int statsValue = -1; + int statsTimer = 0; + + /** + * Breaks and places blocks *really* fast. + * Hold a block in your offhand, and the best tool in your main hand. This hack will automatically fill the offhand with + * more blocks of that type from your inventory if it runs out. + * @see ClientConnectionMixin + */ + public FastBreak() { + super("Fast Break", GLFW.GLFW_KEY_LEFT_BRACKET); + } + + @Override + public void tickEnabled() { + if (client.player == null || client.interactionManager == null) return; + + if (++statsTimer > 20*60) { // 1 minute + statsTimer = 0; + networkHandler.sendPacket(new ClientStatusC2SPacket(ClientStatusC2SPacket.Mode.REQUEST_STATS)); + } + + if (++timer % 2 != 0) return; // Only run every few ticks + if (!(client.player.getMainHandStack().getItem() instanceof MiningToolItem)) return; // Stop if not holding a tool + + for (int i = 0; i < 9; i++) { + if (client.player.getOffHandStack().getCount() == 0) { + int slot = findItemSlot(itemToPlace); + if (slot == -1) { + message("§cNo cobblestone in inventory"); + return; + } + client.interactionManager.clickSlot(client.player.currentScreenHandler.syncId, slot, 40, SlotActionType.SWAP, client.player); + } + + placeAt(targetPos); + networkHandler.sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.START_DESTROY_BLOCK, targetPos, Direction.UP)); + networkHandler.sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK, targetPos, Direction.UP)); + } + } + + @Override + public void onEnable() { + super.onEnable(); + if (client.player == null) return; + + timer = 0; + statsTimer = 0; + itemToPlace = client.player.getOffHandStack().getItem(); + + networkHandler.sendPacket(new ClientStatusC2SPacket(ClientStatusC2SPacket.Mode.REQUEST_STATS)); // Send initial + + switch (client.player.getHorizontalFacing()) { + case NORTH -> targetPos = client.player.getBlockPos().add(0, 0, -1); + case SOUTH -> targetPos = client.player.getBlockPos().add(0, 0, 1); + case WEST -> targetPos = client.player.getBlockPos().add(-1, 0, 0); + case EAST -> targetPos = client.player.getBlockPos().add(1, 0, 0); + default -> targetPos = client.player.getBlockPos(); + } + } + + public void onStatResponse(Integer newValue) { // Will get a callback from ClientConnectionMixin + if (!enabled || client.player == null) return; + + if (statsValue == -1) { // Initial value + statsValue = newValue; + } + if (newValue == null) { // If not updated, value will be null + newValue = statsValue; + } + + client.player.sendMessage(Text.of(String.format(PREFIX + "%s: §b%d§r/min (§a%d§r total)", + itemToPlace.getName().getString(), + newValue - statsValue, + newValue + )), false); + + statsValue = newValue; + } + + public int findItemSlot(Item item) { + if (client.player == null) return -1; + + for (int i = 9; i < 36; i++) { // Inventory slots + ItemStack stack = client.player.getInventory().getStack(i); + if (stack.getItem() == item) { + return i; + } + } + return -1; // Not found + } + + public static void placeAt(BlockPos pos) { + BlockHitResult hitResult = new BlockHitResult( + new Vec3d(pos.getX(), pos.getY(), pos.getZ()), + Direction.UP, + pos, + false + ); + networkHandler.sendPacket(new PlayerInteractBlockC2SPacket(Hand.OFF_HAND, hitResult, 0)); + } +} diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PanicMode.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PanicMode.java index d05652e..427720d 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PanicMode.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PanicMode.java @@ -4,17 +4,22 @@ import com.jorianwoltjer.liveoverflowmod.mixin.ClientPlayNetworkHandlerMixin; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.DisconnectedScreen; +import net.minecraft.client.network.AbstractClientPlayerEntity; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; import net.minecraft.text.Text; import net.minecraft.util.math.Vec3d; import org.lwjgl.glfw.GLFW; +import java.util.List; + import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.PREFIX; import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*; public class PanicMode extends ToggledHack { final double MAX_DELTA = 10; boolean panicActive = false; + PanicReason reason; /** * Fly up and disconnect if the player is in a dangerous situation. @@ -23,7 +28,7 @@ public class PanicMode extends ToggledHack { * @see ClientPlayNetworkHandlerMixin */ public PanicMode() { - super("Panic", GLFW.GLFW_KEY_M); + super("Panic", GLFW.GLFW_KEY_COMMA); } @Override @@ -33,8 +38,15 @@ public void tick(MinecraftClient client) { if (panicActive && packetQueue.size() == 0) { // If ended, disconnect panicActive = false; // Disable for next join + + StringBuilder message = new StringBuilder("Panic Mode: §cTriggered§r\n"); + switch (reason.reason) { + case PLAYER_NEARBY -> message.append(String.format("§7Player §a%s §7was nearby", reason.player.getName().getString())); + case DAMAGE -> message.append("§7You took damage"); + } + client.world.disconnect(); - client.disconnect(new DisconnectedScreen(null, Text.of(PREFIX), Text.of("Panic Mode: §cTriggered"))); + client.disconnect(new DisconnectedScreen(null, Text.of(PREFIX), Text.of(message.toString()))); } } @@ -42,14 +54,17 @@ public void tick(MinecraftClient client) { public void tickEnabled() { if (client.world == null) return; - if (client.world.getPlayers().size() > 1) { - triggerPanic(); + List players = client.world.getPlayers(); + if (players.size() > 1) { + AbstractClientPlayerEntity nearby = players.get(1); + triggerPanic(new PanicReason(PanicReason.Reason.PLAYER_NEARBY, nearby, (double) nearby.distanceTo(client.player))); } } - public void triggerPanic() { + public void triggerPanic(PanicReason reason) { if (client.player == null) return; + this.reason = reason; this.enabled = false; // Don't trigger repeatedly panicActive = true; message("§cTriggered§r, flying up..."); @@ -67,4 +82,22 @@ public void triggerPanic() { } } + + public static class PanicReason { + public Reason reason; + public Double distance; + public PlayerEntity player; + + public PanicReason(Reason reason, PlayerEntity nearbyPlayer, Double distance) { + this.reason = reason; + this.distance = distance; + this.player = nearbyPlayer; + } + + public enum Reason { + PLAYER_NEARBY, + DAMAGE + } + } + } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PassiveMods.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PassiveMods.java index 84f4fc5..b4f3726 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PassiveMods.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PassiveMods.java @@ -1,7 +1,7 @@ package com.jorianwoltjer.liveoverflowmod.hacks; import com.jorianwoltjer.liveoverflowmod.mixin.*; -import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.Entity; import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.client; import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.globalTimer; @@ -14,6 +14,7 @@ public class PassiveMods extends ToggledHack { * - Disable Weird Packets: World Border, Creative Mode, Demo Mode, End Credits * - Insta-Mine * - Anti-Human Bypass (round coordinates) + * - Find Herobrine * @see AbstractBlockMixin * @see ClientPlayNetworkHandlerMixin * @see ClientPlayerInteractionManagerMixin @@ -31,13 +32,13 @@ public void tickEnabled() { if (client.world == null) return; // Find Herobrine - for (PlayerEntity player : client.world.getPlayers()) { - if (player.getName().getString().equals("Herobrine")) { + for (Entity entity : client.world.getEntities()) { + if (entity.getName().getString().equals("Herobrine")) { message(String.format( "%sFound %s §r(%.1f, %.1f, %.1f)", globalTimer % 8 > 4 ? "" : "§a", // Blinking - player.getName().getString(), - player.getX(), player.getY(), player.getZ() + entity.getName().getString(), + entity.getX(), entity.getY(), entity.getZ() )); break; } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/WorldGuardBypass.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/WorldGuardBypass.java index 2f30ed3..7c402c2 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/WorldGuardBypass.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/WorldGuardBypass.java @@ -25,7 +25,7 @@ public WorldGuardBypass() { public void tickEnabled() { if (client.player == null) return; - if (++flyingTimer > 20) { // Max 80, to bypass "Flying is not enabled" + if (client.options.sprintKey.isPressed() && ++flyingTimer > 20) { // Max 80, to bypass "Flying is not enabled" ((ClientConnectionInvoker) networkHandler.getConnection())._sendImmediately(new PlayerMoveC2SPacket.PositionAndOnGround(client.player.getX(), client.player.getY() - 0.04, client.player.getZ(), client.player.isOnGround()), null); flyingTimer = 0; // Reset diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java index a349aa4..c3dfc5d 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java @@ -1,17 +1,30 @@ package com.jorianwoltjer.liveoverflowmod.mixin; +import net.minecraft.block.Block; +import net.minecraft.item.Items; import net.minecraft.network.ClientConnection; import net.minecraft.network.Packet; import net.minecraft.network.PacketCallbacks; import net.minecraft.network.listener.PacketListener; +import net.minecraft.network.packet.c2s.play.KeepAliveC2SPacket; import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; +import net.minecraft.network.packet.s2c.play.StatisticsS2CPacket; +import net.minecraft.stat.Stat; +import net.minecraft.stat.Stats; +import net.minecraft.text.Text; import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.util.Map; +import java.util.Queue; + import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.LOGGER; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*; @Mixin(ClientConnection.class) public class ClientConnectionMixin { @@ -30,9 +43,25 @@ void onSendImmediately(Packet packet, @Nullable PacketCallbacks callbacks, Ca // } } - @SuppressWarnings({"EmptyMethod"}) @Inject(method = "handlePacket", at = @At("HEAD")) private static void onHandlePacket(Packet packet, PacketListener listener, CallbackInfo ci) { // LOGGER.info("<--- " + packet.getClass().getSimpleName()); + + if (packet instanceof StatisticsS2CPacket statsPacket) { + if (client.player == null) return; + // Get cobblestone mined stat + Integer statsValue = statsPacket.getStatMap().get(Stats.MINED.getOrCreateStat(Block.getBlockFromItem(fastBreakHack.itemToPlace))); + + fastBreakHack.onStatResponse(statsValue); + } + } + + @Inject(method = "send*", at = @At("HEAD"), cancellable = true) + private void normalSend(Packet packet, CallbackInfo ci) { + if (packetQueue.size() > 0) { + LOGGER.info("Cancelled packet: " + packet.getClass().getSimpleName()); + packetQueue.add(packet); + ci.cancel(); + } } } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayNetworkHandlerMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayNetworkHandlerMixin.java index 5e62aa0..10cbb6e 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayNetworkHandlerMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayNetworkHandlerMixin.java @@ -1,5 +1,6 @@ package com.jorianwoltjer.liveoverflowmod.mixin; +import com.jorianwoltjer.liveoverflowmod.hacks.PanicMode; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.network.packet.c2s.play.ClientStatusC2SPacket; import net.minecraft.network.packet.s2c.play.GameStateChangeS2CPacket; @@ -49,7 +50,7 @@ private GameStateChangeS2CPacket.Reason getReason(GameStateChangeS2CPacket insta @Inject(method = "onHealthUpdate", at = @At("HEAD")) void onHealthUpdate(HealthUpdateS2CPacket packet, CallbackInfo ci) { if (panicModeHack.enabled && packet.getHealth() < 20.0F) { - panicModeHack.triggerPanic(); + panicModeHack.triggerPanic(new PanicMode.PanicReason(PanicMode.PanicReason.Reason.DAMAGE, null, null)); } } } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerEntityMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerEntityMixin.java deleted file mode 100644 index 74422ee..0000000 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerEntityMixin.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.jorianwoltjer.liveoverflowmod.mixin; - -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.network.Packet; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.packetQueue; - -@Mixin(ClientPlayerEntity.class) -public class ClientPlayerEntityMixin { - // If this is false, no movement packets will be sent - @Redirect(method = "sendMovementPackets", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isCamera()Z")) - private boolean isCamera(ClientPlayerEntity instance) { - return ((ClientPlayerEntityAccessor)instance)._client().getCameraEntity() == instance && - packetQueue.size() == 0; - } - - // No boat movement packets - @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;hasVehicle()Z")) - private boolean hasVehicle(ClientPlayerEntity instance) { - return instance.getVehicle() != null && - packetQueue.size() == 0; - } - - // No hand swing before attack (will reset the attack cooldown otherwise) - @Redirect(method = "swingHand", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendPacket(Lnet/minecraft/network/Packet;)V")) - private void swingHand(ClientPlayNetworkHandler instance, Packet packet) { - if (packetQueue.size() == 0) { - instance.getConnection().send(packet); - } - } - -} diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java index 0249eae..052137a 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java @@ -67,29 +67,25 @@ private void attackEntity(ClientPlayerInteractionManager instance, PlayerEntity reachHack.message(String.format("Hit §a%s §r(%.1fm)", targetName, target.distanceTo(client.player))); Vec3d virtualPosition = client.player.getPos(); - // Move close enough to target - while (true) { - // If player is too far away, move closer - if (target.squaredDistanceTo(virtualPosition.add(0, client.player.getStandingEyeHeight(), 0)) >= MathHelper.square(6.0)) { - Vec3d movement = target.getPos().subtract(virtualPosition); - double length = movement.lengthSquared(); + Vec3d targetPos = target.getPos().subtract( // Subtract a bit from the end + target.getPos().subtract(virtualPosition).normalize().multiply(2) + ); + // If player is too far away, move closer + while (target.squaredDistanceTo(virtualPosition.add(0, client.player.getStandingEyeHeight(), 0)) >= MathHelper.square(6.0)) { + Vec3d movement = targetPos.subtract(virtualPosition); - boolean lastPacket = false; - if (length >= 100) { // Length squared is max 100 - // Normalize to length 10 - movement = movement.multiply(9.9 / Math.sqrt(length)); - } else { // If short enough, this is last packet - movement = movement.multiply(Math.max(0, Math.sqrt(length) - 2) / 10); // Reduce length by 2 blocks to prevent collision - lastPacket = true; - } - virtualPosition = virtualPosition.add(movement); - // Add forward and backwards packets + boolean lastPacket = false; + if (movement.lengthSquared() >= 100) { // Length squared is max 100 (otherwise "moved too quickly") + // Normalize to length 10 + movement = movement.normalize().multiply(9.9); + } else { // If short enough, this is last packet + lastPacket = true; + } + virtualPosition = virtualPosition.add(movement); + // Add forward and backwards packets + insertToCenter(packetQueue, new PlayerMoveC2SPacket.PositionAndOnGround(virtualPosition.x, virtualPosition.y, virtualPosition.z, true)); + if (!lastPacket) { // If not the last packet, add a backwards packet (only need one at the sheep) insertToCenter(packetQueue, new PlayerMoveC2SPacket.PositionAndOnGround(virtualPosition.x, virtualPosition.y, virtualPosition.z, true)); - if (!lastPacket) { // If not the last packet, add a backwards packet (only need one at the sheep) - insertToCenter(packetQueue, new PlayerMoveC2SPacket.PositionAndOnGround(virtualPosition.x, virtualPosition.y, virtualPosition.z, true)); - } - } else { - break; } } // Add hit packet in the middle and original position at the end diff --git a/src/main/resources/liveoverflowmod.mixins.json b/src/main/resources/liveoverflowmod.mixins.json index 1cc2f24..20a329b 100644 --- a/src/main/resources/liveoverflowmod.mixins.json +++ b/src/main/resources/liveoverflowmod.mixins.json @@ -18,7 +18,6 @@ }, "client": [ "ClientPlayerEntityAccessor", - "ClientPlayerEntityMixin", "ClientPlayerInteractionManagerAccessor", "ClientPlayNetworkHandlerMixin", "GameStateChangeS2CPacketAccessor", From 77276416677b438dc74ffb55a8e07635163e47da Mon Sep 17 00:00:00 2001 From: Jorian Woltjer Date: Wed, 30 Nov 2022 21:42:22 +0100 Subject: [PATCH 07/20] Clear packetQueue on disconnect --- .../mixin/ClientConnectionMixin.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java index c3dfc5d..87673f8 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java @@ -28,7 +28,7 @@ @Mixin(ClientConnection.class) public class ClientConnectionMixin { - // Log packets (for debugging) + // Log outgoing packets (for debugging) @SuppressWarnings({"EmptyMethod", "CommentedOutCode"}) @Inject(method = "sendImmediately", at = @At("HEAD")) void onSendImmediately(Packet packet, @Nullable PacketCallbacks callbacks, CallbackInfo ci) { @@ -43,25 +43,31 @@ void onSendImmediately(Packet packet, @Nullable PacketCallbacks callbacks, Ca // } } + // Log incoming packets (for debugging) @Inject(method = "handlePacket", at = @At("HEAD")) private static void onHandlePacket(Packet packet, PacketListener listener, CallbackInfo ci) { // LOGGER.info("<--- " + packet.getClass().getSimpleName()); + // Save statistics response if (packet instanceof StatisticsS2CPacket statsPacket) { - if (client.player == null) return; - // Get cobblestone mined stat + // Get mined stat for FastBreak Integer statsValue = statsPacket.getStatMap().get(Stats.MINED.getOrCreateStat(Block.getBlockFromItem(fastBreakHack.itemToPlace))); - fastBreakHack.onStatResponse(statsValue); } } + // Delay other packets while any packets in packetQueue @Inject(method = "send*", at = @At("HEAD"), cancellable = true) private void normalSend(Packet packet, CallbackInfo ci) { if (packetQueue.size() > 0) { - LOGGER.info("Cancelled packet: " + packet.getClass().getSimpleName()); - packetQueue.add(packet); + packetQueue.add(packet); // Do send them later ci.cancel(); } } + + // Clear packet queue + @Inject(method = "disconnect", at = @At("HEAD")) + void onDisconnect(Text reason, CallbackInfo ci) { + packetQueue.clear(); + } } From 68dfe53158d4eb82351a82f4dc3d31991113a289 Mon Sep 17 00:00:00 2001 From: Jorian Woltjer Date: Thu, 1 Dec 2022 08:18:41 +0100 Subject: [PATCH 08/20] Simplify ToggledHack usage --- .../client/ClientEntrypoint.java | 2 +- .../liveoverflowmod/hacks/FastBreak.java | 1 - .../liveoverflowmod/hacks/PassiveMods.java | 4 --- .../liveoverflowmod/hacks/ToggledHack.java | 36 ++++++++++++++----- .../hacks/WorldGuardBypass.java | 2 -- .../mixin/ClientConnectionMixin.java | 14 +++----- .../assets/liveoverflowmod/lang/en_us.json | 1 + 7 files changed, 33 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java index cf5190c..147e9f8 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java @@ -23,7 +23,7 @@ public class ClientEntrypoint implements ClientModInitializer { public static final Reach reachHack = new Reach(); public static final PanicMode panicModeHack = new PanicMode(); public static final FastBreak fastBreakHack = new FastBreak(); - final ToggledHack[] toggledHacks = new ToggledHack[] { + public static final ToggledHack[] toggledHacks = new ToggledHack[] { passiveMods, worldGuardBypassHack, reachHack, diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/FastBreak.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/FastBreak.java index bf06623..5516a85 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/FastBreak.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/FastBreak.java @@ -68,7 +68,6 @@ public void tickEnabled() { @Override public void onEnable() { - super.onEnable(); if (client.player == null) return; timer = 0; diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PassiveMods.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PassiveMods.java index b4f3726..bd770e0 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PassiveMods.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PassiveMods.java @@ -47,15 +47,11 @@ public void tickEnabled() { @Override public void onEnable() { - super.onEnable(); - client.worldRenderer.reload(); // Reload chunks (for Texture Rotations) } @Override public void onDisable() { - super.onDisable(); - client.worldRenderer.reload(); // Reload chunks (for Texture Rotations) } } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java index ab75691..e1fb490 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java @@ -31,36 +31,54 @@ public abstract class ToggledHack { */ public void tick(MinecraftClient client) { // Called every tick if (keybind.wasPressed()) { - enabled = !enabled; - if (enabled) { - onEnable(); - } else { - onDisable(); - } + toggle(); } if (enabled && networkHandler != null) { // networkHandler = Safety check tickEnabled(); } } + /** + * Toggle the hack on/off + */ + void toggle() { + if (enabled) { + disable(); + } else { + enable(); + } + } + /** * Called every tick, but only when the hack is enabled */ - public void tickEnabled() {} + void tickEnabled() {} /** * Called when the hack is enabled */ - void onEnable() { + public void enable() { + enabled = true; message("§aEnabled"); + onEnable(); } + /** + * Overridable method to add extra functionality when the hack is enabled + */ + void onEnable() {} /** * Called when the hack is disabled */ - void onDisable() { + public void disable() { + enabled = false; message("§cDisabled"); + onDisable(); } + /** + * Overridable method to add extra functionality when the hack is disabled + */ + void onDisable() {} /** * Send a message via the action bar with the prefix diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/WorldGuardBypass.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/WorldGuardBypass.java index 7c402c2..6805e27 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/WorldGuardBypass.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/WorldGuardBypass.java @@ -96,8 +96,6 @@ public void tickEnabled() { @Override public void onDisable() { - super.onDisable(); - flyingTimer = 0; } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java index 87673f8..d489454 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java @@ -1,29 +1,20 @@ package com.jorianwoltjer.liveoverflowmod.mixin; +import com.jorianwoltjer.liveoverflowmod.hacks.ToggledHack; import net.minecraft.block.Block; -import net.minecraft.item.Items; import net.minecraft.network.ClientConnection; import net.minecraft.network.Packet; import net.minecraft.network.PacketCallbacks; import net.minecraft.network.listener.PacketListener; -import net.minecraft.network.packet.c2s.play.KeepAliveC2SPacket; -import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; import net.minecraft.network.packet.s2c.play.StatisticsS2CPacket; -import net.minecraft.stat.Stat; import net.minecraft.stat.Stats; import net.minecraft.text.Text; import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import java.util.Map; -import java.util.Queue; - -import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.LOGGER; import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*; @Mixin(ClientConnection.class) @@ -69,5 +60,8 @@ private void normalSend(Packet packet, CallbackInfo ci) { @Inject(method = "disconnect", at = @At("HEAD")) void onDisconnect(Text reason, CallbackInfo ci) { packetQueue.clear(); + for (ToggledHack hack : toggledHacks) { + hack.disable(); + } } } diff --git a/src/main/resources/assets/liveoverflowmod/lang/en_us.json b/src/main/resources/assets/liveoverflowmod/lang/en_us.json index 4af39bd..69d3cb4 100644 --- a/src/main/resources/assets/liveoverflowmod/lang/en_us.json +++ b/src/main/resources/assets/liveoverflowmod/lang/en_us.json @@ -4,5 +4,6 @@ "key.liveoverflowmod.reach_toggle": "Toggle Reach", "key.liveoverflowmod.autoplace_toggle": "Toggle Auto Place", "key.liveoverflowmod.panicmode_toggle": "Toggle Panic Mode", + "key.liveoverflowmod.fastbreak_toggle": "Toggle Fast Break", "key.liveoverflowmod.passivemods_toggle": "Toggle Passive Mods" } \ No newline at end of file From a7db70b0b34384a1f450e7ccec3b9e8b3d083fa1 Mon Sep 17 00:00:00 2001 From: Jorian Woltjer Date: Mon, 5 Dec 2022 08:46:50 +0100 Subject: [PATCH 09/20] Set hacks to default on disconnect --- .../liveoverflowmod/hacks/FastBreak.java | 1 + .../liveoverflowmod/hacks/PassiveMods.java | 7 +++++-- .../liveoverflowmod/hacks/ToggledHack.java | 12 ++++++++++-- .../liveoverflowmod/mixin/ClientConnectionMixin.java | 6 +++++- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/FastBreak.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/FastBreak.java index 5516a85..91fa49d 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/FastBreak.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/FastBreak.java @@ -72,6 +72,7 @@ public void onEnable() { timer = 0; statsTimer = 0; + statsValue = -1; itemToPlace = client.player.getOffHandStack().getItem(); networkHandler.sendPacket(new ClientStatusC2SPacket(ClientStatusC2SPacket.Mode.REQUEST_STATS)); // Send initial diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PassiveMods.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PassiveMods.java index bd770e0..31bf8d1 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PassiveMods.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PassiveMods.java @@ -24,7 +24,8 @@ public class PassiveMods extends ToggledHack { */ public PassiveMods() { super("Passive Mods", GLFW_KEY_MINUS); - this.enabled = true; // Default on + this.defaultEnabled = true; + this.enabled = defaultEnabled; } @Override @@ -52,6 +53,8 @@ public void onEnable() { @Override public void onDisable() { - client.worldRenderer.reload(); // Reload chunks (for Texture Rotations) + if (client.world != null) { + client.worldRenderer.reload(); // Reload chunks (for Texture Rotations) + } } } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java index e1fb490..a2a2d95 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java @@ -5,6 +5,7 @@ import net.minecraft.text.Text; import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.PREFIX; +import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.LOGGER; import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.client; import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.networkHandler; @@ -13,7 +14,8 @@ public abstract class ToggledHack { public final KeyBinding keybind; public final String name; - public boolean enabled = false; + public boolean defaultEnabled = false; + public boolean enabled = defaultEnabled; /** * A hack that can be toggled on/off @@ -41,7 +43,7 @@ public void tick(MinecraftClient client) { // Called every tick /** * Toggle the hack on/off */ - void toggle() { + public void toggle() { if (enabled) { disable(); } else { @@ -60,6 +62,7 @@ void tickEnabled() {} public void enable() { enabled = true; message("§aEnabled"); + LOGGER.info("Enabled " + name); onEnable(); } /** @@ -73,6 +76,7 @@ void onEnable() {} public void disable() { enabled = false; message("§cDisabled"); + LOGGER.info("Disabled " + name); onDisable(); } /** @@ -89,4 +93,8 @@ public void message(String message) { client.player.sendMessage(Text.of(PREFIX + name + ": " + message), true); } + + public boolean isEnabled() { + return enabled; + } } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java index d489454..b428aac 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java @@ -15,6 +15,8 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.util.Arrays; + import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*; @Mixin(ClientConnection.class) @@ -61,7 +63,9 @@ private void normalSend(Packet packet, CallbackInfo ci) { void onDisconnect(Text reason, CallbackInfo ci) { packetQueue.clear(); for (ToggledHack hack : toggledHacks) { - hack.disable(); + if (hack.enabled != hack.defaultEnabled) { + hack.toggle(); + } } } } From 7eb3c96c6b6252535abdafb0afc84bbff50724a9 Mon Sep 17 00:00:00 2001 From: Jorian Woltjer Date: Tue, 6 Dec 2022 22:06:17 +0100 Subject: [PATCH 10/20] Improve clipping exploit --- .../client/ClientEntrypoint.java | 3 +- .../liveoverflowmod/command/ClipCommand.java | 179 ++++++++++++++---- .../liveoverflowmod/hacks/ToggledHack.java | 1 + .../mixin/ClientConnectionMixin.java | 2 - 4 files changed, 141 insertions(+), 44 deletions(-) diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java index 147e9f8..4a8b443 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java @@ -52,7 +52,7 @@ public static void tick(MinecraftClient client) { networkHandler = client.getNetworkHandler(); globalTimer++; - // Send packets from reach queue (max 5) + // Send packets from queue (max 5) int movementPacketsLeft = 5; while (packetQueue.size() > 0 && movementPacketsLeft > 0) { Packet packet = packetQueue.remove(0); @@ -61,6 +61,7 @@ public static void tick(MinecraftClient client) { } ((ClientConnectionInvoker) networkHandler.getConnection())._sendImmediately(packet, null); } + } public static void registerCommands(CommandDispatcher dispatcher) { diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java index b365195..c3ab82e 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java @@ -1,17 +1,21 @@ package com.jorianwoltjer.liveoverflowmod.command; import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.context.CommandContext; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.network.Packet; import net.minecraft.network.packet.c2s.play.PlayerInteractBlockC2SPacket; +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; import net.minecraft.network.packet.c2s.play.VehicleMoveC2SPacket; +import net.minecraft.text.Text; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; -import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.packetQueue; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*; import static com.mojang.brigadier.arguments.IntegerArgumentType.integer; import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.*; import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.LOGGER; @@ -29,7 +33,7 @@ public static void moveVehicleTo(Entity vehicle, Vec3d pos) { } private static void pressButtonAt(PlayerEntity player, BlockPos pos) { - packetQueue.add( + networkHandler.sendPacket( new PlayerInteractBlockC2SPacket( player.preferredHand, new BlockHitResult( @@ -45,57 +49,150 @@ private static void pressButtonAt(PlayerEntity player, BlockPos pos) { public static void register(CommandDispatcher dispatcher) { dispatcher.register(literal("vault") - .executes(context -> { - PlayerEntity player = context.getSource().getPlayer(); - Entity vehicle = player.getVehicle(); - - if (vehicle == null) return 0; - - LOGGER.info("Pressing start button"); - pressButtonAt(player, new BlockPos(4729, 125, 1337)); // Start button - - // y += 53.0 - LOGGER.info("Moving to ceiling right above end button"); - moveVehicleTo(vehicle, vehicle.getPos().add(0, 9.9, 0)); - moveVehicleTo(vehicle, vehicle.getPos().add(0, 9.9, 0)); - moveVehicleTo(vehicle, vehicle.getPos().add(0, 9.9, 0)); - moveVehicleTo(vehicle, vehicle.getPos().add(0, 9.9, 0)); - moveVehicleTo(vehicle, vehicle.getPos().add(0, 9.9, 0)); - moveVehicleTo(vehicle, vehicle.getPos().add(0, 3.5, 0)); - - // x += 53.0 - moveVehicleTo(vehicle, vehicle.getPos().add(9.9, 0, 0)); - moveVehicleTo(vehicle, vehicle.getPos().add(9.9, 0, 0)); - moveVehicleTo(vehicle, vehicle.getPos().add(9.9, 0, 0)); - moveVehicleTo(vehicle, vehicle.getPos().add(9.9, 0, 0)); - moveVehicleTo(vehicle, vehicle.getPos().add(9.9, 0, 0)); - moveVehicleTo(vehicle, vehicle.getPos().add(3.0, 0, 0)); - - // y -= 53.0 (through box) - LOGGER.info("Clipping down through box"); - clipVehicleTo(vehicle, vehicle.getPos().add(0, -53, 0)); - - LOGGER.info("Pressing end button"); - pressButtonAt(player, new BlockPos(4780, 125, 1336)); // End button - - return 1; - }) + .executes(context -> { + PlayerEntity player = context.getSource().getPlayer(); + Vec3d pos = player.getPos(); + + pressButtonAt(player, new BlockPos(4729, 125, 1337)); // Start button + + // y += 53.0 + for (int i = 0; i < 5; i++) { + pos = pos.add(0, 9.9, 0); + networkHandler.sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true)); + } + pos = pos.add(0, 3.5, 0); + networkHandler.sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true)); + + // x += 53.0 + for (int i = 0; i < 5; i++) { + pos = pos.add(9.9, 0, 0); + networkHandler.sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true)); + } + pos = pos.add(3.0, 0, 0); + networkHandler.sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true)); + + // y -= 53.0 (through box) + pos = pos.add(0, -53, 0); + networkHandler.sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true)); + player.setPosition(pos); + + pressButtonAt(player, new BlockPos(4780, 125, 1336)); // End button + + return 1; + }) + ); + + dispatcher.register(literal("vclip") + .then(argument("distance", integer()) + .executes(context -> { + int distance = context.getArgument("distance", Integer.class); + PlayerEntity player = context.getSource().getPlayer(); + + Vec3d pos = player.getPos(); + Vec3d targetPos = pos.add(0, distance, 0); + + clipTo(targetPos); + + return 1; + }) + ) ); - dispatcher.register(literal("boatclip") + dispatcher.register(literal("hclip") .then(argument("distance", integer()) .executes(context -> { int distance = context.getArgument("distance", Integer.class); PlayerEntity player = context.getSource().getPlayer(); - Entity vehicle = player.getVehicle(); - if (vehicle == null) return 0; + Vec3d pos = player.getPos(); + // Move into players viewing direction + Vec3d targetPos = pos.add(player.getRotationVector().multiply(1, 0, 1).multiply(distance)); - clipVehicleTo(vehicle, vehicle.getPos().add(0, distance, 0)); + clipTo(targetPos); return 1; }) ) ); + + dispatcher.register(literal("autoclip") + .then(literal("up") + .executes(context -> executeAutoClip(context, 1)) + ) + .then(literal("down") + .executes(context -> executeAutoClip(context, -1)) + ) + ); + + dispatcher.register(literal("clubmate") + .executes(context -> { + PlayerEntity player = context.getSource().getPlayer(); + + + return 1; + }) + ); + } + + private static void clipTo(Vec3d targetPos) { + if (client.player == null) return; + + Vec3d pos = client.player.getPos(); + + Packet homePacket; + Packet targetPacket; + if (client.player.getVehicle() != null) { + homePacket = new VehicleMoveC2SPacket(client.player.getVehicle()); + client.player.getVehicle().setPosition(targetPos); + targetPacket = new VehicleMoveC2SPacket(client.player.getVehicle()); + } else { + homePacket = new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, false); + targetPacket = new PlayerMoveC2SPacket.PositionAndOnGround(targetPos.x, targetPos.y, targetPos.z, false); + } + + for (int i = 0; i < 18; i++) { // Send a lot of the same movement packets to increase max travel distance + networkHandler.sendPacket(homePacket); + } + // Send one big movement packet to actually move the player + networkHandler.sendPacket(targetPacket); + client.player.setPosition(targetPos); + } + + private static int executeAutoClip(CommandContext context, int direction) { + if (client.player == null) return 0; + + Vec3d pos = getAutoClipPos(direction); + if (pos == null) { + context.getSource().sendFeedback(Text.of("§cNo valid position found within 150 blocks")); + return 0; + } else { + context.getSource().sendFeedback(Text.of(String.format("§7Clipping §a%.0f§7 blocks", pos.y - (int) client.player.getPos().y))); + clipTo(pos); + return 1; + } + } + + /** + * Automatically go through the nearest blocks in the given direction. + * Credits to @EnderKill98 for the original code. + */ + private static Vec3d getAutoClipPos(int direction) { + if (client.player == null || client.world == null) return null; + + boolean inside = false; + for (float i = 0; i < 150; i += 0.25) { + Vec3d pos = client.player.getPos(); + Vec3d targetPos = pos.add(0, direction * i, 0); + + boolean collides = !client.world.isSpaceEmpty(client.player, client.player.getBoundingBox().offset(targetPos.subtract(pos))); + + if (!inside && collides) { // Step 1: Into the blocks + inside = true; + } else if (inside && !collides) { // Step 2: Out of the blocks + return targetPos; + } + } + + return null; // Nothing found } } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java index a2a2d95..bd2fac2 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java @@ -91,6 +91,7 @@ void onDisable() {} public void message(String message) { if (client.player == null) return; + // TODO: maybe convert all white text to gray client.player.sendMessage(Text.of(PREFIX + name + ": " + message), true); } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java index b428aac..16e575c 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java @@ -15,8 +15,6 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import java.util.Arrays; - import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*; @Mixin(ClientConnection.class) From 6adc50b1b955a1bb2371beee394a74e4df3d5364 Mon Sep 17 00:00:00 2001 From: Jorian Woltjer Date: Tue, 6 Dec 2022 23:11:07 +0100 Subject: [PATCH 11/20] Add automatic /clubmate command --- .../liveoverflowmod/command/ClipCommand.java | 46 +++++++------------ .../liveoverflowmod/hacks/PanicMode.java | 8 +++- .../mixin/ClientConnectionMixin.java | 10 ++-- 3 files changed, 28 insertions(+), 36 deletions(-) diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java index c3ab82e..83e02eb 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java @@ -3,13 +3,15 @@ import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.context.CommandContext; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.entity.Entity; +import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.Packet; import net.minecraft.network.packet.c2s.play.PlayerInteractBlockC2SPacket; import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; import net.minecraft.network.packet.c2s.play.VehicleMoveC2SPacket; import net.minecraft.text.Text; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; @@ -18,33 +20,17 @@ import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*; import static com.mojang.brigadier.arguments.IntegerArgumentType.integer; import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.*; -import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.LOGGER; public class ClipCommand { - public static void clipVehicleTo(Entity vehicle, Vec3d pos) { - packetQueue.add(new VehicleMoveC2SPacket(vehicle)); - vehicle.updatePosition(pos.x, pos.y, pos.z); - packetQueue.add(new VehicleMoveC2SPacket(vehicle)); - } - - public static void moveVehicleTo(Entity vehicle, Vec3d pos) { - vehicle.updatePosition(pos.x, pos.y, pos.z); - packetQueue.add(new VehicleMoveC2SPacket(vehicle)); - } - - private static void pressButtonAt(PlayerEntity player, BlockPos pos) { - networkHandler.sendPacket( - new PlayerInteractBlockC2SPacket( - player.preferredHand, - new BlockHitResult( - new Vec3d(pos.getX(), pos.getY(), pos.getZ()), - Direction.DOWN, - pos, - false - ), - 0 - ) - ); + private static void interactAt(BlockPos pos) { + if (client.interactionManager == null) return; + + client.interactionManager.interactBlock(client.player, Hand.MAIN_HAND, new BlockHitResult( + new Vec3d(pos.getX(), pos.getY(), pos.getZ()), + Direction.DOWN, + pos, + false + )); } public static void register(CommandDispatcher dispatcher) { @@ -53,7 +39,7 @@ public static void register(CommandDispatcher dispatc PlayerEntity player = context.getSource().getPlayer(); Vec3d pos = player.getPos(); - pressButtonAt(player, new BlockPos(4729, 125, 1337)); // Start button + interactAt(new BlockPos(4729, 125, 1337)); // Start button // y += 53.0 for (int i = 0; i < 5; i++) { @@ -76,7 +62,7 @@ public static void register(CommandDispatcher dispatc networkHandler.sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true)); player.setPosition(pos); - pressButtonAt(player, new BlockPos(4780, 125, 1336)); // End button + interactAt(new BlockPos(4780, 125, 1336)); // End button return 1; }) @@ -126,8 +112,10 @@ public static void register(CommandDispatcher dispatc dispatcher.register(literal("clubmate") .executes(context -> { - PlayerEntity player = context.getSource().getPlayer(); + clipTo(new Vec3d(1331, 89, 1330)); + assert client.player != null; + interactAt(new BlockPos(1331, 89, 1331)); // Chest return 1; }) diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PanicMode.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PanicMode.java index 427720d..4122fae 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PanicMode.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/PanicMode.java @@ -5,8 +5,10 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.DisconnectedScreen; import net.minecraft.client.network.AbstractClientPlayerEntity; +import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; +import net.minecraft.network.packet.c2s.play.VehicleMoveC2SPacket; import net.minecraft.text.Text; import net.minecraft.util.math.Vec3d; import org.lwjgl.glfw.GLFW; @@ -74,7 +76,7 @@ public void triggerPanic(PanicReason reason) { Vec3d pos = client.player.getPos().add(0, MAX_DELTA, 0); // Max 10 blocks per packet if (client.player.getVehicle() != null) { // If in boat - ClipCommand.moveVehicleTo(client.player.getVehicle(), pos); + moveVehicleTo(client.player.getVehicle(), pos); } else { client.player.setPosition(pos); packetQueue.add(new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true)); @@ -100,4 +102,8 @@ public enum Reason { } } + public static void moveVehicleTo(Entity vehicle, Vec3d pos) { + vehicle.updatePosition(pos.x, pos.y, pos.z); + packetQueue.add(new VehicleMoveC2SPacket(vehicle)); + } } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java index 16e575c..5518d6a 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java @@ -6,6 +6,7 @@ import net.minecraft.network.Packet; import net.minecraft.network.PacketCallbacks; import net.minecraft.network.listener.PacketListener; +import net.minecraft.network.packet.c2s.play.PlayerInteractBlockC2SPacket; import net.minecraft.network.packet.s2c.play.StatisticsS2CPacket; import net.minecraft.stat.Stats; import net.minecraft.text.Text; @@ -16,6 +17,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*; +import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.LOGGER; @Mixin(ClientConnection.class) public class ClientConnectionMixin { @@ -25,12 +27,8 @@ public class ClientConnectionMixin { void onSendImmediately(Packet packet, @Nullable PacketCallbacks callbacks, CallbackInfo ci) { // LOGGER.info("---> " + packet.getClass().getSimpleName()); // -// if (packet instanceof PlayerMoveC2SPacket _packet) { -// LOGGER.info(String.format("PlayerMoveC2SPacket(%.3f, %.3f, %.3f)", -// _packet.getX(0), -// _packet.getY(0), -// _packet.getZ(0) -// )); +// if (packet instanceof PlayerInteractBlockC2SPacket _packet) { +// LOGGER.info(String.format("PlayerInteractBlockC2SPacket(%s, %s, %s)", _packet.getHand(), _packet.getBlockHitResult().getBlockPos(), _packet.getBlockHitResult().getPos())); // } } From 2b64f2c274daf5c34a2fe697bf6429fe0db11ae1 Mon Sep 17 00:00:00 2001 From: Jorian Woltjer Date: Wed, 7 Dec 2022 16:56:34 +0100 Subject: [PATCH 12/20] Add /hclip and simplify code --- .../liveoverflowmod/command/ClipCommand.java | 86 +++++++++++++------ 1 file changed, 59 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java index 83e02eb..cbab89c 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java @@ -3,14 +3,10 @@ import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.context.CommandContext; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.network.Packet; -import net.minecraft.network.packet.c2s.play.PlayerInteractBlockC2SPacket; import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; import net.minecraft.network.packet.c2s.play.VehicleMoveC2SPacket; import net.minecraft.text.Text; -import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; @@ -18,6 +14,7 @@ import net.minecraft.util.math.Vec3d; import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*; +import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.LOGGER; import static com.mojang.brigadier.arguments.IntegerArgumentType.integer; import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.*; @@ -68,7 +65,7 @@ public static void register(CommandDispatcher dispatc }) ); - dispatcher.register(literal("vclip") + dispatcher.register(literal("vclip") // Vertical clip .then(argument("distance", integer()) .executes(context -> { int distance = context.getArgument("distance", Integer.class); @@ -77,14 +74,14 @@ public static void register(CommandDispatcher dispatc Vec3d pos = player.getPos(); Vec3d targetPos = pos.add(0, distance, 0); - clipTo(targetPos); + clipStraight(targetPos); return 1; }) ) ); - dispatcher.register(literal("hclip") + dispatcher.register(literal("dclip") // Directional clip .then(argument("distance", integer()) .executes(context -> { int distance = context.getArgument("distance", Integer.class); @@ -92,9 +89,9 @@ public static void register(CommandDispatcher dispatc Vec3d pos = player.getPos(); // Move into players viewing direction - Vec3d targetPos = pos.add(player.getRotationVector().multiply(1, 0, 1).multiply(distance)); + Vec3d targetPos = pos.add(player.getRotationVector().normalize().multiply(distance)); - clipTo(targetPos); + clipStraight(targetPos); return 1; }) @@ -111,39 +108,62 @@ public static void register(CommandDispatcher dispatc ); dispatcher.register(literal("clubmate") + .executes(context -> { + clipStraight(new Vec3d(1331, 89, 1330)); // Next to chest + + assert client.player != null; + interactAt(new BlockPos(1331, 89, 1331)); // Chest + + return 1; + }) + ); + + dispatcher.register(literal("hclip") // Horizontal clip (up -> horizontal -> down: to go through walls) + .then(argument("distance", integer()) .executes(context -> { - clipTo(new Vec3d(1331, 89, 1330)); + int distance = context.getArgument("distance", Integer.class); assert client.player != null; - interactAt(new BlockPos(1331, 89, 1331)); // Chest + // Move `direction` blocks into viewing direction + Vec3d targetPos = client.player.getPos().add( + client.player.getRotationVector().multiply(1, 0, 1).normalize().multiply(distance) + ); + clipUpDown(targetPos); return 1; }) + ) ); } - private static void clipTo(Vec3d targetPos) { + private static void clipStraight(Vec3d targetPos) { if (client.player == null) return; Vec3d pos = client.player.getPos(); - Packet homePacket; - Packet targetPacket; - if (client.player.getVehicle() != null) { - homePacket = new VehicleMoveC2SPacket(client.player.getVehicle()); - client.player.getVehicle().setPosition(targetPos); - targetPacket = new VehicleMoveC2SPacket(client.player.getVehicle()); - } else { - homePacket = new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, false); - targetPacket = new PlayerMoveC2SPacket.PositionAndOnGround(targetPos.x, targetPos.y, targetPos.z, false); - } - for (int i = 0; i < 18; i++) { // Send a lot of the same movement packets to increase max travel distance - networkHandler.sendPacket(homePacket); + moveTo(pos); } // Send one big movement packet to actually move the player - networkHandler.sendPacket(targetPacket); - client.player.setPosition(targetPos); + moveTo(targetPos); + } + + private static void clipUpDown(Vec3d targetPos) { + if (client.player == null) return; + + Vec3d pos = client.player.getPos(); + + for (int i = 0; i < 15; i++) { // Send a lot of the same movement packets to increase max travel distance + moveTo(pos); + } + + pos = pos.add(0, 100, 0); // Up + moveTo(pos); + + pos = new Vec3d(targetPos.x, pos.y, targetPos.z); // Horizontal + moveTo(pos); + + moveTo(targetPos); // Down } private static int executeAutoClip(CommandContext context, int direction) { @@ -155,7 +175,7 @@ private static int executeAutoClip(CommandContext con return 0; } else { context.getSource().sendFeedback(Text.of(String.format("§7Clipping §a%.0f§7 blocks", pos.y - (int) client.player.getPos().y))); - clipTo(pos); + clipStraight(pos); return 1; } } @@ -183,4 +203,16 @@ private static Vec3d getAutoClipPos(int direction) { return null; // Nothing found } + + private static void moveTo(Vec3d pos) { + if (client.player == null) return; + + if (client.player.getVehicle() != null) { + client.player.getVehicle().setPosition(pos); + networkHandler.sendPacket(new VehicleMoveC2SPacket(client.player.getVehicle())); + } else { + client.player.setPosition(pos); + networkHandler.sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true)); + } + } } From d1ac9710ee62ca66dd6b29b8fbfec98c50f252c1 Mon Sep 17 00:00:00 2001 From: Jorian Woltjer Date: Wed, 7 Dec 2022 19:19:38 +0100 Subject: [PATCH 13/20] Improve consistency of WorldGuard Bypass and fix anti-flykick --- .../hacks/WorldGuardBypass.java | 97 ++++++++++++------- .../mixin/ClientConnectionMixin.java | 2 +- .../mixin/PlayerPositionFullPacketMixin.java | 1 + 3 files changed, 62 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/WorldGuardBypass.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/WorldGuardBypass.java index 6805e27..2514804 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/WorldGuardBypass.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/WorldGuardBypass.java @@ -1,6 +1,5 @@ package com.jorianwoltjer.liveoverflowmod.hacks; -import com.jorianwoltjer.liveoverflowmod.mixin.ClientConnectionInvoker; import com.jorianwoltjer.liveoverflowmod.mixin.LivingEntityMixin; import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; import net.minecraft.util.math.Vec3d; @@ -10,7 +9,7 @@ import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.networkHandler; public class WorldGuardBypass extends ToggledHack { - final double MAX_DELTA = 0.05; // Absolute maximum is sqrt(1/256) = 0.0625 + final double MAX_DELTA = 0.05001; // Absolute maximum is sqrt(1/256) = 0.0625 int flyingTimer = 0; /** @@ -23,41 +22,25 @@ public WorldGuardBypass() { @Override public void tickEnabled() { - if (client.player == null) return; + if (client.player == null || client.world == null) return; + + client.player.setVelocity(0, 0, 0); + + if (++flyingTimer > 20) { // Max 80, to bypass "Flying is not enabled" + Vec3d pos = client.player.getPos(); + pos = pos.add(0, -MAX_DELTA, 0); // Small down position + + client.player.setPosition(pos.x, pos.y, pos.z); + networkHandler.sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true)); + networkHandler.sendPacket(new PlayerMoveC2SPacket.Full(pos.x + 1337.0, pos.y + 1337.0, // Far packet again to keep bypassing + pos.z + 1337.0, client.player.getYaw(), client.player.getPitch(), true)); - if (client.options.sprintKey.isPressed() && ++flyingTimer > 20) { // Max 80, to bypass "Flying is not enabled" - ((ClientConnectionInvoker) networkHandler.getConnection())._sendImmediately(new PlayerMoveC2SPacket.PositionAndOnGround(client.player.getX(), - client.player.getY() - 0.04, client.player.getZ(), client.player.isOnGround()), null); flyingTimer = 0; // Reset } else { - client.player.setVelocity(0, 0, 0); - - Vec3d vec = new Vec3d(0, 0, 0); - - // Key presses changing position - if (client.player.input.jumping) { // Move up - vec = vec.add(new Vec3d(0, 1, 0)); - } else if (client.player.input.sneaking) { // Move down - vec = vec.add(new Vec3d(0, -1, 0)); - } else { - // Horizontal movement (not at the same time as vertical) - if (client.player.input.pressingForward) { - vec = vec.add(new Vec3d(0, 0, 1)); - } - if (client.player.input.pressingRight) { - vec = vec.add(new Vec3d(1, 0, 0)); - } - if (client.player.input.pressingBack) { - vec = vec.add(new Vec3d(0, 0, -1)); - } - if (client.player.input.pressingLeft) { - vec = vec.add(new Vec3d(-1, 0, 0)); - } - } + Vec3d vec = getMovementVec(); + assert vec != null; if (vec.length() > 0) { - vec = vec.normalize(); // Normalize to length 1 - if (!(vec.x == 0 && vec.z == 0)) { // Rotate by looking yaw (won't change length) double moveAngle = Math.atan2(vec.x, vec.z) + Math.toRadians(client.player.getYaw() + 90); double x = Math.cos(moveAngle); @@ -68,10 +51,14 @@ public void tickEnabled() { vec = vec.multiply(MAX_DELTA); // Scale to maxDelta Vec3d newPos = new Vec3d(client.player.getX() + vec.x, client.player.getY() + vec.y, client.player.getZ() + vec.z); + if (collides(newPos)) return; // Don't move if it would collide + // If able to add more without going over a block boundary, add more boolean extra = false; if (client.options.sprintKey.isPressed()) { // Trigger by sprinting - while (inSameBlock(newPos.add(vec.multiply(1.5)), new Vec3d(client.player.prevX, client.player.prevY, client.player.prevZ))) { + // If doesn't cross block boundary, and doesn't collide with anything, add more + while (inSameBlock(newPos.add(vec.multiply(1.5)), new Vec3d(client.player.prevX, client.player.prevY, client.player.prevZ)) && + !collides(newPos.add(vec.multiply(1.5)))) { newPos = newPos.add(vec); extra = true; } @@ -81,14 +68,14 @@ public void tickEnabled() { // Send tiny movement so delta is small enough PlayerMoveC2SPacket.Full smallMovePacket = new PlayerMoveC2SPacket.Full(client.player.getX(), client.player.getY(), - client.player.getZ(), client.player.getYaw(), client.player.getPitch(), client.player.isOnGround()); - networkHandler.getConnection().send(smallMovePacket); + client.player.getZ(), client.player.getYaw(), client.player.getPitch(), true); + networkHandler.sendPacket(smallMovePacket); // Send far away packet for "moving too quickly!" to reset position if (!extra) { PlayerMoveC2SPacket.Full farPacket = new PlayerMoveC2SPacket.Full(client.player.getX() + 1337.0, client.player.getY() + 1337.0, - client.player.getZ() + 1337.0, client.player.getYaw(), client.player.getPitch(), client.player.isOnGround()); - networkHandler.getConnection().send(farPacket); + client.player.getZ() + 1337.0, client.player.getYaw(), client.player.getPitch(), true); + networkHandler.sendPacket(farPacket); } } } @@ -99,10 +86,46 @@ public void onDisable() { flyingTimer = 0; } + public static boolean inSameBlock(Vec3d vector, Vec3d other) { return other.x >= Math.floor(vector.x) && other.x <= Math.ceil(vector.x) && other.y >= Math.floor(vector.y) && other.y <= Math.ceil(vector.y) && other.z >= Math.floor(vector.z) && other.z <= Math.ceil(vector.z); } + public static boolean collides(Vec3d pos) { + if (client.player == null || client.world == null) return false; + + return !client.world.isSpaceEmpty(client.player, client.player.getBoundingBox().offset(pos.subtract(client.player.getPos()))); + } + + public static Vec3d getMovementVec() { + if (client.player == null) return null; + + Vec3d vec = new Vec3d(0, 0, 0); + + // Key presses changing position + if (client.player.input.jumping) { // Move up + vec = vec.add(new Vec3d(0, 1, 0)); + } else if (client.player.input.sneaking) { // Move down + vec = vec.add(new Vec3d(0, -1, 0)); + } else { + // Horizontal movement (not at the same time as vertical) + if (client.player.input.pressingForward) { + vec = vec.add(new Vec3d(0, 0, 1)); + } + if (client.player.input.pressingRight) { + vec = vec.add(new Vec3d(1, 0, 0)); + } + if (client.player.input.pressingBack) { + vec = vec.add(new Vec3d(0, 0, -1)); + } + if (client.player.input.pressingLeft) { + vec = vec.add(new Vec3d(-1, 0, 0)); + } + } + + return vec.normalize(); + } + } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java index 5518d6a..d19dd12 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java @@ -48,7 +48,7 @@ private static void onHandlePacket(Packet packet, // Delay other packets while any packets in packetQueue @Inject(method = "send*", at = @At("HEAD"), cancellable = true) private void normalSend(Packet packet, CallbackInfo ci) { - if (packetQueue.size() > 0) { + if (packetQueue.size() > 0 || worldGuardBypassHack.enabled) { // WorldGuard Bypass also needs it for anti-flykick to work packetQueue.add(packet); // Do send them later ci.cancel(); } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/PlayerPositionFullPacketMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/PlayerPositionFullPacketMixin.java index 611d72d..a266ab9 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/PlayerPositionFullPacketMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/PlayerPositionFullPacketMixin.java @@ -8,6 +8,7 @@ import org.spongepowered.asm.mixin.injection.invoke.arg.Args; import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.passiveMods; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.worldGuardBypassHack; @Mixin(PlayerMoveC2SPacket.Full.class) public abstract class PlayerPositionFullPacketMixin { From e9877d0b8b748d7dd28c7de8ffd93a38f45ca26b Mon Sep 17 00:00:00 2001 From: Jorian Woltjer Date: Wed, 7 Dec 2022 23:42:36 +0100 Subject: [PATCH 14/20] Add random name capitalisation on join --- .../liveoverflowmod/command/ClipCommand.java | 35 ++++++++++--------- .../liveoverflowmod/mixin/SessionMixin.java | 28 +++++++++++++++ .../resources/liveoverflowmod.mixins.json | 3 +- 3 files changed, 48 insertions(+), 18 deletions(-) create mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/SessionMixin.java diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java index cbab89c..d6f6baf 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java @@ -81,6 +81,24 @@ public static void register(CommandDispatcher dispatc ) ); + dispatcher.register(literal("hclip") // Horizontal clip (up -> horizontal -> down: to go through walls) + .then(argument("distance", integer()) + .executes(context -> { + int distance = context.getArgument("distance", Integer.class); + + assert client.player != null; + + // Move `direction` blocks into viewing direction + Vec3d targetPos = client.player.getPos().add( + client.player.getRotationVector().multiply(1, 0, 1).normalize().multiply(distance) + ); + clipUpDown(targetPos); + + return 1; + }) + ) + ); + dispatcher.register(literal("dclip") // Directional clip .then(argument("distance", integer()) .executes(context -> { @@ -117,23 +135,6 @@ public static void register(CommandDispatcher dispatc return 1; }) ); - - dispatcher.register(literal("hclip") // Horizontal clip (up -> horizontal -> down: to go through walls) - .then(argument("distance", integer()) - .executes(context -> { - int distance = context.getArgument("distance", Integer.class); - - assert client.player != null; - // Move `direction` blocks into viewing direction - Vec3d targetPos = client.player.getPos().add( - client.player.getRotationVector().multiply(1, 0, 1).normalize().multiply(distance) - ); - clipUpDown(targetPos); - - return 1; - }) - ) - ); } private static void clipStraight(Vec3d targetPos) { diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/SessionMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/SessionMixin.java new file mode 100644 index 0000000..552c74e --- /dev/null +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/SessionMixin.java @@ -0,0 +1,28 @@ +package com.jorianwoltjer.liveoverflowmod.mixin; + +import net.minecraft.client.util.Session; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; + +@Mixin(Session.class) +public class SessionMixin { + private final HashMap> names = new HashMap<>() {{ + put("Hackende", new HashSet<>(List.of("Hackende", "HACKENDE", "hackende", "HACKende", "hackENDe", "HaCkEnDe", "hAcKeNdE", "HackendE", "HackEnde"))); + // Put your own fun name in here :) + }}; + + @Inject(method = "getUsername", at = @At("RETURN"), cancellable = true) + private void getUsername(CallbackInfoReturnable cir) { + String name = cir.getReturnValue(); + if (name != null && names.containsKey(name)) { + String random = (String) names.get(name).toArray()[(int) (Math.random() * names.get(name).size())]; + cir.setReturnValue(random); + } + } +} diff --git a/src/main/resources/liveoverflowmod.mixins.json b/src/main/resources/liveoverflowmod.mixins.json index 20a329b..6c68193 100644 --- a/src/main/resources/liveoverflowmod.mixins.json +++ b/src/main/resources/liveoverflowmod.mixins.json @@ -21,6 +21,7 @@ "ClientPlayerInteractionManagerAccessor", "ClientPlayNetworkHandlerMixin", "GameStateChangeS2CPacketAccessor", - "MinecraftClientMixin" + "MinecraftClientMixin", + "SessionMixin" ] } From ce8ac4d2b6363dae055e4f3da81dcca4f771c057 Mon Sep 17 00:00:00 2001 From: Jorian Woltjer Date: Sun, 11 Dec 2022 18:17:48 +0100 Subject: [PATCH 15/20] move some code around --- .../liveoverflowmod/command/ClipCommand.java | 24 +++---- .../liveoverflowmod/hacks/Reach.java | 5 ++ .../liveoverflowmod/helper/Utils.java | 7 ++ .../ClientPlayerInteractionManagerMixin.java | 61 +++++++++++++++++ .../mixin/MinecraftClientMixin.java | 65 ------------------- 5 files changed, 85 insertions(+), 77 deletions(-) diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java index d6f6baf..fedb5d2 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java @@ -137,6 +137,18 @@ public static void register(CommandDispatcher dispatc ); } + private static void moveTo(Vec3d pos) { + if (client.player == null) return; + + if (client.player.getVehicle() != null) { + client.player.getVehicle().setPosition(pos); + networkHandler.sendPacket(new VehicleMoveC2SPacket(client.player.getVehicle())); + } else { + client.player.setPosition(pos); + networkHandler.sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true)); + } + } + private static void clipStraight(Vec3d targetPos) { if (client.player == null) return; @@ -204,16 +216,4 @@ private static Vec3d getAutoClipPos(int direction) { return null; // Nothing found } - - private static void moveTo(Vec3d pos) { - if (client.player == null) return; - - if (client.player.getVehicle() != null) { - client.player.getVehicle().setPosition(pos); - networkHandler.sendPacket(new VehicleMoveC2SPacket(client.player.getVehicle())); - } else { - client.player.setPosition(pos); - networkHandler.sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true)); - } - } } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/Reach.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/Reach.java index bf16df3..34afd2e 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/Reach.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/Reach.java @@ -1,12 +1,17 @@ package com.jorianwoltjer.liveoverflowmod.hacks; +import com.jorianwoltjer.liveoverflowmod.mixin.ClientPlayerInteractionManagerMixin; import com.jorianwoltjer.liveoverflowmod.mixin.MinecraftClientMixin; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; import org.lwjgl.glfw.GLFW; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; public class Reach extends ToggledHack { /** * Hit enitities from far away * @see MinecraftClientMixin + * @see ClientPlayerInteractionManagerMixin */ public Reach() { super("Reach", GLFW.GLFW_KEY_BACKSLASH); diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/helper/Utils.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/helper/Utils.java index 137fe9e..1f85f2c 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/helper/Utils.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/helper/Utils.java @@ -2,6 +2,8 @@ import org.spongepowered.asm.mixin.injection.invoke.arg.Args; +import java.util.LinkedList; + public class Utils { public static double roundCoordinate(double n) { @@ -23,5 +25,10 @@ public static void onPositionPacket(Args args) { args.set(2, z); } + @SuppressWarnings("SameParameterValue") + public static void insertToCenter(LinkedList list, T object) { + int middle = (list.size() + 1) / 2; // Rounded up + list.add(middle, object); + } } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerMixin.java index 71408e8..c7e493f 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerMixin.java @@ -2,15 +2,27 @@ import net.minecraft.block.BlockState; import net.minecraft.client.network.ClientPlayerInteractionManager; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket; import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket; +import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket; +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.util.LinkedList; + import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*; +import static com.jorianwoltjer.liveoverflowmod.helper.Utils.insertToCenter; @Mixin(ClientPlayerInteractionManager.class) public class ClientPlayerInteractionManagerMixin { @@ -32,4 +44,53 @@ private void attackBlock(BlockPos pos, Direction direction, CallbackInfoReturnab } } + // On attack, use Reach + @Inject(method = "attackEntity", at = @At(value = "HEAD"), cancellable = true) + private void attackEntity(PlayerEntity player, Entity target, CallbackInfo ci) { + if (client.player == null) return; + + if (reachHack.enabled) { + if (packetQueue.size() > 0) { + return; // Already running + } + String targetName; + if (target.getType().equals(EntityType.PLAYER)) { + targetName = target.getName().getString(); + } else { + targetName = target.getType().getName().getString(); + } + reachHack.message(String.format("Hit §a%s §r(%.1fm)", targetName, target.distanceTo(client.player))); + + Vec3d virtualPosition = client.player.getPos(); + Vec3d targetPos = target.getPos().subtract( // Subtract a bit from the end + target.getPos().subtract(virtualPosition).normalize().multiply(2) + ); + // If player is too far away, move closer + while (target.squaredDistanceTo(virtualPosition.add(0, client.player.getStandingEyeHeight(), 0)) >= MathHelper.square(6.0)) { + Vec3d movement = targetPos.subtract(virtualPosition); + + boolean lastPacket = false; + if (movement.lengthSquared() >= 100) { // Length squared is max 100 (otherwise "moved too quickly") + // Normalize to length 10 + movement = movement.normalize().multiply(9.9); + } else { // If short enough, this is last packet + lastPacket = true; + } + virtualPosition = virtualPosition.add(movement); + // Add forward and backwards packets + insertToCenter(packetQueue, new PlayerMoveC2SPacket.PositionAndOnGround(virtualPosition.x, virtualPosition.y, virtualPosition.z, true)); + if (!lastPacket) { // If not the last packet, add a backwards packet (only need one at the sheep) + insertToCenter(packetQueue, new PlayerMoveC2SPacket.PositionAndOnGround(virtualPosition.x, virtualPosition.y, virtualPosition.z, true)); + } + } + // Add hit packet in the middle and original position at the end + insertToCenter(packetQueue, PlayerInteractEntityC2SPacket.attack(target, client.player.isSneaking())); + packetQueue.add(new PlayerMoveC2SPacket.PositionAndOnGround(client.player.getX(), client.player.getY(), client.player.getZ(), true)); + packetQueue.add(new HandSwingC2SPacket(client.player.getActiveHand())); // Serverside animation + client.player.resetLastAttackedTicks(); // Reset attack cooldown + + ci.cancel(); + } + } + } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java index 052137a..3bb710a 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java @@ -29,12 +29,6 @@ @Mixin(MinecraftClient.class) public class MinecraftClientMixin { - @SuppressWarnings("SameParameterValue") - private static void insertToCenter(LinkedList list, T object) { - int middle = (list.size() + 1) / 2; // Rounded up - list.add(middle, object); - } - // Extend reach @Inject(method = "doAttack", at = @At(value = "HEAD")) private void doAttack(CallbackInfoReturnable cir) { @@ -45,63 +39,4 @@ private void doAttack(CallbackInfoReturnable cir) { } } - // On attack - @Redirect(method = "doAttack", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerInteractionManager;attackEntity(Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/entity/Entity;)V")) - private void attackEntity(ClientPlayerInteractionManager instance, PlayerEntity player, Entity target) { - // packetQueue: [1, 2, 3, 4, 5, A, 4, 3, 2, 1, 0] - // A = attack packet - // 0 = starting position - // 1-5 = path - if (client.player == null) return; - - if (reachHack.enabled) { - if (packetQueue.size() > 0) { - return; // Already running - } - String targetName; - if (target.getType().equals(EntityType.PLAYER)) { - targetName = target.getName().getString(); - } else { - targetName = target.getType().getName().getString(); - } - reachHack.message(String.format("Hit §a%s §r(%.1fm)", targetName, target.distanceTo(client.player))); - - Vec3d virtualPosition = client.player.getPos(); - Vec3d targetPos = target.getPos().subtract( // Subtract a bit from the end - target.getPos().subtract(virtualPosition).normalize().multiply(2) - ); - // If player is too far away, move closer - while (target.squaredDistanceTo(virtualPosition.add(0, client.player.getStandingEyeHeight(), 0)) >= MathHelper.square(6.0)) { - Vec3d movement = targetPos.subtract(virtualPosition); - - boolean lastPacket = false; - if (movement.lengthSquared() >= 100) { // Length squared is max 100 (otherwise "moved too quickly") - // Normalize to length 10 - movement = movement.normalize().multiply(9.9); - } else { // If short enough, this is last packet - lastPacket = true; - } - virtualPosition = virtualPosition.add(movement); - // Add forward and backwards packets - insertToCenter(packetQueue, new PlayerMoveC2SPacket.PositionAndOnGround(virtualPosition.x, virtualPosition.y, virtualPosition.z, true)); - if (!lastPacket) { // If not the last packet, add a backwards packet (only need one at the sheep) - insertToCenter(packetQueue, new PlayerMoveC2SPacket.PositionAndOnGround(virtualPosition.x, virtualPosition.y, virtualPosition.z, true)); - } - } - // Add hit packet in the middle and original position at the end - insertToCenter(packetQueue, PlayerInteractEntityC2SPacket.attack(target, client.player.isSneaking())); - packetQueue.add(new PlayerMoveC2SPacket.PositionAndOnGround(client.player.getX(), client.player.getY(), client.player.getZ(), true)); - packetQueue.add(new HandSwingC2SPacket(client.player.getActiveHand())); // Serverside animation - client.player.resetLastAttackedTicks(); // Reset attack cooldown - - } else { // Orignal `attackEntity()` code if not enabled - ClientPlayerInteractionManagerAccessor _instance = (ClientPlayerInteractionManagerAccessor) instance; - _instance._syncSelectedSlot(); - _instance._networkHandler().sendPacket(PlayerInteractEntityC2SPacket.attack(target, player.isSneaking())); - if (_instance._gameMode() != GameMode.SPECTATOR) { - player.attack(target); - player.resetLastAttackedTicks(); - } - } - } } From b3a2453c2d9db52b0a9ce05592762253151f0317 Mon Sep 17 00:00:00 2001 From: Jorian Woltjer Date: Wed, 14 Dec 2022 21:04:39 +0100 Subject: [PATCH 16/20] Separate Reach and ClipReach --- .../client/ClientEntrypoint.java | 11 ++-- .../liveoverflowmod/command/ClipCommand.java | 10 ++-- .../hacks/{FastBreak.java => BlockMiner.java} | 27 +++++---- .../liveoverflowmod/hacks/ClipReach.java | 59 ++++++++++++++++++ .../liveoverflowmod/hacks/Reach.java | 54 ++++++++++++++++- .../liveoverflowmod/hacks/ToggledHack.java | 3 +- .../mixin/ClientConnectionMixin.java | 18 ++++-- .../ClientPlayerInteractionManagerMixin.java | 60 +++++++------------ .../mixin/MinecraftClientMixin.java | 6 +- 9 files changed, 177 insertions(+), 71 deletions(-) rename src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/{FastBreak.java => BlockMiner.java} (90%) create mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ClipReach.java diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java index 4a8b443..080f970 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java @@ -21,19 +21,21 @@ 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 FastBreak fastBreakHack = new FastBreak(); + public static final BlockMiner fastBreakHack = new BlockMiner(); public static final ToggledHack[] toggledHacks = new ToggledHack[] { passiveMods, worldGuardBypassHack, reachHack, + clipReachHack, panicModeHack, fastBreakHack }; public static final MinecraftClient client = MinecraftClient.getInstance(); public static ClientPlayNetworkHandler networkHandler; public static int globalTimer = 0; - public static final LinkedList> packetQueue = new LinkedList<>(); + public static final LinkedList> packetQueue = new LinkedList<>(); // Max 5 per tick @Override public void onInitializeClient() { @@ -43,11 +45,11 @@ public void onInitializeClient() { ClientTickEvents.END_CLIENT_TICK.register(hack::tick); // Every tick } - ClientTickEvents.END_CLIENT_TICK.register(ClientEntrypoint::tick); // Every tick + ClientTickEvents.END_CLIENT_TICK.register(ClientEntrypoint::tickEnd); // End of every tick ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> registerCommands(dispatcher)); // Commands } - public static void tick(MinecraftClient client) { + public static void tickEnd(MinecraftClient client) { // Update variables networkHandler = client.getNetworkHandler(); globalTimer++; @@ -61,7 +63,6 @@ public static void tick(MinecraftClient client) { } ((ClientConnectionInvoker) networkHandler.getConnection())._sendImmediately(packet, null); } - } public static void registerCommands(CommandDispatcher dispatcher) { diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java index fedb5d2..eb688a2 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java @@ -137,7 +137,7 @@ public static void register(CommandDispatcher dispatc ); } - private static void moveTo(Vec3d pos) { + public static void moveTo(Vec3d pos) { if (client.player == null) return; if (client.player.getVehicle() != null) { @@ -149,7 +149,7 @@ private static void moveTo(Vec3d pos) { } } - private static void clipStraight(Vec3d targetPos) { + public static void clipStraight(Vec3d targetPos) { if (client.player == null) return; Vec3d pos = client.player.getPos(); @@ -161,7 +161,7 @@ private static void clipStraight(Vec3d targetPos) { moveTo(targetPos); } - private static void clipUpDown(Vec3d targetPos) { + public static void clipUpDown(Vec3d targetPos) { if (client.player == null) return; Vec3d pos = client.player.getPos(); @@ -179,7 +179,7 @@ private static void clipUpDown(Vec3d targetPos) { moveTo(targetPos); // Down } - private static int executeAutoClip(CommandContext context, int direction) { + public static int executeAutoClip(CommandContext context, int direction) { if (client.player == null) return 0; Vec3d pos = getAutoClipPos(direction); @@ -197,7 +197,7 @@ private static int executeAutoClip(CommandContext con * Automatically go through the nearest blocks in the given direction. * Credits to @EnderKill98 for the original code. */ - private static Vec3d getAutoClipPos(int direction) { + public static Vec3d getAutoClipPos(int direction) { if (client.player == null || client.world == null) return null; boolean inside = false; diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/FastBreak.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/BlockMiner.java similarity index 90% rename from src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/FastBreak.java rename to src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/BlockMiner.java index 91fa49d..e014c6e 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/FastBreak.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/BlockMiner.java @@ -3,6 +3,7 @@ import com.jorianwoltjer.liveoverflowmod.mixin.ClientConnectionMixin; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; import net.minecraft.item.MiningToolItem; import net.minecraft.network.packet.c2s.play.ClientStatusC2SPacket; import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket; @@ -20,7 +21,7 @@ import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.client; import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.networkHandler; -public class FastBreak extends ToggledHack { +public class BlockMiner extends ToggledHack { BlockPos targetPos; int timer; public Item itemToPlace; @@ -34,8 +35,8 @@ public class FastBreak extends ToggledHack { * more blocks of that type from your inventory if it runs out. * @see ClientConnectionMixin */ - public FastBreak() { - super("Fast Break", GLFW.GLFW_KEY_LEFT_BRACKET); + public BlockMiner() { + super("Block Miner", GLFW.GLFW_KEY_BACKSLASH); } @Override @@ -60,7 +61,7 @@ public void tickEnabled() { client.interactionManager.clickSlot(client.player.currentScreenHandler.syncId, slot, 40, SlotActionType.SWAP, client.player); } - placeAt(targetPos); + placeOffhandAt(targetPos); networkHandler.sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.START_DESTROY_BLOCK, targetPos, Direction.UP)); networkHandler.sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK, targetPos, Direction.UP)); } @@ -75,6 +76,12 @@ public void onEnable() { statsValue = -1; itemToPlace = client.player.getOffHandStack().getItem(); + if (itemToPlace == Items.AIR) { + message("§cNo block in offhand"); + enabled = false; + return; + } + networkHandler.sendPacket(new ClientStatusC2SPacket(ClientStatusC2SPacket.Mode.REQUEST_STATS)); // Send initial switch (client.player.getHorizontalFacing()) { @@ -89,17 +96,17 @@ public void onEnable() { public void onStatResponse(Integer newValue) { // Will get a callback from ClientConnectionMixin if (!enabled || client.player == null) return; - if (statsValue == -1) { // Initial value - statsValue = newValue; - } if (newValue == null) { // If not updated, value will be null newValue = statsValue; } + if (statsValue == -1) { // Initial value + statsValue = newValue; + } - client.player.sendMessage(Text.of(String.format(PREFIX + "%s: §b%d§r/min (§a%d§r total)", + client.player.sendMessage(Text.of(String.format(PREFIX + "%s: §b%d§r/min (§a%s§r total)", itemToPlace.getName().getString(), newValue - statsValue, - newValue + newValue == -1 ? "?" : newValue )), false); statsValue = newValue; @@ -117,7 +124,7 @@ public int findItemSlot(Item item) { return -1; // Not found } - public static void placeAt(BlockPos pos) { + public static void placeOffhandAt(BlockPos pos) { BlockHitResult hitResult = new BlockHitResult( new Vec3d(pos.getX(), pos.getY(), pos.getZ()), Direction.UP, diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ClipReach.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ClipReach.java new file mode 100644 index 0000000..d220c27 --- /dev/null +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ClipReach.java @@ -0,0 +1,59 @@ +package com.jorianwoltjer.liveoverflowmod.hacks; + +import com.jorianwoltjer.liveoverflowmod.mixin.ClientPlayerInteractionManagerMixin; +import com.jorianwoltjer.liveoverflowmod.mixin.MinecraftClientMixin; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket; +import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import org.lwjgl.glfw.GLFW; + +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.client; +import static com.jorianwoltjer.liveoverflowmod.command.ClipCommand.moveTo; + +public class ClipReach extends ToggledHack { + /** + * Hit enitities from far away *through blocks* by vclipping + * + * @see MinecraftClientMixin + * @see ClientPlayerInteractionManagerMixin + */ + public ClipReach() { + super("Clip Reach", GLFW.GLFW_KEY_LEFT_BRACKET); + } + + @Override + public void onEnable() { + reachHack.enabled = false; // Disable normal reach + } + + public void hitEntity(Entity target) { + if (client.player == null) return; + + Vec3d pos = client.player.getPos(); + Vec3d targetPos = target.getPos(); + + double maxDistance = 99.0D; + Vec3d diff = pos.subtract(targetPos); + double flatUp = Math.sqrt(maxDistance * maxDistance - (diff.x * diff.x + diff.z * diff.z)); + double targetUp = flatUp + diff.y; + + for (int i = 0; i < 9; i++) { // Build up TP range + moveTo(pos); + } + moveTo(pos.add(0, maxDistance, 0)); // V-Clip up + moveTo(targetPos.add(0, targetUp, 0)); // Can now move freely + moveTo(targetPos); // V-Clip down to target + + networkHandler.sendPacket(PlayerInteractEntityC2SPacket.attack(target, client.player.isSneaking())); // Hit packet + networkHandler.sendPacket(new HandSwingC2SPacket(client.player.getActiveHand())); // Serverside animation + + moveTo(targetPos.add(0, targetUp + 0.01, 0)); // V-Clip up + moveTo(pos.add(0, maxDistance + 0.01, 0)); // Can now move freely + moveTo(pos); // V-Clip down to original position + client.player.setPosition(pos); // Set position on client-side + } +} diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/Reach.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/Reach.java index 34afd2e..9a8551b 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/Reach.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/Reach.java @@ -3,10 +3,20 @@ import com.jorianwoltjer.liveoverflowmod.mixin.ClientPlayerInteractionManagerMixin; import com.jorianwoltjer.liveoverflowmod.mixin.MinecraftClientMixin; import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket; +import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket; +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; import org.lwjgl.glfw.GLFW; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.client; +import static com.jorianwoltjer.liveoverflowmod.helper.Utils.insertToCenter; + public class Reach extends ToggledHack { /** * Hit enitities from far away @@ -14,6 +24,48 @@ public class Reach extends ToggledHack { * @see ClientPlayerInteractionManagerMixin */ public Reach() { - super("Reach", GLFW.GLFW_KEY_BACKSLASH); + super("Reach", GLFW.GLFW_KEY_RIGHT_BRACKET); + } + + @Override + public void onEnable() { + clipReachHack.enabled = false; // Disable clip reach + } + + public void hitEntity(Entity target) { + if (client.player == null) return; + + if (packetQueue.size() > 0) { + return; // Already running (may take multiple ticks) + } + + Vec3d pos = client.player.getPos(); + Vec3d targetPos = target.getPos().subtract( // Subtract a bit from the end + target.getPos().subtract(pos).normalize().multiply(2) + ); + // If player is still too far away, move closer + while (target.squaredDistanceTo(pos.add(0, client.player.getStandingEyeHeight(), 0)) >= MathHelper.square(6.0)) { + Vec3d movement = targetPos.subtract(pos); + + boolean lastPacket = false; + if (movement.lengthSquared() >= 100) { // Length squared is max 100 (otherwise "moved too quickly") + // Normalize to length 10 + movement = movement.normalize().multiply(9.9); + } else { // If short enough, this is last packet + lastPacket = true; + } + pos = pos.add(movement); + + // Add forward and backwards packets + insertToCenter(packetQueue, new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true)); + if (!lastPacket) { // If not the last packet, add a backwards packet (only need one at the sheep) + insertToCenter(packetQueue, new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true)); + } + } + // Add hit packet in the middle and original position at the end + insertToCenter(packetQueue, PlayerInteractEntityC2SPacket.attack(target, client.player.isSneaking())); + packetQueue.add(new PlayerMoveC2SPacket.PositionAndOnGround(client.player.getX(), client.player.getY(), client.player.getZ(), true)); + packetQueue.add(new HandSwingC2SPacket(client.player.getActiveHand())); // Serverside animation + client.player.resetLastAttackedTicks(); // Reset attack cooldown } } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java index bd2fac2..6769de8 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java @@ -91,7 +91,8 @@ void onDisable() {} public void message(String message) { if (client.player == null) return; - // TODO: maybe convert all white text to gray + message = "§7" + message.replace("§r", "§7"); // Make white text gray + client.player.sendMessage(Text.of(PREFIX + name + ": " + message), true); } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java index d19dd12..3a40025 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java @@ -7,6 +7,8 @@ import net.minecraft.network.PacketCallbacks; import net.minecraft.network.listener.PacketListener; import net.minecraft.network.packet.c2s.play.PlayerInteractBlockC2SPacket; +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; +import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket; import net.minecraft.network.packet.s2c.play.StatisticsS2CPacket; import net.minecraft.stat.Stats; import net.minecraft.text.Text; @@ -16,6 +18,8 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.time.ZonedDateTime; + import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*; import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.LOGGER; @@ -25,17 +29,17 @@ public class ClientConnectionMixin { @SuppressWarnings({"EmptyMethod", "CommentedOutCode"}) @Inject(method = "sendImmediately", at = @At("HEAD")) void onSendImmediately(Packet packet, @Nullable PacketCallbacks callbacks, CallbackInfo ci) { -// LOGGER.info("---> " + packet.getClass().getSimpleName()); -// -// if (packet instanceof PlayerInteractBlockC2SPacket _packet) { -// LOGGER.info(String.format("PlayerInteractBlockC2SPacket(%s, %s, %s)", _packet.getHand(), _packet.getBlockHitResult().getBlockPos(), _packet.getBlockHitResult().getPos())); +// LOGGER.info(String.format("---> [%04d] %s", ZonedDateTime.now().toInstant().toEpochMilli() % 1000, packet.getClass().getSimpleName())); + +// if (packet instanceof PlayerMoveC2SPacket _packet) { +// LOGGER.info(String.format(" PlayerMoveC2SPacket(%.2f, %.2f, %.2f)", _packet.getX(0), _packet.getY(0), _packet.getZ(0))); // } } // Log incoming packets (for debugging) @Inject(method = "handlePacket", at = @At("HEAD")) private static void onHandlePacket(Packet packet, PacketListener listener, CallbackInfo ci) { -// LOGGER.info("<--- " + packet.getClass().getSimpleName()); +// LOGGER.info(String.format("<--- [%04d] %s", ZonedDateTime.now().toInstant().toEpochMilli() % 1000, packet.getClass().getSimpleName())); // Save statistics response if (packet instanceof StatisticsS2CPacket statsPacket) { @@ -43,6 +47,10 @@ private static void onHandlePacket(Packet packet, Integer statsValue = statsPacket.getStatMap().get(Stats.MINED.getOrCreateStat(Block.getBlockFromItem(fastBreakHack.itemToPlace))); fastBreakHack.onStatResponse(statsValue); } + +// if (packet instanceof PlayerPositionLookS2CPacket _packet) { +// LOGGER.info(String.format(" PlayerPositionLookS2CPacket(%.2f, %.2f, %.2f)", _packet.getX(), _packet.getY(), _packet.getZ())); +// } } // Delay other packets while any packets in packetQueue diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerMixin.java index c7e493f..14ffef5 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerMixin.java @@ -19,9 +19,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.util.LinkedList; - import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*; +import static com.jorianwoltjer.liveoverflowmod.command.ClipCommand.moveTo; +import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.LOGGER; import static com.jorianwoltjer.liveoverflowmod.helper.Utils.insertToCenter; @Mixin(ClientPlayerInteractionManager.class) @@ -49,48 +49,28 @@ private void attackBlock(BlockPos pos, Direction direction, CallbackInfoReturnab private void attackEntity(PlayerEntity player, Entity target, CallbackInfo ci) { if (client.player == null) return; - if (reachHack.enabled) { - if (packetQueue.size() > 0) { - return; // Already running - } - String targetName; - if (target.getType().equals(EntityType.PLAYER)) { - targetName = target.getName().getString(); - } else { - targetName = target.getType().getName().getString(); - } - reachHack.message(String.format("Hit §a%s §r(%.1fm)", targetName, target.distanceTo(client.player))); - - Vec3d virtualPosition = client.player.getPos(); - Vec3d targetPos = target.getPos().subtract( // Subtract a bit from the end - target.getPos().subtract(virtualPosition).normalize().multiply(2) - ); - // If player is too far away, move closer - while (target.squaredDistanceTo(virtualPosition.add(0, client.player.getStandingEyeHeight(), 0)) >= MathHelper.square(6.0)) { - Vec3d movement = targetPos.subtract(virtualPosition); + if (reachHack.enabled || clipReachHack.enabled) { + Vec3d pos = client.player.getPos(); - boolean lastPacket = false; - if (movement.lengthSquared() >= 100) { // Length squared is max 100 (otherwise "moved too quickly") - // Normalize to length 10 - movement = movement.normalize().multiply(9.9); - } else { // If short enough, this is last packet - lastPacket = true; + // If player is too far away, needs reach + if (target.squaredDistanceTo(pos.add(0, client.player.getStandingEyeHeight(), 0)) >= MathHelper.square(6.0)) { + String targetName; + if (target.getType().equals(EntityType.PLAYER)) { + targetName = target.getName().getString(); + } else { + targetName = target.getType().getName().getString(); } - virtualPosition = virtualPosition.add(movement); - // Add forward and backwards packets - insertToCenter(packetQueue, new PlayerMoveC2SPacket.PositionAndOnGround(virtualPosition.x, virtualPosition.y, virtualPosition.z, true)); - if (!lastPacket) { // If not the last packet, add a backwards packet (only need one at the sheep) - insertToCenter(packetQueue, new PlayerMoveC2SPacket.PositionAndOnGround(virtualPosition.x, virtualPosition.y, virtualPosition.z, true)); + + if (reachHack.enabled) { + reachHack.message(String.format("Hit §a%s §r(§b%.0fm§r)", targetName, target.distanceTo(client.player))); + reachHack.hitEntity(target); + } else if (clipReachHack.enabled) { + clipReachHack.message(String.format("Hit §a%s §r(§b%.0fm§r)", targetName, target.distanceTo(client.player))); + clipReachHack.hitEntity(target); } - } - // Add hit packet in the middle and original position at the end - insertToCenter(packetQueue, PlayerInteractEntityC2SPacket.attack(target, client.player.isSneaking())); - packetQueue.add(new PlayerMoveC2SPacket.PositionAndOnGround(client.player.getX(), client.player.getY(), client.player.getZ(), true)); - packetQueue.add(new HandSwingC2SPacket(client.player.getActiveHand())); // Serverside animation - client.player.resetLastAttackedTicks(); // Reset attack cooldown - ci.cancel(); + ci.cancel(); + } } } - } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java index 3bb710a..cb9aa9f 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java @@ -22,9 +22,7 @@ import java.util.LinkedList; import java.util.Optional; -import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.client; -import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.packetQueue; -import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.reachHack; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*; @Mixin(MinecraftClient.class) public class MinecraftClientMixin { @@ -32,7 +30,7 @@ public class MinecraftClientMixin { // Extend reach @Inject(method = "doAttack", at = @At(value = "HEAD")) private void doAttack(CallbackInfoReturnable cir) { - if (reachHack.enabled) { + if (reachHack.enabled || clipReachHack.enabled) { MinecraftClient client = MinecraftClient.getInstance(); Optional entity = DebugRenderer.getTargetedEntity(client.player, 100); entity.ifPresent(e -> client.crosshairTarget = new EntityHitResult(e)); From c4727d9bcaef78c6a7540bed641f7038f9ba8c9c Mon Sep 17 00:00:00 2001 From: Jorian Woltjer Date: Fri, 10 Feb 2023 23:12:13 +0100 Subject: [PATCH 17/20] Add right click interact to reach + nicer action bar --- .../liveoverflowmod/command/ClipCommand.java | 16 +++++++- .../liveoverflowmod/hacks/ClipReach.java | 37 +++++++++++++++++-- .../mixin/ClientPlayerEntityAccessor.java | 13 ------- ...lientPlayerInteractionManagerAccessor.java | 21 ----------- .../ClientPlayerInteractionManagerMixin.java | 35 +++++++++++++++--- .../mixin/InGameHudAccessor.java | 15 ++++++++ .../liveoverflowmod/mixin/InGameHudMixin.java | 27 ++++++++++++++ .../mixin/LivingEntityMixin.java | 1 + .../mixin/MinecraftClientMixin.java | 31 ++++++++-------- .../resources/liveoverflowmod.mixins.json | 4 +- 10 files changed, 139 insertions(+), 61 deletions(-) delete mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerEntityAccessor.java delete mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerAccessor.java create mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/InGameHudAccessor.java create mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/InGameHudMixin.java diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java index eb688a2..7671751 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/command/ClipCommand.java @@ -14,7 +14,6 @@ import net.minecraft.util.math.Vec3d; import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*; -import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.LOGGER; import static com.mojang.brigadier.arguments.IntegerArgumentType.integer; import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.*; @@ -148,6 +147,20 @@ public static void moveTo(Vec3d pos) { networkHandler.sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround(pos.x, pos.y, pos.z, true)); } } + public static void moveTo(Vec3d pos, float yaw, float pitch) { + if (client.player == null) return; + + if (client.player.getVehicle() != null) { + client.player.getVehicle().setPosition(pos); + networkHandler.sendPacket(new VehicleMoveC2SPacket(client.player.getVehicle())); + } else { + client.player.setPosition(pos); + networkHandler.sendPacket(new PlayerMoveC2SPacket.Full( + pos.x, pos.y, pos.z, + yaw, pitch, + client.player.isOnGround())); + } + } public static void clipStraight(Vec3d targetPos) { if (client.player == null) return; @@ -161,6 +174,7 @@ public static void clipStraight(Vec3d targetPos) { moveTo(targetPos); } + // TODO: maybe refactor this to be the same as ClipReach#hitEntity public static void clipUpDown(Vec3d targetPos) { if (client.player == null) return; diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ClipReach.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ClipReach.java index d220c27..e61f79b 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ClipReach.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ClipReach.java @@ -3,10 +3,10 @@ import com.jorianwoltjer.liveoverflowmod.mixin.ClientPlayerInteractionManagerMixin; import com.jorianwoltjer.liveoverflowmod.mixin.MinecraftClientMixin; import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket; import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket; -import net.minecraft.util.math.MathHelper; +import net.minecraft.network.packet.c2s.play.PlayerInteractItemC2SPacket; +import net.minecraft.util.Hand; import net.minecraft.util.math.Vec3d; import org.lwjgl.glfw.GLFW; @@ -16,7 +16,10 @@ public class ClipReach extends ToggledHack { /** - * Hit enitities from far away *through blocks* by vclipping + * Hit enitities from far away *through blocks* by vclipping. + * Not compatible with Meteor Client's: + * - Anti-Hunger: will set onGound to false making you take fall damage + * - Criticals: will send an extra move packet going over the limit * * @see MinecraftClientMixin * @see ClientPlayerInteractionManagerMixin @@ -56,4 +59,32 @@ public void hitEntity(Entity target) { moveTo(pos); // V-Clip down to original position client.player.setPosition(pos); // Set position on client-side } + + public void interactAtEntity(Entity target) { + if (client.player == null) return; + + Vec3d pos = client.player.getPos(); + Vec3d targetPos = target.getPos(); + + double maxDistance = 99.0D; + Vec3d diff = pos.subtract(targetPos); + double flatUp = Math.sqrt(maxDistance * maxDistance - (diff.x * diff.x + diff.z * diff.z)); + double targetUp = flatUp + diff.y; + + for (int i = 0; i < 9; i++) { // Build up TP range + moveTo(pos); + } + moveTo(pos.add(0, maxDistance, 0)); // V-Clip up + moveTo(targetPos.add(0, targetUp, 0)); // Can now move freely + moveTo(targetPos, client.player.getYaw(), 90); // V-Clip down to target (looking down) + + networkHandler.sendPacket(new PlayerInteractItemC2SPacket(Hand.MAIN_HAND, 0)); // Interact item packet + networkHandler.sendPacket(PlayerInteractEntityC2SPacket.interact(target, client.player.isSneaking(), Hand.MAIN_HAND)); // Interact entity packet + networkHandler.sendPacket(new HandSwingC2SPacket(client.player.getActiveHand())); // Serverside animation + + moveTo(targetPos.add(0, targetUp + 0.01, 0), client.player.getYaw(), client.player.getPitch()); // V-Clip up (looking normal) + moveTo(pos.add(0, maxDistance + 0.01, 0)); // Can now move freely + moveTo(pos); // V-Clip down to original position + client.player.setPosition(pos); // Set position on client-side + } } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerEntityAccessor.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerEntityAccessor.java deleted file mode 100644 index d05c7cc..0000000 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerEntityAccessor.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.jorianwoltjer.liveoverflowmod.mixin; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayerEntity; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(ClientPlayerEntity.class) -public interface ClientPlayerEntityAccessor { - @Accessor("client") - MinecraftClient _client(); - -} diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerAccessor.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerAccessor.java deleted file mode 100644 index a6614aa..0000000 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerAccessor.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.jorianwoltjer.liveoverflowmod.mixin; - -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.client.network.ClientPlayerInteractionManager; -import net.minecraft.world.GameMode; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; -import org.spongepowered.asm.mixin.gen.Invoker; - -@Mixin(ClientPlayerInteractionManager.class) -public interface ClientPlayerInteractionManagerAccessor { - @Invoker("syncSelectedSlot") - void _syncSelectedSlot(); - - @Accessor("networkHandler") - ClientPlayNetworkHandler _networkHandler(); - - @Accessor("gameMode") - GameMode _gameMode(); - -} diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerMixin.java index 14ffef5..d1e4fd5 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientPlayerInteractionManagerMixin.java @@ -5,10 +5,10 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket; import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket; -import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket; -import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.EntityHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.MathHelper; @@ -20,9 +20,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*; -import static com.jorianwoltjer.liveoverflowmod.command.ClipCommand.moveTo; -import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.LOGGER; -import static com.jorianwoltjer.liveoverflowmod.helper.Utils.insertToCenter; @Mixin(ClientPlayerInteractionManager.class) public class ClientPlayerInteractionManagerMixin { @@ -73,4 +70,30 @@ private void attackEntity(PlayerEntity player, Entity target, CallbackInfo ci) { } } } + + // On interact, use Reach + @Inject(method = "interactEntityAtLocation", at = @At(value = "HEAD"), cancellable = true) + private void interactEntityAtLocation(PlayerEntity player, Entity entity, EntityHitResult hitResult, Hand hand, CallbackInfoReturnable cir) { + if (client.player == null) return; + + if (clipReachHack.enabled && hand.equals(Hand.MAIN_HAND)) { + Vec3d pos = client.player.getPos(); + + // If player is too far away, needs reach + if (entity.squaredDistanceTo(pos.add(0, client.player.getStandingEyeHeight(), 0)) >= MathHelper.square(6.0)) { + String targetName; + if (entity.getType().equals(EntityType.PLAYER)) { + targetName = entity.getName().getString(); + } else { + targetName = entity.getType().getName().getString(); + } + + clipReachHack.message(String.format("Interacted with §a%s §r(§b%.0fm§r)", targetName, entity.distanceTo(client.player))); + clipReachHack.interactAtEntity(entity); + + cir.setReturnValue(ActionResult.SUCCESS); + } + } + } + } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/InGameHudAccessor.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/InGameHudAccessor.java new file mode 100644 index 0000000..78ed5fa --- /dev/null +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/InGameHudAccessor.java @@ -0,0 +1,15 @@ +package com.jorianwoltjer.liveoverflowmod.mixin; + +import net.minecraft.client.gui.hud.InGameHud; +import net.minecraft.text.Text; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(InGameHud.class) +public interface InGameHudAccessor { + @Accessor("overlayMessage") + Text _overlayMessage(); + + @Accessor("overlayRemaining") + int _overlayRemaining(); +} diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/InGameHudMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/InGameHudMixin.java new file mode 100644 index 0000000..b002eb8 --- /dev/null +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/InGameHudMixin.java @@ -0,0 +1,27 @@ +package com.jorianwoltjer.liveoverflowmod.mixin; + +import net.minecraft.client.gui.hud.InGameHud; +import net.minecraft.text.Text; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.client; + +@Mixin(InGameHud.class) +public class InGameHudMixin { + + // Don't overwrite the overlay message if it contains "LiveOverflow" + @Inject(method = "setOverlayMessage", at = @At("HEAD"), cancellable = true) + private void setOverlayMessage(Text message, boolean tinted, CallbackInfo ci) { + Text currentMessage = ((InGameHudAccessor) client.inGameHud)._overlayMessage(); + int remaining = ((InGameHudAccessor) client.inGameHud)._overlayRemaining(); + if (currentMessage == null || message == null) return; + + if (currentMessage.getString().contains("LiveOverflow") && !message.getString().contains("LiveOverflow") && remaining > 20) { + ci.cancel(); + } + } + +} diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/LivingEntityMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/LivingEntityMixin.java index b041805..01933ae 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/LivingEntityMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/LivingEntityMixin.java @@ -13,4 +13,5 @@ public class LivingEntityMixin { private boolean isImmobile(net.minecraft.entity.LivingEntity livingEntity) { return worldGuardBypassHack.enabled; } + } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java index cb9aa9f..8237726 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/MinecraftClientMixin.java @@ -1,35 +1,24 @@ package com.jorianwoltjer.liveoverflowmod.mixin; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayerInteractionManager; import net.minecraft.client.render.debug.DebugRenderer; import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket; -import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket; -import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; import net.minecraft.util.hit.EntityHitResult; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.GameMode; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.util.LinkedList; import java.util.Optional; -import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.clipReachHack; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.reachHack; @Mixin(MinecraftClient.class) public class MinecraftClientMixin { - // Extend reach - @Inject(method = "doAttack", at = @At(value = "HEAD")) - private void doAttack(CallbackInfoReturnable cir) { + private void updateCrossairTarget() { if (reachHack.enabled || clipReachHack.enabled) { MinecraftClient client = MinecraftClient.getInstance(); Optional entity = DebugRenderer.getTargetedEntity(client.player, 100); @@ -37,4 +26,16 @@ private void doAttack(CallbackInfoReturnable cir) { } } + // Extend reach for attack + @Inject(method = "doAttack", at = @At(value = "HEAD")) + private void doAttack(CallbackInfoReturnable cir) { + updateCrossairTarget(); + } + + // Extend reach for interact + @Inject(method = "doItemUse", at = @At(value = "HEAD")) + private void doItemUse(CallbackInfo ci) { + updateCrossairTarget(); + } + } diff --git a/src/main/resources/liveoverflowmod.mixins.json b/src/main/resources/liveoverflowmod.mixins.json index 6c68193..833dec3 100644 --- a/src/main/resources/liveoverflowmod.mixins.json +++ b/src/main/resources/liveoverflowmod.mixins.json @@ -17,10 +17,10 @@ "defaultRequire": 1 }, "client": [ - "ClientPlayerEntityAccessor", - "ClientPlayerInteractionManagerAccessor", "ClientPlayNetworkHandlerMixin", "GameStateChangeS2CPacketAccessor", + "InGameHudAccessor", + "InGameHudMixin", "MinecraftClientMixin", "SessionMixin" ] From ef8a1bf5f120f35ec6600baecf203eadc4a96bed Mon Sep 17 00:00:00 2001 From: Jorian Woltjer Date: Sat, 4 Mar 2023 14:25:08 +0100 Subject: [PATCH 18/20] Add simple text GUI --- .../client/ClientEntrypoint.java | 7 ++-- .../liveoverflowmod/client/Gui.java | 32 +++++++++++++++++++ .../hacks/{BlockMiner.java => FastMiner.java} | 6 ++-- .../liveoverflowmod/hacks/ToggledHack.java | 4 +-- .../mixin/ClientConnectionMixin.java | 10 ++---- 5 files changed, 44 insertions(+), 15 deletions(-) create mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/client/Gui.java rename src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/{BlockMiner.java => FastMiner.java} (97%) diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java index 080f970..5f26765 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java @@ -9,6 +9,7 @@ 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.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.network.Packet; @@ -23,14 +24,14 @@ public class ClientEntrypoint implements ClientModInitializer { public static final Reach reachHack = new Reach(); public static final ClipReach clipReachHack = new ClipReach(); public static final PanicMode panicModeHack = new PanicMode(); - public static final BlockMiner fastBreakHack = new BlockMiner(); + public static final FastMiner fastMinerHack = new FastMiner(); public static final ToggledHack[] toggledHacks = new ToggledHack[] { passiveMods, worldGuardBypassHack, reachHack, clipReachHack, panicModeHack, - fastBreakHack + fastMinerHack }; public static final MinecraftClient client = MinecraftClient.getInstance(); public static ClientPlayNetworkHandler networkHandler; @@ -47,6 +48,8 @@ public void onInitializeClient() { ClientTickEvents.END_CLIENT_TICK.register(ClientEntrypoint::tickEnd); // End of every tick ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> registerCommands(dispatcher)); // Commands + + HudRenderCallback.EVENT.register(Gui::render); // Render GUI } public static void tickEnd(MinecraftClient client) { diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/client/Gui.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/client/Gui.java new file mode 100644 index 0000000..6defdc8 --- /dev/null +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/client/Gui.java @@ -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); + } +} diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/BlockMiner.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/FastMiner.java similarity index 97% rename from src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/BlockMiner.java rename to src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/FastMiner.java index e014c6e..e5117a4 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/BlockMiner.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/FastMiner.java @@ -21,7 +21,7 @@ import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.client; import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.networkHandler; -public class BlockMiner extends ToggledHack { +public class FastMiner extends ToggledHack { BlockPos targetPos; int timer; public Item itemToPlace; @@ -35,8 +35,8 @@ public class BlockMiner extends ToggledHack { * more blocks of that type from your inventory if it runs out. * @see ClientConnectionMixin */ - public BlockMiner() { - super("Block Miner", GLFW.GLFW_KEY_BACKSLASH); + public FastMiner() { + super("Fast Miner", GLFW.GLFW_KEY_BACKSLASH); } @Override diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java index 6769de8..a5bbcb9 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/hacks/ToggledHack.java @@ -61,7 +61,7 @@ void tickEnabled() {} */ public void enable() { enabled = true; - message("§aEnabled"); + message("§aON"); LOGGER.info("Enabled " + name); onEnable(); } @@ -75,7 +75,7 @@ void onEnable() {} */ public void disable() { enabled = false; - message("§cDisabled"); + message("§cOFF"); LOGGER.info("Disabled " + name); onDisable(); } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java index 3a40025..fa10256 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java @@ -6,9 +6,6 @@ import net.minecraft.network.Packet; import net.minecraft.network.PacketCallbacks; import net.minecraft.network.listener.PacketListener; -import net.minecraft.network.packet.c2s.play.PlayerInteractBlockC2SPacket; -import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; -import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket; import net.minecraft.network.packet.s2c.play.StatisticsS2CPacket; import net.minecraft.stat.Stats; import net.minecraft.text.Text; @@ -18,10 +15,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import java.time.ZonedDateTime; - import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*; -import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.LOGGER; @Mixin(ClientConnection.class) public class ClientConnectionMixin { @@ -44,8 +38,8 @@ private static void onHandlePacket(Packet packet, // Save statistics response if (packet instanceof StatisticsS2CPacket statsPacket) { // Get mined stat for FastBreak - Integer statsValue = statsPacket.getStatMap().get(Stats.MINED.getOrCreateStat(Block.getBlockFromItem(fastBreakHack.itemToPlace))); - fastBreakHack.onStatResponse(statsValue); + Integer statsValue = statsPacket.getStatMap().get(Stats.MINED.getOrCreateStat(Block.getBlockFromItem(fastMinerHack.itemToPlace))); + fastMinerHack.onStatResponse(statsValue); } // if (packet instanceof PlayerPositionLookS2CPacket _packet) { From 354211d7983f16861b456191727d8a142fbc3b1e Mon Sep 17 00:00:00 2001 From: Jorian Woltjer Date: Sat, 20 May 2023 11:43:39 +0200 Subject: [PATCH 19/20] Move server-side commands to separate class --- .../liveoverflowmod/LiveOverflowMod.java | 96 ---------------- .../client/ClientEntrypoint.java | 11 +- .../command/GetCodeCommand.java | 108 ++++++++++++++++++ 3 files changed, 117 insertions(+), 98 deletions(-) create mode 100644 src/main/java/com/jorianwoltjer/liveoverflowmod/command/GetCodeCommand.java diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/LiveOverflowMod.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/LiveOverflowMod.java index b7e55af..c39f921 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/LiveOverflowMod.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/LiveOverflowMod.java @@ -1,111 +1,15 @@ package com.jorianwoltjer.liveoverflowmod; -import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType; import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; -import net.minecraft.block.Blocks; -import net.minecraft.command.argument.BlockPosArgumentType; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.text.Text; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.BlockBox; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.ChunkPos; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.random.Random; -import net.minecraft.util.math.random.RandomSplitter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static net.minecraft.server.command.CommandManager.argument; -import static net.minecraft.server.command.CommandManager.literal; - public class LiveOverflowMod implements ModInitializer { public static final Logger LOGGER = LoggerFactory.getLogger("liveoverflowmod"); public static final String PREFIX = "§8[§c⬤§7 §7LiveOverflowMod§8] §r"; - private static final Dynamic2CommandExceptionType TOO_BIG_EXCEPTION = new Dynamic2CommandExceptionType((maxCount, count) -> Text.translatable("commands.fill.toobig", maxCount, count)); @Override public void onInitialize() { LOGGER.info("Successfully loaded LiveOverflowMod"); - - // Checks to see if bedrock is at a certain position - CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> dispatcher.register(literal("bedrock") - .then(argument("pos", BlockPosArgumentType.blockPos()) - .executes(context -> { - BlockPos pos = BlockPosArgumentType.getBlockPos(context, "pos"); - ServerWorld world = context.getSource().getWorld(); - - boolean result = checkBedrock(world, pos); // <--- Try setting a breakpoint here - - context.getSource().sendFeedback(Text.of("Bedrock at " + pos.getX() + " " + pos.getY() + " " + pos.getZ() + - ": " + (result ? "§atrue" : "§cfalse")), false); - - return 1; - })) - )); - - // Generate the checks for the Rust code to brute-force a recreated bedrock formation - CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> dispatcher.register(literal("getcode") - .then(argument("from", BlockPosArgumentType.blockPos()) - .then(argument("to", BlockPosArgumentType.blockPos()) - .executes(context -> { - BlockBox area = BlockBox.create(BlockPosArgumentType.getLoadedBlockPos(context, "from"), BlockPosArgumentType.getLoadedBlockPos(context, "to")); - ChunkPos centerChunk = new ChunkPos(area.getCenter()); - BlockPos start = new BlockPos(centerChunk.getStartX(), area.getMaxY(), centerChunk.getStartZ()); - - int i = area.getBlockCountX() * area.getBlockCountY() * area.getBlockCountZ(); - if (i > 32768) { - throw TOO_BIG_EXCEPTION.create(32768, i); - } - - ServerWorld world = context.getSource().getWorld(); - - for (BlockPos blockPos : BlockPos.iterate(area.getMinX(), area.getMinY(), area.getMinZ(), area.getMaxX(), area.getMaxY(), area.getMaxZ())) { - String code = ""; - if (world.getBlockState(blockPos).getBlock() == Blocks.BEDROCK) { // Is bedrock - BlockPos pos = blockPos.subtract(start); - code = String.format("generator.is_bedrock(chunk_x + %d, y + %d, chunk_z + %d) == true", pos.getX(), pos.getY(), pos.getZ()); - } else if (world.getBlockState(blockPos).getBlock() == Blocks.GLASS) { // Is empty - BlockPos pos = blockPos.subtract(start); - code = String.format("generator.is_bedrock(chunk_x + %d, y + %d, chunk_z + %d) == false", pos.getX(), pos.getY(), pos.getZ()); - } else if (world.getBlockState(blockPos).getBlock() == Blocks.REDSTONE_BLOCK) { // Is unused bedrock - BlockPos pos = blockPos.subtract(start); - code = String.format("// generator.is_bedrock(chunk_x + %d, y + %d, chunk_z + %d) == true", pos.getX(), pos.getY(), pos.getZ()); - } else if (world.getBlockState(blockPos).getBlock() == Blocks.RED_STAINED_GLASS) { // Is unused empty - BlockPos pos = blockPos.subtract(start); - code = String.format("// generator.is_bedrock(chunk_x + %d, y + %d, chunk_z + %d) == false", pos.getX(), pos.getY(), pos.getZ()); - } - if (!code.isEmpty()) { - context.getSource().sendFeedback(Text.of(code), false); - } - } - - return 1; - })) - ))); - } - - private static boolean checkBedrock(ServerWorld world, BlockPos pos) { - RandomSplitter randomSplitter = world.getChunkManager().getNoiseConfig().getOrCreateRandomDeriver(new Identifier("bedrock_floor")); - - int i = 0; - int j = 5; - - int i2 = pos.getY(); - if (i2 <= i) { - return true; - } - if (i2 >= j) { - return false; - } - double d = MathHelper.map(i2, i, j, 1.0, 0.0); - LOGGER.info("d: " + d); - - Random random = randomSplitter.split(pos.getX(), i, pos.getZ()); - - return (double)random.nextFloat() < d; - } - } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java index 5f26765..2ed0f9b 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java @@ -10,11 +10,13 @@ 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; 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; @@ -47,7 +49,8 @@ public void onInitializeClient() { } ClientTickEvents.END_CLIENT_TICK.register(ClientEntrypoint::tickEnd); // End of every tick - ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> registerCommands(dispatcher)); // Commands + 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 } @@ -68,7 +71,11 @@ public static void tickEnd(MinecraftClient client) { } } - public static void registerCommands(CommandDispatcher dispatcher) { + public static void registerClientCommands(CommandDispatcher dispatcher) { ClipCommand.register(dispatcher); } + + public static void registerServerCommands(CommandDispatcher dispatcher) { + GetCodeCommand.register(dispatcher); + } } diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/command/GetCodeCommand.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/command/GetCodeCommand.java new file mode 100644 index 0000000..4ced3ea --- /dev/null +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/command/GetCodeCommand.java @@ -0,0 +1,108 @@ +package com.jorianwoltjer.liveoverflowmod.command; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType; +import net.minecraft.block.Blocks; +import net.minecraft.command.argument.BlockPosArgumentType; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.text.Text; +import net.minecraft.util.Hand; +import net.minecraft.util.Identifier; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.*; +import net.minecraft.util.math.random.Random; +import net.minecraft.util.math.random.RandomSplitter; + +import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.LOGGER; +import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.*; + +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; + +public class GetCodeCommand { + private static final Dynamic2CommandExceptionType TOO_BIG_EXCEPTION = new Dynamic2CommandExceptionType((maxCount, count) -> Text.translatable("commands.fill.toobig", maxCount, count)); + + public static void register(CommandDispatcher dispatcher) { + // Checks to see if bedrock is at a certain position (for tracing in debugger) + dispatcher.register(literal("bedrock") + .then(argument("pos", BlockPosArgumentType.blockPos()) + .executes(context -> { + BlockPos pos = BlockPosArgumentType.getBlockPos(context, "pos"); + ServerWorld world = context.getSource().getWorld(); + + boolean result = checkBedrock(world, pos); // <--- Try setting a breakpoint here + + context.getSource().sendFeedback(Text.of("Bedrock at " + pos.getX() + " " + pos.getY() + " " + pos.getZ() + + ": " + (result ? "§atrue" : "§cfalse")), false); + + return 1; + }) + ) + ); + + // Generate the checks for the Rust code to brute-force a recreated bedrock formation + dispatcher.register(literal("getcode") + .then(argument("from", BlockPosArgumentType.blockPos()) + .then(argument("to", BlockPosArgumentType.blockPos()) + .executes(context -> { + BlockBox area = BlockBox.create(BlockPosArgumentType.getLoadedBlockPos(context, "from"), BlockPosArgumentType.getLoadedBlockPos(context, "to")); + ChunkPos centerChunk = new ChunkPos(area.getCenter()); + BlockPos start = new BlockPos(centerChunk.getStartX(), area.getMaxY(), centerChunk.getStartZ()); + + int i = area.getBlockCountX() * area.getBlockCountY() * area.getBlockCountZ(); + if (i > 32768) { + throw TOO_BIG_EXCEPTION.create(32768, i); + } + + ServerWorld world = context.getSource().getWorld(); + + for (BlockPos blockPos : BlockPos.iterate(area.getMinX(), area.getMinY(), area.getMinZ(), area.getMaxX(), area.getMaxY(), area.getMaxZ())) { + String code = ""; + if (world.getBlockState(blockPos).getBlock() == Blocks.BEDROCK) { // Is bedrock + BlockPos pos = blockPos.subtract(start); + code = String.format("generator.is_bedrock(chunk_x + %d, y + %d, chunk_z + %d) == true", pos.getX(), pos.getY(), pos.getZ()); + } else if (world.getBlockState(blockPos).getBlock() == Blocks.GLASS) { // Is empty + BlockPos pos = blockPos.subtract(start); + code = String.format("generator.is_bedrock(chunk_x + %d, y + %d, chunk_z + %d) == false", pos.getX(), pos.getY(), pos.getZ()); + } else if (world.getBlockState(blockPos).getBlock() == Blocks.REDSTONE_BLOCK) { // Is unused bedrock + BlockPos pos = blockPos.subtract(start); + code = String.format("// generator.is_bedrock(chunk_x + %d, y + %d, chunk_z + %d) == true", pos.getX(), pos.getY(), pos.getZ()); + } else if (world.getBlockState(blockPos).getBlock() == Blocks.RED_STAINED_GLASS) { // Is unused empty + BlockPos pos = blockPos.subtract(start); + code = String.format("// generator.is_bedrock(chunk_x + %d, y + %d, chunk_z + %d) == false", pos.getX(), pos.getY(), pos.getZ()); + } + if (!code.isEmpty()) { + context.getSource().sendFeedback(Text.of(code), false); + } + } + + return 1; + }) + ) + ) + ); + } + + private static boolean checkBedrock(ServerWorld world, BlockPos pos) { + RandomSplitter randomSplitter = world.getChunkManager().getNoiseConfig().getOrCreateRandomDeriver(new Identifier("bedrock_floor")); + + int i = 0; + int j = 5; + + int i2 = pos.getY(); + if (i2 <= i) { + return true; + } + if (i2 >= j) { + return false; + } + double d = MathHelper.map(i2, i, j, 1.0, 0.0); + LOGGER.info("d: " + d); + + Random random = randomSplitter.split(pos.getX(), i, pos.getZ()); + + return (double)random.nextFloat() < d; + } +} From 3ca3be441f00ef8b6aaf9bd40ed2c8525ee29352 Mon Sep 17 00:00:00 2001 From: Jorian Woltjer Date: Sat, 20 May 2023 18:50:10 +0200 Subject: [PATCH 20/20] 1.19.4 + Improve /getcode command to copy to clipboard --- gradle.properties | 8 ++--- .../client/ClientEntrypoint.java | 2 +- .../command/GetCodeCommand.java | 35 +++++++++++-------- .../mixin/ClientConnectionInvoker.java | 2 +- .../mixin/ClientConnectionMixin.java | 2 +- src/main/resources/fabric.mod.json | 4 +-- 6 files changed, 29 insertions(+), 24 deletions(-) diff --git a/gradle.properties b/gradle.properties index 700c8a0..a17f9de 100644 --- a/gradle.properties +++ b/gradle.properties @@ -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 diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java index 2ed0f9b..4ade93f 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/client/ClientEntrypoint.java @@ -13,7 +13,7 @@ import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.network.Packet; +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; diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/command/GetCodeCommand.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/command/GetCodeCommand.java index 4ced3ea..4328cfa 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/command/GetCodeCommand.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/command/GetCodeCommand.java @@ -2,22 +2,22 @@ import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType; +import net.minecraft.block.Block; import net.minecraft.block.Blocks; import net.minecraft.command.argument.BlockPosArgumentType; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.world.ServerWorld; import net.minecraft.text.Text; -import net.minecraft.util.Hand; +import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; -import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.*; import net.minecraft.util.math.random.Random; import net.minecraft.util.math.random.RandomSplitter; import static com.jorianwoltjer.liveoverflowmod.LiveOverflowMod.LOGGER; import static com.jorianwoltjer.liveoverflowmod.client.ClientEntrypoint.*; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.*; +import static net.minecraft.client.util.SelectionManager.setClipboard; import static net.minecraft.server.command.CommandManager.argument; import static net.minecraft.server.command.CommandManager.literal; @@ -57,27 +57,32 @@ public static void register(CommandDispatcher dispatcher) { } ServerWorld world = context.getSource().getWorld(); + StringBuilder code = new StringBuilder(); for (BlockPos blockPos : BlockPos.iterate(area.getMinX(), area.getMinY(), area.getMinZ(), area.getMaxX(), area.getMaxY(), area.getMaxZ())) { - String code = ""; - if (world.getBlockState(blockPos).getBlock() == Blocks.BEDROCK) { // Is bedrock + Block block = world.getBlockState(blockPos).getBlock(); + if (block == Blocks.BEDROCK) { BlockPos pos = blockPos.subtract(start); - code = String.format("generator.is_bedrock(chunk_x + %d, y + %d, chunk_z + %d) == true", pos.getX(), pos.getY(), pos.getZ()); - } else if (world.getBlockState(blockPos).getBlock() == Blocks.GLASS) { // Is empty + code.append(String.format(" generator.is_bedrock(chunk_x + %d, y + %d, chunk_z + %d) &&\n", pos.getX(), pos.getY(), pos.getZ())); + } else if (block == Blocks.GLASS) { BlockPos pos = blockPos.subtract(start); - code = String.format("generator.is_bedrock(chunk_x + %d, y + %d, chunk_z + %d) == false", pos.getX(), pos.getY(), pos.getZ()); - } else if (world.getBlockState(blockPos).getBlock() == Blocks.REDSTONE_BLOCK) { // Is unused bedrock + code.append(String.format("!generator.is_bedrock(chunk_x + %d, y + %d, chunk_z + %d) &&\n", pos.getX(), pos.getY(), pos.getZ())); + } else if (block == Blocks.REDSTONE_BLOCK) { BlockPos pos = blockPos.subtract(start); - code = String.format("// generator.is_bedrock(chunk_x + %d, y + %d, chunk_z + %d) == true", pos.getX(), pos.getY(), pos.getZ()); - } else if (world.getBlockState(blockPos).getBlock() == Blocks.RED_STAINED_GLASS) { // Is unused empty + code.append(String.format("// generator.is_bedrock(chunk_x + %d, y + %d, chunk_z + %d) &&\n", pos.getX(), pos.getY(), pos.getZ())); + } else if (block == Blocks.RED_STAINED_GLASS) { BlockPos pos = blockPos.subtract(start); - code = String.format("// generator.is_bedrock(chunk_x + %d, y + %d, chunk_z + %d) == false", pos.getX(), pos.getY(), pos.getZ()); - } - if (!code.isEmpty()) { - context.getSource().sendFeedback(Text.of(code), false); + code.append(String.format("// !generator.is_bedrock(chunk_x + %d, y + %d, chunk_z + %d) &&\n", pos.getX(), pos.getY(), pos.getZ())); } } + setClipboard(client, code.toString()); + + int lineCount = code.toString().split("\n").length; + context.getSource().sendFeedback(Text.literal("Copied ") + .append(Text.literal(String.valueOf(lineCount)).formatted(Formatting.GREEN)) + .append(Text.literal(" lines to clipboard")), false); + return 1; }) ) diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionInvoker.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionInvoker.java index d0b77b7..eb40e69 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionInvoker.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionInvoker.java @@ -1,7 +1,7 @@ package com.jorianwoltjer.liveoverflowmod.mixin; import net.minecraft.network.ClientConnection; -import net.minecraft.network.Packet; +import net.minecraft.network.packet.Packet; import net.minecraft.network.PacketCallbacks; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; diff --git a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java index fa10256..34a3e68 100644 --- a/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java +++ b/src/main/java/com/jorianwoltjer/liveoverflowmod/mixin/ClientConnectionMixin.java @@ -3,7 +3,7 @@ import com.jorianwoltjer.liveoverflowmod.hacks.ToggledHack; import net.minecraft.block.Block; import net.minecraft.network.ClientConnection; -import net.minecraft.network.Packet; +import net.minecraft.network.packet.Packet; import net.minecraft.network.PacketCallbacks; import net.minecraft.network.listener.PacketListener; import net.minecraft.network.packet.s2c.play.StatisticsS2CPacket; diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 2305e24..4b81762 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -21,8 +21,8 @@ "liveoverflowmod.mixins.json" ], "depends": { - "fabricloader": ">=0.14.9", + "fabricloader": ">=0.14.17", "fabric": "*", - "minecraft": "1.19.2" + "minecraft": "1.19.4" } }