diff --git a/build.gradle b/build.gradle index b0d64d9..34675f2 100644 --- a/build.gradle +++ b/build.gradle @@ -16,6 +16,10 @@ repositories { // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. // See https://docs.gradle.org/current/userguide/declaring_repositories.html // for more information about repositories. + maven { + name = "meteor-maven" + url = "https://maven.meteordev.org/releases" + } } dependencies { @@ -24,6 +28,7 @@ dependencies { mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + implementation "meteordevelopment:orbit:0.2.3" // Uncomment the following line to enable the deprecated Fabric API modules. // These are included in the Fabric API production distribution and allow you to update your mod to the latest modules at a later more convenient time. diff --git a/src/main/java/dev/coredoes/clientmod/ClientMod.java b/src/main/java/dev/coredoes/clientmod/ClientMod.java index 2a1aee7..cd5d3a2 100644 --- a/src/main/java/dev/coredoes/clientmod/ClientMod.java +++ b/src/main/java/dev/coredoes/clientmod/ClientMod.java @@ -1,20 +1,25 @@ package dev.coredoes.clientmod; +import com.mojang.brigadier.CommandDispatcher; import dev.coredoes.clientmod.hud.HudManager; import dev.coredoes.clientmod.modmenu.ModMenu; -import dev.coredoes.clientmod.modules.CreativeFlight; -import dev.coredoes.clientmod.modules.Jetpack; -import dev.coredoes.clientmod.modules.ModuleManager; -import dev.coredoes.clientmod.modules.NoFall; +import dev.coredoes.clientmod.modules.*; +import meteordevelopment.orbit.EventBus; import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; import net.minecraft.client.option.KeyBinding; import net.minecraft.client.util.InputUtil; +import net.minecraft.command.CommandRegistryAccess; import org.lwjgl.glfw.GLFW; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.lang.invoke.MethodHandles; + public class ClientMod implements ClientModInitializer { // This logger is used to write text to the console and the log file. // It is considered best practice to use your mod id as the logger's name. @@ -26,11 +31,13 @@ public class ClientMod implements ClientModInitializer { private static KeyBinding modMenuKeyBinding; + public static EventBus eventBus; + @Override public void onInitializeClient() { LOGGER.info("Hello, world! ClientMod is loading up"); - LOGGER.info("[Stage 1/3: ModMenuInit] Creating ModMenu keybinding"); + LOGGER.info("[Stage 1/5: ModMenuInit] Creating ModMenu keybinding"); modMenuKeyBinding = KeyBindingHelper.registerKeyBinding(new KeyBinding( "key.clientmod.modmenu", InputUtil.Type.KEYSYM, @@ -44,13 +51,21 @@ public class ClientMod implements ClientModInitializer { } }); - LOGGER.info("[Stage 2/3: ModuleInit] Registering modules"); + LOGGER.info("[State 2/5: BusInit] Registered module event system; creating plugin event bus"); + eventBus = new EventBus(); + eventBus.registerLambdaFactory("dev.coredoes.clientmod", (lookupInMethod, klass) -> (MethodHandles.Lookup) lookupInMethod.invoke(null, klass, MethodHandles.lookup())); + + LOGGER.info("[Stage 3/5: ModuleInit] Started event bus; registering modules"); moduleManager.registerModule(new Jetpack()); moduleManager.registerModule(new NoFall()); moduleManager.registerModule(new CreativeFlight()); + moduleManager.registerModule(new PacketFreezer()); + moduleManager.registerModule(new BotMovementBypass()); + moduleManager.registerModule(new WorldBorderBypass()); + moduleManager.registerModule(new BunkerBuster()); - LOGGER.info("[Stage 3/3: EventInit] Registered modules; registering module event system"); + LOGGER.info("[Stage 4/5: EventInit] Registered modules; registering module event system"); moduleManager.registerEvents(); } } diff --git a/src/main/java/dev/coredoes/clientmod/commands/AirTPCommand.java b/src/main/java/dev/coredoes/clientmod/commands/AirTPCommand.java new file mode 100644 index 0000000..bb6d334 --- /dev/null +++ b/src/main/java/dev/coredoes/clientmod/commands/AirTPCommand.java @@ -0,0 +1,49 @@ +package dev.coredoes.clientmod.commands; + +import dev.coredoes.clientmod.util.ConnectionInterface; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; + +public class AirTPCommand extends Command { + + private void doAirTpTo(MinecraftClient client, double x, double y, double z) { + // STEP 1: Massively increase our movement cap + PlayerMoveC2SPacket packet = new PlayerMoveC2SPacket.PositionAndOnGround( + client.player.getX(), + client.player.getY(), + client.player.getZ(), + client.player.isOnGround() + ); + for (int i = 0; i < 8; i++) { + ((ConnectionInterface) client.getNetworkHandler().getConnection()).sendVolatile(packet, null); + } + // STEP 2: Send the teleport packet + PlayerMoveC2SPacket realPacket = new PlayerMoveC2SPacket.PositionAndOnGround( + x, + y, + z, + client.player.isOnGround() + ); + ((ConnectionInterface) client.getNetworkHandler().getConnection()).sendVolatile(realPacket, null); + client.player.setPosition(x, y, z); + } + + @Override + void execute(String[] argv) { + + MinecraftClient client = MinecraftClient.getInstance(); + ClientPlayerEntity player = client.player; + + + // STEP 1: Teleport into the sky + assert client.player != null; + + double atY = client.player.getY() - 51; + + doAirTpTo(client, client.player.getX(), atY, client.player.getZ()); + + // STEP 5: Update the client + //client.player.setPositio n(x, client.player.getY() + 300, z); + } +} diff --git a/src/main/java/dev/coredoes/clientmod/commands/Command.java b/src/main/java/dev/coredoes/clientmod/commands/Command.java new file mode 100644 index 0000000..9edc07a --- /dev/null +++ b/src/main/java/dev/coredoes/clientmod/commands/Command.java @@ -0,0 +1,5 @@ +package dev.coredoes.clientmod.commands; + +public abstract class Command { + abstract void execute(String[] argv); +} diff --git a/src/main/java/dev/coredoes/clientmod/commands/CommandParser.java b/src/main/java/dev/coredoes/clientmod/commands/CommandParser.java new file mode 100644 index 0000000..933fddb --- /dev/null +++ b/src/main/java/dev/coredoes/clientmod/commands/CommandParser.java @@ -0,0 +1,63 @@ +package dev.coredoes.clientmod.commands; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import dev.coredoes.clientmod.ClientMod; +import net.minecraft.client.MinecraftClient; +import net.minecraft.entity.Entity; +import net.minecraft.entity.mob.DrownedEntity; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.predicate.entity.EntityPredicate; +import net.minecraft.predicate.entity.EntityPredicates; +import net.minecraft.text.Text; +import net.minecraft.util.TypeFilter; +import net.minecraft.util.hit.EntityHitResult; +import net.minecraft.util.hit.HitResult; +import net.minecraft.util.math.Box; + +import java.util.List; +import java.util.Objects; + +public class CommandParser { + public static void parseCommand(String command_str) { + String[] components = command_str.substring(1).split(" "); + + String command = components[0]; + + if (Objects.equals(command, "airtp")) { + new AirTPCommand().execute(components); + } else if (Objects.equals(command, "vault")) { + new Vault().execute(components); + } else if (Objects.equals(command, "getentity")) { + // TODO: breakout to another class + HitResult hit = MinecraftClient.getInstance().crosshairTarget; + if (hit.getType() == HitResult.Type.ENTITY) { + EntityHitResult res = (EntityHitResult) hit; + Entity entity = res.getEntity(); + Gson gson = new GsonBuilder().serializeSpecialFloatingPointValues().serializeNulls().create(); + MinecraftClient.getInstance().player.sendMessage(Text.of("---- START ENTITY ----")); + MinecraftClient.getInstance().player.sendMessage(Text.of("UUID: " + entity.getUuidAsString())); + MinecraftClient.getInstance().player.sendMessage(Text.of(entity.toString())); + NbtCompound compound = new NbtCompound(); + entity.saveSelfNbt(compound); + MinecraftClient.getInstance().player.sendMessage(Text.of(compound.toString())); + MinecraftClient.getInstance().player.sendMessage(Text.of("---- END ENTITY ----")); + } else { + MinecraftClient.getInstance().player.sendMessage(Text.of("---- START ENTITY ----")); + MinecraftClient.getInstance().player.sendMessage(Text.of("You are not looking at an entity.")); + MinecraftClient.getInstance().player.sendMessage(Text.of("---- END ENTITY ----")); + } + } else if (Objects.equals(command, "findHerobrine")) { + MinecraftClient client = MinecraftClient.getInstance(); + assert client.world != null; + List drownedEntities = client.world.getEntitiesByType(TypeFilter.instanceOf(DrownedEntity.class), + new Box(client.player.getX() - 1000, client.player.getY() - 1000, client.player.getZ() - 1000, client.player.getX() + 1000, client.player.getY() + 1000, client.player.getZ() + 1000), + EntityPredicates.VALID_LIVING_ENTITY); + client.player.sendMessage(Text.of("--- START DROWNED LIST ---")); + for (DrownedEntity entity : drownedEntities) { + client.player.sendMessage(Text.of("Found drowned at " + entity.getPos().toString())); + } + client.player.sendMessage(Text.of("--- END DROWNED LIST ---")); + } + } +} diff --git a/src/main/java/dev/coredoes/clientmod/commands/Vault.java b/src/main/java/dev/coredoes/clientmod/commands/Vault.java new file mode 100644 index 0000000..01ceb16 --- /dev/null +++ b/src/main/java/dev/coredoes/clientmod/commands/Vault.java @@ -0,0 +1,80 @@ +package dev.coredoes.clientmod.commands; + +import dev.coredoes.clientmod.util.ConnectionInterface; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; +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; + +public class Vault extends Command { + + private void doAirTpTo(MinecraftClient client, double x, double y, double z) { + // STEP 1: Massively increase our movement cap + PlayerMoveC2SPacket packet = new PlayerMoveC2SPacket.PositionAndOnGround( + client.player.getX(), + client.player.getY(), + client.player.getZ(), + client.player.isOnGround() + ); + for (int i = 0; i < 7; i++) { + ((ConnectionInterface) client.getNetworkHandler().getConnection()).sendVolatile(packet, null); + } + // STEP 2: Send the teleport packet + PlayerMoveC2SPacket realPacket = new PlayerMoveC2SPacket.PositionAndOnGround( + x, + y, + z, + client.player.isOnGround() + ); + ((ConnectionInterface) client.getNetworkHandler().getConnection()).sendVolatile(realPacket, null); + client.player.setPosition(x, y, z); + } + + @Override + void execute(String[] argv) { + + MinecraftClient client = MinecraftClient.getInstance(); + ClientPlayerEntity player = client.player; + + // press ze button + BlockPos blockPos = new BlockPos(4780, 125, 1286); + Direction direction = Direction.NORTH; + BlockHitResult blockHitResult = new BlockHitResult(new Vec3d(blockPos.getX(), blockPos.getY(), blockPos.getZ()), direction, blockPos, false); + client.interactionManager.interactBlock(client.player, Hand.MAIN_HAND, blockHitResult); + + // STEP 1: Teleport into the sky + assert client.player != null; + + double atY = client.player.getY() + 60; + + doAirTpTo(client, client.player.getX(), atY, client.player.getZ()); + try { Thread.sleep(50); } catch (InterruptedException ignored) {} + + doAirTpTo(client, client.player.getX(), client.player.getY() - 3, client.player.getZ() + 52); + try { Thread.sleep(50); } catch (InterruptedException ignored) {} + + doAirTpTo(client, client.player.getX(), client.player.getY() - 55, client.player.getZ()); + try { Thread.sleep(10); } catch (InterruptedException ignored) {} + + BlockPos blockPos2 = new BlockPos(4780, 125, 1336); + Direction direction2 = Direction.NORTH; + BlockHitResult blockHitResult2 = new BlockHitResult(new Vec3d(blockPos2.getX(), blockPos2.getY(), blockPos2.getZ()), direction2, blockPos2, false); + client.interactionManager.interactBlock(client.player, Hand.MAIN_HAND, blockHitResult2); + + try { Thread.sleep(20); } catch (InterruptedException ignored) {} + + doAirTpTo(client, client.player.getX(), client.player.getY() + 56, client.player.getZ()); + try { Thread.sleep(10); } catch (InterruptedException ignored) {} + + doAirTpTo(client, client.player.getX(), client.player.getY(), client.player.getZ() - 52); + try { Thread.sleep(20); } catch (InterruptedException ignored) {} + + doAirTpTo(client, client.player.getX(), client.player.getY() - 55, client.player.getZ()); + try { Thread.sleep(10); } catch (InterruptedException ignored) {} + + } +} diff --git a/src/main/java/dev/coredoes/clientmod/events/Cancellable.java b/src/main/java/dev/coredoes/clientmod/events/Cancellable.java new file mode 100644 index 0000000..dd4913c --- /dev/null +++ b/src/main/java/dev/coredoes/clientmod/events/Cancellable.java @@ -0,0 +1,17 @@ +package dev.coredoes.clientmod.events; + +import meteordevelopment.orbit.ICancellable; + +public class Cancellable implements ICancellable { + private boolean cancelled = false; + + @Override + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } + + @Override + public boolean isCancelled() { + return cancelled; + } +} \ No newline at end of file diff --git a/src/main/java/dev/coredoes/clientmod/events/ConnectEvent.java b/src/main/java/dev/coredoes/clientmod/events/ConnectEvent.java new file mode 100644 index 0000000..ba73821 --- /dev/null +++ b/src/main/java/dev/coredoes/clientmod/events/ConnectEvent.java @@ -0,0 +1,9 @@ +package dev.coredoes.clientmod.events; + +public class ConnectEvent { + private static final ConnectEvent INSTANCE = new ConnectEvent(); + + public static ConnectEvent get() { + return INSTANCE; + } +} diff --git a/src/main/java/dev/coredoes/clientmod/events/DisconnectEvent.java b/src/main/java/dev/coredoes/clientmod/events/DisconnectEvent.java new file mode 100644 index 0000000..33b1105 --- /dev/null +++ b/src/main/java/dev/coredoes/clientmod/events/DisconnectEvent.java @@ -0,0 +1,9 @@ +package dev.coredoes.clientmod.events; + +public class DisconnectEvent { + private static final DisconnectEvent INSTANCE = new DisconnectEvent(); + + public static DisconnectEvent get() { + return INSTANCE; + } +} diff --git a/src/main/java/dev/coredoes/clientmod/events/PacketEvent.java b/src/main/java/dev/coredoes/clientmod/events/PacketEvent.java new file mode 100644 index 0000000..21c1095 --- /dev/null +++ b/src/main/java/dev/coredoes/clientmod/events/PacketEvent.java @@ -0,0 +1,36 @@ +package dev.coredoes.clientmod.events; + +import net.minecraft.network.Packet; + +public class PacketEvent extends Cancellable { + public Packet packet; + + public static class Receive extends PacketEvent { + private static final Receive INSTANCE = new Receive(); + + public static Receive get(Packet packet) { + INSTANCE.setCancelled(false); + INSTANCE.packet = packet; + return INSTANCE; + } + } + + public static class Send extends PacketEvent { + private static final Send INSTANCE = new Send(); + + public static Send get(Packet packet) { + INSTANCE.setCancelled(false); + INSTANCE.packet = packet; + return INSTANCE; + } + } + + public static class Sent extends PacketEvent { + private static final Sent INSTANCE = new Sent(); + + public static Sent get(Packet packet) { + INSTANCE.packet = packet; + return INSTANCE; + } + } +} diff --git a/src/main/java/dev/coredoes/clientmod/events/SendPacketEvent.java b/src/main/java/dev/coredoes/clientmod/events/SendPacketEvent.java new file mode 100644 index 0000000..1f303d5 --- /dev/null +++ b/src/main/java/dev/coredoes/clientmod/events/SendPacketEvent.java @@ -0,0 +1,14 @@ +package dev.coredoes.clientmod.events; + +import net.minecraft.network.Packet; + +public class SendPacketEvent extends Cancellable { + public Packet packet; + private static final SendPacketEvent INSTANCE = new SendPacketEvent(); + + public static SendPacketEvent get(Packet packet) { + INSTANCE.packet = packet; + INSTANCE.setCancelled(false); + return INSTANCE; + } +} diff --git a/src/main/java/dev/coredoes/clientmod/mixin/BotMovementFullMixin.java b/src/main/java/dev/coredoes/clientmod/mixin/BotMovementFullMixin.java new file mode 100644 index 0000000..3112c40 --- /dev/null +++ b/src/main/java/dev/coredoes/clientmod/mixin/BotMovementFullMixin.java @@ -0,0 +1,23 @@ +package dev.coredoes.clientmod.mixin; + +import dev.coredoes.clientmod.ClientMod; +import dev.coredoes.clientmod.modules.BotMovementBypass; +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; + +@Mixin(PlayerMoveC2SPacket.Full.class) +public abstract class BotMovementFullMixin { + @ModifyArgs(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/packet/c2s/play/PlayerMoveC2SPacket;(DDDFFZZZ)V")) + private static void init(Args args) { + if (((BotMovementBypass) ClientMod.moduleManager.getModuleById("BotBypass")).isEnabled()) { + double newX = Math.round((double) args.get(0) * 100) / 100d; + double newZ = Math.round((double) args.get(2) * 100) / 100d; + args.set(0, Math.nextAfter(newX, newX + Math.signum(newX))); // Round x + args.set(2, Math.nextAfter(newZ, newZ + Math.signum(newZ))); // Round z + } + } +} + diff --git a/src/main/java/dev/coredoes/clientmod/mixin/BotMovementOnGroundMixin.java b/src/main/java/dev/coredoes/clientmod/mixin/BotMovementOnGroundMixin.java new file mode 100644 index 0000000..4c859af --- /dev/null +++ b/src/main/java/dev/coredoes/clientmod/mixin/BotMovementOnGroundMixin.java @@ -0,0 +1,23 @@ +package dev.coredoes.clientmod.mixin; + +import dev.coredoes.clientmod.ClientMod; +import dev.coredoes.clientmod.modules.BotMovementBypass; +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; + +@Mixin(PlayerMoveC2SPacket.PositionAndOnGround.class) +public abstract class BotMovementOnGroundMixin { + @ModifyArgs(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/packet/c2s/play/PlayerMoveC2SPacket;(DDDFFZZZ)V")) + private static void init(Args args) { + if (((BotMovementBypass) ClientMod.moduleManager.getModuleById("BotBypass")).isEnabled()) { + double newX = Math.round((double) args.get(0) * 100) / 100d; + double newZ = Math.round((double) args.get(2) * 100) / 100d; + args.set(0, Math.nextAfter(newX, newX + Math.signum(newX))); // Round x + args.set(2, Math.nextAfter(newZ, newZ + Math.signum(newZ))); // Round z + } + } +} + diff --git a/src/main/java/dev/coredoes/clientmod/mixin/ChatMixin.java b/src/main/java/dev/coredoes/clientmod/mixin/ChatMixin.java new file mode 100644 index 0000000..3778d70 --- /dev/null +++ b/src/main/java/dev/coredoes/clientmod/mixin/ChatMixin.java @@ -0,0 +1,20 @@ +package dev.coredoes.clientmod.mixin; + +import dev.coredoes.clientmod.commands.CommandParser; +import net.minecraft.text.Text; +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; + +@Mixin(net.minecraft.client.network.ClientPlayerEntity.class) +public class ChatMixin { + @Inject(method = "sendChatMessage(Ljava/lang/String;Lnet/minecraft/text/Text;)V", at = @At("HEAD"), cancellable = true) + public void sendChatMessage(String message, @Nullable Text preview, CallbackInfo ci) { + if (message.startsWith(".")) { + CommandParser.parseCommand(message); + ci.cancel(); + } + } +} diff --git a/src/main/java/dev/coredoes/clientmod/mixin/ClientConnectionMixin.java b/src/main/java/dev/coredoes/clientmod/mixin/ClientConnectionMixin.java new file mode 100644 index 0000000..7bf4097 --- /dev/null +++ b/src/main/java/dev/coredoes/clientmod/mixin/ClientConnectionMixin.java @@ -0,0 +1,52 @@ +package dev.coredoes.clientmod.mixin; + +import dev.coredoes.clientmod.ClientMod; +import dev.coredoes.clientmod.events.ConnectEvent; +import dev.coredoes.clientmod.events.DisconnectEvent; +import dev.coredoes.clientmod.events.PacketEvent; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import net.minecraft.network.ClientConnection; +import net.minecraft.network.Packet; +import net.minecraft.network.PacketCallbacks; +import net.minecraft.network.listener.PacketListener; +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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.net.InetSocketAddress; + +@Mixin(ClientConnection.class) +public class ClientConnectionMixin { + @Inject(method = "handlePacket", at = @At("HEAD"), cancellable = true) + private static void onHandlePacket(Packet packet, PacketListener listener, CallbackInfo info) { + if (ClientMod.eventBus.post(PacketEvent.Receive.get(packet)).isCancelled()) info.cancel(); + } + + @Inject(method = "send(Lnet/minecraft/network/Packet;)V", at = @At("HEAD"), cancellable = true) + private void onSendPacket(Packet packet, CallbackInfo info) { + if (ClientMod.eventBus.post(PacketEvent.Send.get(packet)).isCancelled()) { + // we should cancel this packet + info.cancel(); + ClientMod.LOGGER.info("Outgoing packet cancelled"); + } + } + + @Inject(method = "send(Lnet/minecraft/network/Packet;)V", at = @At("TAIL")) + private void onSentPacket(Packet packet, CallbackInfo info) { + ClientMod.eventBus.post(PacketEvent.Sent.get(packet)); + } + + @Inject(method = "disconnect", at = @At("HEAD")) + private void disconnect(Text disconnectReason, CallbackInfo ci) { + ClientMod.eventBus.post(DisconnectEvent.get()); + } + + @Inject(method = "connect", at = @At("HEAD")) + private static void onConnect(InetSocketAddress address, boolean useEpoll, CallbackInfoReturnable info) { + ClientMod.eventBus.post(ConnectEvent.get()); + } +} diff --git a/src/main/java/dev/coredoes/clientmod/mixin/ConnectionMixin.java b/src/main/java/dev/coredoes/clientmod/mixin/ConnectionMixin.java new file mode 100644 index 0000000..c8290ff --- /dev/null +++ b/src/main/java/dev/coredoes/clientmod/mixin/ConnectionMixin.java @@ -0,0 +1,18 @@ +package dev.coredoes.clientmod.mixin; + +import dev.coredoes.clientmod.util.ConnectionInterface; +import net.minecraft.network.ClientConnection; +import net.minecraft.network.Packet; +import net.minecraft.network.PacketCallbacks; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(ClientConnection.class) +public abstract class ConnectionMixin implements ConnectionInterface { + @Shadow protected abstract void sendImmediately(Packet packet, @Nullable PacketCallbacks callbacks); + + public void sendVolatile(Packet packet, @Nullable PacketCallbacks callbacks) { + this.sendImmediately(packet, callbacks); + } +} diff --git a/src/main/java/dev/coredoes/clientmod/mixin/VehicleMovementMixin.java b/src/main/java/dev/coredoes/clientmod/mixin/VehicleMovementMixin.java new file mode 100644 index 0000000..4af3db0 --- /dev/null +++ b/src/main/java/dev/coredoes/clientmod/mixin/VehicleMovementMixin.java @@ -0,0 +1,39 @@ +package dev.coredoes.clientmod.mixin; + +import dev.coredoes.clientmod.ClientMod; +import dev.coredoes.clientmod.modules.BotMovementBypass; +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; +import net.minecraft.network.packet.c2s.play.VehicleMoveC2SPacket; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +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.ModifyArgs; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.invoke.arg.Args; + +@Mixin(VehicleMoveC2SPacket.class) +public abstract class VehicleMovementMixin { + @Shadow public abstract double getX(); + + @Shadow public abstract double getY(); + + @Mutable + @Shadow @Final private double x; + + @Mutable + @Shadow @Final private double z; + + @Inject(method = "(Lnet/minecraft/entity/Entity;)V", at = @At("TAIL")) + public void init(CallbackInfo info) { + if (((BotMovementBypass) ClientMod.moduleManager.getModuleById("BotBypass")).isEnabled()) { + double newX = Math.round((double) this.getX() * 100) / 100d; + double newZ = Math.round((double) this.getY() * 100) / 100d; + this.x = newX; + this.z = newZ; + } + } +} + diff --git a/src/main/java/dev/coredoes/clientmod/mixin/WorldBorderMixin.java b/src/main/java/dev/coredoes/clientmod/mixin/WorldBorderMixin.java new file mode 100644 index 0000000..0c7f862 --- /dev/null +++ b/src/main/java/dev/coredoes/clientmod/mixin/WorldBorderMixin.java @@ -0,0 +1,27 @@ +package dev.coredoes.clientmod.mixin; + +import dev.coredoes.clientmod.ClientMod; +import dev.coredoes.clientmod.modules.WorldBorderBypass; +import net.minecraft.world.border.WorldBorder; +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; + +@Mixin(WorldBorder.class) +public class WorldBorderMixin { + @Inject(method = "canCollide", at = @At("HEAD"), cancellable = true) + private void canCollide(CallbackInfoReturnable info) { + if (((WorldBorderBypass) ClientMod.moduleManager.getModuleById("WorldborderBypass")).isEnabled()) { + info.setReturnValue(false); + } + } + + + @Inject(method = "contains(Lnet/minecraft/util/math/BlockPos;)Z", at = @At("HEAD"), cancellable = true) + private void contains(CallbackInfoReturnable info) { + if (((WorldBorderBypass) ClientMod.moduleManager.getModuleById("WorldborderBypass")).isEnabled()) { + info.setReturnValue(false); + } + } +} diff --git a/src/main/java/dev/coredoes/clientmod/modmenu/ModMenu.java b/src/main/java/dev/coredoes/clientmod/modmenu/ModMenu.java index dfeb4bd..c20f8d3 100644 --- a/src/main/java/dev/coredoes/clientmod/modmenu/ModMenu.java +++ b/src/main/java/dev/coredoes/clientmod/modmenu/ModMenu.java @@ -1,7 +1,9 @@ package dev.coredoes.clientmod.modmenu; import dev.coredoes.clientmod.ClientMod; +import dev.coredoes.clientmod.modules.*; import dev.coredoes.clientmod.modules.Module; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.Drawable; import net.minecraft.client.gui.Element; import net.minecraft.client.gui.screen.Screen; @@ -33,10 +35,25 @@ public class ModMenu extends Screen { this.client.setScreen(this.parent); })); + this.addDrawableChild(new ButtonWidget(5, this.height - 45, 40, 20, Text.of("Reload all modules"), (button) -> { + ClientMod.moduleManager.unregisterModule("Jetpack"); + ClientMod.moduleManager.registerModule(new Jetpack()); + ClientMod.moduleManager.unregisterModule("NoFall"); + ClientMod.moduleManager.registerModule(new NoFall()); + ClientMod.moduleManager.unregisterModule("CreativeFlight"); + ClientMod.moduleManager.registerModule(new CreativeFlight()); + ClientMod.moduleManager.unregisterModule("PacketFreezer"); + ClientMod.moduleManager.registerModule(new PacketFreezer()); + ClientMod.moduleManager.unregisterModule("BotBypass"); + ClientMod.moduleManager.registerModule(new BotMovementBypass()); + ClientMod.moduleManager.unregisterModule("WorldborderBypass"); + ClientMod.moduleManager.registerModule(new WorldBorderBypass()); + })); + for (Module module : ClientMod.moduleManager.getModules().values()) { Screen moduleUI = module.getUI(this, this.settings); if (moduleUI != null) { - this.addDrawableChild(new ButtonWidget(5, lastHeight + 5, 70, 20, Text.of(module.getId()), (button) -> { + this.addDrawableChild(new ButtonWidget(5, lastHeight + 5, 100, 20, Text.of(module.getId()), (button) -> { this.client.setScreen(moduleUI); })); this.lastHeight += 25; diff --git a/src/main/java/dev/coredoes/clientmod/modules/BotMovementBypass.java b/src/main/java/dev/coredoes/clientmod/modules/BotMovementBypass.java new file mode 100644 index 0000000..a18ecef --- /dev/null +++ b/src/main/java/dev/coredoes/clientmod/modules/BotMovementBypass.java @@ -0,0 +1,117 @@ +package dev.coredoes.clientmod.modules; + +import dev.coredoes.clientmod.ClientMod; +import dev.coredoes.clientmod.events.PacketEvent; +import dev.coredoes.clientmod.hud.HudColor; +import dev.coredoes.clientmod.hud.HudMessage; +import meteordevelopment.orbit.EventHandler; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.option.GameOptions; +import net.minecraft.network.Packet; +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; +import net.minecraft.network.packet.s2c.play.GameMessageS2CPacket; +import net.minecraft.network.packet.s2c.play.GameStateChangeS2CPacket; +import net.minecraft.screen.ScreenTexts; +import net.minecraft.text.Text; +import net.minecraft.util.profiling.jfr.event.PacketReceivedEvent; + +public class BotMovementBypass implements Module { + protected boolean enabled = true; + @Override + public void disable() { + this.enabled = false; + } + + @Override + public void enable() { + this.enabled = true; + } + + @Override + public String getId() { + return "BotBypass"; + } + + public boolean isEnabled() { + return this.enabled; + } + + @EventHandler + public void onPacket(PacketEvent.Receive e) { + if (this.enabled) { + if (e.packet instanceof GameStateChangeS2CPacket) { + GameStateChangeS2CPacket packet = (GameStateChangeS2CPacket) e.packet; + + if (packet.getReason() == GameStateChangeS2CPacket.GAME_MODE_CHANGED) { + e.setCancelled(true); + return; + } + if (packet.getReason() == GameStateChangeS2CPacket.DEMO_MESSAGE_SHOWN) { + e.setCancelled(true); + return; + } + } + } + } + + @Override + public String getVersion() { + return "1.0.0"; + } + + @Override + public void postRegister() { + Module.super.postRegister(); + + // Register our event handler + ClientMod.eventBus.subscribe(this); + } + + @Override + public void preUnregister() { + Module.super.preUnregister(); + + // Unregister our event handler + ClientMod.eventBus.unsubscribe(this); + } + + @Override + public void endTick(MinecraftClient client) { + Module.super.endTick(client); + if (this.enabled) { + ClientMod.hudManager.setMesssage("botbypass", new HudMessage("Bot Bypass: Enabled", HudColor.LightPurple)); + } else { + ClientMod.hudManager.clearMessage("botbypass"); + } + } + + @Override + public Screen getUI(Screen parent, GameOptions options) { + return new BotMovementBypass.ModuleUI(parent, options, this); + } + + class ModuleUI extends Screen { + private final Screen parent; + private final GameOptions settings; + private BotMovementBypass parentModule; + + public ModuleUI(Screen parent, GameOptions gameOptions, BotMovementBypass parentModule) { + super(Text.of("BotMovementModule")); + this.parent = parent; + this.settings = gameOptions; + this.parentModule = parentModule; + } + protected void init() { + this.addDrawableChild(new ButtonWidget(5, 5, 70, 20, Text.of("Enabled: " + (this.parentModule.enabled ? "yes" : "no")), (button) -> { + this.parentModule.enabled = !this.parentModule.enabled; + button.setMessage(Text.of("Enabled: " + (this.parentModule.enabled ? "yes" : "no"))); + })); + + this.addDrawableChild(new ButtonWidget(5, this.height - 25, 40, 20, ScreenTexts.BACK, (button) -> { + this.client.setScreen(this.parent); + })); + } + } +} diff --git a/src/main/java/dev/coredoes/clientmod/modules/BunkerBuster.java b/src/main/java/dev/coredoes/clientmod/modules/BunkerBuster.java new file mode 100644 index 0000000..d9d687f --- /dev/null +++ b/src/main/java/dev/coredoes/clientmod/modules/BunkerBuster.java @@ -0,0 +1,135 @@ +package dev.coredoes.clientmod.modules; + +import dev.coredoes.clientmod.ClientMod; +import dev.coredoes.clientmod.util.ConnectionInterface; +import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.option.GameOptions; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.client.util.InputUtil; +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; +import net.minecraft.screen.ScreenTexts; +import net.minecraft.text.Text; +import org.lwjgl.glfw.GLFW; + +import java.text.DecimalFormat; + +public class BunkerBuster implements Module { + private static KeyBinding toggleBinding; + + protected double amount = 1; + + @Override + public void postRegister() { + Module.super.postRegister(); + + toggleBinding = KeyBindingHelper.registerKeyBinding(new KeyBinding( + "key.clientmod.bunkerbuster", + InputUtil.Type.KEYSYM, + GLFW.GLFW_KEY_UNKNOWN, + "category.clientmod.modules" + )); + } + + @Override + public void endTick(MinecraftClient client) { + Module.super.endTick(client); + } + + @Override + public String getId() { + return "BunkerBuster"; + } + + @Override + public String getVersion() { + return "1.0.0"; + } + + @Override + public Screen getUI(Screen parent, GameOptions options) { + return new ModuleUI(parent, options, this); + } + + protected void bunkerBust(MinecraftClient client) { + // STEP 1: Send a bunch of teleports to our current location + + PlayerMoveC2SPacket packet = new PlayerMoveC2SPacket.PositionAndOnGround( + client.player.getX(), + client.player.getY(), + client.player.getZ(), + client.player.isOnGround() + ); + for (int i = 0; i < 50; i++) { + ((ConnectionInterface)client.getNetworkHandler().getConnection()).sendVolatile(packet, null); + } + + // STEP 2: Send the real teleport + PlayerMoveC2SPacket realTeleport = new PlayerMoveC2SPacket.PositionAndOnGround( + client.player.getX(), + client.player.getY() + this.amount, + client.player.getZ(), + false + ); + ((ConnectionInterface)client.getNetworkHandler().getConnection()).sendVolatile(realTeleport, null); + client.player.setPosition(client.player.getX(), client.player.getY() + this.amount, client.player.getZ()); + } + class ModuleUI extends Screen { + private final Screen parent; + private final GameOptions settings; + private BunkerBuster parentModule; + + private ButtonWidget amtBtn; + private ButtonWidget maxSpdBtn; + + public ModuleUI(Screen parent, GameOptions gameOptions, BunkerBuster parentModule) { + super(Text.of("BunkerBusterModule")); + this.parent = parent; + this.settings = gameOptions; + this.parentModule = parentModule; + } + + protected void init() { + DecimalFormat df = new DecimalFormat("#.00"); + + this.addDrawableChild(new ButtonWidget(5, 55, 20, 20, Text.of("++"), (button) -> { + this.parentModule.amount += 1; + this.amtBtn.setMessage(Text.of("BunkerBust: " + df.format((this.parentModule.amount)))); + })); + this.addDrawableChild(new ButtonWidget(30, 55, 20, 20, Text.of("+"), (button) -> { + this.parentModule.amount += 0.1; + this.amtBtn.setMessage(Text.of("BunkerBust: " + df.format((this.parentModule.amount)))); + })); + + this.amtBtn = new ButtonWidget(55, 55, 90, 20, Text.of("BunkerBust: " + df.format((this.parentModule.amount))), (button) -> { + this.parentModule.bunkerBust(MinecraftClient.getInstance()); + }); + this.addDrawableChild(this.amtBtn); + + this.addDrawableChild(new ButtonWidget(150, 55, 20, 20, Text.of("-"), (button) -> { + this.parentModule.amount -= 0.1; + this.amtBtn.setMessage(Text.of("BunkerBust: " + df.format((this.parentModule.amount)))); + })); + this.addDrawableChild(new ButtonWidget(175, 55, 20, 20, Text.of("--"), (button) -> { + this.parentModule.amount -= 1; + this.amtBtn.setMessage(Text.of("BunkerBust: " + df.format((this.parentModule.amount)))); + })); + + this.addDrawableChild(new ButtonWidget(5, this.height - 25, 40, 20, ScreenTexts.BACK, (button) -> { + this.client.setScreen(this.parent); + })); + } + } + + @Override + public void disable() { + + } + + @Override + public void enable() { + + } +} diff --git a/src/main/java/dev/coredoes/clientmod/modules/Module.java b/src/main/java/dev/coredoes/clientmod/modules/Module.java index 6661b62..f8274ee 100644 --- a/src/main/java/dev/coredoes/clientmod/modules/Module.java +++ b/src/main/java/dev/coredoes/clientmod/modules/Module.java @@ -19,8 +19,8 @@ public interface Module { default void startTick(MinecraftClient client) {} default void endTick(MinecraftClient client) {} - default void disable() {} - default void enable() {} + void disable(); + void enable(); // Manager stuff String getId(); diff --git a/src/main/java/dev/coredoes/clientmod/modules/PacketFreezer.java b/src/main/java/dev/coredoes/clientmod/modules/PacketFreezer.java new file mode 100644 index 0000000..2004f72 --- /dev/null +++ b/src/main/java/dev/coredoes/clientmod/modules/PacketFreezer.java @@ -0,0 +1,140 @@ +package dev.coredoes.clientmod.modules; + +import dev.coredoes.clientmod.ClientMod; +import dev.coredoes.clientmod.events.ConnectEvent; +import dev.coredoes.clientmod.events.PacketEvent; +import dev.coredoes.clientmod.events.SendPacketEvent; +import dev.coredoes.clientmod.hud.HudColor; +import dev.coredoes.clientmod.hud.HudMessage; +import meteordevelopment.orbit.EventHandler; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.option.GameOptions; +import net.minecraft.network.Packet; +import net.minecraft.screen.ScreenTexts; +import net.minecraft.text.Text; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; + +public class PacketFreezer implements Module { + protected boolean enabled; + + // List of packets that were queued while we were frozen. + private ArrayList> packets = new ArrayList<>(); + + @Override + public void disable() { + this.enabled = false; + } + + @Override + public void enable() { + this.enabled = true; + } + + @Override + public String getId() { + return "PacketFreezer"; + } + + @Override + public String getVersion() { + return "1.0.0"; + } + + @Override + public Screen getUI(Screen parent, GameOptions options) { + return new PacketFreezer.ModuleUI(parent, options, this); + } + + @EventHandler + public void onPacketSend(PacketEvent.Send event) { + // We still always want to send the keepalive packets, otherwise we'll get kicked + if (this.enabled && event.packet.getClass() != net.minecraft.network.packet.c2s.play.KeepAliveC2SPacket.class) { + event.setCancelled(true); + this.packets.add(event.packet); + } + ClientMod.LOGGER.info(event.packet.toString()); + } + + private void sendAllQueuedPackets(MinecraftClient client) { + if (!this.enabled) { + ArrayList> packetQueueClone = this.packets; + for (Iterator> it = packetQueueClone.iterator(); it.hasNext(); ) { + Packet packet = it.next(); + ClientMod.eventBus.post(SendPacketEvent.get(packet)); + } + this.packets = new ArrayList<>(); + } + } + + @EventHandler + public void onConnect(ConnectEvent e) { + // we need to disable ourselves when joining servers, otherwise we will get precisely nowhere + this.disable(); + } + + @EventHandler + public void onSendPacket(SendPacketEvent e) { + ClientMod.LOGGER.info("Sending queued packet " + e.packet.toString()); + Objects.requireNonNull(MinecraftClient.getInstance().getNetworkHandler()).sendPacket(e.packet); + } + + @Override + public void postRegister() { + Module.super.postRegister(); + + // Register our event handler + ClientMod.eventBus.subscribe(this); + } + + @Override + public void preUnregister() { + Module.super.preUnregister(); + + // Unregister our event handler + ClientMod.eventBus.unsubscribe(this); + } + + @Override + public void startTick(MinecraftClient client) { + this.sendAllQueuedPackets(client); + } + + @Override + public void endTick(MinecraftClient client) { + Module.super.endTick(client); + if (this.enabled) { + ClientMod.hudManager.setMesssage("packetfreezer", new HudMessage("Outgoing Packets: Frozen", HudColor.Red)); + } else { + ClientMod.hudManager.clearMessage("packetfreezer"); + } + } + + class ModuleUI extends Screen { + private final Screen parent; + private final GameOptions settings; + private PacketFreezer parentModule; + + public ModuleUI(Screen parent, GameOptions gameOptions, PacketFreezer parentModule) { + super(Text.of("PacketFreezerModule")); + this.parent = parent; + this.settings = gameOptions; + this.parentModule = parentModule; + } + protected void init() { + this.addDrawableChild(new ButtonWidget(5, 5, 70, 20, Text.of("Enabled: " + (this.parentModule.enabled ? "yes" : "no")), (button) -> { + this.parentModule.enabled = !this.parentModule.enabled; + button.setMessage(Text.of("Enabled: " + (this.parentModule.enabled ? "yes" : "no"))); + })); + + this.addDrawableChild(new ButtonWidget(5, this.height - 25, 40, 20, ScreenTexts.BACK, (button) -> { + this.client.setScreen(this.parent); + })); + } + } +} diff --git a/src/main/java/dev/coredoes/clientmod/modules/WorldBorderBypass.java b/src/main/java/dev/coredoes/clientmod/modules/WorldBorderBypass.java new file mode 100644 index 0000000..50eeff2 --- /dev/null +++ b/src/main/java/dev/coredoes/clientmod/modules/WorldBorderBypass.java @@ -0,0 +1,107 @@ +package dev.coredoes.clientmod.modules; + +import dev.coredoes.clientmod.ClientMod; +import dev.coredoes.clientmod.events.PacketEvent; +import dev.coredoes.clientmod.hud.HudColor; +import dev.coredoes.clientmod.hud.HudMessage; +import meteordevelopment.orbit.EventHandler; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.option.GameOptions; +import net.minecraft.network.Packet; +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; +import net.minecraft.network.packet.s2c.play.WorldBorderInitializeS2CPacket; +import net.minecraft.screen.ScreenTexts; +import net.minecraft.text.Text; + +public class WorldBorderBypass implements Module { + protected boolean enabled = true; + @Override + public void disable() { + this.enabled = false; + } + + @Override + public void enable() { + this.enabled = true; + } + + @Override + public String getId() { + return "WorldborderBypass"; + } + + @EventHandler + public void onPacket(PacketEvent.Receive e) { + if (this.enabled) { + if (e.packet instanceof WorldBorderInitializeS2CPacket) { + e.setCancelled(true); + return; + } + } + } + + public boolean isEnabled() { + return this.enabled; + } + + @Override + public String getVersion() { + return "1.0.0"; + } + + @Override + public void postRegister() { + Module.super.postRegister(); + + // Register our event handler + ClientMod.eventBus.subscribe(this); + } + + @Override + public void preUnregister() { + Module.super.preUnregister(); + + // Unregister our event handler + ClientMod.eventBus.unsubscribe(this); + } + + @Override + public void endTick(MinecraftClient client) { + Module.super.endTick(client); + if (this.enabled) { + ClientMod.hudManager.setMesssage("worldborderbypass", new HudMessage("Worldborder Bypass: Enabled", HudColor.DarkPurple)); + } else { + ClientMod.hudManager.clearMessage("worldborderbypass"); + } + } + + @Override + public Screen getUI(Screen parent, GameOptions options) { + return new WorldBorderBypass.ModuleUI(parent, options, this); + } + + class ModuleUI extends Screen { + private final Screen parent; + private final GameOptions settings; + private WorldBorderBypass parentModule; + + public ModuleUI(Screen parent, GameOptions gameOptions, WorldBorderBypass parentModule) { + super(Text.of("WorldBorderBypassModule")); + this.parent = parent; + this.settings = gameOptions; + this.parentModule = parentModule; + } + protected void init() { + this.addDrawableChild(new ButtonWidget(5, 5, 70, 20, Text.of("Enabled: " + (this.parentModule.enabled ? "yes" : "no")), (button) -> { + this.parentModule.enabled = !this.parentModule.enabled; + button.setMessage(Text.of("Enabled: " + (this.parentModule.enabled ? "yes" : "no"))); + })); + + this.addDrawableChild(new ButtonWidget(5, this.height - 25, 40, 20, ScreenTexts.BACK, (button) -> { + this.client.setScreen(this.parent); + })); + } + } +} diff --git a/src/main/java/dev/coredoes/clientmod/util/ConnectionInterface.java b/src/main/java/dev/coredoes/clientmod/util/ConnectionInterface.java new file mode 100644 index 0000000..7d6ab1a --- /dev/null +++ b/src/main/java/dev/coredoes/clientmod/util/ConnectionInterface.java @@ -0,0 +1,9 @@ +package dev.coredoes.clientmod.util; + +import net.minecraft.network.Packet; +import net.minecraft.network.PacketCallbacks; +import org.jetbrains.annotations.Nullable; + +public interface ConnectionInterface { + void sendVolatile(Packet packet, @Nullable PacketCallbacks callbacks); +} diff --git a/src/main/java/dev/coredoes/clientmod/util/Position.java b/src/main/java/dev/coredoes/clientmod/util/Position.java new file mode 100644 index 0000000..b937fce --- /dev/null +++ b/src/main/java/dev/coredoes/clientmod/util/Position.java @@ -0,0 +1,17 @@ +package dev.coredoes.clientmod.util; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; +import net.minecraft.util.math.Vec3d; + +import java.util.Objects; + +public class Position { + public static void sendPositionVolatile(double x, double y, double z, MinecraftClient client) { + assert client.player != null; + Objects.requireNonNull(client.getNetworkHandler()).sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround( + x, y, z, client.player.isOnGround() + )); + client.player.setPosition(x, y, z); + } +} diff --git a/src/main/resources/coreclientmod.mixins.json b/src/main/resources/coreclientmod.mixins.json index 5327577..aa3d455 100644 --- a/src/main/resources/coreclientmod.mixins.json +++ b/src/main/resources/coreclientmod.mixins.json @@ -3,10 +3,14 @@ "minVersion": "0.8", "package": "dev.coredoes.clientmod.mixin", "compatibilityLevel": "JAVA_17", - "mixins": [ - ], "client": [ - "GameMenuScreenMixin" + "GameMenuScreenMixin", + "ClientConnectionMixin", + "BotMovementFullMixin", + "BotMovementOnGroundMixin", + "VehicleMovementMixin", + "ChatMixin", + "ConnectionMixin" ], "injectors": { "defaultRequire": 1