diff --git a/src/main/java/meteordevelopment/meteorclient/events/entity/player/TeleportParticleEvent.java b/src/main/java/meteordevelopment/meteorclient/events/entity/player/TeleportParticleEvent.java new file mode 100644 index 0000000000..9868e2cb8d --- /dev/null +++ b/src/main/java/meteordevelopment/meteorclient/events/entity/player/TeleportParticleEvent.java @@ -0,0 +1,19 @@ +/* + * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client/). + * Copyright (c) 2021 Meteor Development. + */ + +package meteordevelopment.meteorclient.events.entity.player; + +public class TeleportParticleEvent { + private static final TeleportParticleEvent INSTANCE = new TeleportParticleEvent(); + + public double x, y, z; + + public static TeleportParticleEvent get(double x, double y, double z) { + INSTANCE.x = x; + INSTANCE.y = y; + INSTANCE.z = z; + return INSTANCE; + } +} diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/LivingEntityMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/LivingEntityMixin.java index 67b2730ff8..232ca79fe6 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/LivingEntityMixin.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/LivingEntityMixin.java @@ -9,6 +9,7 @@ import meteordevelopment.meteorclient.events.entity.DamageEvent; import meteordevelopment.meteorclient.events.entity.TookDamageEvent; import meteordevelopment.meteorclient.events.entity.player.CanWalkOnFluidEvent; +import meteordevelopment.meteorclient.events.entity.player.TeleportParticleEvent; import meteordevelopment.meteorclient.systems.modules.Modules; import meteordevelopment.meteorclient.systems.modules.movement.AntiLevitation; import meteordevelopment.meteorclient.systems.modules.player.OffhandCrash; @@ -86,6 +87,14 @@ private void onEquipStack(ItemStack stack, CallbackInfo info) { } } + @Inject(method = "handleStatus", at = @At("HEAD"), cancellable = true) + private void onHandleStatus(byte status, CallbackInfo ci) { + //ty rybot youre a hero + if ((Object) this == mc.player && status == 46 && Utils.canUpdate()) { + MeteorClient.EVENT_BUS.post(TeleportParticleEvent.get(this.getX(), this.getY(), this.getZ())); + } + } + @ModifyArg(method = "swingHand(Lnet/minecraft/util/Hand;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;swingHand(Lnet/minecraft/util/Hand;Z)V")) private Hand setHand(Hand hand) { HandView handView = Modules.get().get(HandView.class); diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/Modules.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/Modules.java index f6165dcb1e..fbf066ec09 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/Modules.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/Modules.java @@ -392,6 +392,7 @@ private void initPlayer() { add(new AutoReplenish()); add(new AutoTool()); add(new ChestSwap()); + add(new ChorusExploit()); add(new EXPThrower()); add(new FakePlayer()); add(new FastUse()); diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/player/ChorusExploit.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/player/ChorusExploit.java new file mode 100644 index 0000000000..afe8cc7b00 --- /dev/null +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/player/ChorusExploit.java @@ -0,0 +1,249 @@ +/* + * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client/). + * Copyright (c) 2021 Meteor Development. + */ + +package meteordevelopment.meteorclient.systems.modules.player; + +import meteordevelopment.meteorclient.events.entity.player.FinishUsingItemEvent; +import meteordevelopment.meteorclient.events.entity.player.TeleportParticleEvent; +import meteordevelopment.meteorclient.events.packets.PacketEvent; +import meteordevelopment.meteorclient.events.render.Render3DEvent; +import meteordevelopment.meteorclient.events.world.TickEvent; +import meteordevelopment.meteorclient.settings.*; +import meteordevelopment.meteorclient.systems.modules.Categories; +import meteordevelopment.meteorclient.systems.modules.Module; +import meteordevelopment.meteorclient.utils.Utils; +import meteordevelopment.meteorclient.utils.entity.fakeplayer.FakePlayerEntity; +import meteordevelopment.meteorclient.utils.entity.fakeplayer.FakePlayerManager; +import meteordevelopment.meteorclient.utils.misc.Keybind; +import meteordevelopment.meteorclient.utils.render.RenderUtils; +import meteordevelopment.meteorclient.utils.render.color.SettingColor; +import meteordevelopment.orbit.EventHandler; +import net.minecraft.item.Items; +import net.minecraft.network.packet.c2s.play.TeleportConfirmC2SPacket; +import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket; +import net.minecraft.util.math.BlockPos; + +import java.util.*; + +public class ChorusExploit extends Module { + private final SettingGroup sgGeneral = settings.getDefaultGroup(); + private final SettingGroup sgRender = settings.createGroup("Render"); + + private final Setting positionMode = sgGeneral.add(new EnumSetting.Builder() + .name("position-mode") + .description("How your teleport position is calculated.") + .defaultValue(PositionMode.Particle) + .build() + ); + + private final Setting onItemSwitch = sgGeneral.add(new BoolSetting.Builder() + .name("tp-on-switch") + .description("Teleports you when you switch items.") + .defaultValue(true) + .build() + ); + + private final Setting onDeactivate = sgGeneral.add(new BoolSetting.Builder() + .name("tp-on-deactivate") + .description("Teleports you when the module is deactivated.") + .defaultValue(false) + .build() + ); + + private final Setting onKey = sgGeneral.add(new KeybindSetting.Builder() + .name("on-key") + .description("Teleports when a key is pressed.") + .defaultValue(Keybind.none()) + .action(this::sendPackets) + .build() + ); + + private final Setting autoTeleport = sgGeneral.add(new BoolSetting.Builder() + .name("automatically-teleport") + .description("Automatically teleports you after a fixed number of ticks.") + .defaultValue(false) + .build() + ); + + private final Setting ticksToTeleport = sgGeneral.add(new IntSetting.Builder() + .name("ticks-to-teleport") + .description("The amount of ticks to wait before automatically teleporting.") + .defaultValue(40) + .min(0) + .sliderMax(100) + .visible(autoTeleport::get) + .build() + ); + + //render + private final Setting renderActual = sgRender.add(new BoolSetting.Builder() + .name("set-position") + .description("Sets you clientside to your actual position.") + .defaultValue(true) + .build() + ); + + private final Setting fakeplayerOnDestination = sgRender.add(new BoolSetting.Builder() + .name("fakeplayer-on-destination") + .description("Creates a fakeplayer at the destination.") + .defaultValue(true) + .build() + ); + + private final Setting drawLine = sgRender.add(new BoolSetting.Builder() + .name("draw-line") + .description("Draws a line to where you are going to be.") + .defaultValue(true) + .build() + ); + + private final Setting lineColour = sgRender.add(new ColorSetting.Builder() + .name("line-color") + .description("The lines color.") + .defaultValue(new SettingColor(205, 205, 205, 127)) + .visible(drawLine::get) + .build() + ); + + private int slot; + private int delay = 0; + private boolean ateChorus, sending, fakePlayerSpawned, gotPosition = false; + private double posX, posY, posZ, cposX, cposY, cposZ; + private FakePlayerEntity fakePlayer = null; + private final Queue telePackets = new LinkedList<>(); + + + public ChorusExploit() { + super(Categories.Movement, "chorus-exploit", "Delays teleporting with a chorus fruit."); + } + + @Override + public void onActivate() { + ateChorus = false; + delay = 0; + telePackets.clear(); + fakePlayerSpawned = false; + gotPosition = false; + } + + @Override + public void onDeactivate() { + if (Utils.canUpdate() && ateChorus && onDeactivate.get()) { + sendPackets(); + } + telePackets.clear(); + fakePlayerSpawned = false; + gotPosition = false; + } + + @EventHandler + private void onPacketSend(PacketEvent.Send event) { + if (event.packet instanceof TeleportConfirmC2SPacket telepacket && ateChorus && !sending) { + telePackets.add(telepacket); + event.cancel(); + } + } + + @EventHandler + private void onPacketRecieve(PacketEvent.Receive event) { + if (event.packet instanceof PlayerPositionLookS2CPacket posPacket && ateChorus) { + event.setCancelled(true); + if (positionMode.get() == PositionMode.PosLook) { + cposX = posPacket.getX(); + cposY = posPacket.getY(); + cposZ = posPacket.getZ(); + gotPosition = true; + if (fakeplayerOnDestination.get() && renderActual.get() && !fakePlayerSpawned) spawnFakeplayer(cposX, cposY, cposZ); + } + } + } + + @EventHandler + private void onTick(TickEvent.Pre event) { + if (ateChorus) { + delay++; + if (!mc.player.getPos().equals(new BlockPos(posX, posY, posZ)) && renderActual.get()) { + mc.player.setPos(posX, posY, posZ); + } + + if (autoTeleport.get() && delay >= ticksToTeleport.get()) { + sendPackets(); + } + + if (onItemSwitch.get() && slot != mc.player.getInventory().selectedSlot) { + sendPackets(); + } + } + } + + @EventHandler + private void onEat(FinishUsingItemEvent event) { + if (event.itemStack.getItem().equals(Items.CHORUS_FRUIT)) { + posX = mc.player.getX(); + posY = mc.player.getY(); + posZ = mc.player.getZ(); + ateChorus = true; + slot = mc.player.getInventory().selectedSlot; + } + } + + @EventHandler + private void onRender3D(Render3DEvent event) { + if (drawLine.get() && ateChorus && gotPosition) { + event.renderer.line(RenderUtils.center.x, RenderUtils.center.y, RenderUtils.center.z, cposX, cposY, cposZ, lineColour.get()); + } + } + + @EventHandler + private void onTeleportParticle(TeleportParticleEvent event) { + if (ateChorus && positionMode.get() == PositionMode.Particle) { + cposX = event.x; + cposY = event.y; + cposZ = event.z; + gotPosition = true; + if (fakeplayerOnDestination.get() && renderActual.get() && !fakePlayerSpawned) spawnFakeplayer(cposX, cposY, cposZ); + } + } + + private void sendPackets() { + sending = true; + + while (!telePackets.isEmpty()) { + mc.getNetworkHandler().sendPacket(telePackets.poll()); + } + + delay = 0; + ateChorus = false; + sending = false; + gotPosition = false; + + if (fakePlayer != null) { + FakePlayerManager.fakePlayers.remove(fakePlayer); + fakePlayer.despawn(); + fakePlayer = null; + fakePlayerSpawned = false; + } + } + + private void spawnFakeplayer(double x, double y, double z) { + fakePlayer = new FakePlayerEntity(mc.player, mc.player.getEntityName(), mc.player.getHealth(), false); + fakePlayer.spawn(); + fakePlayer.setPos(x, y ,z); + FakePlayerManager.fakePlayers.add(fakePlayer); + fakePlayerSpawned = true; + } + + @Override + public String getInfoString() { + if (autoTeleport.get() && ateChorus) return String.valueOf(ticksToTeleport.get() - delay); + return null; + } + + public enum PositionMode { + Particle, + PosLook, + None + } +} diff --git a/src/main/java/meteordevelopment/meteorclient/utils/entity/fakeplayer/FakePlayerManager.java b/src/main/java/meteordevelopment/meteorclient/utils/entity/fakeplayer/FakePlayerManager.java index 1b1546ae60..3d0925db8f 100644 --- a/src/main/java/meteordevelopment/meteorclient/utils/entity/fakeplayer/FakePlayerManager.java +++ b/src/main/java/meteordevelopment/meteorclient/utils/entity/fakeplayer/FakePlayerManager.java @@ -11,7 +11,7 @@ import static meteordevelopment.meteorclient.MeteorClient.mc; public class FakePlayerManager { - private static final List fakePlayers = new ArrayList<>(); + public static final List fakePlayers = new ArrayList<>(); public static void add(String name, float health, boolean copyInv) { FakePlayerEntity fakePlayer = new FakePlayerEntity(mc.player, name, health, copyInv);