diff --git a/build.gradle b/build.gradle index 1efc5489a3..c529fcb87d 100644 --- a/build.gradle +++ b/build.gradle @@ -60,6 +60,7 @@ dependencies { modCompileOnly("maven.modrinth:lithium:${project.lithium_version}") { transitive = false } modCompileOnly("maven.modrinth:iris:${project.iris_version}") { transitive = false } //modCompileOnly("io.vram:canvas-fabric-mc119:1.0.+") { transitive = false } // TODO: 1.19.3 + modCompileOnly("maven.modrinth:indium:${project.indium_version}") { transitive = false } // Baritone (https://github.com/MeteorDevelopment/baritone) modInclude "baritone:fabric:${project.minecraft_version}-SNAPSHOT" diff --git a/gradle.properties b/gradle.properties index ddf07e5d5c..6c66c54f06 100644 --- a/gradle.properties +++ b/gradle.properties @@ -39,3 +39,6 @@ netty_version=4.1.90.Final # Mixin Extras (https://github.com/LlamaLad7/MixinExtras) mixin_extras_version=0.2.0-beta.8 + +# Indium (https://github.com/comp500/Indium) +indium_version=1.0.25+mc1.20.1 diff --git a/src/main/java/meteordevelopment/meteorclient/MixinPlugin.java b/src/main/java/meteordevelopment/meteorclient/MixinPlugin.java index 66c3f1a4a9..348f256ccd 100644 --- a/src/main/java/meteordevelopment/meteorclient/MixinPlugin.java +++ b/src/main/java/meteordevelopment/meteorclient/MixinPlugin.java @@ -23,6 +23,7 @@ public class MixinPlugin implements IMixinConfigPlugin { private static boolean isCanvasPresent; private static boolean isLithiumPresent; public static boolean isIrisPresent; + private static boolean isIndiumPresent; @Override public void onLoad(String mixinPackage) { @@ -33,6 +34,7 @@ public void onLoad(String mixinPackage) { isCanvasPresent = FabricLoader.getInstance().isModLoaded("canvas"); isLithiumPresent = FabricLoader.getInstance().isModLoaded("lithium"); isIrisPresent = FabricLoader.getInstance().isModLoaded("iris"); + isIndiumPresent = FabricLoader.getInstance().isModLoaded("indium"); loaded = true; } @@ -59,6 +61,9 @@ else if (mixinClassName.startsWith(mixinPackage + ".canvas")) { else if (mixinClassName.startsWith(mixinPackage + ".lithium")) { return isLithiumPresent; } + else if (mixinClassName.startsWith(mixinPackage + ".indium")) { + return isIndiumPresent; + } return true; diff --git a/src/main/java/meteordevelopment/meteorclient/asm/Asm.java b/src/main/java/meteordevelopment/meteorclient/asm/Asm.java index 1746c3984e..0519f53a75 100644 --- a/src/main/java/meteordevelopment/meteorclient/asm/Asm.java +++ b/src/main/java/meteordevelopment/meteorclient/asm/Asm.java @@ -10,6 +10,7 @@ import meteordevelopment.meteorclient.MeteorClient; import meteordevelopment.meteorclient.asm.transformers.CanvasWorldRendererTransformer; import meteordevelopment.meteorclient.asm.transformers.GameRendererTransformer; +import meteordevelopment.meteorclient.asm.transformers.PacketInflaterTransformer; import net.fabricmc.loader.api.FabricLoader; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassWriter; @@ -38,6 +39,7 @@ public Asm() { add(new GameRendererTransformer()); add(new CanvasWorldRendererTransformer()); + add(new PacketInflaterTransformer()); } private void add(AsmTransformer transformer) { diff --git a/src/main/java/meteordevelopment/meteorclient/asm/AsmTransformer.java b/src/main/java/meteordevelopment/meteorclient/asm/AsmTransformer.java index e0020c2bf9..573da6f774 100644 --- a/src/main/java/meteordevelopment/meteorclient/asm/AsmTransformer.java +++ b/src/main/java/meteordevelopment/meteorclient/asm/AsmTransformer.java @@ -26,6 +26,11 @@ protected MethodNode getMethod(ClassNode klass, MethodInfo methodInfo) { return null; } + protected static void error(String message) { + System.err.println(message); + throw new RuntimeException(message); + } + protected static String mapClassName(String name) { return FabricLoader.getInstance().getMappingResolver().mapClassName("intermediary", name.replace('/', '.')); } diff --git a/src/main/java/meteordevelopment/meteorclient/asm/transformers/GameRendererTransformer.java b/src/main/java/meteordevelopment/meteorclient/asm/transformers/GameRendererTransformer.java index 459d063cfe..c8c5ea1fb2 100644 --- a/src/main/java/meteordevelopment/meteorclient/asm/transformers/GameRendererTransformer.java +++ b/src/main/java/meteordevelopment/meteorclient/asm/transformers/GameRendererTransformer.java @@ -24,10 +24,11 @@ public GameRendererTransformer() { public void transform(ClassNode klass) { // Modify GameRenderer.getFov() MethodNode method = getMethod(klass, getFovMethod); - if (method == null) throw new RuntimeException("[Meteor Client] Could not find method GameRenderer.getFov()"); + if (method == null) error("[Meteor Client] Could not find method GameRenderer.getFov()"); int injectionCount = 0; + //noinspection DataFlowIssue for (AbstractInsnNode insn : method.instructions) { if (insn instanceof LdcInsnNode in && in.cst instanceof Double && (double) in.cst == 90) { InsnList insns = new InsnList(); @@ -52,7 +53,7 @@ else if ( } } - if (injectionCount < 2) throw new RuntimeException("[Meteor Client] Failed to modify GameRenderer.getFov()"); + if (injectionCount < 2) error("[Meteor Client] Failed to modify GameRenderer.getFov()"); } private void generateEventCall(InsnList insns, AbstractInsnNode loadPreviousFov) { diff --git a/src/main/java/meteordevelopment/meteorclient/asm/transformers/PacketInflaterTransformer.java b/src/main/java/meteordevelopment/meteorclient/asm/transformers/PacketInflaterTransformer.java new file mode 100644 index 0000000000..0e30913175 --- /dev/null +++ b/src/main/java/meteordevelopment/meteorclient/asm/transformers/PacketInflaterTransformer.java @@ -0,0 +1,62 @@ +/* + * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client). + * Copyright (c) Meteor Development. + */ + +package meteordevelopment.meteorclient.asm.transformers; + +import meteordevelopment.meteorclient.asm.AsmTransformer; +import meteordevelopment.meteorclient.asm.Descriptor; +import meteordevelopment.meteorclient.asm.MethodInfo; +import meteordevelopment.meteorclient.systems.modules.misc.AntiPacketKick; +import org.objectweb.asm.Label; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.*; + +// Future compatibility +// Future uses @ModifyConstant which does not chain when multiple mods do it and mixins / mixinextra can't target throw +// statements. So using a custom ASM transformer we wrap the throw statement inside another if statement. +public class PacketInflaterTransformer extends AsmTransformer { + private final MethodInfo decodeMethod; + + public PacketInflaterTransformer() { + super(mapClassName("net/minecraft/class_2532")); + + decodeMethod = new MethodInfo("net/minecraft/class_2532", "decode", new Descriptor("Lio/netty/channel/ChannelHandlerContext;", "Lio/netty/buffer/ByteBuf;", "Ljava/util/List;", "V"), true); + } + + @Override + public void transform(ClassNode klass) { + MethodNode method = getMethod(klass, decodeMethod); + if (method == null) error("[Meteor Client] Could not find method PacketInflater.decode()"); + + int newCount = 0; + LabelNode label = new LabelNode(new Label()); + + //noinspection DataFlowIssue + for (AbstractInsnNode insn : method.instructions) { + if (insn instanceof TypeInsnNode typeInsn && typeInsn.getOpcode() == Opcodes.NEW && typeInsn.desc.equals("io/netty/handler/codec/DecoderException")) { + newCount++; + + if (newCount == 2) { + InsnList list = new InsnList(); + + list.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "meteordevelopment/meteorclient/systems/modules/Modules", "get", "()Lmeteordevelopment/meteorclient/systems/modules/Modules;", false)); + list.add(new LdcInsnNode(Type.getType(AntiPacketKick.class))); + list.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "meteordevelopment/meteorclient/systems/modules/Modules", "isActive", "(Ljava/lang/Class;)Z", false)); + + list.add(new JumpInsnNode(Opcodes.IFNE, label)); + + method.instructions.insertBefore(insn, list); + } + } + else if (newCount == 2 && insn.getOpcode() == Opcodes.ATHROW) { + method.instructions.insert(insn, label); + return; + } + } + + error("[Meteor Client] Failed to modify PacketInflater.decode()"); + } +} diff --git a/src/main/java/meteordevelopment/meteorclient/commands/commands/ServerCommand.java b/src/main/java/meteordevelopment/meteorclient/commands/commands/ServerCommand.java index c825bb0469..bf532fed28 100644 --- a/src/main/java/meteordevelopment/meteorclient/commands/commands/ServerCommand.java +++ b/src/main/java/meteordevelopment/meteorclient/commands/commands/ServerCommand.java @@ -36,7 +36,7 @@ import static meteordevelopment.meteorclient.MeteorClient.mc; public class ServerCommand extends Command { - private static final List ANTICHEAT_LIST = Arrays.asList("nocheatplus", "negativity", "warden", "horizon", "illegalstack", "coreprotect", "exploitsx", "vulcan", "abc", "spartan", "kauri", "anticheatreloaded", "witherac", "godseye", "matrix", "wraith"); + private static final List ANTICHEAT_LIST = Arrays.asList("nocheatplus", "negativity", "warden", "horizon", "illegalstack", "coreprotect", "exploitsx", "vulcan", "abc", "spartan", "kauri", "anticheatreloaded", "witherac", "godseye", "matrix", "wraith", "antixrayheuristics"); private static final String completionStarts = "/:abcdefghijklmnopqrstuvwxyz0123456789-"; private int ticks = 0; private boolean bukkitMode = false; diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/ChatHudLineMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/ChatHudLineMixin.java index c8cb0b6b30..77a94679a0 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/ChatHudLineMixin.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/ChatHudLineMixin.java @@ -5,22 +5,43 @@ package meteordevelopment.meteorclient.mixin; +import com.mojang.authlib.GameProfile; import meteordevelopment.meteorclient.mixininterface.IChatHudLine; import net.minecraft.client.gui.hud.ChatHudLine; +import net.minecraft.text.Text; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; -@Mixin(value = { ChatHudLine.class, ChatHudLine.Visible.class }) +@Mixin(value = ChatHudLine.class) public class ChatHudLineMixin implements IChatHudLine { + @Shadow @Final private Text content; @Unique private int id; + @Unique private GameProfile sender; @Override - public int getId() { + public String meteor$getText() { + return content.getString(); + } + + @Override + public int meteor$getId() { return id; } @Override - public void setId(int id) { + public void meteor$setId(int id) { this.id = id; } + + @Override + public GameProfile meteor$getSender() { + return sender; + } + + @Override + public void meteor$setSender(GameProfile profile) { + sender = profile; + } } diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/ChatHudLineVisibleMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/ChatHudLineVisibleMixin.java new file mode 100644 index 0000000000..f797b6401b --- /dev/null +++ b/src/main/java/meteordevelopment/meteorclient/mixin/ChatHudLineVisibleMixin.java @@ -0,0 +1,65 @@ +/* + * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client). + * Copyright (c) Meteor Development. + */ + +package meteordevelopment.meteorclient.mixin; + +import com.mojang.authlib.GameProfile; +import meteordevelopment.meteorclient.mixininterface.IChatHudLineVisible; +import net.minecraft.client.gui.hud.ChatHudLine; +import net.minecraft.text.OrderedText; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; + +@Mixin(ChatHudLine.Visible.class) +public class ChatHudLineVisibleMixin implements IChatHudLineVisible { + @Shadow @Final private OrderedText content; + @Unique private int id; + @Unique private GameProfile sender; + @Unique private boolean startOfEntry; + + @Override + public String meteor$getText() { + StringBuilder sb = new StringBuilder(); + + content.accept((index, style, codePoint) -> { + sb.appendCodePoint(codePoint); + return true; + }); + + return sb.toString(); + } + + @Override + public int meteor$getId() { + return id; + } + + @Override + public void meteor$setId(int id) { + this.id = id; + } + + @Override + public GameProfile meteor$getSender() { + return sender; + } + + @Override + public void meteor$setSender(GameProfile profile) { + sender = profile; + } + + @Override + public boolean meteor$isStartOfEntry() { + return startOfEntry; + } + + @Override + public void meteor$setStartOfEntry(boolean start) { + startOfEntry = start; + } +} diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/ChatHudMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/ChatHudMixin.java index 3d221a4c0b..9f194d731a 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/ChatHudMixin.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/ChatHudMixin.java @@ -6,30 +6,26 @@ package meteordevelopment.meteorclient.mixin; import com.llamalad7.mixinextras.injector.ModifyExpressionValue; -import com.mojang.blaze3d.systems.RenderSystem; +import com.llamalad7.mixinextras.injector.ModifyReceiver; +import com.llamalad7.mixinextras.sugar.Local; import meteordevelopment.meteorclient.MeteorClient; import meteordevelopment.meteorclient.events.game.ReceiveMessageEvent; import meteordevelopment.meteorclient.mixininterface.IChatHud; import meteordevelopment.meteorclient.mixininterface.IChatHudLine; +import meteordevelopment.meteorclient.mixininterface.IChatHudLineVisible; +import meteordevelopment.meteorclient.mixininterface.IMessageHandler; import meteordevelopment.meteorclient.systems.modules.Modules; import meteordevelopment.meteorclient.systems.modules.misc.BetterChat; import meteordevelopment.meteorclient.systems.modules.render.NoRender; -import meteordevelopment.meteorclient.utils.misc.MeteorIdentifier; -import meteordevelopment.meteorclient.utils.misc.text.StringCharacterVisitor; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.hud.ChatHud; import net.minecraft.client.gui.hud.ChatHudLine; import net.minecraft.client.gui.hud.MessageIndicator; -import net.minecraft.client.gui.screen.ChatScreen; -import net.minecraft.client.network.PlayerListEntry; -import net.minecraft.client.option.ChatVisibility; -import net.minecraft.client.util.math.MatrixStack; import net.minecraft.network.message.MessageSignatureData; import net.minecraft.text.OrderedText; import net.minecraft.text.Text; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.MathHelper; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -42,25 +38,25 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import java.util.List; -import java.util.regex.Pattern; @Mixin(ChatHud.class) public abstract class ChatHudMixin implements IChatHud { - private static final MinecraftClient mc = MinecraftClient.getInstance(); - - private static final Pattern METEOR_PREFIX_REGEX = Pattern.compile("^\\s{0,2}(<[0-9]{1,2}:[0-9]{1,2}>\\s)?\\[Meteor]"); - private static final Pattern BARITONE_PREFIX_REGEX = Pattern.compile("^\\s{0,2}(<[0-9]{1,2}:[0-9]{1,2}>\\s)?\\[Baritone]"); - private static final Identifier METEOR_CHAT_ICON = new MeteorIdentifier("textures/icons/chat/meteor.png"); - private static final Identifier BARITONE_CHAT_ICON = new MeteorIdentifier("textures/icons/chat/baritone.png"); - + @Shadow @Final private MinecraftClient client; @Shadow @Final private List visibleMessages; - @Shadow private int scrolledLines; + @Shadow @Final private List messages; + @Unique private BetterChat betterChat; @Unique private int nextId; @Unique private boolean skipOnAddMessage; + @Shadow + protected abstract void addMessage(Text message, @Nullable MessageSignatureData signature, int ticks, @Nullable MessageIndicator indicator, boolean refresh); + + @Shadow + public abstract void addMessage(Text message); + @Override - public void add(Text message, int id) { + public void meteor$add(Text message, int id) { nextId = id; addMessage(message); nextId = 0; @@ -68,12 +64,31 @@ public void add(Text message, int id) { @Inject(method = "addMessage(Lnet/minecraft/text/Text;Lnet/minecraft/network/message/MessageSignatureData;ILnet/minecraft/client/gui/hud/MessageIndicator;Z)V", at = @At(value = "INVOKE", target = "Ljava/util/List;add(ILjava/lang/Object;)V", ordinal = 0, shift = At.Shift.AFTER)) private void onAddMessageAfterNewChatHudLineVisible(Text message, MessageSignatureData signature, int ticks, MessageIndicator indicator, boolean refresh, CallbackInfo info) { - ((IChatHudLine) (Object) visibleMessages.get(0)).setId(nextId); + ((IChatHudLine) (Object) visibleMessages.get(0)).meteor$setId(nextId); } @Inject(method = "addMessage(Lnet/minecraft/text/Text;Lnet/minecraft/network/message/MessageSignatureData;ILnet/minecraft/client/gui/hud/MessageIndicator;Z)V", at = @At(value = "INVOKE", target = "Ljava/util/List;add(ILjava/lang/Object;)V", ordinal = 1, shift = At.Shift.AFTER)) private void onAddMessageAfterNewChatHudLine(Text message, MessageSignatureData signature, int ticks, MessageIndicator indicator, boolean refresh, CallbackInfo info) { - ((IChatHudLine) (Object) messages.get(0)).setId(nextId); + ((IChatHudLine) (Object) messages.get(0)).meteor$setId(nextId); + } + + @SuppressWarnings("DataFlowIssue") + @ModifyExpressionValue(method = "addMessage(Lnet/minecraft/text/Text;Lnet/minecraft/network/message/MessageSignatureData;ILnet/minecraft/client/gui/hud/MessageIndicator;Z)V", at = @At(value = "NEW", target = "(ILnet/minecraft/text/OrderedText;Lnet/minecraft/client/gui/hud/MessageIndicator;Z)Lnet/minecraft/client/gui/hud/ChatHudLine$Visible;")) + private ChatHudLine.Visible onAddMessage_modifyChatHudLineVisible(ChatHudLine.Visible line, @Local(ordinal = 2) int j) { + IMessageHandler handler = (IMessageHandler) client.getMessageHandler(); + IChatHudLineVisible meteorLine = (IChatHudLineVisible) (Object) line; + + meteorLine.meteor$setSender(handler.meteor$getSender()); + meteorLine.meteor$setStartOfEntry(j == 0); + + return line; + } + + @ModifyExpressionValue(method = "addMessage(Lnet/minecraft/text/Text;Lnet/minecraft/network/message/MessageSignatureData;ILnet/minecraft/client/gui/hud/MessageIndicator;Z)V", at = @At(value = "NEW", target = "(ILnet/minecraft/text/Text;Lnet/minecraft/network/message/MessageSignatureData;Lnet/minecraft/client/gui/hud/MessageIndicator;)Lnet/minecraft/client/gui/hud/ChatHudLine;")) + private ChatHudLine onAddMessage_modifyChatHudLine(ChatHudLine line) { + IMessageHandler handler = (IMessageHandler) client.getMessageHandler(); + ((IChatHudLine) (Object) line).meteor$setSender(handler.meteor$getSender()); + return line; } @Inject(at = @At("HEAD"), method = "addMessage(Lnet/minecraft/text/Text;Lnet/minecraft/network/message/MessageSignatureData;ILnet/minecraft/client/gui/hud/MessageIndicator;Z)V", cancellable = true) @@ -84,10 +99,10 @@ private void onAddMessage(Text message, @Nullable MessageSignatureData signature if (event.isCancelled()) info.cancel(); else { - visibleMessages.removeIf(msg -> ((IChatHudLine) (Object) msg).getId() == nextId && nextId != 0); + visibleMessages.removeIf(msg -> ((IChatHudLine) (Object) msg).meteor$getId() == nextId && nextId != 0); for (int i = messages.size() - 1; i > -1 ; i--) { - if (((IChatHudLine) (Object) messages.get(i)).getId() == nextId && nextId != 0) { + if (((IChatHudLine) (Object) messages.get(i)).meteor$getId() == nextId && nextId != 0) { messages.remove(i); Modules.get().get(BetterChat.class).lines.removeInt(i); } @@ -106,111 +121,22 @@ private void onAddMessage(Text message, @Nullable MessageSignatureData signature @ModifyExpressionValue(method = "addMessage(Lnet/minecraft/text/Text;Lnet/minecraft/network/message/MessageSignatureData;ILnet/minecraft/client/gui/hud/MessageIndicator;Z)V", slice = @Slice(from = @At(value = "FIELD", target = "Lnet/minecraft/client/gui/hud/ChatHud;visibleMessages:Ljava/util/List;")), at = @At(value = "INVOKE", target = "Ljava/util/List;size()I")) private int addMessageListSizeProxy(int size) { - BetterChat betterChat = Modules.get().get(BetterChat.class); + BetterChat betterChat = getBetterChat(); if (betterChat.isLongerChat() && betterChat.getChatLength() >= 100) return size - betterChat.getChatLength(); return size; } - @Inject(method = "render", at = @At("TAIL")) - private void onRender(DrawContext context, int currentTick, int mouseX, int mouseY, CallbackInfo ci) { - if (!Modules.get().get(BetterChat.class).displayPlayerHeads()) return; - if (mc.options.getChatVisibility().getValue() == ChatVisibility.HIDDEN) return; - int maxLineCount = mc.inGameHud.getChatHud().getVisibleLineCount(); - - double d = mc.options.getChatOpacity().getValue() * 0.8999999761581421D + 0.10000000149011612D; - double g = 9.0D * (mc.options.getChatLineSpacing().getValue() + 1.0D); - double h = -8.0D * (mc.options.getChatLineSpacing().getValue() + 1.0D) + 4.0D * mc.options.getChatLineSpacing().getValue() + 8.0D; - - float chatScale = (float) getChatScale(); - float scaledHeight = mc.getWindow().getScaledHeight(); - - MatrixStack matrices = context.getMatrices(); - matrices.push(); - matrices.scale(chatScale, chatScale, 1.0f); - matrices.translate(2.0f, MathHelper.floor((scaledHeight - 40) / chatScale) - g - 0.1f, 10.0f); - RenderSystem.enableBlend(); - for (int m = 0; m + scrolledLines < visibleMessages.size() && m < maxLineCount; ++m) { - ChatHudLine.Visible chatHudLine = visibleMessages.get(m + scrolledLines); - if (chatHudLine != null) { - int x = currentTick - chatHudLine.addedTime(); - if (x < 200 || isChatFocused()) { - double o = isChatFocused() ? 1.0D : getMessageOpacityMultiplier(x); - if (o * d > 0.01D) { - double s = -m * g; - StringCharacterVisitor visitor = new StringCharacterVisitor(); - chatHudLine.content().accept(visitor); - drawIcon(context, matrices, visitor.result.toString(), (int) (s + h), (float) (o * d)); - } - } - } - } - RenderSystem.disableBlend(); - matrices.pop(); - - } - - private boolean isChatFocused() { - return mc.currentScreen instanceof ChatScreen; - } - - @Shadow - private static double getMessageOpacityMultiplier(int age) { - throw new AssertionError(); - } - - @Shadow - protected abstract void addMessage(Text message, @Nullable MessageSignatureData signature, int ticks, @Nullable MessageIndicator indicator, boolean refresh); - - @Shadow - public abstract void addMessage(Text message); - - @Shadow - @Final - private List messages; + // Player Heads - @Shadow - public abstract double getChatScale(); - - private void drawIcon(DrawContext drawContext, MatrixStack matrices, String line, int y, float opacity) { - if (METEOR_PREFIX_REGEX.matcher(line).find()) { - matrices.push(); - RenderSystem.setShaderColor(1, 1, 1, opacity); - matrices.translate(0, y, 0); - matrices.scale(0.125f, 0.125f, 1); - drawContext.drawTexture(METEOR_CHAT_ICON, 0, 0, 0f, 0f, 64, 64, 64, 64); - RenderSystem.setShaderColor(1, 1, 1, 1); - matrices.pop(); - return; - } else if (BARITONE_PREFIX_REGEX.matcher(line).find()) { - matrices.push(); - RenderSystem.setShaderColor(1, 1, 1, opacity); - matrices.translate(0, y, 10); - matrices.scale(0.125f, 0.125f, 1); - drawContext.drawTexture(BARITONE_CHAT_ICON, 0, 0, 0f, 0f, 64, 64, 64, 64); - RenderSystem.setShaderColor(1, 1, 1, 1); - matrices.pop(); - return; - } - - Identifier skin = getMessageTexture(line); - if (skin != null) { - RenderSystem.setShaderColor(1, 1, 1, opacity); - drawContext.drawTexture(skin, 0, y, 8, 8, 8.0F, 8.0F, 8, 8, 64, 64); - drawContext.drawTexture(skin, 0, y, 8, 8, 40.0F, 8.0F, 8, 8, 64, 64); - RenderSystem.setShaderColor(1, 1, 1, 1); - } + @ModifyExpressionValue(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/MathHelper;ceil(F)I")) + private int onRender_modifyWidth(int width) { + return getBetterChat().modifyChatWidth(width); } - private static Identifier getMessageTexture(String message) { - if (mc.getNetworkHandler() == null) return null; - for (String part : message.split("(ยง.)|[^\\w]")) { - if (part.isBlank()) continue; - PlayerListEntry p = mc.getNetworkHandler().getPlayerListEntry(part); - if (p != null) { - return p.getSkinTexture(); - } - } - return null; + @ModifyReceiver(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawTextWithShadow(Lnet/minecraft/client/font/TextRenderer;Lnet/minecraft/text/OrderedText;III)I")) + private DrawContext onRender_beforeDrawTextWithShadow(DrawContext context, TextRenderer textRenderer, OrderedText text, int x, int y, int color, @Local ChatHudLine.Visible line) { + getBetterChat().drawPlayerHead(context, line, y, color); + return context; } // No Message Signature Indicator @@ -225,13 +151,13 @@ private MessageIndicator onRender_modifyIndicator(MessageIndicator indicator) { @Inject(method = "addMessage(Lnet/minecraft/text/Text;Lnet/minecraft/network/message/MessageSignatureData;ILnet/minecraft/client/gui/hud/MessageIndicator;Z)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/ChatHud;isChatFocused()Z"), locals = LocalCapture.CAPTURE_FAILSOFT) private void onBreakChatMessageLines(Text message, MessageSignatureData signature, int ticks, MessageIndicator indicator, boolean refresh, CallbackInfo ci, int i, List list) { - Modules.get().get(BetterChat.class).lines.add(0, list.size()); + getBetterChat().lines.add(0, list.size()); } @Inject(method = "addMessage(Lnet/minecraft/text/Text;Lnet/minecraft/network/message/MessageSignatureData;ILnet/minecraft/client/gui/hud/MessageIndicator;Z)V", slice = @Slice(from = @At(value = "FIELD", target = "Lnet/minecraft/client/gui/hud/ChatHud;messages:Ljava/util/List;")), at = @At(value = "INVOKE", target = "Ljava/util/List;remove(I)Ljava/lang/Object;")) private void onRemoveMessage(Text message, MessageSignatureData signature, int ticks, MessageIndicator indicator, boolean refresh, CallbackInfo ci) { - BetterChat betterChat = Modules.get().get(BetterChat.class); + BetterChat betterChat = getBetterChat(); int size = betterChat.lines.size() - (betterChat.isLongerChat() && betterChat.getChatLength() >= 100 ? betterChat.getChatLength() : 0); while (size > 100) { @@ -242,11 +168,21 @@ private void onRemoveMessage(Text message, MessageSignatureData signature, int t @Inject(method = "clear", at = @At("HEAD")) private void onClear(boolean clearHistory, CallbackInfo ci) { - Modules.get().get(BetterChat.class).lines.clear(); + getBetterChat().lines.clear(); } @Inject(method = "refresh", at = @At("HEAD")) private void onRefresh(CallbackInfo ci) { - Modules.get().get(BetterChat.class).lines.clear(); + getBetterChat().lines.clear(); + } + + // Other + @Unique + private BetterChat getBetterChat() { + if (betterChat == null) { + betterChat = Modules.get().get(BetterChat.class); + } + + return betterChat; } } diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/ChatScreenMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/ChatScreenMixin.java index c2463e8fd8..e0a3086f69 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/ChatScreenMixin.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/ChatScreenMixin.java @@ -19,7 +19,7 @@ public abstract class ChatScreenMixin { @Shadow protected TextFieldWidget chatField; - @Inject(method = "init", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/widget/TextFieldWidget;setMaxLength(I)V", shift = At.Shift.AFTER)) + @Inject(method = "init", at = @At(value = "TAIL")) private void onInit(CallbackInfo info) { if (Modules.get().get(BetterChat.class).isInfiniteChatBox()) chatField.setMaxLength(Integer.MAX_VALUE); } diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/ClientPlayerInteractionManagerAccessor.java b/src/main/java/meteordevelopment/meteorclient/mixin/ClientPlayerInteractionManagerAccessor.java index 7df6e86e59..5fa0a26f4a 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/ClientPlayerInteractionManagerAccessor.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/ClientPlayerInteractionManagerAccessor.java @@ -15,6 +15,9 @@ public interface ClientPlayerInteractionManagerAccessor { @Accessor("currentBreakingProgress") float getBreakingProgress(); + @Accessor("currentBreakingProgress") + void setCurrentBreakingProgress(float progress); + @Accessor("currentBreakingPos") BlockPos getCurrentBreakingBlockPos(); } diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/ClientPlayerInteractionManagerMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/ClientPlayerInteractionManagerMixin.java index 3f316accf5..582f8d62a2 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/ClientPlayerInteractionManagerMixin.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/ClientPlayerInteractionManagerMixin.java @@ -13,14 +13,17 @@ import meteordevelopment.meteorclient.systems.modules.misc.InventoryTweaks; import meteordevelopment.meteorclient.systems.modules.player.BreakDelay; import meteordevelopment.meteorclient.systems.modules.player.Reach; +import meteordevelopment.meteorclient.systems.modules.player.SpeedMine; import meteordevelopment.meteorclient.utils.player.Rotations; import meteordevelopment.meteorclient.utils.world.BlockUtils; import net.minecraft.block.BlockState; +import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.network.ClientPlayerInteractionManager; import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; +import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket; import net.minecraft.screen.PlayerScreenHandler; import net.minecraft.screen.ScreenHandler; import net.minecraft.screen.slot.SlotActionType; @@ -31,6 +34,7 @@ import net.minecraft.util.math.Direction; import net.minecraft.world.BlockView; import org.objectweb.asm.Opcodes; +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; @@ -41,6 +45,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.invoke.arg.Args; +import static meteordevelopment.meteorclient.MeteorClient.mc; + @Mixin(ClientPlayerInteractionManager.class) public abstract class ClientPlayerInteractionManagerMixin implements IClientPlayerInteractionManager { @Shadow private int blockBreakingCooldown; @@ -50,6 +56,10 @@ public abstract class ClientPlayerInteractionManagerMixin implements IClientPlay @Shadow public abstract void clickSlot(int syncId, int slotId, int button, SlotActionType actionType, PlayerEntity player); + @Shadow + @Final + private ClientPlayNetworkHandler networkHandler; + @Inject(method = "clickSlot", at = @At("HEAD"), cancellable = true) private void onClickSlot(int syncId, int slotId, int button, SlotActionType actionType, PlayerEntity player, CallbackInfo info) { if (actionType == SlotActionType.THROW && slotId >= 0 && slotId < player.currentScreenHandler.slots.size()) { @@ -91,6 +101,19 @@ public void onClickArmorSlot(int syncId, int slotId, int button, SlotActionType @Inject(method = "attackBlock", at = @At("HEAD"), cancellable = true) private void onAttackBlock(BlockPos blockPos, Direction direction, CallbackInfoReturnable info) { if (MeteorClient.EVENT_BUS.post(StartBreakingBlockEvent.get(blockPos, direction)).isCancelled()) info.cancel(); + else { + SpeedMine sm = Modules.get().get(SpeedMine.class); + BlockState state = mc.world.getBlockState(blockPos); + + if (!sm.instamine() || !sm.filter(state.getBlock())) return; + + if (state.calcBlockBreakingDelta(mc.player, mc.world, blockPos) > 0.5f) { + mc.world.breakBlock(blockPos, true, mc.player); + networkHandler.sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.START_DESTROY_BLOCK, blockPos, direction)); + networkHandler.sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK, blockPos, direction)); + info.setReturnValue(true); + } + } } @Inject(method = "interactBlock", at = @At("HEAD"), cancellable = true) diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/HeldItemRendererMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/HeldItemRendererMixin.java index e6f21a619f..72748fa436 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/HeldItemRendererMixin.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/HeldItemRendererMixin.java @@ -16,9 +16,11 @@ import net.minecraft.client.render.item.HeldItemRenderer; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.ItemStack; +import net.minecraft.util.Arm; import net.minecraft.util.Hand; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.*; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -83,6 +85,13 @@ private void onRenderArm(AbstractClientPlayerEntity player, float tickDelta, flo MeteorClient.EVENT_BUS.post(ArmRenderEvent.get(hand, matrices)); } + @Inject(method = "applyEatOrDrinkTransformation", at = @At(value = "INVOKE", target = "Ljava/lang/Math;pow(DD)D", shift = At.Shift.BEFORE), cancellable = true) + private void cancelTransformations(MatrixStack matrices, float tickDelta, Arm arm, ItemStack stack, CallbackInfo ci) { + if (Modules.get().get(HandView.class).disableFoodAnimation()) ci.cancel(); + } + + + @Unique private boolean showSwapping(ItemStack stack1, ItemStack stack2) { return !Modules.get().get(HandView.class).showSwapping() || ItemStack.areEqual(stack1, stack2); } diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/LivingEntityMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/LivingEntityMixin.java index 7a19694a92..b4bccd5aa8 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/LivingEntityMixin.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/LivingEntityMixin.java @@ -10,7 +10,9 @@ import meteordevelopment.meteorclient.events.entity.DamageEvent; import meteordevelopment.meteorclient.events.entity.player.CanWalkOnFluidEvent; import meteordevelopment.meteorclient.systems.modules.Modules; +import meteordevelopment.meteorclient.systems.modules.movement.elytrafly.ElytraFlightModes; import meteordevelopment.meteorclient.systems.modules.movement.elytrafly.ElytraFly; +import meteordevelopment.meteorclient.systems.modules.movement.elytrafly.modes.Bounce; import meteordevelopment.meteorclient.systems.modules.player.OffhandCrash; import meteordevelopment.meteorclient.systems.modules.player.PotionSpoof; import meteordevelopment.meteorclient.systems.modules.render.HandView; @@ -109,6 +111,18 @@ private boolean isFallFlyingHook(boolean original) { return original; } + private boolean previousElytra = false; + + @Inject(method = "isFallFlying", at = @At("TAIL"), cancellable = true) + public void recastOnLand(CallbackInfoReturnable cir) { + boolean elytra = cir.getReturnValue(); + ElytraFly elytraFly = Modules.get().get(ElytraFly.class); + if (previousElytra && !elytra && elytraFly.isActive() && elytraFly.flightMode.get() == ElytraFlightModes.Bounce) { + cir.setReturnValue(Bounce.recastElytra(mc.player)); + } + previousElytra = elytra; + } + @ModifyReturnValue(method = "hasStatusEffect", at = @At("RETURN")) private boolean hasStatusEffect(boolean original, StatusEffect effect) { if (Modules.get().get(PotionSpoof.class).shouldBlock(effect)) return false; diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/MessageHandlerMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/MessageHandlerMixin.java new file mode 100644 index 0000000000..ef2ef3f283 --- /dev/null +++ b/src/main/java/meteordevelopment/meteorclient/mixin/MessageHandlerMixin.java @@ -0,0 +1,41 @@ +/* + * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client). + * Copyright (c) Meteor Development. + */ + +package meteordevelopment.meteorclient.mixin; + +import com.mojang.authlib.GameProfile; +import meteordevelopment.meteorclient.mixininterface.IMessageHandler; +import net.minecraft.client.network.message.MessageHandler; +import net.minecraft.network.message.MessageType; +import net.minecraft.network.message.SignedMessage; +import net.minecraft.text.Text; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.time.Instant; + +@Mixin(MessageHandler.class) +public class MessageHandlerMixin implements IMessageHandler { + @Unique + private GameProfile sender; + + @Inject(method = "processChatMessageInternal", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/ChatHud;addMessage(Lnet/minecraft/text/Text;Lnet/minecraft/network/message/MessageSignatureData;Lnet/minecraft/client/gui/hud/MessageIndicator;)V", shift = At.Shift.BEFORE)) + private void onProcessChatMessageInternal_beforeAddMessage(MessageType.Parameters params, SignedMessage message, Text decorated, GameProfile sender, boolean onlyShowSecureChat, Instant receptionTimestamp, CallbackInfoReturnable info) { + this.sender = sender; + } + + @Inject(method = "processChatMessageInternal", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/ChatHud;addMessage(Lnet/minecraft/text/Text;Lnet/minecraft/network/message/MessageSignatureData;Lnet/minecraft/client/gui/hud/MessageIndicator;)V", shift = At.Shift.AFTER)) + private void onProcessChatMessageInternal_afterAddMessage(MessageType.Parameters params, SignedMessage message, Text decorated, GameProfile sender, boolean onlyShowSecureChat, Instant receptionTimestamp, CallbackInfoReturnable info) { + this.sender = null; + } + + @Override + public GameProfile meteor$getSender() { + return sender; + } +} diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/MinecraftClientAccessor.java b/src/main/java/meteordevelopment/meteorclient/mixin/MinecraftClientAccessor.java index 9a878dddef..cdc94cc8fd 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/MinecraftClientAccessor.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/MinecraftClientAccessor.java @@ -36,12 +36,6 @@ static int getFps() { @Accessor("networkProxy") Proxy getProxy(); - @Accessor("itemUseCooldown") - void setItemUseCooldown(int itemUseCooldown); - - @Accessor("itemUseCooldown") - int getItemUseCooldown(); - @Accessor("resourceReloadLogger") ResourceReloadLogger getResourceReloadLogger(); diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/MinecraftClientMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/MinecraftClientMixin.java index e63ea6134f..c6086e54e6 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/MinecraftClientMixin.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/MinecraftClientMixin.java @@ -17,8 +17,11 @@ import meteordevelopment.meteorclient.gui.WidgetScreen; import meteordevelopment.meteorclient.mixininterface.IMinecraftClient; import meteordevelopment.meteorclient.systems.modules.Modules; +import meteordevelopment.meteorclient.systems.modules.player.FastUse; import meteordevelopment.meteorclient.systems.modules.render.UnfocusedCPU; import meteordevelopment.meteorclient.utils.Utils; +import meteordevelopment.meteorclient.utils.misc.CPSUtils; +import meteordevelopment.meteorclient.utils.misc.MeteorStarscript; import meteordevelopment.starscript.Script; import net.minecraft.client.MinecraftClient; import net.minecraft.client.Mouse; @@ -27,6 +30,8 @@ import net.minecraft.client.option.GameOptions; import net.minecraft.client.util.Window; import net.minecraft.client.world.ClientWorld; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Hand; import net.minecraft.util.hit.HitResult; import net.minecraft.util.profiler.Profiler; import org.jetbrains.annotations.Nullable; @@ -39,6 +44,7 @@ import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import java.util.concurrent.CompletableFuture; @@ -63,6 +69,9 @@ public abstract class MinecraftClientMixin implements IMinecraftClient { @Nullable public ClientPlayerInteractionManager interactionManager; + @Shadow + private int itemUseCooldown; + @Inject(method = "", at = @At("TAIL")) private void onInit(CallbackInfo info) { MeteorClient.INSTANCE.onInitializeClient(); @@ -88,6 +97,11 @@ private void onTick(CallbackInfo info) { getProfiler().pop(); } + @Inject(method = "doAttack", at = @At("HEAD")) + private void onAttack(CallbackInfoReturnable cir) { + CPSUtils.onAttack(); + } + @Inject(method = "doItemUse", at = @At("HEAD")) private void onDoItemUse(CallbackInfo info) { doItemUseCalled = true; @@ -110,6 +124,14 @@ private void onSetScreen(Screen screen, CallbackInfo info) { if (event.isCancelled()) info.cancel(); } + @Inject(method = "doItemUse", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;isItemEnabled(Lnet/minecraft/resource/featuretoggle/FeatureSet;)Z"), locals = LocalCapture.CAPTURE_FAILHARD) + private void onDoItemUseHand(CallbackInfo ci, Hand[] var1, int var2, int var3, Hand hand, ItemStack itemStack) { + FastUse fastUse = Modules.get().get(FastUse.class); + if (fastUse.isActive()) { + itemUseCooldown = fastUse.getItemUseCooldown(itemStack); + } + } + @ModifyExpressionValue(method = "doItemUse", at = @At(value = "FIELD", target = "Lnet/minecraft/client/MinecraftClient;crosshairTarget:Lnet/minecraft/util/hit/HitResult;", ordinal = 1)) private HitResult doItemUseMinecraftClientCrosshairTargetProxy(HitResult original) { return MeteorClient.EVENT_BUS.post(ItemUseCrosshairTargetEvent.get(original)).target; diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/PacketInflaterMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/PacketInflaterMixin.java deleted file mode 100644 index 049bb87cd0..0000000000 --- a/src/main/java/meteordevelopment/meteorclient/mixin/PacketInflaterMixin.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client). - * Copyright (c) Meteor Development. - */ - -package meteordevelopment.meteorclient.mixin; - -import meteordevelopment.meteorclient.systems.modules.Modules; -import meteordevelopment.meteorclient.systems.modules.misc.AntiPacketKick; -import net.minecraft.network.PacketInflater; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.Constant; -import org.spongepowered.asm.mixin.injection.ModifyConstant; - -@Mixin(PacketInflater.class) -public class PacketInflaterMixin { - @ModifyConstant(method = "decode", constant = @Constant(intValue = 8388608)) - private int maxValue(int value) { - return Modules.get().isActive(AntiPacketKick.class) ? Integer.MAX_VALUE : value; - } -} diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/indigo/AbstractBlockRenderContextMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/indigo/AbstractBlockRenderContextMixin.java index a4c5837f2f..12c97c52bd 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/indigo/AbstractBlockRenderContextMixin.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/indigo/AbstractBlockRenderContextMixin.java @@ -12,6 +12,7 @@ import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -32,6 +33,7 @@ else if (alpha != -1) { } } + @Unique private int rewriteQuadAlpha(int color, int alpha) { return ((alpha & 0xFF) << 24) | (color & 0x00FFFFFF); } diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/indium/AbstractBlockRenderContextMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/indium/AbstractBlockRenderContextMixin.java new file mode 100644 index 0000000000..8ead45ba5e --- /dev/null +++ b/src/main/java/meteordevelopment/meteorclient/mixin/indium/AbstractBlockRenderContextMixin.java @@ -0,0 +1,29 @@ +/* + * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client). + * Copyright (c) Meteor Development. + */ + +package meteordevelopment.meteorclient.mixin.indium; + +import link.infra.indium.renderer.mesh.MutableQuadViewImpl; +import link.infra.indium.renderer.render.AbstractBlockRenderContext; +import link.infra.indium.renderer.render.BlockRenderInfo; +import meteordevelopment.meteorclient.systems.modules.render.Xray; +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; + +@Mixin(value = AbstractBlockRenderContext.class, remap = false) +public class AbstractBlockRenderContextMixin { + @Shadow + protected BlockRenderInfo blockInfo; + + @Inject(method = "renderQuad(Llink/infra/indium/renderer/mesh/MutableQuadViewImpl;Z)V", at = @At(value = "INVOKE", target = "Llink/infra/indium/renderer/render/AbstractBlockRenderContext;bufferQuad(Llink/infra/indium/renderer/mesh/MutableQuadViewImpl;Lme/jellysquid/mods/sodium/client/render/chunk/terrain/material/Material;)V"), cancellable = true) + private void onBufferQuad(MutableQuadViewImpl quad, boolean isVanilla, CallbackInfo ci) { + int alpha = Xray.getAlpha(blockInfo.blockState, blockInfo.blockPos); + + if (alpha == 0) ci.cancel(); + } +} diff --git a/src/main/java/meteordevelopment/meteorclient/mixininterface/IChatHud.java b/src/main/java/meteordevelopment/meteorclient/mixininterface/IChatHud.java index cf26dcd19d..548489286c 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixininterface/IChatHud.java +++ b/src/main/java/meteordevelopment/meteorclient/mixininterface/IChatHud.java @@ -8,5 +8,5 @@ import net.minecraft.text.Text; public interface IChatHud { - void add(Text message, int id); + void meteor$add(Text message, int id); } diff --git a/src/main/java/meteordevelopment/meteorclient/mixininterface/IChatHudLine.java b/src/main/java/meteordevelopment/meteorclient/mixininterface/IChatHudLine.java index 273e1f43d6..de081990db 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixininterface/IChatHudLine.java +++ b/src/main/java/meteordevelopment/meteorclient/mixininterface/IChatHudLine.java @@ -5,8 +5,14 @@ package meteordevelopment.meteorclient.mixininterface; +import com.mojang.authlib.GameProfile; + public interface IChatHudLine { - int getId(); + String meteor$getText(); + + int meteor$getId(); + void meteor$setId(int id); - void setId(int id); + GameProfile meteor$getSender(); + void meteor$setSender(GameProfile profile); } diff --git a/src/main/java/meteordevelopment/meteorclient/mixininterface/IChatHudLineVisible.java b/src/main/java/meteordevelopment/meteorclient/mixininterface/IChatHudLineVisible.java new file mode 100644 index 0000000000..74a908e96e --- /dev/null +++ b/src/main/java/meteordevelopment/meteorclient/mixininterface/IChatHudLineVisible.java @@ -0,0 +1,11 @@ +/* + * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client). + * Copyright (c) Meteor Development. + */ + +package meteordevelopment.meteorclient.mixininterface; + +public interface IChatHudLineVisible extends IChatHudLine { + boolean meteor$isStartOfEntry(); + void meteor$setStartOfEntry(boolean start); +} diff --git a/src/main/java/meteordevelopment/meteorclient/mixininterface/IMessageHandler.java b/src/main/java/meteordevelopment/meteorclient/mixininterface/IMessageHandler.java new file mode 100644 index 0000000000..57a5793337 --- /dev/null +++ b/src/main/java/meteordevelopment/meteorclient/mixininterface/IMessageHandler.java @@ -0,0 +1,16 @@ +/* + * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client). + * Copyright (c) Meteor Development. + */ + +package meteordevelopment.meteorclient.mixininterface; + +import com.mojang.authlib.GameProfile; +import net.minecraft.client.gui.hud.MessageIndicator; +import net.minecraft.network.message.MessageSignatureData; +import net.minecraft.text.Text; + +public interface IMessageHandler { + /** Only valid inside of {@link net.minecraft.client.gui.hud.ChatHud#addMessage(Text, MessageSignatureData, MessageIndicator)} call */ + GameProfile meteor$getSender(); +} diff --git a/src/main/java/meteordevelopment/meteorclient/systems/hud/elements/PotionTimersHud.java b/src/main/java/meteordevelopment/meteorclient/systems/hud/elements/PotionTimersHud.java index e112c734cb..3b6cae826d 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/hud/elements/PotionTimersHud.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/hud/elements/PotionTimersHud.java @@ -172,7 +172,7 @@ protected double alignX(double width, Alignment alignment) { @Override public void tick(HudRenderer renderer) { - if (mc.player == null || (isInEditor() && mc.player.getStatusEffects().isEmpty())) { + if (mc.player == null || (isInEditor() && hasNoVisibleEffects())) { setSize(renderer.textWidth("Potion Timers 0:00", shadow.get(), getScale()), renderer.textHeight(shadow.get(), getScale())); return; } @@ -199,7 +199,7 @@ public void render(HudRenderer renderer) { renderer.quadRounded(this.x, this.y, getWidth(), getHeight(), backgroundColor.get()); } - if (mc.player == null || (isInEditor() && mc.player.getStatusEffects().isEmpty())) { + if (mc.player == null || (isInEditor() && hasNoVisibleEffects())) { renderer.text("Potion Timers 0:00", x, y, Color.WHITE, shadow.get(), getScale()); return; } @@ -251,6 +251,16 @@ private double getScale() { return customScale.get() ? scale.get() : -1; } + private boolean hasNoVisibleEffects() { + for (StatusEffectInstance statusEffectInstance : mc.player.getStatusEffects()) { + if (hiddenEffects.get().contains(statusEffectInstance.getEffectType())) continue; + if (!showAmbient.get() && statusEffectInstance.isAmbient()) continue; + return false; + } + + return true; + } + public enum ColorMode { Effect, Flat, diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/Modules.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/Modules.java index 892b2f3811..e58bb8f783 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/Modules.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/Modules.java @@ -556,7 +556,6 @@ private void initMisc() { add(new BetterTab()); add(new BookBot()); add(new MessageAura()); - add(new MiddleClickFriend()); add(new NameProtect()); add(new Notebot()); add(new Notifier()); diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/AnchorAura.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/AnchorAura.java index c272a4ba7d..38b1a947da 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/AnchorAura.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/AnchorAura.java @@ -322,6 +322,12 @@ private BlockPos findPlacePos(BlockPos targetPlacePos) { if (isValidPlace(targetPlacePos.down())) return targetPlacePos.down(); else if (isValidPlace(targetPlacePos.up(2))) return targetPlacePos.up(2); break; + case Around: + if (isValidPlace(targetPlacePos.north())) return targetPlacePos.north(); + else if (isValidPlace(targetPlacePos.east())) return targetPlacePos.east(); + else if (isValidPlace(targetPlacePos.west())) return targetPlacePos.west(); + else if (isValidPlace(targetPlacePos.south())) return targetPlacePos.south(); + break; } return null; } @@ -349,7 +355,7 @@ private boolean getDamageBreak(BlockPos pos) { } private boolean isValidPlace(BlockPos pos) { - return (mc.world.getBlockState(pos).isAir() || mc.world.getBlockState(pos).getFluidState().getFluid() instanceof FlowableFluid) && Math.sqrt(mc.player.getBlockPos().getSquaredDistance(pos)) <= placeRange.get() && getDamagePlace(pos); + return Math.sqrt(mc.player.getBlockPos().getSquaredDistance(pos)) <= placeRange.get() && getDamagePlace(pos) && BlockUtils.canPlace(pos, true); } private boolean isValidBreak(BlockPos pos) { @@ -385,6 +391,7 @@ public String getInfoString() { public enum PlaceMode { Above, + Around, AboveAndBelow, All } diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/AutoCity.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/AutoCity.java index 1dc5674676..effcf624a7 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/AutoCity.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/AutoCity.java @@ -211,7 +211,7 @@ public void mine(boolean done) { InvUtils.swap(pick.slot(), switchMode.get() == SwitchMode.Silent); if (rotate.get()) Rotations.rotate(Rotations.getYaw(targetPos), Rotations.getPitch(targetPos)); - Direction direction = (mc.player.getY() > targetPos.getY()) ? Direction.UP : Direction.DOWN; + Direction direction = BlockUtils.getDirection(targetPos); if (!done) mc.getNetworkHandler().sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.START_DESTROY_BLOCK, targetPos, direction)); mc.getNetworkHandler().sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK, targetPos, direction)); diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/Offhand.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/Offhand.java index fe1dd83a50..54851c022f 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/Offhand.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/combat/Offhand.java @@ -7,72 +7,129 @@ import meteordevelopment.meteorclient.events.meteor.MouseButtonEvent; import meteordevelopment.meteorclient.events.world.TickEvent; -import meteordevelopment.meteorclient.settings.BoolSetting; -import meteordevelopment.meteorclient.settings.EnumSetting; -import meteordevelopment.meteorclient.settings.Setting; -import meteordevelopment.meteorclient.settings.SettingGroup; +import meteordevelopment.meteorclient.settings.*; import meteordevelopment.meteorclient.systems.modules.Categories; import meteordevelopment.meteorclient.systems.modules.Module; import meteordevelopment.meteorclient.systems.modules.Modules; import meteordevelopment.meteorclient.utils.misc.input.KeyAction; import meteordevelopment.meteorclient.utils.player.FindItemResult; import meteordevelopment.meteorclient.utils.player.InvUtils; +import meteordevelopment.meteorclient.utils.player.PlayerUtils; import meteordevelopment.orbit.EventHandler; -import net.minecraft.item.AxeItem; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.item.SwordItem; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.item.*; +import static meteordevelopment.orbit.EventPriority.HIGHEST; import static org.lwjgl.glfw.GLFW.GLFW_MOUSE_BUTTON_RIGHT; public class Offhand extends Module { - private final SettingGroup sgGeneral = settings.getDefaultGroup(); + private final SettingGroup sgCombat = settings.createGroup("Combat"); + private final SettingGroup sgTotem = settings.createGroup("Totem"); - private final Setting item = sgGeneral.add(new EnumSetting.Builder() + //Combat + + private final Setting delayTicks = sgCombat.add(new IntSetting.Builder() + .name("item-switch-delay") + .description("The delay in ticks between slot movements.") + .defaultValue(0) + .min(0) + .sliderMax(20) + .build() + ); + private final Setting preferreditem = sgCombat.add(new EnumSetting.Builder() .name("item") .description("Which item to hold in your offhand.") .defaultValue(Item.Crystal) .build() ); - private final Setting hotbar = sgGeneral.add(new BoolSetting.Builder() + private final Setting hotbar = sgCombat.add(new BoolSetting.Builder() .name("hotbar") .description("Whether to use items from your hotbar.") .defaultValue(false) .build() ); - private final Setting rightClick = sgGeneral.add(new BoolSetting.Builder() - .name("right-click") - .description("Only holds the item in your offhand when you are holding right click.") + private final Setting rightgapple = sgCombat.add(new BoolSetting.Builder() + .name("right-gapple") + .description("Will switch to a gapple when holding right click.(DO NOT USE WITH POTION ON)") + .defaultValue(false) + .build() + ); + + + private final Setting SwordGap = sgCombat.add(new BoolSetting.Builder() + .name("sword-gapple") + .description("Will switch to a gapple when holding a sword and right click.") .defaultValue(false) + .visible(rightgapple::get) .build() ); - private final Setting swordGap = sgGeneral.add(new BoolSetting.Builder() - .name("sword-gap") + private final Setting alwaysSwordGap = sgCombat.add(new BoolSetting.Builder() + .name("always-gap-on-sword") .description("Holds an Enchanted Golden Apple when you are holding a sword.") - .defaultValue(true) + .defaultValue(false) + .visible(() -> !rightgapple.get()) .build() ); - private final Setting crystalCa = sgGeneral.add(new BoolSetting.Builder() - .name("crystal-on-ca") - .description("Holds a crystal when you have Crystal Aura enabled.") - .defaultValue(true) + + private final Setting alwaysPot = sgCombat.add(new BoolSetting.Builder() + .name("always-pot-on-sword") + .description("Will switch to a potion when holding a sword") + .defaultValue(false) + .visible(() -> !rightgapple.get() && !alwaysSwordGap.get()) + .build() + ); + private final Setting potionClick = sgCombat.add(new BoolSetting.Builder() + .name("sword-pot") + .description("Will switch to a potion when holding a sword and right click.") + .defaultValue(false) + .visible(() -> !rightgapple.get() && !alwaysPot.get() && !alwaysSwordGap.get() ) .build() ); - private final Setting crystalMine = sgGeneral.add(new BoolSetting.Builder() - .name("crystal-on-mine") - .description("Holds a crystal when you are mining.") + //Totem + + private final Setting minHealth = sgTotem.add(new DoubleSetting.Builder() + .name("min-health") + .description("Will hold a totem when below this amount of health.") + .defaultValue(10) + .range(0,36) + .sliderRange(0,36) + .build() + ); + + private final Setting elytra = sgTotem.add(new BoolSetting.Builder() + .name("elytra") + .description("Will always hold a totem while flying with an elytra.") .defaultValue(false) .build() ); + private final Setting falling = sgTotem.add(new BoolSetting.Builder() + .name("falling") + .description("Will hold a totem if fall damage could kill you.") + .defaultValue(false) + .build() + ); + + private final Setting explosion = sgTotem.add(new BoolSetting.Builder() + .name("explosion") + .description("Will hold a totem when explosion damage could kill you.") + .defaultValue(true) + .build() + ); + + private boolean isClicking; private boolean sentMessage; + private Item currentItem; + public boolean locked; + + private int totems, ticks; public Offhand() { super(Categories.Combat, "offhand", "Allows you to hold specified items in your offhand."); @@ -80,65 +137,111 @@ public Offhand() { @Override public void onActivate() { + ticks = 0; sentMessage = false; isClicking = false; - currentItem = item.get(); + currentItem = preferreditem.get(); } - @EventHandler - private void onTick(TickEvent.Pre event) { - AutoTotem autoTotem = Modules.get().get(AutoTotem.class); + @EventHandler(priority = HIGHEST + 999) + private void onTick(TickEvent.Pre event) throws InterruptedException { + FindItemResult result = InvUtils.find(Items.TOTEM_OF_UNDYING); + totems = result.count(); - // Sword Gap - if ((mc.player.getMainHandStack().getItem() instanceof SwordItem - || mc.player.getMainHandStack().getItem() instanceof AxeItem) && swordGap.get()) currentItem = Item.EGap; + if (totems <= 0) locked = false; + else if (ticks > delayTicks.get()) { + boolean low = mc.player.getHealth() + mc.player.getAbsorptionAmount() - PlayerUtils.possibleHealthReductions(explosion.get(), falling.get()) <= minHealth.get(); + boolean ely = elytra.get() && mc.player.getEquippedStack(EquipmentSlot.CHEST).getItem() == Items.ELYTRA && mc.player.isFallFlying(); + FindItemResult item = InvUtils.find(itemStack -> itemStack.getItem() == currentItem.item, 0, 35); - // Ca and mining - else if ((Modules.get().isActive(CrystalAura.class) && crystalCa.get()) - || mc.interactionManager.isBreakingBlock() && crystalMine.get()) currentItem = Item.Crystal; + // Calculates Damage from Falling, Explosions + Elyta + locked = (low || ely); - else currentItem = item.get(); + if (locked && mc.player.getOffHandStack().getItem() != Items.TOTEM_OF_UNDYING) { + InvUtils.move().from(result.slot()).toOffhand(); + } - // Checking offhand item - if (mc.player.getOffHandStack().getItem() != currentItem.item) { - FindItemResult item = InvUtils.find(itemStack -> itemStack.getItem() == currentItem.item, hotbar.get() ? 0 : 9, 35); + ticks = 0; + return; + } + ticks++; + + AutoTotem autoTotem = Modules.get().get(AutoTotem.class); + + // Returns to the original Item + currentItem = preferreditem.get(); - // No offhand item - if (!item.found()) { - if (!sentMessage) { - warning("Chosen item not found."); - sentMessage = true; + // Sword Gap & Right Gap + if (rightgapple.get()) { + if (!locked) { + if (SwordGap.get() && mc.player.getMainHandStack().getItem() instanceof SwordItem) { + if (isClicking) { + currentItem = Item.EGap; + } + } + if (!SwordGap.get()) { + if (isClicking) { + currentItem = Item.EGap; + } } } + } - // Swap to offhand - else if ((isClicking || !rightClick.get()) && !autoTotem.isLocked() && !item.isOffhand()) { - InvUtils.move().from(item.slot()).toOffhand(); - sentMessage = false; + // Always Gap + else if ((mc.player.getMainHandStack().getItem() instanceof SwordItem || mc.player.getMainHandStack().getItem() instanceof AxeItem) && alwaysSwordGap.get()) currentItem = Item.EGap; + + // Potion Click + else if (potionClick.get()) { + if (!locked) { + if (mc.player.getMainHandStack().getItem() instanceof SwordItem) { + if (isClicking) { + currentItem = Item.Potion; + } + } } } - // If not clicking, set to totem if auto totem is on - else if (!isClicking && rightClick.get()) { - if (autoTotem.isActive()) { - FindItemResult totem = InvUtils.find(itemStack -> itemStack.getItem() == Items.TOTEM_OF_UNDYING, hotbar.get() ? 0 : 9, 35); + // Always Pot + else if ((mc.player.getMainHandStack().getItem() instanceof SwordItem || mc.player.getMainHandStack().getItem() instanceof AxeItem) && alwaysPot.get()) currentItem = Item.Potion; - if (totem.found() && !totem.isOffhand()) { - InvUtils.move().from(totem.slot()).toOffhand(); + + else currentItem = preferreditem.get(); + + // Checking offhand item + if (mc.player.getOffHandStack().getItem() != currentItem.item) { + if (ticks >= delayTicks.get()) { + if (!locked) { + FindItemResult item = InvUtils.find(itemStack -> itemStack.getItem() == currentItem.item, hotbar.get() ? 0 : 9, 35); + + // No offhand item + if (!item.found()) { + if (!sentMessage) { + warning("Chosen item not found."); + sentMessage = true; + } + } + + // Swap to offhand + else if ((isClicking || !autoTotem.isLocked() && !item.isOffhand())) { + InvUtils.move().from(item.slot()).toOffhand(); + sentMessage = false; + } + ticks = 0; + return; } - } else { - FindItemResult empty = InvUtils.find(ItemStack::isEmpty, hotbar.get() ? 0 : 9, 35); - if (empty.found()) InvUtils.move().fromOffhand().to(empty.slot()); + ticks++; } } } @EventHandler private void onMouseButton(MouseButtonEvent event) { + // Detects if the User is right-clicking isClicking = mc.currentScreen == null && !Modules.get().get(AutoTotem.class).isLocked() && !usableItem() && !mc.player.isUsingItem() && event.action == KeyAction.Press && event.button == GLFW_MOUSE_BUTTON_RIGHT; } private boolean usableItem() { + // What counts as a Usable Item return mc.player.getMainHandStack().getItem() == Items.BOW || mc.player.getMainHandStack().getItem() == Items.TRIDENT || mc.player.getMainHandStack().getItem() == Items.CROSSBOW @@ -147,20 +250,21 @@ private boolean usableItem() { @Override public String getInfoString() { - return item.get().name(); + return preferreditem.get().name(); } public enum Item { + // Items the module could put on your offhand EGap(Items.ENCHANTED_GOLDEN_APPLE), Gap(Items.GOLDEN_APPLE), Crystal(Items.END_CRYSTAL), Totem(Items.TOTEM_OF_UNDYING), - Shield(Items.SHIELD); - + Shield(Items.SHIELD), + Potion(Items.POTION); net.minecraft.item.Item item; - Item(net.minecraft.item.Item item) { this.item = item; } } + } diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/BetterChat.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/BetterChat.java index 5b7f925732..6694810b9a 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/BetterChat.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/BetterChat.java @@ -5,6 +5,8 @@ package meteordevelopment.meteorclient.systems.modules.misc; +import com.mojang.authlib.GameProfile; +import com.mojang.blaze3d.systems.RenderSystem; import it.unimi.dsi.fastutil.chars.Char2CharMap; import it.unimi.dsi.fastutil.chars.Char2CharOpenHashMap; import it.unimi.dsi.fastutil.ints.IntArrayList; @@ -13,18 +15,25 @@ import meteordevelopment.meteorclient.events.game.ReceiveMessageEvent; import meteordevelopment.meteorclient.events.game.SendMessageEvent; import meteordevelopment.meteorclient.mixin.ChatHudAccessor; +import meteordevelopment.meteorclient.mixininterface.IChatHudLine; +import meteordevelopment.meteorclient.mixininterface.IChatHudLineVisible; 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.misc.MeteorIdentifier; import meteordevelopment.meteorclient.utils.player.ChatUtils; +import meteordevelopment.meteorclient.utils.render.color.Color; import meteordevelopment.orbit.EventHandler; +import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.hud.ChatHudLine; +import net.minecraft.client.network.PlayerListEntry; import net.minecraft.text.ClickEvent; import net.minecraft.text.HoverEvent; import net.minecraft.text.MutableText; import net.minecraft.text.Text; import net.minecraft.util.Formatting; +import net.minecraft.util.Identifier; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -238,10 +247,6 @@ private void onMessageReceive(ReceiveMessageEvent event) { } } - if (playerHeads.get()) { - message = Text.literal(" ").append(message); - } - if (antiSpam.get()) { Text antiSpammed = appendAntiSpam(message); @@ -341,6 +346,98 @@ private void onMessageSend(SendMessageEvent event) { event.message = message; } + // Player Heads + + private record CustomHeadEntry(String prefix, Identifier texture) {} + + private static final List CUSTOM_HEAD_ENTRIES = new ArrayList<>(); + + private static final Pattern TIMESTAMP_REGEX = Pattern.compile("^<\\d{1,2}:\\d{1,2}>"); + + /** Registers a custom player head to render based on a message prefix */ + public static void registerCustomHead(String prefix, Identifier texture) { + CUSTOM_HEAD_ENTRIES.add(new CustomHeadEntry(prefix, texture)); + } + + static { + registerCustomHead("[Meteor]", new MeteorIdentifier("textures/icons/chat/meteor.png")); + registerCustomHead("[Baritone]", new MeteorIdentifier("textures/icons/chat/baritone.png")); + } + + public int modifyChatWidth(int width) { + if (isActive() && playerHeads.get()) return width + 10; + return width; + } + + public void drawPlayerHead(DrawContext context, ChatHudLine.Visible line, int y, int color) { + if (!isActive() || !playerHeads.get()) return; + + // Only draw the first line of multi line messages + if (((IChatHudLineVisible) (Object) line).meteor$isStartOfEntry()) { + RenderSystem.enableBlend(); + RenderSystem.setShaderColor(1, 1, 1, Color.toRGBAA(color) / 255f); + + drawTexture(context, (IChatHudLine) (Object) line, y); + + RenderSystem.setShaderColor(1, 1, 1, 1); + RenderSystem.disableBlend(); + } + + // Offset + context.getMatrices().translate(10, 0, 0); + } + + private void drawTexture(DrawContext context, IChatHudLine line, int y) { + String text = line.meteor$getText().trim(); + + // Custom + int startOffset = 0; + + try { + startOffset = TIMESTAMP_REGEX.matcher(text).end(); + } + catch (IllegalStateException ignored) {} + + for (CustomHeadEntry entry : CUSTOM_HEAD_ENTRIES) { + // Check prefix + if (text.startsWith(entry.prefix(), startOffset)) { + context.drawTexture(entry.texture(), 0, y, 8, 8, 0, 0, 64, 64, 64, 64); + return; + } + } + + // Player + GameProfile sender = getSender(line, text); + if (sender == null) return; + + PlayerListEntry entry = mc.getNetworkHandler().getPlayerListEntry(sender.getId()); + if (entry == null) return; + + Identifier skin = entry.getSkinTexture(); + + context.drawTexture(skin, 0, y, 8, 8, 8, 8, 8, 8, 64, 64); + context.drawTexture(skin, 0, y, 8, 8, 40, 8, 8, 8, 64, 64); + } + + private GameProfile getSender(IChatHudLine line, String text) { + GameProfile sender = line.meteor$getSender(); + + // If the packet did not contain a sender field then try to get the sender from the message + if (sender == null) { + int openingI = text.indexOf('<'); + int closingI = text.indexOf('>'); + + if (openingI != -1 && closingI != -1 && closingI > openingI) { + String username = text.substring(openingI + 1, closingI); + + PlayerListEntry entry = mc.getNetworkHandler().getPlayerListEntry(username); + if (entry != null) sender = entry.getProfile(); + } + } + + return sender; + } + // Annoy private String applyAnnoy(String message) { @@ -441,8 +538,6 @@ public boolean isLongerChat() { return isActive() && longerChatHistory.get(); } - public boolean displayPlayerHeads() { return isActive() && playerHeads.get(); } - public boolean keepHistory() { return isActive() && keepHistory.get(); } public int getChatLength() { diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/InventoryTweaks.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/InventoryTweaks.java index 729e372a65..c7bc6311ca 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/InventoryTweaks.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/InventoryTweaks.java @@ -398,7 +398,7 @@ private void moveSlots(ScreenHandler handler, int start, int end, boolean steal) int iCopy = i; Rotations.rotate(mc.player.getYaw() - 180, mc.player.getPitch(), () -> InvUtils.drop().slotId(iCopy)); } - } else InvUtils.quickMove().slotId(i); + } else InvUtils.shiftClick().slotId(i); } } diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/MiddleClickFriend.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/MiddleClickFriend.java deleted file mode 100644 index 212506b871..0000000000 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/MiddleClickFriend.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client). - * Copyright (c) Meteor Development. - */ - -package meteordevelopment.meteorclient.systems.modules.misc; - -import meteordevelopment.meteorclient.events.meteor.MouseButtonEvent; -import meteordevelopment.meteorclient.settings.BoolSetting; -import meteordevelopment.meteorclient.settings.Setting; -import meteordevelopment.meteorclient.settings.SettingGroup; -import meteordevelopment.meteorclient.systems.friends.Friend; -import meteordevelopment.meteorclient.systems.friends.Friends; -import meteordevelopment.meteorclient.systems.modules.Categories; -import meteordevelopment.meteorclient.systems.modules.Module; -import meteordevelopment.meteorclient.utils.misc.input.KeyAction; -import meteordevelopment.meteorclient.utils.player.ChatUtils; -import meteordevelopment.orbit.EventHandler; -import net.minecraft.entity.player.PlayerEntity; - -import static org.lwjgl.glfw.GLFW.GLFW_MOUSE_BUTTON_MIDDLE; - -public class MiddleClickFriend extends Module { - private final SettingGroup sgGeneral = settings.getDefaultGroup(); - - private final Setting message = sgGeneral.add(new BoolSetting.Builder() - .name("message") - .description("Sends a message to the player when you add them as a friend.") - .defaultValue(false) - .build() - ); - - public MiddleClickFriend() { - super(Categories.Misc, "middle-click-friend", "Adds or removes a player as a friend via middle click."); - } - - @EventHandler - private void onMouseButton(MouseButtonEvent event) { - if (event.action != KeyAction.Press || event.button != GLFW_MOUSE_BUTTON_MIDDLE || mc.currentScreen != null || mc.targetedEntity == null || !(mc.targetedEntity instanceof PlayerEntity player)) return; - - if (!Friends.get().isFriend(player)) { - Friends.get().add(new Friend(player)); - info("Added %s to friends", player.getEntityName()); - if (message.get()) ChatUtils.sendPlayerMsg("/msg " + player.getEntityName() + " I just friended you on Meteor."); - } - else { - Friends.get().remove(Friends.get().get(player)); - info("Removed %s from friends", player.getEntityName()); - } - } -} diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/movement/AntiAFK.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/movement/AntiAFK.java index 1ab24dfebe..49a4c6200b 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/movement/AntiAFK.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/movement/AntiAFK.java @@ -6,12 +6,6 @@ package meteordevelopment.meteorclient.systems.modules.movement; import meteordevelopment.meteorclient.events.world.TickEvent; -import meteordevelopment.meteorclient.gui.GuiTheme; -import meteordevelopment.meteorclient.gui.widgets.WWidget; -import meteordevelopment.meteorclient.gui.widgets.containers.WTable; -import meteordevelopment.meteorclient.gui.widgets.input.WTextBox; -import meteordevelopment.meteorclient.gui.widgets.pressable.WMinus; -import meteordevelopment.meteorclient.gui.widgets.pressable.WPlus; import meteordevelopment.meteorclient.settings.*; import meteordevelopment.meteorclient.systems.modules.Categories; import meteordevelopment.meteorclient.systems.modules.Module; @@ -19,83 +13,50 @@ import meteordevelopment.meteorclient.utils.player.ChatUtils; import meteordevelopment.meteorclient.utils.player.Rotations; import meteordevelopment.orbit.EventHandler; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtElement; -import net.minecraft.nbt.NbtList; -import net.minecraft.nbt.NbtString; -import java.util.ArrayList; import java.util.List; import java.util.Random; public class AntiAFK extends Module { - public enum SpinMode { - Server, - Client - } - private final SettingGroup sgActions = settings.createGroup("Actions"); private final SettingGroup sgMessages = settings.createGroup("Messages"); // Actions - private final Setting spin = sgActions.add(new BoolSetting.Builder() - .name("spin") - .description("Spins.") - .defaultValue(true) - .build() - ); - - private final Setting spinMode = sgActions.add(new EnumSetting.Builder() - .name("spin-mode") - .description("The method of rotating.") - .defaultValue(SpinMode.Server) - .visible(spin::get) - .build() - ); - - private final Setting spinSpeed = sgActions.add(new IntSetting.Builder() - .name("spin-speed") - .description("The speed to spin you.") - .defaultValue(7) - .visible(spin::get) - .build() - ); - - private final Setting pitch = sgActions.add(new DoubleSetting.Builder() - .name("pitch") - .description("The pitch to set in server mode.") - .defaultValue(-90) - .range(-90, 90) - .sliderRange(-90, 90) - .visible(() -> spin.get() && spinMode.get() == SpinMode.Server) - .build() - ); - private final Setting jump = sgActions.add(new BoolSetting.Builder() .name("jump") - .description("Jumps.") + .description("Jump randomly.") .defaultValue(true) .build() ); - private final Setting click = sgActions.add(new BoolSetting.Builder() - .name("click") - .description("Clicks.") + private final Setting swing = sgActions.add(new BoolSetting.Builder() + .name("swing") + .description("Swings your hand.") .defaultValue(false) .build() ); - private final Setting disco = sgActions.add(new BoolSetting.Builder() - .name("disco") + private final Setting sneak = sgActions.add(new BoolSetting.Builder() + .name("sneak") .description("Sneaks and unsneaks quickly.") .defaultValue(false) .build() ); + private final Setting sneakTime = sgActions.add(new IntSetting.Builder() + .name("sneak-time") + .description("How many ticks to stay sneaked.") + .defaultValue(5) + .min(1) + .sliderMin(1) + .visible(sneak::get) + .build() + ); + private final Setting strafe = sgActions.add(new BoolSetting.Builder() .name("strafe") - .description("Strafe right and left") + .description("Strafe right and left.") .defaultValue(false) .onChanged(aBoolean -> { strafeTimer = 0; @@ -109,6 +70,40 @@ public enum SpinMode { .build() ); + private final Setting spin = sgActions.add(new BoolSetting.Builder() + .name("spin") + .description("Spins the player in place.") + .defaultValue(true) + .build() + ); + + private final Setting spinMode = sgActions.add(new EnumSetting.Builder() + .name("spin-mode") + .description("The method of rotating.") + .defaultValue(SpinMode.Server) + .visible(spin::get) + .build() + ); + + private final Setting spinSpeed = sgActions.add(new IntSetting.Builder() + .name("speed") + .description("The speed to spin you.") + .defaultValue(7) + .visible(spin::get) + .build() + ); + + private final Setting pitch = sgActions.add(new IntSetting.Builder() + .name("pitch") + .description("The pitch to send to the server.") + .defaultValue(0) + .range(-90, 90) + .sliderRange(-90, 90) + .visible(() -> spin.get() && spinMode.get() == SpinMode.Server) + .build() + ); + + // Messages private final Setting sendMessages = sgMessages.add(new BoolSetting.Builder() @@ -118,40 +113,56 @@ public enum SpinMode { .build() ); + private final Setting randomMessage = sgMessages.add(new BoolSetting.Builder() + .name("random") + .description("Selects a random message from your message list.") + .defaultValue(false) + .visible(sendMessages::get) + .build() + ); + private final Setting delay = sgMessages.add(new IntSetting.Builder() .name("delay") .description("The delay between specified messages in seconds.") - .defaultValue(2) + .defaultValue(15) .min(0) - .sliderMax(20) + .sliderMax(30) + .visible(sendMessages::get) .build() ); - private final Setting randomMessage = sgMessages.add(new BoolSetting.Builder() - .name("random") - .description("Selects a random message from your message list.") - .defaultValue(false) + private final Setting> messages = sgMessages.add(new StringListSetting.Builder() + .name("messages") + .description("The messages to choose from.") + .defaultValue( + "Meteor on top!", + "Meteor on crack!" + ) + .visible(sendMessages::get) .build() ); - private final List messages = new ArrayList<>(); - private int timer; - private int messageI; - private int strafeTimer = 0; - private boolean direction = false; + public AntiAFK() { + super(Categories.Player, "anti-afk", "Performs different actions to prevent getting kicked while AFK."); + } private final Random random = new Random(); - + private int messageTimer = 0; + private int messageI = 0; + private int sneakTimer = 0; + private int strafeTimer = 0; + private boolean direction = false; private float prevYaw; - public AntiAFK() { - super(Categories.Player, "anti-afk", "Performs different actions to prevent getting kicked for AFK reasons."); - } - @Override public void onActivate() { + if (sendMessages.get() && messages.get().isEmpty()) { + warning("Message list is empty, disabling messages..."); + sendMessages.set(false); + } + prevYaw = mc.player.getYaw(); - timer = delay.get() * 20; + messageTimer = delay.get() * 20; } @Override @@ -164,127 +175,56 @@ public void onDeactivate() { @EventHandler private void onTick(TickEvent.Pre event) { - if (Utils.canUpdate()) { - //Spin - if (spin.get()) { - prevYaw += spinSpeed.get(); - switch (spinMode.get()) { - case Client -> mc.player.setYaw(prevYaw); - case Server -> Rotations.rotate(prevYaw, pitch.get(), -15, null); - } - } - - //Jump - if (jump.get() && mc.options.jumpKey.isPressed()) mc.options.jumpKey.setPressed(false); - if (jump.get() && mc.options.sneakKey.isPressed()) mc.options.sneakKey.setPressed(false); - else if (jump.get() && random.nextInt(99) + 1 == 50) mc.options.jumpKey.setPressed(true); - - //Click - if (click.get() && random.nextInt(99) + 1 == 45) { - mc.options.attackKey.setPressed(true); - Utils.leftClick(); - mc.options.attackKey.setPressed(false); - } + if (!Utils.canUpdate()) return; - //Disco - if (disco.get() && random.nextInt(24) + 1 == 15) mc.options.sneakKey.setPressed(true); - - //Spam - if (sendMessages.get() && !messages.isEmpty()) - if (timer <= 0) { - int i; - if (randomMessage.get()) { - i = Utils.random(0, messages.size()); - } else { - if (messageI >= messages.size()) messageI = 0; - i = messageI++; - } - - ChatUtils.sendPlayerMsg(messages.get(i)); - - timer = delay.get() * 20; - } else { - timer--; - } - - //Strafe - if (strafe.get() && strafeTimer == 20) { - mc.options.leftKey.setPressed(!direction); - mc.options.rightKey.setPressed(direction); - direction = !direction; - strafeTimer = 0; - } else - strafeTimer++; + // Jump + if (jump.get()) { + if (mc.options.jumpKey.isPressed()) mc.options.jumpKey.setPressed(false); + else if (random.nextInt(99) == 0) mc.options.jumpKey.setPressed(true); } - } - @Override - public WWidget getWidget(GuiTheme theme) { - messages.removeIf(String::isEmpty); + // Swing + if (swing.get() && random.nextInt(99) == 0) { + mc.player.swingHand(mc.player.getActiveHand()); + } - WTable table = theme.table(); - fillTable(theme, table); + // Sneak + if (sneak.get()) { + if (sneakTimer++ >= sneakTime.get()) { + mc.options.sneakKey.setPressed(false); + if (random.nextInt(99) == 0) sneakTimer = 0; // Sneak after ~5 seconds + } else mc.options.sneakKey.setPressed(true); + } - return table; - } + // Strafe + if (strafe.get() && strafeTimer-- <= 0) { + mc.options.leftKey.setPressed(!direction); + mc.options.rightKey.setPressed(direction); + direction = !direction; + strafeTimer = 20; + } - private void fillTable(GuiTheme theme, WTable table) { - table.add(theme.horizontalSeparator("Message List")).expandX(); - table.row(); + // Spin + if (spin.get()) { + prevYaw += spinSpeed.get(); + switch (spinMode.get()) { + case Client -> mc.player.setYaw(prevYaw); + case Server -> Rotations.rotate(prevYaw, pitch.get(), -15); + } + } // Messages - for (int i = 0; i < messages.size(); i++) { - int msgI = i; - String message = messages.get(i); - - WTextBox textBox = table.add(theme.textBox(message)).minWidth(100).expandX().widget(); - textBox.action = () -> messages.set(msgI, textBox.get()); - - WMinus delete = table.add(theme.minus()).widget(); - delete.action = () -> { - messages.remove(msgI); - - table.clear(); - fillTable(theme, table); - }; + if (sendMessages.get() && !messages.get().isEmpty() && messageTimer-- <= 0) { + if (randomMessage.get()) messageI = random.nextInt(messages.get().size()); + else if (++messageI >= messages.get().size()) messageI = 0; - table.row(); + ChatUtils.sendPlayerMsg(messages.get().get(messageI)); + messageTimer = delay.get() * 20; } - - // New Message - WPlus add = table.add(theme.plus()).expandCellX().right().widget(); - add.action = () -> { - messages.add(""); - - table.clear(); - fillTable(theme, table); - }; - } - - @Override - public NbtCompound toTag() { - NbtCompound tag = super.toTag(); - - messages.removeIf(String::isEmpty); - NbtList messagesTag = new NbtList(); - - for (String message : messages) messagesTag.add(NbtString.of(message)); - tag.put("messages", messagesTag); - - return tag; } - @Override - public Module fromTag(NbtCompound tag) { - messages.clear(); - - if (tag.contains("messages")) { - NbtList messagesTag = tag.getList("messages", 8); - for (NbtElement messageTag : messagesTag) messages.add(messageTag.asString()); - } else { - messages.add("This is an AntiAFK message. Meteor on Crack!"); - } - - return super.fromTag(tag); + public enum SpinMode { + Server, + Client } } diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/movement/Sprint.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/movement/Sprint.java index f5ada70e2e..f499316beb 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/movement/Sprint.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/movement/Sprint.java @@ -6,7 +6,7 @@ package meteordevelopment.meteorclient.systems.modules.movement; import meteordevelopment.meteorclient.events.world.TickEvent; -import meteordevelopment.meteorclient.settings.BoolSetting; +import meteordevelopment.meteorclient.settings.EnumSetting; import meteordevelopment.meteorclient.settings.Setting; import meteordevelopment.meteorclient.settings.SettingGroup; import meteordevelopment.meteorclient.systems.modules.Categories; @@ -16,13 +16,21 @@ public class Sprint extends Module { private final SettingGroup sgGeneral = settings.getDefaultGroup(); - private final Setting whenStationary = sgGeneral.add(new BoolSetting.Builder() - .name("when-stationary") - .description("Continues sprinting even if you do not move.") - .defaultValue(false) + public enum Mode { + Strict, + Rage + } + + private final Setting mode = sgGeneral.add(new EnumSetting.Builder() + .name("speed-mode") + .description("What mode of sprinting.") + .defaultValue(Mode.Strict) .build() ); + // Removed whenStationary as it was just Rage sprint + + public Sprint() { super(Categories.Movement, "sprint", "Automatically sprints."); } @@ -32,12 +40,20 @@ public void onDeactivate() { mc.player.setSprinting(false); } + private void sprint() { + if (mc.player.getHungerManager().getFoodLevel() <= 6) return; + mc.player.setSprinting(true); + } + @EventHandler private void onTick(TickEvent.Post event) { - if (mc.player.forwardSpeed > 0 && !whenStationary.get()) { - mc.player.setSprinting(true); - } else if (whenStationary.get()) { - mc.player.setSprinting(true); + switch (mode.get()) { + case Strict -> { + if (mc.player.forwardSpeed > 0) { + sprint(); + } + } + case Rage -> sprint(); + } } - } } diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/movement/elytrafly/ElytraFlightMode.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/movement/elytrafly/ElytraFlightMode.java index 76cede0162..36b3374e46 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/movement/elytrafly/ElytraFlightMode.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/movement/elytrafly/ElytraFlightMode.java @@ -60,9 +60,15 @@ public void onTick() { } } + public void onPreTick() { + } + public void onPacketSend(PacketEvent.Send event) { } + public void onPacketReceive(PacketEvent.Receive event) { + } + public void onPlayerMove() { } @@ -103,7 +109,7 @@ public void autoTakeoff() { public void handleAutopilot() { if (!mc.player.isFallFlying()) return; - if (elytraFly.autoPilot.get() && mc.player.getY() > elytraFly.autoPilotMinimumHeight.get()) { + if (elytraFly.autoPilot.get() && mc.player.getY() > elytraFly.autoPilotMinimumHeight.get() && elytraFly.flightMode.get() != ElytraFlightModes.Bounce) { mc.options.forwardKey.setPressed(true); lastForwardPressed = true; } diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/movement/elytrafly/ElytraFlightModes.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/movement/elytrafly/ElytraFlightModes.java index aa19531e21..46bece5e88 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/movement/elytrafly/ElytraFlightModes.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/movement/elytrafly/ElytraFlightModes.java @@ -8,5 +8,6 @@ public enum ElytraFlightModes { Vanilla, Packet, - Pitch40 + Pitch40, + Bounce } diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/movement/elytrafly/ElytraFly.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/movement/elytrafly/ElytraFly.java index 0264c12ddf..f4440a57a9 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/movement/elytrafly/ElytraFly.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/movement/elytrafly/ElytraFly.java @@ -16,8 +16,10 @@ import meteordevelopment.meteorclient.systems.modules.Modules; import meteordevelopment.meteorclient.systems.modules.movement.elytrafly.modes.Packet; import meteordevelopment.meteorclient.systems.modules.movement.elytrafly.modes.Pitch40; +import meteordevelopment.meteorclient.systems.modules.movement.elytrafly.modes.Bounce; import meteordevelopment.meteorclient.systems.modules.movement.elytrafly.modes.Vanilla; import meteordevelopment.meteorclient.systems.modules.player.ChestSwap; +import meteordevelopment.meteorclient.systems.modules.player.Rotation; import meteordevelopment.meteorclient.systems.modules.render.Freecam; import meteordevelopment.orbit.EventHandler; import net.minecraft.block.Block; @@ -53,7 +55,7 @@ public class ElytraFly extends Module { .name("auto-take-off") .description("Automatically takes off when you hold jump without needing to double jump.") .defaultValue(false) - .visible(() -> flightMode.get() != ElytraFlightModes.Pitch40) + .visible(() -> flightMode.get() != ElytraFlightModes.Pitch40 && flightMode.get() != ElytraFlightModes.Bounce) .build() ); @@ -62,7 +64,7 @@ public class ElytraFly extends Module { .description("Controls how fast will you go down naturally.") .defaultValue(0.01) .min(0) - .visible(() -> flightMode.get() != ElytraFlightModes.Pitch40) + .visible(() -> flightMode.get() != ElytraFlightModes.Pitch40 && flightMode.get() != ElytraFlightModes.Bounce) .build() ); @@ -71,7 +73,7 @@ public class ElytraFly extends Module { .description("How fast you go forward and backward.") .defaultValue(1) .min(0) - .visible(() -> flightMode.get() != ElytraFlightModes.Pitch40) + .visible(() -> flightMode.get() != ElytraFlightModes.Pitch40 && flightMode.get() != ElytraFlightModes.Bounce) .build() ); @@ -80,14 +82,14 @@ public class ElytraFly extends Module { .description("How fast you go up and down.") .defaultValue(1) .min(0) - .visible(() -> flightMode.get() != ElytraFlightModes.Pitch40) + .visible(() -> flightMode.get() != ElytraFlightModes.Pitch40 && flightMode.get() != ElytraFlightModes.Bounce) .build() ); public final Setting acceleration = sgGeneral.add(new BoolSetting.Builder() .name("acceleration") .defaultValue(false) - .visible(() -> flightMode.get() != ElytraFlightModes.Pitch40) + .visible(() -> flightMode.get() != ElytraFlightModes.Pitch40 && flightMode.get() != ElytraFlightModes.Bounce) .build() ); @@ -96,7 +98,7 @@ public class ElytraFly extends Module { .min(0.1) .max(5) .defaultValue(1) - .visible(() -> flightMode.get() != ElytraFlightModes.Pitch40 && acceleration.get()) + .visible(() -> flightMode.get() != ElytraFlightModes.Pitch40 && acceleration.get() && flightMode.get() != ElytraFlightModes.Bounce) .build() ); @@ -104,7 +106,7 @@ public class ElytraFly extends Module { .name("acceleration-start") .min(0.1) .defaultValue(0) - .visible(() -> flightMode.get() != ElytraFlightModes.Pitch40 && acceleration.get()) + .visible(() -> flightMode.get() != ElytraFlightModes.Pitch40 && acceleration.get() && flightMode.get() != ElytraFlightModes.Bounce) .build() ); @@ -112,6 +114,7 @@ public class ElytraFly extends Module { .name("stop-in-water") .description("Stops flying in water.") .defaultValue(true) + .visible(() -> flightMode.get() != ElytraFlightModes.Bounce) .build() ); @@ -126,6 +129,7 @@ public class ElytraFly extends Module { .name("auto-hover") .description("Automatically hover .3 blocks off ground when holding shift.") .defaultValue(false) + .visible(() -> flightMode.get() != ElytraFlightModes.Bounce) .build() ); @@ -133,6 +137,7 @@ public class ElytraFly extends Module { .name("no-crash") .description("Stops you from going into walls.") .defaultValue(false) + .visible(() -> flightMode.get() != ElytraFlightModes.Bounce) .build() ); @@ -142,7 +147,7 @@ public class ElytraFly extends Module { .defaultValue(5) .range(1, 15) .sliderMin(1) - .visible(noCrash::get) + .visible(() -> noCrash.get() && flightMode.get() != ElytraFlightModes.Bounce) .build() ); @@ -150,6 +155,7 @@ public class ElytraFly extends Module { .name("insta-drop") .description("Makes you drop out of flight instantly.") .defaultValue(false) + .visible(() -> flightMode.get() != ElytraFlightModes.Bounce) .build() ); @@ -158,7 +164,7 @@ public class ElytraFly extends Module { .description("The bottom height boundary for pitch40.") .defaultValue(80) .min(-128) - .sliderMax(260) + .sliderMax(360) .visible(() -> flightMode.get() == ElytraFlightModes.Pitch40) .build() ); @@ -168,7 +174,7 @@ public class ElytraFly extends Module { .description("The upper height boundary for pitch40.") .defaultValue(120) .min(-128) - .sliderMax(260) + .sliderMax(360) .visible(() -> flightMode.get() == ElytraFlightModes.Pitch40) .build() ); @@ -183,6 +189,68 @@ public class ElytraFly extends Module { .build() ); + public final Setting autoJump = sgGeneral.add(new BoolSetting.Builder() + .name("auto-jump") + .description("Automatically jumps for you.") + .defaultValue(true) + .visible(() -> flightMode.get() == ElytraFlightModes.Bounce) + .build() + ); + + public final Setting yawLockMode = sgGeneral.add(new EnumSetting.Builder() + .name("yaw-lock") + .description("Whether to enable yaw lock or not") + .defaultValue(Rotation.LockMode.Smart) + .visible(() -> flightMode.get() == ElytraFlightModes.Bounce) + .build() + ); + + public final Setting pitch = sgGeneral.add(new DoubleSetting.Builder() + .name("pitch") + .description("The pitch angle to look at when using the bounce mode.") + .defaultValue(85) + .range(0, 90) + .sliderRange(0, 90) + .visible(() -> flightMode.get() == ElytraFlightModes.Bounce) + .build() + ); + + public final Setting yaw = sgGeneral.add(new DoubleSetting.Builder() + .name("yaw") + .description("The yaw angle to look at when using simple rotation lock in bounce mode.") + .defaultValue(0) + .range(0, 360) + .sliderRange(0,360) + .visible(() -> flightMode.get() == ElytraFlightModes.Bounce && yawLockMode.get() == Rotation.LockMode.Simple) + .build() + ); + + public final Setting restart = sgGeneral.add(new BoolSetting.Builder() + .name("restart") + .description("Restarts flying with the elytra when rubberbanding.") + .defaultValue(true) + .visible(() -> flightMode.get() == ElytraFlightModes.Bounce) + .build() + ); + + public final Setting restartDelay = sgGeneral.add(new IntSetting.Builder() + .name("restart-delay") + .description("How many ticks to wait before restarting the elytra again after rubberbanding.") + .defaultValue(7) + .min(0) + .sliderRange(0, 20) + .visible(() -> flightMode.get() == ElytraFlightModes.Bounce && restart.get()) + .build() + ); + + public final Setting sprint = sgGeneral.add(new BoolSetting.Builder() + .name("sprint") + .description("Sprints all the time. If turned off, it will only sprint when the player is touching the ground.") + .defaultValue(true) + .visible(() -> flightMode.get() == ElytraFlightModes.Bounce) + .build() + ); + // Inventory public final Setting replace = sgInventory.add(new BoolSetting.Builder() @@ -232,7 +300,7 @@ public class ElytraFly extends Module { .name("auto-pilot") .description("Moves forward while elytra flying.") .defaultValue(false) - .visible(() -> flightMode.get() != ElytraFlightModes.Pitch40) + .visible(() -> flightMode.get() != ElytraFlightModes.Pitch40 && flightMode.get() != ElytraFlightModes.Bounce) .build() ); @@ -240,7 +308,7 @@ public class ElytraFly extends Module { .name("use-fireworks") .description("Uses firework rockets every second of your choice.") .defaultValue(false) - .visible(autoPilot::get) + .visible(() -> autoPilot.get() && flightMode.get() != ElytraFlightModes.Pitch40 && flightMode.get() != ElytraFlightModes.Bounce) .build() ); @@ -250,7 +318,7 @@ public class ElytraFly extends Module { .min(1) .defaultValue(8) .sliderMax(20) - .visible(useFireworks::get) + .visible(() -> useFireworks.get() && flightMode.get() != ElytraFlightModes.Pitch40 && flightMode.get() != ElytraFlightModes.Bounce) .build() ); @@ -260,7 +328,7 @@ public class ElytraFly extends Module { .defaultValue(120) .min(-128) .sliderMax(260) - .visible(autoPilot::get) + .visible(() -> autoPilot.get() && flightMode.get() != ElytraFlightModes.Pitch40 && flightMode.get() != ElytraFlightModes.Bounce) .build() ); @@ -274,7 +342,7 @@ public ElytraFly() { public void onActivate() { currentMode.onActivate(); if ((chestSwap.get() == ChestSwapMode.Always || chestSwap.get() == ChestSwapMode.WaitForGround) - && mc.player.getEquippedStack(EquipmentSlot.CHEST).getItem() != Items.ELYTRA) { + && mc.player.getEquippedStack(EquipmentSlot.CHEST).getItem() != Items.ELYTRA) { Modules.get().get(ChestSwap.class).swap(); } } @@ -303,44 +371,47 @@ private void onPlayerMove(PlayerMoveEvent event) { currentMode.autoTakeoff(); if (mc.player.isFallFlying()) { - currentMode.velX = 0; - currentMode.velY = event.movement.y; - currentMode.velZ = 0; - currentMode.forward = Vec3d.fromPolar(0, mc.player.getYaw()).multiply(0.1); - currentMode.right = Vec3d.fromPolar(0, mc.player.getYaw() + 90).multiply(0.1); - - // Handle stopInWater - if (mc.player.isTouchingWater() && stopInWater.get()) { - mc.getNetworkHandler().sendPacket(new ClientCommandC2SPacket(mc.player, ClientCommandC2SPacket.Mode.START_FALL_FLYING)); - return; - } - currentMode.handleFallMultiplier(); - currentMode.handleAutopilot(); + if (flightMode.get() != ElytraFlightModes.Bounce) { + currentMode.velX = 0; + currentMode.velY = event.movement.y; + currentMode.velZ = 0; + currentMode.forward = Vec3d.fromPolar(0, mc.player.getYaw()).multiply(0.1); + currentMode.right = Vec3d.fromPolar(0, mc.player.getYaw() + 90).multiply(0.1); + + // Handle stopInWater + if (mc.player.isTouchingWater() && stopInWater.get()) { + mc.getNetworkHandler().sendPacket(new ClientCommandC2SPacket(mc.player, ClientCommandC2SPacket.Mode.START_FALL_FLYING)); + return; + } - currentMode.handleAcceleration(); - currentMode.handleHorizontalSpeed(event); - currentMode.handleVerticalSpeed(event); + currentMode.handleFallMultiplier(); + currentMode.handleAutopilot(); + + currentMode.handleAcceleration(); + currentMode.handleHorizontalSpeed(event); + currentMode.handleVerticalSpeed(event); + } int chunkX = (int) ((mc.player.getX() + currentMode.velX) / 16); int chunkZ = (int) ((mc.player.getZ() + currentMode.velZ) / 16); if (dontGoIntoUnloadedChunks.get()) { if (mc.world.getChunkManager().isChunkLoaded(chunkX, chunkZ)) { - ((IVec3d) event.movement).set(currentMode.velX, currentMode.velY, currentMode.velZ); + if (flightMode.get() != ElytraFlightModes.Bounce) ((IVec3d) event.movement).set(currentMode.velX, currentMode.velY, currentMode.velZ); } else { ((IVec3d) event.movement).set(0, currentMode.velY, 0); } - } else ((IVec3d) event.movement).set(currentMode.velX, currentMode.velY, currentMode.velZ); + } else if (flightMode.get() != ElytraFlightModes.Bounce) ((IVec3d) event.movement).set(currentMode.velX, currentMode.velY, currentMode.velZ); - currentMode.onPlayerMove(); + if (flightMode.get() != ElytraFlightModes.Bounce) currentMode.onPlayerMove(); } else { - if (currentMode.lastForwardPressed) { + if (currentMode.lastForwardPressed && flightMode.get() != ElytraFlightModes.Bounce) { mc.options.forwardKey.setPressed(false); currentMode.lastForwardPressed = false; } } - if (noCrash.get() && mc.player.isFallFlying()) { + if (noCrash.get() && mc.player.isFallFlying() && flightMode.get() != ElytraFlightModes.Bounce) { Vec3d lookAheadPos = mc.player.getPos().add(mc.player.getVelocity().normalize().multiply(crashLookAhead.get())); RaycastContext raycastContext = new RaycastContext(mc.player.getPos(), new Vec3d(lookAheadPos.getX(), mc.player.getY(), lookAheadPos.getZ()), RaycastContext.ShapeType.COLLIDER, RaycastContext.FluidHandling.NONE, mc.player); BlockHitResult hitResult = mc.world.raycast(raycastContext); @@ -349,7 +420,7 @@ private void onPlayerMove(PlayerMoveEvent event) { } } - if (autoHover.get() && mc.player.input.sneaking && !Modules.get().get(Freecam.class).isActive() && mc.player.isFallFlying()) { + if (autoHover.get() && mc.player.input.sneaking && !Modules.get().get(Freecam.class).isActive() && mc.player.isFallFlying() && flightMode.get() != ElytraFlightModes.Bounce) { BlockState underState = mc.world.getBlockState(mc.player.getBlockPos().down()); Block under = underState.getBlock(); BlockState under2State = mc.world.getBlockState(mc.player.getBlockPos().down().down()); @@ -387,11 +458,21 @@ private void onTick(TickEvent.Post event) { currentMode.onTick(); } + @EventHandler + private void onPreTick(TickEvent.Pre event) { + currentMode.onPreTick(); + } + @EventHandler private void onPacketSend(PacketEvent.Send event) { currentMode.onPacketSend(event); } + @EventHandler + private void onPacketReceive(PacketEvent.Receive event) { + currentMode.onPacketReceive(event); + } + private void onModeChanged(ElytraFlightModes mode) { switch (mode) { case Vanilla -> currentMode = new Vanilla(); @@ -400,6 +481,7 @@ private void onModeChanged(ElytraFlightModes mode) { currentMode = new Pitch40(); autoPilot.set(false); // Pitch 40 is an autopilot of its own } + case Bounce -> currentMode = new Bounce(); } } diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/movement/elytrafly/modes/Bounce.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/movement/elytrafly/modes/Bounce.java new file mode 100644 index 0000000000..deceb1f5a5 --- /dev/null +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/movement/elytrafly/modes/Bounce.java @@ -0,0 +1,149 @@ +/* + * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client). + * Copyright (c) Meteor Development. + */ + +/* + * Credit to Luna (https://github.com/InLieuOfLuna) for making the original Elytra Recast mod (https://github.com/InLieuOfLuna/elytra-recast)! + */ + +package meteordevelopment.meteorclient.systems.modules.movement.elytrafly.modes; + +import meteordevelopment.meteorclient.events.packets.PacketEvent; +import meteordevelopment.meteorclient.systems.modules.movement.elytrafly.ElytraFlightMode; +import meteordevelopment.meteorclient.systems.modules.movement.elytrafly.ElytraFlightModes; +import meteordevelopment.meteorclient.systems.modules.player.Rotation; +import meteordevelopment.meteorclient.utils.misc.input.Input; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.entity.effect.StatusEffects; +import net.minecraft.item.ElytraItem; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.network.packet.c2s.play.ClientCommandC2SPacket; +import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket; + +public class Bounce extends ElytraFlightMode { + + public Bounce() { + super(ElytraFlightModes.Bounce); + } + + boolean rubberbanded = false; + + int tickDelay = elytraFly.restartDelay.get(); + double prevFov; + + @Override + public void onTick() { + super.onTick(); + + if (mc.options.jumpKey.isPressed() && !mc.player.isFallFlying()) mc.getNetworkHandler().sendPacket(new ClientCommandC2SPacket(mc.player, ClientCommandC2SPacket.Mode.START_FALL_FLYING)); + + // Make sure all the conditions are met (player has an elytra, isn't in water, etc) + if (checkConditions(mc.player)) { + + if (!rubberbanded) { + if (prevFov != 0 && !elytraFly.sprint.get()) mc.options.getFovEffectScale().setValue(0.0); // This stops the FOV effects from constantly going on and off. + if (elytraFly.autoJump.get()) setPressed(mc.options.jumpKey, true); + setPressed(mc.options.forwardKey, true); + mc.player.setYaw(getYawDirection()); + mc.player.setPitch(elytraFly.pitch.get().floatValue()); + } + + if (!elytraFly.sprint.get()) { + // Sprinting all the time (when not on ground) makes it rubberband on certain anticheats. + if (mc.player.isFallFlying()) mc.player.setSprinting(mc.player.isOnGround()); + else mc.player.setSprinting(true); + } + + // Rubberbanding + if (rubberbanded && elytraFly.restart.get()) { + if (tickDelay > 0) { + tickDelay--; + } else { + mc.getNetworkHandler().sendPacket(new ClientCommandC2SPacket(mc.player, ClientCommandC2SPacket.Mode.START_FALL_FLYING)); + rubberbanded = false; + tickDelay = elytraFly.restartDelay.get(); + } + } + } + } + + @Override + public void onPreTick() { + super.onPreTick(); + + if (checkConditions(mc.player) && elytraFly.sprint.get()) mc.player.setSprinting(true); + } + + private void unpress() { + setPressed(mc.options.forwardKey, false); + if (elytraFly.autoJump.get()) setPressed(mc.options.jumpKey, false); + } + + @Override + public void onPacketReceive(PacketEvent.Receive event) { + if (event.packet instanceof PlayerPositionLookS2CPacket) { + rubberbanded = true; + mc.player.stopFallFlying(); + } + } + + @Override + public void onPacketSend(PacketEvent.Send event) { + if (event.packet instanceof ClientCommandC2SPacket && ((ClientCommandC2SPacket) event.packet).getMode().equals(ClientCommandC2SPacket.Mode.START_FALL_FLYING) && !elytraFly.sprint.get()) { + mc.player.setSprinting(true); + } + } + + + private void setPressed(KeyBinding key, boolean pressed) { + key.setPressed(pressed); + Input.setKeyState(key, pressed); + } + + public static boolean recastElytra(ClientPlayerEntity player) { + if (checkConditions(player) && ignoreGround(player)) { + player.networkHandler.sendPacket(new ClientCommandC2SPacket(player, ClientCommandC2SPacket.Mode.START_FALL_FLYING)); + return true; + } else return false; + } + + public static boolean checkConditions(ClientPlayerEntity player) { + ItemStack itemStack = player.getEquippedStack(EquipmentSlot.CHEST); + return (!player.getAbilities().flying && !player.hasVehicle() && !player.isClimbing() && itemStack.isOf(Items.ELYTRA) && ElytraItem.isUsable(itemStack)); + } + + private static boolean ignoreGround(ClientPlayerEntity player) { + if (!player.isTouchingWater() && !player.hasStatusEffect(StatusEffects.LEVITATION)) { + ItemStack itemStack = player.getEquippedStack(EquipmentSlot.CHEST); + if (itemStack.isOf(Items.ELYTRA) && ElytraItem.isUsable(itemStack)) { + player.startFallFlying(); + return true; + } else return false; + } else return false; + } + + private float getYawDirection() { + return switch (elytraFly.yawLockMode.get()) { + case None -> mc.player.getYaw(); + case Smart -> Math.round((mc.player.getYaw() + 1f) / 45f) * 45f; + case Simple -> elytraFly.yaw.get().floatValue(); + }; + + } + + @Override + public void onActivate() { + prevFov = mc.options.getFovEffectScale().getValue(); + } + + @Override + public void onDeactivate() { + unpress(); + rubberbanded = false; + if (prevFov != 0 && !elytraFly.sprint.get()) mc.options.getFovEffectScale().setValue(prevFov); + } +} diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/player/AutoEat.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/player/AutoEat.java index 57725b8cd8..2ed7a92a6c 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/player/AutoEat.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/player/AutoEat.java @@ -26,12 +26,13 @@ import java.util.ArrayList; import java.util.List; +import java.util.function.BiPredicate; public class AutoEat extends Module { private static final Class[] AURAS = new Class[] { KillAura.class, CrystalAura.class, AnchorAura.class, BedAura.class }; private final SettingGroup sgGeneral = settings.getDefaultGroup(); - private final SettingGroup sgHunger = settings.createGroup("Hunger"); + private final SettingGroup sgThreshold = settings.createGroup("Threshold"); // General @@ -67,14 +68,32 @@ public class AutoEat extends Module { .build() ); - // Hunger + // Threshold - private final Setting hungerThreshold = sgHunger.add(new IntSetting.Builder() + private final Setting thresholdMode = sgThreshold.add(new EnumSetting.Builder() + .name("threshold-mode") + .description("The threshold mode to trigger auto eat.") + .defaultValue(ThresholdMode.Any) + .build() + ); + + private final Setting healthThreshold = sgThreshold.add(new DoubleSetting.Builder() + .name("health-threshold") + .description("The level of health you eat at.") + .defaultValue(10) + .range(1, 19) + .sliderRange(1, 19) + .visible(() -> thresholdMode.get() != ThresholdMode.Hunger) + .build() + ); + + private final Setting hungerThreshold = sgThreshold.add(new IntSetting.Builder() .name("hunger-threshold") .description("The level of hunger you eat at.") .defaultValue(16) .range(1, 19) .sliderRange(1, 19) + .visible(() -> thresholdMode.get() != ThresholdMode.Health) .build() ); @@ -207,8 +226,11 @@ private void changeSlot(int slot) { this.slot = slot; } - private boolean shouldEat() { - return mc.player.getHungerManager().getFoodLevel() <= hungerThreshold.get(); + public boolean shouldEat() { + boolean health = mc.player.getHealth() <= healthThreshold.get(); + boolean hunger = mc.player.getHungerManager().getFoodLevel() <= hungerThreshold.get(); + + return thresholdMode.get().test(health, hunger); } private int findSlot() { @@ -237,4 +259,21 @@ private int findSlot() { return slot; } + + public enum ThresholdMode { + Health((health, hunger) -> health), + Hunger((health, hunger) -> hunger), + Any((health, hunger) -> health || hunger), + Both((health, hunger) -> health && hunger); + + private final BiPredicate predicate; + + ThresholdMode(BiPredicate predicate) { + this.predicate = predicate; + } + + public boolean test(boolean health, boolean hunger) { + return predicate.test(health, hunger); + } + } } diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/player/AutoTool.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/player/AutoTool.java index b272b0b81a..6e0abfaad4 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/player/AutoTool.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/player/AutoTool.java @@ -12,15 +12,13 @@ import meteordevelopment.meteorclient.systems.modules.Categories; import meteordevelopment.meteorclient.systems.modules.Module; import meteordevelopment.meteorclient.systems.modules.Modules; +import meteordevelopment.meteorclient.systems.modules.render.Xray; import meteordevelopment.meteorclient.systems.modules.world.InfinityMiner; import meteordevelopment.meteorclient.utils.player.InvUtils; import meteordevelopment.meteorclient.utils.world.BlockUtils; import meteordevelopment.orbit.EventHandler; import meteordevelopment.orbit.EventPriority; -import net.minecraft.block.BambooBlock; -import net.minecraft.block.BambooSaplingBlock; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; +import net.minecraft.block.*; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.enchantment.Enchantments; import net.minecraft.item.*; @@ -48,6 +46,13 @@ public class AutoTool extends Module { .build() ); + private final Setting fortuneForOresCrops = sgGeneral.add(new BoolSetting.Builder() + .name("fortune-for-ores-and-crops") + .description("Mines Ores and crops only with the Fortune enchantment.") + .defaultValue(false) + .build() + ); + private final Setting antiBreak = sgGeneral.add(new BoolSetting.Builder() .name("anti-break") .description("Stops you from breaking your tool.") @@ -153,7 +158,7 @@ private void onStartBreakingBlock(StartBreakingBlockEvent event) { if (listMode.get() == ListMode.Whitelist && !whitelist.get().contains(itemStack.getItem())) continue; if (listMode.get() == ListMode.Blacklist && blacklist.get().contains(itemStack.getItem())) continue; - double score = getScore(itemStack, blockState, silkTouchForEnderChest.get(), prefer.get(), itemStack2 -> !shouldStopUsing(itemStack2)); + double score = getScore(itemStack, blockState, silkTouchForEnderChest.get(), fortuneForOresCrops.get(), prefer.get(), itemStack2 -> !shouldStopUsing(itemStack2)); if (score < 0) continue; if (score > bestScore) { @@ -162,7 +167,7 @@ private void onStartBreakingBlock(StartBreakingBlockEvent event) { } } - if (bestSlot != -1 && bestScore > getScore(currentStack, blockState, silkTouchForEnderChest.get(), prefer.get(), itemStack -> !shouldStopUsing(itemStack)) || shouldStopUsing(currentStack)) { + if ((bestSlot != -1 && (bestScore > getScore(currentStack, blockState, silkTouchForEnderChest.get(), fortuneForOresCrops.get(), prefer.get(), itemStack -> !shouldStopUsing(itemStack))) || shouldStopUsing(currentStack) || !isTool(currentStack))) { ticks = switchDelay.get(); if (ticks == 0) InvUtils.swap(bestSlot, true); @@ -182,7 +187,7 @@ private boolean shouldStopUsing(ItemStack itemStack) { return antiBreak.get() && (itemStack.getMaxDamage() - itemStack.getDamage()) < (itemStack.getMaxDamage() * breakDurability.get() / 100); } - public static double getScore(ItemStack itemStack, BlockState state, boolean silkTouchEnderChest, EnchantPreference enchantPreference, Predicate good) { + public static double getScore(ItemStack itemStack, BlockState state, boolean silkTouchEnderChest, boolean fortuneOre, EnchantPreference enchantPreference, Predicate good) { if (!good.test(itemStack) || !isTool(itemStack)) return -1; if (!itemStack.isSuitableFor(state) && !(itemStack.getItem() instanceof SwordItem && (state.getBlock() instanceof BambooBlock || state.getBlock() instanceof BambooSaplingBlock))) return -1; @@ -192,6 +197,12 @@ public static double getScore(ItemStack itemStack, BlockState state, boolean sil return -1; } + if (fortuneOre + && isFortunable(state.getBlock()) + && EnchantmentHelper.getLevel(Enchantments.FORTUNE, itemStack) == 0) { + return -1; + } + double score = 0; score += itemStack.getMiningSpeedMultiplier(state) * 1000; @@ -216,6 +227,11 @@ public static boolean isTool(ItemStack itemStack) { return isTool(itemStack.getItem()); } + private static boolean isFortunable(Block block) { + if (block == Blocks.ANCIENT_DEBRIS) return false; + return Xray.ORES.contains(block) || block instanceof CropBlock; + } + public enum EnchantPreference { None, Fortune, diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/player/FastUse.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/player/FastUse.java index b394c4fa40..c0715d585c 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/player/FastUse.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/player/FastUse.java @@ -5,12 +5,9 @@ package meteordevelopment.meteorclient.systems.modules.player; -import meteordevelopment.meteorclient.events.world.TickEvent; -import meteordevelopment.meteorclient.mixin.MinecraftClientAccessor; import meteordevelopment.meteorclient.settings.*; import meteordevelopment.meteorclient.systems.modules.Categories; import meteordevelopment.meteorclient.systems.modules.Module; -import meteordevelopment.orbit.EventHandler; import net.minecraft.item.BlockItem; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -60,15 +57,11 @@ public FastUse() { super(Categories.Player, "fast-use", "Allows you to use items at very high speeds.", "place"); } - @EventHandler - private void onTick(TickEvent.Post event) { - int cooldownTicks = Math.min(((MinecraftClientAccessor) mc).getItemUseCooldown(), cooldown.get()); - if (mode.get() == Mode.All || shouldWorkSome()) ((MinecraftClientAccessor) mc).setItemUseCooldown(cooldownTicks); - } - - private boolean shouldWorkSome() { - if (shouldWorkSome(mc.player.getMainHandStack())) return true; - return shouldWorkSome(mc.player.getOffHandStack()); + public int getItemUseCooldown(ItemStack itemStack) { + if (mode.get() == Mode.All || shouldWorkSome(itemStack)) { + return cooldown.get(); + } + return 4; //default cooldown } private boolean shouldWorkSome(ItemStack itemStack) { diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/player/MiddleClickExtra.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/player/MiddleClickExtra.java index 8e518b2323..0af7d1116e 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/player/MiddleClickExtra.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/player/MiddleClickExtra.java @@ -8,20 +8,26 @@ import meteordevelopment.meteorclient.events.entity.player.FinishUsingItemEvent; import meteordevelopment.meteorclient.events.entity.player.StoppedUsingItemEvent; import meteordevelopment.meteorclient.events.meteor.MouseButtonEvent; +import meteordevelopment.meteorclient.events.packets.PacketEvent; import meteordevelopment.meteorclient.events.world.TickEvent; import meteordevelopment.meteorclient.settings.BoolSetting; import meteordevelopment.meteorclient.settings.EnumSetting; import meteordevelopment.meteorclient.settings.Setting; import meteordevelopment.meteorclient.settings.SettingGroup; +import meteordevelopment.meteorclient.systems.friends.Friend; +import meteordevelopment.meteorclient.systems.friends.Friends; import meteordevelopment.meteorclient.systems.modules.Categories; import meteordevelopment.meteorclient.systems.modules.Module; import meteordevelopment.meteorclient.utils.misc.input.KeyAction; +import meteordevelopment.meteorclient.utils.player.ChatUtils; import meteordevelopment.meteorclient.utils.player.FindItemResult; import meteordevelopment.meteorclient.utils.player.InvUtils; import meteordevelopment.orbit.EventHandler; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.BowItem; import net.minecraft.item.Item; import net.minecraft.item.Items; +import net.minecraft.network.packet.c2s.play.UpdateSelectedSlotC2SPacket; import net.minecraft.util.Hand; import static org.lwjgl.glfw.GLFW.GLFW_MOUSE_BUTTON_MIDDLE; @@ -36,105 +42,162 @@ public class MiddleClickExtra extends Module { .build() ); + private final Setting message = sgGeneral.add(new BoolSetting.Builder() + .name("message") + .description("Sends a message to the player when you add them as a friend.") + .defaultValue(false) + .visible(() -> mode.get() == Mode.AddFriend) + .build() + ); + + private final Setting quickSwap = sgGeneral.add(new BoolSetting.Builder() + .name("quick-swap") + .description("Allows you to use items in your inventory by simulating hotbar key presses. May get flagged by anticheats.") + .defaultValue(false) + .visible(() -> mode.get() != Mode.AddFriend) + .build() + ); + + private final Setting swapBack = sgGeneral.add(new BoolSetting.Builder() + .name("swap-back") + .description("Swap back to your original slot when you finish using an item.") + .defaultValue(false) + .visible(() -> mode.get() != Mode.AddFriend && !quickSwap.get()) + .build() + ); + private final Setting notify = sgGeneral.add(new BoolSetting.Builder() .name("notify") .description("Notifies you when you do not have the specified item in your hotbar.") .defaultValue(true) + .visible(() -> mode.get() != Mode.AddFriend) .build() ); - private boolean isUsing; - public MiddleClickExtra() { - super(Categories.Player, "middle-click-extra", "Lets you use items when you middle click."); + super(Categories.Player, "middle-click-extra", "Perform various actions when you middle click."); } + private boolean isUsing; + private boolean wasHeld; + private int itemSlot; + private int selectedSlot; + @Override public void onDeactivate() { - stopIfUsing(); + stopIfUsing(false); } @EventHandler private void onMouseButton(MouseButtonEvent event) { if (event.action != KeyAction.Press || event.button != GLFW_MOUSE_BUTTON_MIDDLE || mc.currentScreen != null) return; - FindItemResult result = InvUtils.findInHotbar(mode.get().item); + if (mode.get() == Mode.AddFriend) { + if (mc.targetedEntity == null) return; + if (!(mc.targetedEntity instanceof PlayerEntity player)) return; + + if (!Friends.get().isFriend(player)) { + Friends.get().add(new Friend(player)); + info("Added %s to friends", player.getEntityName()); + if (message.get()) ChatUtils.sendPlayerMsg("/msg " + player.getEntityName() + " I just friended you on Meteor."); + } else { + Friends.get().remove(Friends.get().get(player)); + info("Removed %s from friends", player.getEntityName()); + } + + return; + } - if (!result.found()) { + FindItemResult result = InvUtils.find(mode.get().item); + if (!result.found() || !result.isHotbar() && !quickSwap.get()) { if (notify.get()) warning("Unable to find specified item."); return; } - InvUtils.swap(result.slot(), true); + selectedSlot = mc.player.getInventory().selectedSlot; + itemSlot = result.slot(); + wasHeld = result.isMainHand(); - switch (mode.get().type) { - case Immediate -> { - mc.interactionManager.interactItem(mc.player, Hand.MAIN_HAND); - InvUtils.swapBack(); - } - case LongerSingleClick -> mc.interactionManager.interactItem(mc.player, Hand.MAIN_HAND); - case Longer -> { - mc.options.useKey.setPressed(true); - isUsing = true; - } + if (!wasHeld) { + if (!quickSwap.get()) InvUtils.swap(result.slot(), swapBack.get()); + else InvUtils.quickSwap().fromId(selectedSlot).to(itemSlot); + } + + if (mode.get().immediate) { + mc.interactionManager.interactItem(mc.player, Hand.MAIN_HAND); + swapBack(false); + } else { + mc.options.useKey.setPressed(true); + isUsing = true; } } @EventHandler private void onTick(TickEvent.Pre event) { - if (isUsing) { - boolean pressed = true; + if (!isUsing) return; + boolean pressed = true; - if (mc.player.getMainHandStack().getItem() instanceof BowItem) { - pressed = BowItem.getPullProgress(mc.player.getItemUseTime()) < 1; - } - - mc.options.useKey.setPressed(pressed); + if (mc.player.getMainHandStack().getItem() instanceof BowItem) { + pressed = BowItem.getPullProgress(mc.player.getItemUseTime()) < 1; } + + mc.options.useKey.setPressed(pressed); } @EventHandler - private void onFinishUsingItem(FinishUsingItemEvent event) { - stopIfUsing(); + private void onPacketSendEvent(PacketEvent.Send event) { + if (event.packet instanceof UpdateSelectedSlotC2SPacket) { + stopIfUsing(true); + } } @EventHandler private void onStoppedUsingItem(StoppedUsingItemEvent event) { - stopIfUsing(); + stopIfUsing(false); } - private void stopIfUsing() { + @EventHandler + private void onFinishUsingItem(FinishUsingItemEvent event) { + stopIfUsing(false); + } + + private void stopIfUsing(boolean wasCancelled) { if (isUsing) { + swapBack(wasCancelled); mc.options.useKey.setPressed(false); - InvUtils.swapBack(); isUsing = false; } } + void swapBack(boolean wasCancelled) { + if (wasHeld) return; + + if (quickSwap.get()) { + InvUtils.quickSwap().fromId(selectedSlot).to(itemSlot); + } else { + if (!swapBack.get() || wasCancelled) return; + InvUtils.swapBack(); + } + } + public enum Mode { - Pearl(Items.ENDER_PEARL, Type.Immediate), - Rocket(Items.FIREWORK_ROCKET, Type.Immediate), + Pearl(Items.ENDER_PEARL, true), + XP(Items.EXPERIENCE_BOTTLE, true), + Rocket(Items.FIREWORK_ROCKET, true), - Rod(Items.FISHING_ROD, Type.LongerSingleClick), + Bow(Items.BOW, false), + Gap(Items.GOLDEN_APPLE, false), + EGap(Items.ENCHANTED_GOLDEN_APPLE, false), + Chorus(Items.CHORUS_FRUIT, false), - Bow(Items.BOW, Type.Longer), - Gap(Items.GOLDEN_APPLE, Type.Longer), - EGap(Items.ENCHANTED_GOLDEN_APPLE, Type.Longer), - Chorus(Items.CHORUS_FRUIT, Type.Longer), - XP(Items.EXPERIENCE_BOTTLE, Type.Immediate); + AddFriend(null, true); private final Item item; - private final Type type; + private final boolean immediate; - Mode(Item item, Type type) { + Mode(Item item, boolean immediate) { this.item = item; - this.type = type; + this.immediate = immediate; } } - - private enum Type { - Immediate, - LongerSingleClick, - Longer - } } diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/player/SpeedMine.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/player/SpeedMine.java index 1ce472f551..70af4e4e6a 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/player/SpeedMine.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/player/SpeedMine.java @@ -6,6 +6,7 @@ package meteordevelopment.meteorclient.systems.modules.player; import meteordevelopment.meteorclient.events.world.TickEvent; +import meteordevelopment.meteorclient.mixin.ClientPlayerInteractionManagerAccessor; import meteordevelopment.meteorclient.settings.*; import meteordevelopment.meteorclient.systems.modules.Categories; import meteordevelopment.meteorclient.systems.modules.Module; @@ -13,6 +14,7 @@ import meteordevelopment.orbit.EventHandler; import net.minecraft.block.Block; import net.minecraft.entity.effect.StatusEffectInstance; +import net.minecraft.util.math.BlockPos; import java.util.List; @@ -32,7 +34,7 @@ public class SpeedMine extends Module { .name("blocks") .description("Selected blocks.") .filter(block -> block.getHardness() > 0) - .visible(() -> mode.get() == Mode.Normal) + .visible(() -> mode.get() != Mode.Haste) .build() ); @@ -40,7 +42,7 @@ public class SpeedMine extends Module { .name("blocks-filter") .description("How to use the blocks setting.") .defaultValue(ListMode.Blacklist) - .visible(() -> mode.get() == Mode.Normal) + .visible(() -> mode.get() != Mode.Haste) .build() ); @@ -53,6 +55,24 @@ public class SpeedMine extends Module { .build() ); + private final Setting hasteAmplifier = sgGeneral.add(new IntSetting.Builder() + .name("haste-amplifier") + .description("What value of haste to give you. Above 2 not recommended.") + .defaultValue(2) + .min(1) + .visible(() -> mode.get() == Mode.Haste) + .onChanged(i -> removeHaste()) + .build() + ); + + private final Setting instamine = sgGeneral.add(new BoolSetting.Builder() + .name("instamine") + .description("Whether or not to instantly mine blocks under certain conditions.") + .defaultValue(true) + .visible(() -> mode.get() == Mode.Damage) + .build() + ); + public SpeedMine() { super(Categories.Player, "speed-mine", "Allows you to quickly mine blocks.", "fast", "break"); } @@ -65,14 +85,22 @@ public void onDeactivate() { @EventHandler private void onTick(TickEvent.Pre event) { if (!Utils.canUpdate()) return; - if (mode.get() == Mode.Normal) return; - - int amplifier = mode.get() == Mode.Haste2 ? 1 : 0; - StatusEffectInstance haste = mc.player.getStatusEffect(HASTE); + if (mode.get() == Mode.Haste) { + StatusEffectInstance haste = mc.player.getStatusEffect(HASTE); - if (haste == null || haste.getAmplifier() <= amplifier) { - mc.player.setStatusEffect(new StatusEffectInstance(HASTE, -1, amplifier, false, false, false), null); + if (haste == null || haste.getAmplifier() <= hasteAmplifier.get() - 1) { + mc.player.setStatusEffect(new StatusEffectInstance(HASTE, -1, hasteAmplifier.get() - 1, false, false, false), null); + } + } + else if (mode.get() == Mode.Damage) { + ClientPlayerInteractionManagerAccessor im = (ClientPlayerInteractionManagerAccessor) mc.interactionManager; + float progress = im.getBreakingProgress(); + BlockPos pos = im.getCurrentBreakingBlockPos(); + + if (pos == null || progress <= 0) return; + if (progress + mc.world.getBlockState(pos).calcBlockBreakingDelta(mc.player, mc.world, pos) >= 0.7f) + im.setCurrentBreakingProgress(1f); } } @@ -88,10 +116,14 @@ public boolean filter(Block block) { return blocksFilter.get() == ListMode.Whitelist && blocks.get().contains(block); } + public boolean instamine() { + return isActive() && mode.get() == Mode.Damage && instamine.get(); + } + public enum Mode { Normal, - Haste1, - Haste2 + Haste, + Damage } public enum ListMode { diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/HandView.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/HandView.java index 9aa25519a4..fd718dec4d 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/HandView.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/HandView.java @@ -32,6 +32,27 @@ public class HandView extends Module { .build() ); + public final Setting oldAnimations = sgGeneral.add(new BoolSetting.Builder() + .name("old-animations") + .description("Changes hit animations to those like 1.8") + .defaultValue(false) + .build() + ); + + public final Setting showSwapping = sgGeneral.add(new BoolSetting.Builder() + .name("show-swapping") + .description("Whether or not to show the item swapping animation") + .defaultValue(true) + .build() + ); + + private final Setting disableFoodAnimation = sgGeneral.add(new BoolSetting.Builder() + .name("disable-eating-animation") + .description("Disables the eating animation. Potentially desirable if it goes offscreen.") + .defaultValue(false) + .build() + ); + public final Setting swingMode = sgGeneral.add(new EnumSetting.Builder() .name("swing-mode") .description("Modifies your client & server hand swinging.") @@ -66,20 +87,6 @@ public class HandView extends Module { .build() ); - public final Setting oldAnimations = sgGeneral.add(new BoolSetting.Builder() - .name("old-animations") - .description("Changes hit animations to those like 1.8") - .defaultValue(false) - .build() - ); - - public final Setting showSwapping = sgGeneral.add(new BoolSetting.Builder() - .name("show-swapping") - .description("Whether or not to show the item swapping animation") - .defaultValue(true) - .build() - ); - // Main Hand private final Setting scaleMain = sgMainHand.add(new Vector3dSetting.Builder() @@ -109,7 +116,7 @@ public class HandView extends Module { .build() ); - // Off Hand + // Offhand private final Setting scaleOff = sgOffHand.add(new Vector3dSetting.Builder() .name("scale") @@ -220,6 +227,10 @@ public boolean showSwapping() { return isActive() && showSwapping.get(); } + public boolean disableFoodAnimation() { + return isActive() && disableFoodAnimation.get(); + } + public enum SwingMode { Offhand, Mainhand, diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/Xray.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/Xray.java index 4a83972073..2ab23b7150 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/Xray.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/Xray.java @@ -31,30 +31,12 @@ public class Xray extends Module { private final SettingGroup sgGeneral = settings.getDefaultGroup(); + public static final List ORES = List.of(Blocks.COAL_ORE, Blocks.DEEPSLATE_COAL_ORE, Blocks.IRON_ORE, Blocks.DEEPSLATE_IRON_ORE, Blocks.GOLD_ORE, Blocks.DEEPSLATE_GOLD_ORE, Blocks.LAPIS_ORE, Blocks.DEEPSLATE_LAPIS_ORE, Blocks.REDSTONE_ORE, Blocks.REDSTONE_ORE, Blocks.DIAMOND_ORE, Blocks.DEEPSLATE_DIAMOND_ORE, Blocks.EMERALD_ORE, Blocks.DEEPSLATE_EMERALD_ORE, Blocks.COPPER_ORE, Blocks.DEEPSLATE_COPPER_ORE, Blocks.NETHER_GOLD_ORE, Blocks.NETHER_QUARTZ_ORE, Blocks.ANCIENT_DEBRIS); + private final Setting> blocks = sgGeneral.add(new BlockListSetting.Builder() .name("whitelist") .description("Which blocks to show x-rayed.") - .defaultValue( - Blocks.COAL_ORE, - Blocks.DEEPSLATE_COAL_ORE, - Blocks.IRON_ORE, - Blocks.DEEPSLATE_IRON_ORE, - Blocks.GOLD_ORE, - Blocks.DEEPSLATE_GOLD_ORE, - Blocks.LAPIS_ORE, - Blocks.DEEPSLATE_LAPIS_ORE, - Blocks.REDSTONE_ORE, - Blocks.DEEPSLATE_REDSTONE_ORE, - Blocks.DIAMOND_ORE, - Blocks.DEEPSLATE_DIAMOND_ORE, - Blocks.EMERALD_ORE, - Blocks.DEEPSLATE_EMERALD_ORE, - Blocks.COPPER_ORE, - Blocks.DEEPSLATE_COPPER_ORE, - Blocks.NETHER_GOLD_ORE, - Blocks.NETHER_QUARTZ_ORE, - Blocks.ANCIENT_DEBRIS - ) + .defaultValue(ORES) .onChanged(v -> { if (isActive()) mc.worldRenderer.reload(); }) diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/blockesp/ESPChunk.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/blockesp/ESPChunk.java index cc39ce2a30..0fac693cf3 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/blockesp/ESPChunk.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/blockesp/ESPChunk.java @@ -21,7 +21,6 @@ import static meteordevelopment.meteorclient.utils.Utils.getRenderDistance; public class ESPChunk { - private static final BlockPos.Mutable blockPos = new BlockPos.Mutable(); private final int x, z; public Long2ObjectMap blocks; @@ -91,6 +90,8 @@ public static ESPChunk searchChunk(Chunk chunk, List blocks) { ESPChunk schunk = new ESPChunk(chunk.getPos().x, chunk.getPos().z); if (schunk.shouldBeDeleted()) return schunk; + BlockPos.Mutable blockPos = new BlockPos.Mutable(); + for (int x = chunk.getPos().getStartX(); x <= chunk.getPos().getEndX(); x++) { for (int z = chunk.getPos().getStartZ(); z <= chunk.getPos().getEndZ(); z++) { int height = chunk.getHeightmap(Heightmap.Type.WORLD_SURFACE).get(x - chunk.getPos().getStartX(), z - chunk.getPos().getStartZ()); diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoBrewer.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoBrewer.java index 2482423a1b..4384ee17ce 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoBrewer.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoBrewer.java @@ -159,7 +159,7 @@ private boolean insertWaterBottles(BrewingStandScreenHandler c) { private boolean takePotions(BrewingStandScreenHandler c) { for (int i = 0; i < 3; i++) { - InvUtils.quickMove().slotId(i); + InvUtils.shiftClick().slotId(i); if (!c.slots.get(i).getStack().isEmpty()) { error("You do not have a sufficient amount of inventory space... disabling."); diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoMount.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoMount.java index 1f2fb0a21f..74a40224ff 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoMount.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoMount.java @@ -9,26 +9,30 @@ import meteordevelopment.meteorclient.events.world.TickEvent; import meteordevelopment.meteorclient.settings.BoolSetting; +import meteordevelopment.meteorclient.settings.EntityTypeListSetting; import meteordevelopment.meteorclient.settings.Setting; import meteordevelopment.meteorclient.settings.SettingGroup; import meteordevelopment.meteorclient.systems.modules.Categories; import meteordevelopment.meteorclient.systems.modules.Module; +import meteordevelopment.meteorclient.utils.entity.EntityUtils; import meteordevelopment.meteorclient.utils.player.PlayerUtils; import meteordevelopment.meteorclient.utils.player.Rotations; import meteordevelopment.orbit.EventHandler; import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.Saddleable; import net.minecraft.entity.mob.SkeletonHorseEntity; -import net.minecraft.entity.passive.*; -import net.minecraft.entity.vehicle.BoatEntity; -import net.minecraft.entity.vehicle.MinecartEntity; +import net.minecraft.entity.mob.ZombieHorseEntity; +import net.minecraft.entity.passive.LlamaEntity; +import net.minecraft.entity.passive.PigEntity; +import net.minecraft.entity.passive.StriderEntity; import net.minecraft.item.SpawnEggItem; import net.minecraft.util.Hand; +import java.util.Set; + public class AutoMount extends Module { private final SettingGroup sgGeneral = settings.getDefaultGroup(); - private final SettingGroup sgMount = settings.createGroup("Mount"); - - // General private final Setting checkSaddle = sgGeneral.add(new BoolSetting.Builder() .name("check-saddle") @@ -44,61 +48,10 @@ public class AutoMount extends Module { .build() ); - // Mount - - private final Setting horses = sgMount.add(new BoolSetting.Builder() - .name("horse") - .description("Horse") - .defaultValue(false) - .build() - ); - - private final Setting donkeys = sgMount.add(new BoolSetting.Builder() - .name("donkey") - .description("Donkey") - .defaultValue(false) - .build() - ); - - private final Setting mules = sgMount.add(new BoolSetting.Builder() - .name("mule") - .description("Mule") - .defaultValue(false) - .build() - ); - - private final Setting skeletonHorse = sgMount.add(new BoolSetting.Builder() - .name("skeleton-horse") - .description("Skeleton Horse") - .defaultValue(false) - .build() - ); - - private final Setting llamas = sgMount.add(new BoolSetting.Builder() - .name("llama") - .description("Llama") - .defaultValue(false) - .build() - ); - - private final Setting pigs = sgMount.add(new BoolSetting.Builder() - .name("pig") - .description("Pig") - .defaultValue(false) - .build() - ); - - private final Setting boats = sgMount.add(new BoolSetting.Builder() - .name("boat") - .description("Boat") - .defaultValue(false) - .build() - ); - - private final Setting minecarts = sgMount.add(new BoolSetting.Builder() - .name("minecart") - .description("Minecart") - .defaultValue(false) + private final Setting>> entities = sgGeneral.add(new EntityTypeListSetting.Builder() + .name("entities") + .description("Rideable entities.") + .filter(EntityUtils::isRideable) .build() ); @@ -109,29 +62,16 @@ public AutoMount() { @EventHandler private void onTick(TickEvent.Pre event) { if (mc.player.hasVehicle()) return; + if (mc.player.isSneaking()) return; + if (mc.player.getMainHandStack().getItem() instanceof SpawnEggItem) return; - for (Entity entity : mc.world.getEntities()){ + for (Entity entity : mc.world.getEntities()) { + if (!entities.get().contains(entity.getType())) continue; if (!PlayerUtils.isWithin(entity, 4)) continue; - - if (mc.player.getMainHandStack().getItem() instanceof SpawnEggItem) return; - - if (donkeys.get() && entity instanceof DonkeyEntity && (!checkSaddle.get() || ((DonkeyEntity) entity).isSaddled())) { - interact(entity); - } else if (llamas.get() && entity instanceof LlamaEntity) { - interact(entity); - } else if (boats.get() && entity instanceof BoatEntity) { - interact(entity); - } else if (minecarts.get() && entity instanceof MinecartEntity) { - interact(entity); - } else if (horses.get() && entity instanceof HorseEntity && (!checkSaddle.get() || ((HorseEntity) entity).isSaddled())) { - interact(entity); - } else if (pigs.get() && entity instanceof PigEntity && ((PigEntity) entity).isSaddled()) { - interact(entity); - } else if (mules.get() && entity instanceof MuleEntity && (!checkSaddle.get() || ((MuleEntity) entity).isSaddled())) { - interact(entity); - } else if (skeletonHorse.get() && entity instanceof SkeletonHorseEntity && (!checkSaddle.get() || ((SkeletonHorseEntity) entity).isSaddled())) { - interact(entity); - } + if ((entity instanceof PigEntity || entity instanceof SkeletonHorseEntity || entity instanceof StriderEntity || entity instanceof ZombieHorseEntity) && !((Saddleable) entity).isSaddled()) continue; + if (!(entity instanceof LlamaEntity) && entity instanceof Saddleable saddleable && checkSaddle.get() && !saddleable.isSaddled()) continue; + interact(entity); + return; } } diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoSmelter.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoSmelter.java index 2b98278154..f74847aa5b 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoSmelter.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoSmelter.java @@ -138,7 +138,7 @@ private void takeResults(AbstractFurnaceScreenHandler c) { ItemStack resultStack = c.slots.get(2).getStack(); if (resultStack.isEmpty()) return; - InvUtils.quickMove().slotId(2); + InvUtils.shiftClick().slotId(2); if (!resultStack.isEmpty()) { error("Your inventory is full. Disabling."); diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/world/HighwayBuilder.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/world/HighwayBuilder.java index 1c8739104c..8908aac703 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/world/HighwayBuilder.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/world/HighwayBuilder.java @@ -864,7 +864,7 @@ protected int findAndMoveBestToolToHotbar(HighwayBuilder b, BlockState blockStat int bestSlot = -1; for (int i = 0; i < b.mc.player.getInventory().main.size(); i++) { - double score = AutoTool.getScore(b.mc.player.getInventory().getStack(i), blockState, false, AutoTool.EnchantPreference.None, itemStack -> { + double score = AutoTool.getScore(b.mc.player.getInventory().getStack(i), blockState, false, false, AutoTool.EnchantPreference.None, itemStack -> { if (noSilkTouch && EnchantmentHelper.getLevel(Enchantments.SILK_TOUCH, itemStack) != 0) return false; return !b.dontBreakTools.get() || itemStack.getMaxDamage() - itemStack.getDamage() > 1; }); diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/world/InfinityMiner.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/world/InfinityMiner.java index 4a133445ec..1d8eb64b1b 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/world/InfinityMiner.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/world/InfinityMiner.java @@ -188,7 +188,7 @@ private boolean findPickaxe() { && !Utils.hasEnchantments(stack, Enchantments.SILK_TOUCH)); FindItemResult bestPick = InvUtils.findInHotbar(pickaxePredicate); - if (bestPick.isOffhand()) InvUtils.quickMove().fromOffhand().toHotbar(mc.player.getInventory().selectedSlot); + if (bestPick.isOffhand()) InvUtils.shiftClick().fromOffhand().toHotbar(mc.player.getInventory().selectedSlot); else if (bestPick.isHotbar()) InvUtils.swap(bestPick.slot(), false); return InvUtils.testInMainHand(pickaxePredicate); @@ -233,7 +233,7 @@ private boolean isFull() { for (int i = 0; i <= 35; i++) { ItemStack itemStack = mc.player.getInventory().getStack(i); if (itemStack.isEmpty()) return false; - + for (Item item : targetItems.get()) { if (itemStack.getItem() == item && itemStack.getCount() < itemStack.getMaxCount()) { return false; diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/world/LiquidFiller.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/world/LiquidFiller.java index bbafad9bcd..da46f73021 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/world/LiquidFiller.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/world/LiquidFiller.java @@ -9,56 +9,91 @@ 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.player.FindItemResult; import meteordevelopment.meteorclient.utils.player.InvUtils; import meteordevelopment.meteorclient.utils.world.BlockIterator; import meteordevelopment.meteorclient.utils.world.BlockUtils; import meteordevelopment.orbit.EventHandler; import net.minecraft.block.Block; -import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; +import net.minecraft.fluid.Fluid; +import net.minecraft.fluid.Fluids; import net.minecraft.item.BlockItem; +import net.minecraft.util.math.BlockPos; +import java.util.ArrayList; +import java.util.Comparator; import java.util.List; public class LiquidFiller extends Module { private final SettingGroup sgGeneral = settings.getDefaultGroup(); + private final SettingGroup sgWhitelist = settings.createGroup("Whitelist"); private final Setting placeInLiquids = sgGeneral.add(new EnumSetting.Builder() .name("place-in") .description("What type of liquids to place in.") - .defaultValue(PlaceIn.Lava) + .defaultValue(PlaceIn.Both) .build() ); - private final Setting horizontalRadius = sgGeneral.add(new IntSetting.Builder() - .name("horizontal-radius") - .description("Horizontal radius in which to search for liquids.") - .defaultValue(4) - .min(0) - .sliderMax(6) + private final Setting shape = sgGeneral.add(new EnumSetting.Builder() + .name("shape") + .description("The shape of placing algorithm.") + .defaultValue(Shape.Sphere) .build() ); - private final Setting verticalRadius = sgGeneral.add(new IntSetting.Builder() - .name("vertical-radius") - .description("Vertical radius in which to search for liquids.") + private final Setting range = sgGeneral.add(new DoubleSetting.Builder() + .name("range") + .description("The place range.") .defaultValue(4) .min(0) - .sliderMax(6) .build() ); private final Setting delay = sgGeneral.add(new IntSetting.Builder() .name("delay") .description("Delay between actions in ticks.") - .defaultValue(1) + .defaultValue(0) .min(0) .build() ); - private final Setting> whitelist = sgGeneral.add(new BlockListSetting.Builder() - .name("block-whitelist") + private final Setting maxBlocksPerTick = sgGeneral.add(new IntSetting.Builder() + .name("max-blocks-per-tick") + .description("Maximum blocks to try to place per tick.") + .defaultValue(1) + .min(1) + .sliderRange(1, 10) + .build() + ); + + private final Setting sortMode = sgGeneral.add(new EnumSetting.Builder() + .name("sort-mode") + .description("The blocks you want to place first.") + .defaultValue(SortMode.Closest) + .build() + ); + + private final Setting rotate = sgGeneral.add(new BoolSetting.Builder() + .name("rotate") + .description("Automatically rotates towards the space targeted for filling.") + .defaultValue(true) + .build() + ); + + // Whitelist and blacklist + + private final Setting listMode = sgWhitelist.add(new EnumSetting.Builder() + .name("list-mode") + .description("Selection mode.") + .defaultValue(ListMode.Whitelist) + .build() + ); + + private final Setting> whitelist = sgWhitelist.add(new BlockListSetting.Builder() + .name("whitelist") .description("The allowed blocks that it will use to fill up the liquid.") .defaultValue( Blocks.DIRT, @@ -69,16 +104,19 @@ public class LiquidFiller extends Module { Blocks.GRANITE, Blocks.ANDESITE ) + .visible(() -> listMode.get() == ListMode.Whitelist) .build() ); - private final Setting rotate = sgGeneral.add(new BoolSetting.Builder() - .name("rotate") - .description("Automatically rotates towards the space targeted for filling.") - .defaultValue(true) + private final Setting> blacklist = sgWhitelist.add(new BlockListSetting.Builder() + .name("blacklist") + .description("The denied blocks that it not will use to fill up the liquid.") + .visible(() -> listMode.get() == ListMode.Blacklist) .build() ); + private final List blocks = new ArrayList<>(); + private int timer; public LiquidFiller(){ @@ -100,33 +138,93 @@ private void onTick(TickEvent.Pre event) { timer = 0; } + // Calculate some stuff + double pX = mc.player.getX(); + double pY = mc.player.getY(); + double pZ = mc.player.getZ(); + + double rangeSq = Math.pow(range.get(), 2); + + if (shape.get() == Shape.UniformCube) range.set((double) Math.round(range.get())); + // Find slot with a block - FindItemResult item = InvUtils.findInHotbar(itemStack -> itemStack.getItem() instanceof BlockItem && whitelist.get().contains(Block.getBlockFromItem(itemStack.getItem()))); + FindItemResult item; + if (listMode.get() == ListMode.Whitelist) { + item = InvUtils.findInHotbar(itemStack -> itemStack.getItem() instanceof BlockItem && whitelist.get().contains(Block.getBlockFromItem(itemStack.getItem()))); + } else { + item = InvUtils.findInHotbar(itemStack -> itemStack.getItem() instanceof BlockItem && !blacklist.get().contains(Block.getBlockFromItem(itemStack.getItem()))); + } if (!item.found()) return; // Loop blocks around the player - BlockIterator.register(horizontalRadius.get(), verticalRadius.get(), (blockPos, blockState) -> { - // Check if the block a source liquid block - if (isSource(blockState)) { - Block liquid = blockState.getBlock(); - - PlaceIn placeIn = placeInLiquids.get(); - if (placeIn == PlaceIn.Both || (placeIn == PlaceIn.Lava && liquid == Blocks.LAVA) || (placeIn == PlaceIn.Water && liquid == Blocks.WATER)) { - if (BlockUtils.place(blockPos, item, rotate.get(), 0, true)) { - BlockIterator.disableCurrent(); - } - } + BlockIterator.register((int) Math.ceil(range.get()+1), (int) Math.ceil(range.get()), (blockPos, blockState) -> { + boolean toofarSphere = Utils.squaredDistance(pX, pY, pZ, blockPos.getX() + 0.5, blockPos.getY() + 0.5, blockPos.getZ() + 0.5) > rangeSq; + boolean toofarUniformCube = maxDist(Math.floor(pX), Math.floor(pY), Math.floor(pZ), blockPos.getX(), blockPos.getY(), blockPos.getZ()) >= range.get(); + + // Check distance + if ((toofarSphere && shape.get() == Shape.Sphere) || (toofarUniformCube && shape.get() == Shape.UniformCube)) return; + + // Check if the block is a source block and set to be filled + Fluid fluid = blockState.getFluidState().getFluid(); + if ((placeInLiquids.get() == PlaceIn.Both && (fluid != Fluids.WATER && fluid != Fluids.LAVA)) + || (placeInLiquids.get() == PlaceIn.Water && fluid != Fluids.WATER) + || (placeInLiquids.get() == PlaceIn.Lava && fluid != Fluids.LAVA)) + return; + + // Check if the player can place at pos + if (!BlockUtils.canPlace(blockPos)) return; + + // Add block + blocks.add(blockPos.mutableCopy()); + }); + + BlockIterator.after(() -> { + // Sort blocks + if (sortMode.get() == SortMode.TopDown || sortMode.get() == SortMode.BottomUp) + blocks.sort(Comparator.comparingDouble(value -> value.getY() * (sortMode.get() == SortMode.BottomUp ? 1 : -1))); + else if (sortMode.get() != SortMode.None) + blocks.sort(Comparator.comparingDouble(value -> Utils.squaredDistance(pX, pY, pZ, value.getX() + 0.5, value.getY() + 0.5, value.getZ() + 0.5) * (sortMode.get() == SortMode.Closest ? 1 : -1))); + + // Place and clear place positions + int count = 0; + for (BlockPos pos : blocks) { + if (count >= maxBlocksPerTick.get()) break; + BlockUtils.place(pos, item, rotate.get(), 0, true); + count++; } + blocks.clear(); }); } - private boolean isSource(BlockState blockState) { - return blockState.getFluidState().getLevel() == 8 && blockState.getFluidState().isStill(); + public enum ListMode { + Whitelist, + Blacklist } public enum PlaceIn { - Lava, + Both, Water, - Both + Lava + } + + public enum SortMode { + None, + Closest, + Furthest, + TopDown, + BottomUp + } + + public enum Shape { + Sphere, + UniformCube + } + + private static double maxDist(double x1, double y1, double z1, double x2, double y2, double z2) { + // Gets the largest X, Y or Z difference, manhattan style + double dX = Math.ceil(Math.abs(x2 - x1)); + double dY = Math.ceil(Math.abs(y2 - y1)); + double dZ = Math.ceil(Math.abs(z2 - z1)); + return Math.max(Math.max(dX, dY), dZ); } } diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/world/Nuker.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/world/Nuker.java index ca691ea6cd..71dd4fd48e 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/world/Nuker.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/world/Nuker.java @@ -14,6 +14,7 @@ import meteordevelopment.meteorclient.systems.modules.Module; import meteordevelopment.meteorclient.utils.Utils; import meteordevelopment.meteorclient.utils.misc.Pool; +import meteordevelopment.meteorclient.utils.player.Rotations; import meteordevelopment.meteorclient.utils.render.RenderUtils; import meteordevelopment.meteorclient.utils.render.color.SettingColor; import meteordevelopment.meteorclient.utils.world.BlockIterator; @@ -25,7 +26,6 @@ import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; -import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import java.util.ArrayList; @@ -40,201 +40,208 @@ public class Nuker extends Module { // General private final Setting shape = sgGeneral.add(new EnumSetting.Builder() - .name("shape") - .description("The shape of nuking algorithm.") - .defaultValue(Shape.Sphere) - .build() + .name("shape") + .description("The shape of nuking algorithm.") + .defaultValue(Shape.Sphere) + .build() ); private final Setting mode = sgGeneral.add(new EnumSetting.Builder() - .name("mode") - .description("The way the blocks are broken.") - .defaultValue(Nuker.Mode.Flatten) - .build() + .name("mode") + .description("The way the blocks are broken.") + .defaultValue(Nuker.Mode.Flatten) + .build() ); private final Setting range = sgGeneral.add(new DoubleSetting.Builder() - .name("range") - .description("The break range.") - .defaultValue(4) - .min(0) - .visible(() -> shape.get() != Shape.Cube) - .build() + .name("range") + .description("The break range.") + .defaultValue(4) + .min(0) + .visible(() -> shape.get() != Shape.Cube) + .build() ); private final Setting range_up = sgGeneral.add(new IntSetting.Builder() - .name("up") - .description("The break range.") - .defaultValue(1) - .min(0) - .visible(() -> shape.get() == Shape.Cube) - .build() + .name("up") + .description("The break range.") + .defaultValue(1) + .min(0) + .visible(() -> shape.get() == Shape.Cube) + .build() ); private final Setting range_down = sgGeneral.add(new IntSetting.Builder() - .name("down") - .description("The break range.") - .defaultValue(1) - .min(0) - .visible(() -> shape.get() == Shape.Cube) - .build() + .name("down") + .description("The break range.") + .defaultValue(1) + .min(0) + .visible(() -> shape.get() == Shape.Cube) + .build() ); private final Setting range_left = sgGeneral.add(new IntSetting.Builder() - .name("left") - .description("The break range.") - .defaultValue(1) - .min(0) - .visible(() -> shape.get() == Shape.Cube) - .build() + .name("left") + .description("The break range.") + .defaultValue(1) + .min(0) + .visible(() -> shape.get() == Shape.Cube) + .build() ); private final Setting range_right = sgGeneral.add(new IntSetting.Builder() - .name("right") - .description("The break range.") - .defaultValue(1) - .min(0) - .visible(() -> shape.get() == Shape.Cube) - .build() + .name("right") + .description("The break range.") + .defaultValue(1) + .min(0) + .visible(() -> shape.get() == Shape.Cube) + .build() ); private final Setting range_forward = sgGeneral.add(new IntSetting.Builder() - .name("forward") - .description("The break range.") - .defaultValue(1) - .min(0) - .visible(() -> shape.get() == Shape.Cube) - .build() + .name("forward") + .description("The break range.") + .defaultValue(1) + .min(0) + .visible(() -> shape.get() == Shape.Cube) + .build() ); private final Setting range_back = sgGeneral.add(new IntSetting.Builder() - .name("back") - .description("The break range.") - .defaultValue(1) - .min(0) - .visible(() -> shape.get() == Shape.Cube) - .build() + .name("back") + .description("The break range.") + .defaultValue(1) + .min(0) + .visible(() -> shape.get() == Shape.Cube) + .build() ); private final Setting delay = sgGeneral.add(new IntSetting.Builder() - .name("delay") - .description("Delay in ticks between breaking blocks.") - .defaultValue(0) - .build() + .name("delay") + .description("Delay in ticks between breaking blocks.") + .defaultValue(0) + .build() ); private final Setting maxBlocksPerTick = sgGeneral.add(new IntSetting.Builder() - .name("max-blocks-per-tick") - .description("Maximum blocks to try to break per tick. Useful when insta mining.") - .defaultValue(1) - .min(1) - .sliderRange(1, 6) - .build() + .name("max-blocks-per-tick") + .description("Maximum blocks to try to break per tick. Useful when insta mining.") + .defaultValue(1) + .min(1) + .sliderRange(1, 6) + .build() ); private final Setting sortMode = sgGeneral.add(new EnumSetting.Builder() - .name("sort-mode") - .description("The blocks you want to mine first.") - .defaultValue(Nuker.SortMode.Closest) - .build() + .name("sort-mode") + .description("The blocks you want to mine first.") + .defaultValue(Nuker.SortMode.Closest) + .build() ); private final Setting swingHand = sgGeneral.add(new BoolSetting.Builder() - .name("swing-hand") - .description("Swing hand client side.") - .defaultValue(true) - .build() + .name("swing-hand") + .description("Swing hand client side.") + .defaultValue(true) + .build() ); private final Setting packetMine = sgGeneral.add(new BoolSetting.Builder() - .name("packet-mine") - .description("Attempt to instamine everything at once.") - .defaultValue(false) - .build() + .name("packet-mine") + .description("Attempt to instamine everything at once.") + .defaultValue(false) + .build() + ); + + private final Setting rotate = sgGeneral.add(new BoolSetting.Builder() + .name("rotate") + .description("Rotates server-side to the block being mined.") + .defaultValue(true) + .build() ); // Whitelist and blacklist private final Setting listMode = sgWhitelist.add(new EnumSetting.Builder() - .name("list-mode") - .description("Selection mode.") - .defaultValue(ListMode.Whitelist) - .build() + .name("list-mode") + .description("Selection mode.") + .defaultValue(ListMode.Whitelist) + .build() ); private final Setting> blacklist = sgWhitelist.add(new BlockListSetting.Builder() - .name("blacklist") - .description("The blocks you don't want to mine.") - .visible(() -> listMode.get() == ListMode.Blacklist) - .build() + .name("blacklist") + .description("The blocks you don't want to mine.") + .visible(() -> listMode.get() == ListMode.Blacklist) + .build() ); private final Setting> whitelist = sgWhitelist.add(new BlockListSetting.Builder() - .name("whitelist") - .description("The blocks you want to mine.") - .visible(() -> listMode.get() == ListMode.Whitelist) - .build() + .name("whitelist") + .description("The blocks you want to mine.") + .visible(() -> listMode.get() == ListMode.Whitelist) + .build() ); // Rendering private final Setting enableRenderBounding = sgRender.add(new BoolSetting.Builder() - .name("bounding-box") - .description("Enable rendering bounding box for Cube and Uniform Cube.") - .defaultValue(true) - .build() + .name("bounding-box") + .description("Enable rendering bounding box for Cube and Uniform Cube.") + .defaultValue(true) + .build() ); private final Setting shapeModeBox = sgRender.add(new EnumSetting.Builder() - .name("nuke-box-mode") - .description("How the shape for the bounding box is rendered.") - .defaultValue(ShapeMode.Both) - .build() + .name("nuke-box-mode") + .description("How the shape for the bounding box is rendered.") + .defaultValue(ShapeMode.Both) + .build() ); private final Setting sideColorBox = sgRender.add(new ColorSetting.Builder() - .name("side-color") - .description("The side color of the bounding box.") - .defaultValue(new SettingColor(16,106,144, 100)) - .build() + .name("side-color") + .description("The side color of the bounding box.") + .defaultValue(new SettingColor(16,106,144, 100)) + .build() ); private final Setting lineColorBox = sgRender.add(new ColorSetting.Builder() - .name("line-color") - .description("The line color of the bounding box.") - .defaultValue(new SettingColor(16,106,144, 255)) - .build() + .name("line-color") + .description("The line color of the bounding box.") + .defaultValue(new SettingColor(16,106,144, 255)) + .build() ); private final Setting enableRenderBreaking = sgRender.add(new BoolSetting.Builder() - .name("broken-blocks") - .description("Enable rendering bounding box for Cube and Uniform Cube.") - .defaultValue(true) - .build() + .name("broken-blocks") + .description("Enable rendering bounding box for Cube and Uniform Cube.") + .defaultValue(true) + .build() ); private final Setting shapeModeBreak = sgRender.add(new EnumSetting.Builder() - .name("nuke-block-mode") - .description("How the shapes for broken blocks are rendered.") - .defaultValue(ShapeMode.Both) - .visible(enableRenderBreaking::get) - .build() + .name("nuke-block-mode") + .description("How the shapes for broken blocks are rendered.") + .defaultValue(ShapeMode.Both) + .visible(enableRenderBreaking::get) + .build() ); private final Setting sideColor = sgRender.add(new ColorSetting.Builder() - .name("side-color") - .description("The side color of the target block rendering.") - .defaultValue(new SettingColor(255, 0, 0, 80)) - .visible(enableRenderBreaking::get) - .build() + .name("side-color") + .description("The side color of the target block rendering.") + .defaultValue(new SettingColor(255, 0, 0, 80)) + .visible(enableRenderBreaking::get) + .build() ); private final Setting lineColor = sgRender.add(new ColorSetting.Builder() - .name("line-color") - .description("The line color of the target block rendering.") - .defaultValue(new SettingColor(255, 0, 0, 255)) - .visible(enableRenderBreaking::get) - .build() + .name("line-color") + .description("The line color of the target block rendering.") + .defaultValue(new SettingColor(255, 0, 0, 255)) + .visible(enableRenderBreaking::get) + .build() ); private final Pool blockPosPool = new Pool<>(BlockPos.Mutable::new); @@ -344,9 +351,9 @@ private void onTickPre(TickEvent.Pre event) { boolean toofarCube = !box.contains(Vec3d.ofCenter(blockPos)); if (!BlockUtils.canBreak(blockPos, blockState) - || (toofarSphere && shape.get() == Shape.Sphere) - || (toofarUniformCube && shape.get() == Shape.UniformCube) - || (toofarCube && shape.get() == Shape.Cube)) + || (toofarSphere && shape.get() == Shape.Sphere) + || (toofarUniformCube && shape.get() == Shape.UniformCube) + || (toofarCube && shape.get() == Shape.Cube)) return; // Flatten @@ -366,7 +373,7 @@ private void onTickPre(TickEvent.Pre event) { // Break block if found BlockIterator.after(() -> { // Sort blocks - if (sortMode.get() == SortMode.TopDown) + if (sortMode.get() == SortMode.TopDown) blocks.sort(Comparator.comparingDouble(value -> -1*value.getY())); else if (sortMode.get() != SortMode.None) blocks.sort(Comparator.comparingDouble(value -> Utils.squaredDistance(pX, pY, pZ, value.getX() + 0.5, value.getY() + 0.5, value.getZ() + 0.5) * (sortMode.get() == SortMode.Closest ? 1 : -1))); @@ -399,13 +406,8 @@ else if (sortMode.get() != SortMode.None) boolean canInstaMine = BlockUtils.canInstaBreak(block); - if (packetMine.get()) { - mc.getNetworkHandler().sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.START_DESTROY_BLOCK, block, Direction.UP)); - mc.player.swingHand(Hand.MAIN_HAND); - mc.getNetworkHandler().sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK, block, Direction.UP)); - } else { - BlockUtils.breakBlock(block, swingHand.get()); - } + if (rotate.get()) Rotations.rotate(Rotations.getYaw(block), Rotations.getPitch(block), () -> breakBlock(block)); + else breakBlock(block); if (enableRenderBreaking.get()) RenderUtils.renderTickingBlock(block.toImmutable(), sideColor.get(), lineColor.get(), shapeModeBreak.get(), 0, 8, true, false); lastBlockPos.set(block); @@ -421,7 +423,17 @@ else if (sortMode.get() != SortMode.None) blocks.clear(); }); } - + + private void breakBlock(BlockPos blockPos) { + if (packetMine.get()) { + mc.getNetworkHandler().sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.START_DESTROY_BLOCK, blockPos, BlockUtils.getDirection(blockPos))); + mc.player.swingHand(Hand.MAIN_HAND); + mc.getNetworkHandler().sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK, blockPos, BlockUtils.getDirection(blockPos))); + } else { + BlockUtils.breakBlock(blockPos, swingHand.get()); + } + } + @EventHandler(priority = EventPriority.HIGHEST) private void onBlockBreakingCooldown(BlockBreakingCooldownEvent event) { event.cooldown = 0; diff --git a/src/main/java/meteordevelopment/meteorclient/utils/Utils.java b/src/main/java/meteordevelopment/meteorclient/utils/Utils.java index df8bfa0b4e..c8e84ac468 100644 --- a/src/main/java/meteordevelopment/meteorclient/utils/Utils.java +++ b/src/main/java/meteordevelopment/meteorclient/utils/Utils.java @@ -64,17 +64,17 @@ import static org.lwjgl.glfw.GLFW.*; public class Utils { + public static final Pattern FILE_NAME_INVALID_CHARS_PATTERN = Pattern.compile("[\\s\\\\/:*?\"<>|]"); + public static final Color WHITE = new Color(255, 255, 255); + private static final Random random = new Random(); public static boolean firstTimeTitleScreen = true; public static boolean isReleasingTrident; - public static final Color WHITE = new Color(255, 255, 255); public static boolean rendering3D = true; public static double frameTime; public static Screen screenToOpen; public static VertexSorter vertexSorter; - public static final Pattern FILE_NAME_INVALID_CHARS_PATTERN = Pattern.compile("[\\s\\\\/:*?\"<>|]"); - @PreInit public static void init() { MeteorClient.EVENT_BUS.subscribe(Utils.class); diff --git a/src/main/java/meteordevelopment/meteorclient/utils/entity/EntityUtils.java b/src/main/java/meteordevelopment/meteorclient/utils/entity/EntityUtils.java index 0736545c4b..1b2edf76e6 100644 --- a/src/main/java/meteordevelopment/meteorclient/utils/entity/EntityUtils.java +++ b/src/main/java/meteordevelopment/meteorclient/utils/entity/EntityUtils.java @@ -48,6 +48,10 @@ public static boolean isAttackable(EntityType type) { return type != EntityType.AREA_EFFECT_CLOUD && type != EntityType.ARROW && type != EntityType.FALLING_BLOCK && type != EntityType.FIREWORK_ROCKET && type != EntityType.ITEM && type != EntityType.LLAMA_SPIT && type != EntityType.SPECTRAL_ARROW && type != EntityType.ENDER_PEARL && type != EntityType.EXPERIENCE_BOTTLE && type != EntityType.POTION && type != EntityType.TRIDENT && type != EntityType.LIGHTNING_BOLT && type != EntityType.FISHING_BOBBER && type != EntityType.EXPERIENCE_ORB && type != EntityType.EGG; } + public static boolean isRideable(EntityType type) { + return type == EntityType.MINECART || type == EntityType.BOAT || type == EntityType.CAMEL || type == EntityType.DONKEY || type == EntityType.HORSE || type == EntityType.LLAMA || type == EntityType.MULE || type == EntityType.PIG || type == EntityType.SKELETON_HORSE || type == EntityType.STRIDER || type == EntityType.ZOMBIE_HORSE; + } + public static float getTotalHealth(PlayerEntity target) { return target.getHealth() + target.getAbsorptionAmount(); } diff --git a/src/main/java/meteordevelopment/meteorclient/utils/misc/CPSUtils.java b/src/main/java/meteordevelopment/meteorclient/utils/misc/CPSUtils.java new file mode 100644 index 0000000000..ecbc4c056c --- /dev/null +++ b/src/main/java/meteordevelopment/meteorclient/utils/misc/CPSUtils.java @@ -0,0 +1,50 @@ +/* + * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client). + * Copyright (c) Meteor Development. + */ + +package meteordevelopment.meteorclient.utils.misc; + +import meteordevelopment.meteorclient.MeteorClient; +import meteordevelopment.meteorclient.events.world.TickEvent; +import meteordevelopment.meteorclient.utils.PreInit; +import meteordevelopment.orbit.EventHandler; + + +public class CPSUtils { + private static int clicks; + private static int cps; + private static int secondsClicking; + private static long lastTime; + + @PreInit + public static void init() { + MeteorClient.EVENT_BUS.subscribe(CPSUtils.class); + } + + @EventHandler + private static void onTick(TickEvent.Pre event) { + long currentTime = System.currentTimeMillis(); + // Run every second + if (currentTime - CPSUtils.lastTime >= 1000) { + if (CPSUtils.cps == 0) { + CPSUtils.clicks = 0; + CPSUtils.secondsClicking = 0; + } else { + CPSUtils.lastTime = currentTime; + CPSUtils.secondsClicking++; + CPSUtils.cps = 0; + } + } + } + + + public static void onAttack() { + CPSUtils.clicks++; + CPSUtils.cps++; + } + + public static int getCpsAverage() { + return clicks / (secondsClicking == 0 ? 1 : secondsClicking); + } +} diff --git a/src/main/java/meteordevelopment/meteorclient/utils/misc/MeteorStarscript.java b/src/main/java/meteordevelopment/meteorclient/utils/misc/MeteorStarscript.java index 96ee3fa554..3c4fab8487 100644 --- a/src/main/java/meteordevelopment/meteorclient/utils/misc/MeteorStarscript.java +++ b/src/main/java/meteordevelopment/meteorclient/utils/misc/MeteorStarscript.java @@ -78,6 +78,7 @@ public static void init() { ss.set("fps", () -> Value.number(MinecraftClientAccessor.getFps())); ss.set("ping", MeteorStarscript::ping); ss.set("time", () -> Value.string(LocalTime.now().format(DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT)))); + ss.set("cps", () -> Value.number(CPSUtils.getCpsAverage())); // Meteor ss.set("meteor", new ValueMap() diff --git a/src/main/java/meteordevelopment/meteorclient/utils/network/MeteorExecutor.java b/src/main/java/meteordevelopment/meteorclient/utils/network/MeteorExecutor.java index adcddfd021..d1ec0d8071 100644 --- a/src/main/java/meteordevelopment/meteorclient/utils/network/MeteorExecutor.java +++ b/src/main/java/meteordevelopment/meteorclient/utils/network/MeteorExecutor.java @@ -9,13 +9,21 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicInteger; public class MeteorExecutor { public static ExecutorService executor; @PreInit public static void init() { - executor = Executors.newSingleThreadExecutor(); + AtomicInteger threadNumber = new AtomicInteger(1); + + executor = Executors.newCachedThreadPool((task) -> { + Thread thread = new Thread(task); + thread.setDaemon(true); + thread.setName("Meteor-Executor-" + threadNumber.getAndIncrement()); + return thread; + }); } public static void execute(Runnable task) { diff --git a/src/main/java/meteordevelopment/meteorclient/utils/player/ChatUtils.java b/src/main/java/meteordevelopment/meteorclient/utils/player/ChatUtils.java index ad1fef9c71..bf2283e4f6 100644 --- a/src/main/java/meteordevelopment/meteorclient/utils/player/ChatUtils.java +++ b/src/main/java/meteordevelopment/meteorclient/utils/player/ChatUtils.java @@ -6,6 +6,7 @@ package meteordevelopment.meteorclient.utils.player; import baritone.api.BaritoneAPI; +import com.mojang.brigadier.StringReader; import meteordevelopment.meteorclient.MeteorClient; import meteordevelopment.meteorclient.mixininterface.IChatHud; import meteordevelopment.meteorclient.systems.config.Config; @@ -30,7 +31,7 @@ public class ChatUtils { @PostInit public static void init() { - PREFIX = Text.literal("") + PREFIX = Text.empty() .setStyle(Style.EMPTY.withFormatting(Formatting.GRAY)) .append("[") .append(Text.literal("Meteor").setStyle(Style.EMPTY.withColor(TextColor.fromRgb(MeteorClient.ADDON.color.getPacked())))) @@ -121,30 +122,30 @@ public static void sendMsg(int id, Formatting color, String message, Object... a } public static void sendMsg(int id, @Nullable String prefixTitle, @Nullable Formatting prefixColor, Formatting messageColor, String messageContent, Object... args) { - sendMsg(id, prefixTitle, prefixColor, formatMsg(messageContent, messageColor, args), messageColor); + MutableText message = formatMsg(String.format(messageContent, args), messageColor); + sendMsg(id, prefixTitle, prefixColor, message); } public static void sendMsg(int id, @Nullable String prefixTitle, @Nullable Formatting prefixColor, String messageContent, Formatting messageColor) { - MutableText message = Text.literal(messageContent); - message.setStyle(message.getStyle().withFormatting(messageColor)); + MutableText message = formatMsg(messageContent, messageColor); sendMsg(id, prefixTitle, prefixColor, message); } public static void sendMsg(int id, @Nullable String prefixTitle, @Nullable Formatting prefixColor, Text msg) { if (mc.world == null) return; - MutableText message = Text.literal(""); + MutableText message = Text.empty(); message.append(getPrefix()); if (prefixTitle != null) message.append(getCustomPrefix(prefixTitle, prefixColor)); message.append(msg); if (!Config.get().deleteChatFeedback.get()) id = 0; - ((IChatHud) mc.inGameHud.getChatHud()).add(message, id); + ((IChatHud) mc.inGameHud.getChatHud()).meteor$add(message, id); } private static MutableText getCustomPrefix(String prefixTitle, Formatting prefixColor) { - MutableText prefix = Text.literal(""); + MutableText prefix = Text.empty(); prefix.setStyle(prefix.getStyle().withFormatting(Formatting.GRAY)); prefix.append("["); @@ -196,19 +197,50 @@ private static Text getPrefix() { return PREFIX; } - private static String formatMsg(String format, Formatting defaultColor, Object... args) { - String msg = String.format(format, args); - msg = msg.replace("(default)", defaultColor.toString()); - msg = msg.replace("(highlight)", Formatting.WHITE.toString()); - msg = msg.replace("(underline)", Formatting.UNDERLINE.toString()); + private static MutableText formatMsg(String message, Formatting defaultColor) { + StringReader reader = new StringReader(message); + MutableText text = Text.empty(); + Style style = Style.EMPTY.withFormatting(defaultColor); + StringBuilder result = new StringBuilder(); + boolean formatting = false; + while (reader.canRead()) { + char c = reader.read(); + if (c == '(') { + text.append(Text.literal(result.toString()).setStyle(style)); + result.setLength(0); + result.append(c); + formatting = true; + } else { + result.append(c); + + if (formatting && c == ')') { + switch (result.toString()) { + case "(default)" -> { + style = style.withFormatting(defaultColor); + result.setLength(0); + } + case "(highlight)" -> { + style = style.withFormatting(Formatting.WHITE); + result.setLength(0); + } + case "(underline)" -> { + style = style.withFormatting(Formatting.UNDERLINE); + result.setLength(0); + } + } + formatting = false; + } + } + } + + if (!result.isEmpty()) text.append(Text.literal(result.toString()).setStyle(style)); - return msg; + return text; } public static MutableText formatCoords(Vec3d pos) { String coordsString = String.format("(highlight)(underline)%.0f, %.0f, %.0f(default)", pos.x, pos.y, pos.z); - coordsString = formatMsg(coordsString, Formatting.GRAY); - MutableText coordsText = Text.literal(coordsString); + MutableText coordsText = formatMsg(coordsString, Formatting.GRAY); coordsText.setStyle(coordsText.getStyle() .withFormatting(Formatting.BOLD) .withClickEvent(new ClickEvent( diff --git a/src/main/java/meteordevelopment/meteorclient/utils/player/InvUtils.java b/src/main/java/meteordevelopment/meteorclient/utils/player/InvUtils.java index 11e5602a81..620b77adc0 100644 --- a/src/main/java/meteordevelopment/meteorclient/utils/player/InvUtils.java +++ b/src/main/java/meteordevelopment/meteorclient/utils/player/InvUtils.java @@ -178,7 +178,17 @@ public static Action click() { return ACTION; } - public static Action quickMove() { + /** + * When writing code with quickSwap, both to and from should provide the ID of a slot, not the index. + * From should be the slot in the hotbar, to should be the slot you're switching an item from. + */ + + public static Action quickSwap() { + ACTION.type = SlotActionType.SWAP; + return ACTION; + } + + public static Action shiftClick() { ACTION.type = SlotActionType.QUICK_MOVE; return ACTION; } @@ -290,6 +300,11 @@ public void slotArmor(int i) { private void run() { boolean hadEmptyCursor = mc.player.currentScreenHandler.getCursorStack().isEmpty(); + if (type == SlotActionType.SWAP) { + data = from; + from = to; + } + if (type != null && from != -1 && to != -1) { click(from); if (two) click(to); diff --git a/src/main/java/meteordevelopment/meteorclient/utils/world/BlockUtils.java b/src/main/java/meteordevelopment/meteorclient/utils/world/BlockUtils.java index 2ebc57c29b..e7a53280c3 100644 --- a/src/main/java/meteordevelopment/meteorclient/utils/world/BlockUtils.java +++ b/src/main/java/meteordevelopment/meteorclient/utils/world/BlockUtils.java @@ -88,11 +88,11 @@ public static boolean place(BlockPos blockPos, Hand hand, int slot, boolean rota side = Direction.UP; neighbour = blockPos; } else { - neighbour = blockPos.offset(side.getOpposite()); - hitPos.add(side.getOffsetX() * 0.5, side.getOffsetY() * 0.5, side.getOffsetZ() * 0.5); + neighbour = blockPos.offset(side); + hitPos = hitPos.add(side.getOffsetX() * 0.5, side.getOffsetY() * 0.5, side.getOffsetZ() * 0.5); } - BlockHitResult bhr = new BlockHitResult(hitPos, side, neighbour, false); + BlockHitResult bhr = new BlockHitResult(hitPos, side.getOpposite(), neighbour, false); if (rotate) { Rotations.rotate(Rotations.getYaw(hitPos), Rotations.getPitch(hitPos), rotationPriority, () -> { @@ -148,8 +148,6 @@ public static boolean canPlace(BlockPos blockPos) { public static Direction getPlaceSide(BlockPos blockPos) { for (Direction side : Direction.values()) { BlockPos neighbor = blockPos.offset(side); - Direction side2 = side.getOpposite(); - BlockState state = mc.world.getBlockState(neighbor); // Check if neighbour isn't empty @@ -158,7 +156,7 @@ public static Direction getPlaceSide(BlockPos blockPos) { // Check if neighbour is a fluid if (!state.getFluidState().isEmpty()) continue; - return side2; + return side; } return null; @@ -189,8 +187,8 @@ public static boolean breakBlock(BlockPos blockPos, boolean swing) { BlockPos pos = blockPos instanceof BlockPos.Mutable ? new BlockPos(blockPos) : blockPos; if (mc.interactionManager.isBreakingBlock()) - mc.interactionManager.updateBlockBreakingProgress(pos, Direction.UP); - else mc.interactionManager.attackBlock(pos, Direction.UP); + mc.interactionManager.updateBlockBreakingProgress(pos, getDirection(blockPos)); + else mc.interactionManager.attackBlock(pos, getDirection(blockPos)); if (swing) mc.player.swingHand(Hand.MAIN_HAND); else mc.getNetworkHandler().sendPacket(new HandSwingC2SPacket(Hand.MAIN_HAND)); @@ -267,6 +265,17 @@ public static boolean topSurface(BlockState blockState) { else return blockState.getBlock() instanceof StairsBlock && blockState.get(StairsBlock.HALF) == BlockHalf.TOP; } + // Finds the best block direction to get when interacting with the block. + public static Direction getDirection(BlockPos pos) { + Vec3d eyesPos = new Vec3d(mc.player.getX(), mc.player.getY() + mc.player.getEyeHeight(mc.player.getPose()), mc.player.getZ()); + if ((double) pos.getY() > eyesPos.y) { + if (mc.world.getBlockState(pos.add(0, -1, 0)).isReplaceable()) return Direction.DOWN; + else return mc.player.getHorizontalFacing().getOpposite(); + } + if (!mc.world.getBlockState(pos.add(0, 1, 0)).isReplaceable()) return mc.player.getHorizontalFacing().getOpposite(); + return Direction.UP; + } + public enum MobSpawn { Never, Potential, diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 71af4daf46..39d223e798 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -28,7 +28,8 @@ "meteor-client-indigo.mixins.json", "meteor-client-sodium.mixins.json", "meteor-client-canvas.mixins.json", - "meteor-client-lithium.mixins.json" + "meteor-client-lithium.mixins.json", + "meteor-client-indium.mixins.json" ], "accessWidener": "meteor-client.accesswidener", "custom": { @@ -43,6 +44,7 @@ "optifabric": "*", "feather": "*", "origins": "*", - "wurst": "*" + "wurst": "*", + "sodium": "<0.5.0" } } diff --git a/src/main/resources/meteor-client-indium.mixins.json b/src/main/resources/meteor-client-indium.mixins.json new file mode 100644 index 0000000000..536550283b --- /dev/null +++ b/src/main/resources/meteor-client-indium.mixins.json @@ -0,0 +1,12 @@ +{ + "required": true, + "package": "meteordevelopment.meteorclient.mixin.indium", + "compatibilityLevel": "JAVA_17", + "plugin": "meteordevelopment.meteorclient.MixinPlugin", + "client": [ + "AbstractBlockRenderContextMixin" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/src/main/resources/meteor-client.mixins.json b/src/main/resources/meteor-client.mixins.json index 80a3e4deb5..5447b260ff 100644 --- a/src/main/resources/meteor-client.mixins.json +++ b/src/main/resources/meteor-client.mixins.json @@ -117,7 +117,6 @@ "MouseMixin", "MultiplayerScreenMixin", "PacketByteBufMixin", - "PacketInflaterMixin", "ParticleManagerMixin", "PlayerArmorSlotMixin", "PlayerEntityMixin", @@ -164,7 +163,9 @@ "WorldChunkMixin", "WorldRendererAccessor", "WorldRendererMixin", - "YggdrasilMinecraftSessionServiceAccessor" + "YggdrasilMinecraftSessionServiceAccessor", + "MessageHandlerMixin", + "ChatHudLineVisibleMixin" ], "injectors": { "defaultRequire": 1