diff --git a/build.gradle b/build.gradle index 7c632e818e..bde82aacda 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ buildscript { dependencies { - classpath "org.kohsuke:github-api:1.324" + classpath "org.kohsuke:github-api:1.326" } } diff --git a/gradle.properties b/gradle.properties index c51438601a..f51fa62194 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,13 +7,13 @@ org.gradle.parallel=true # https://modrinth.com/mod/fabric-api/versions minecraft_version=1.21.1 yarn_mappings=1.21.1+build.3 -loader_version=0.16.4 +loader_version=0.16.5 # Fabric API -fabric_version=0.103.0+1.21.1 +fabric_version=0.105.0+1.21.1 # Mod Properties -mod_version = v7.45.1-MC1.21.1 +mod_version = v7.46-MC1.21.1 maven_group = net.wurstclient archives_base_name = Wurst-Client diff --git a/src/main/java/net/wurstclient/WurstClient.java b/src/main/java/net/wurstclient/WurstClient.java index 459ca8559e..d7fc59253a 100644 --- a/src/main/java/net/wurstclient/WurstClient.java +++ b/src/main/java/net/wurstclient/WurstClient.java @@ -50,7 +50,7 @@ public enum WurstClient public static MinecraftClient MC; public static IMinecraftClient IMC; - public static final String VERSION = "7.45.1"; + public static final String VERSION = "7.46"; public static final String MC_VERSION = "1.21.1"; private WurstAnalytics analytics; diff --git a/src/main/java/net/wurstclient/WurstTranslator.java b/src/main/java/net/wurstclient/WurstTranslator.java index 610a88db97..1f11ef192b 100644 --- a/src/main/java/net/wurstclient/WurstTranslator.java +++ b/src/main/java/net/wurstclient/WurstTranslator.java @@ -10,9 +10,11 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.IllegalFormatException; import java.util.List; +import java.util.Map; import java.util.function.BiConsumer; import com.google.common.collect.Lists; @@ -31,8 +33,8 @@ public class WurstTranslator implements SynchronousResourceReloader private final WurstClient wurst = WurstClient.INSTANCE; private TranslationStorage mcEnglish; - private final HashMap englishOnlyStrings = new HashMap<>(); - private final HashMap currentLangStrings = new HashMap<>(); + private Map currentLangStrings = Map.of(); + private Map englishOnlyStrings = Map.of(); @Override public void reload(ResourceManager manager) @@ -40,12 +42,16 @@ public void reload(ResourceManager manager) mcEnglish = TranslationStorage.load(manager, Lists.newArrayList("en_us"), false); - currentLangStrings.clear(); + HashMap currentLangStrings = new HashMap<>(); loadTranslations(manager, getCurrentLangCodes(), currentLangStrings::put); + this.currentLangStrings = + Collections.unmodifiableMap(currentLangStrings); - englishOnlyStrings.clear(); + HashMap englishOnlyStrings = new HashMap<>(); loadTranslations(manager, List.of("en_us"), englishOnlyStrings::put); + this.englishOnlyStrings = + Collections.unmodifiableMap(englishOnlyStrings); } /** @@ -146,6 +152,17 @@ public TranslationStorage getMcEnglish() return mcEnglish; } + public Map getMinecraftsCurrentLanguage() + { + return currentLangStrings; + } + + public Map getWurstsCurrentLanguage() + { + return isForcedEnglish() ? englishOnlyStrings + : getMinecraftsCurrentLanguage(); + } + private ArrayList getCurrentLangCodes() { // Weird bug: Some users have their language set to "en_US" instead of diff --git a/src/main/java/net/wurstclient/altmanager/screens/AddAltScreen.java b/src/main/java/net/wurstclient/altmanager/screens/AddAltScreen.java index b438483263..d095cd1706 100644 --- a/src/main/java/net/wurstclient/altmanager/screens/AddAltScreen.java +++ b/src/main/java/net/wurstclient/altmanager/screens/AddAltScreen.java @@ -26,7 +26,7 @@ public AddAltScreen(Screen prevScreen, AltManager altManager) @Override protected String getDoneButtonText() { - return "Add"; + return getPassword().isEmpty() ? "Add Cracked Alt" : "Add Premium Alt"; } @Override diff --git a/src/main/java/net/wurstclient/altmanager/screens/AltEditorScreen.java b/src/main/java/net/wurstclient/altmanager/screens/AltEditorScreen.java index 4c54f11147..d1cd2f2e5d 100644 --- a/src/main/java/net/wurstclient/altmanager/screens/AltEditorScreen.java +++ b/src/main/java/net/wurstclient/altmanager/screens/AltEditorScreen.java @@ -73,6 +73,25 @@ public AltEditorScreen(Screen prevScreen, Text title) @Override public final void init() { + nameOrEmailBox = new TextFieldWidget(textRenderer, width / 2 - 100, 60, + 200, 20, Text.literal("")); + nameOrEmailBox.setMaxLength(48); + nameOrEmailBox.setFocused(true); + nameOrEmailBox.setText(getDefaultNameOrEmail()); + addSelectableChild(nameOrEmailBox); + + passwordBox = new TextFieldWidget(textRenderer, width / 2 - 100, 100, + 200, 20, Text.literal("")); + passwordBox.setText(getDefaultPassword()); + passwordBox.setRenderTextProvider((text, int_1) -> { + String stars = ""; + for(int i = 0; i < text.length(); i++) + stars += "*"; + return OrderedText.styledForwardsVisitedString(stars, Style.EMPTY); + }); + passwordBox.setMaxLength(256); + addSelectableChild(passwordBox); + addDrawableChild(doneButton = ButtonWidget .builder(Text.literal(getDoneButtonText()), b -> pressDoneButton()) .dimensions(width / 2 - 100, height / 4 + 72 + 12, 200, 20) @@ -101,25 +120,6 @@ public final void init() .dimensions((width / 2 - 100) / 2 - 64, height - 32, 128, 20) .build()); - nameOrEmailBox = new TextFieldWidget(textRenderer, width / 2 - 100, 60, - 200, 20, Text.literal("")); - nameOrEmailBox.setMaxLength(48); - nameOrEmailBox.setFocused(true); - nameOrEmailBox.setText(getDefaultNameOrEmail()); - addSelectableChild(nameOrEmailBox); - - passwordBox = new TextFieldWidget(textRenderer, width / 2 - 100, 100, - 200, 20, Text.literal("")); - passwordBox.setText(getDefaultPassword()); - passwordBox.setRenderTextProvider((text, int_1) -> { - String stars = ""; - for(int i = 0; i < text.length(); i++) - stars += "*"; - return OrderedText.styledForwardsVisitedString(stars, Style.EMPTY); - }); - passwordBox.setMaxLength(256); - addSelectableChild(passwordBox); - setFocused(nameOrEmailBox); } @@ -150,6 +150,7 @@ public final void tick() doneButton.active = !nameOrEmail.isEmpty() && !(alex && passwordBox.getText().isEmpty()); + doneButton.setMessage(Text.literal(getDoneButtonText())); stealSkinButton.active = !alex; } @@ -358,14 +359,17 @@ public void render(DrawContext context, int mouseX, int mouseY, AltRenderer.drawAltBody(context, nameOrEmailBox.getText(), width - (width / 2 - 100) / 2 - 64, height / 2 - 128, 128, 256); + String accountType = getPassword().isEmpty() ? "cracked" : "premium"; + // text context.drawTextWithShadow(textRenderer, "Name (for cracked alts), or", width / 2 - 100, 37, 10526880); context.drawTextWithShadow(textRenderer, "E-Mail (for premium alts)", width / 2 - 100, 47, 10526880); - context.drawTextWithShadow(textRenderer, - "Password (leave blank for cracked alts)", width / 2 - 100, 87, - 10526880); + context.drawTextWithShadow(textRenderer, "Password (for premium alts)", + width / 2 - 100, 87, 10526880); + context.drawTextWithShadow(textRenderer, "Account type: " + accountType, + width / 2 - 100, 127, 10526880); String[] lines = message.split("\n"); for(int i = 0; i < lines.length; i++) diff --git a/src/main/java/net/wurstclient/altmanager/screens/DirectLoginScreen.java b/src/main/java/net/wurstclient/altmanager/screens/DirectLoginScreen.java index d399d19790..7f090cfd10 100644 --- a/src/main/java/net/wurstclient/altmanager/screens/DirectLoginScreen.java +++ b/src/main/java/net/wurstclient/altmanager/screens/DirectLoginScreen.java @@ -24,7 +24,8 @@ public DirectLoginScreen(Screen prevScreen) @Override protected String getDoneButtonText() { - return "Login"; + return getPassword().isEmpty() ? "Change Cracked Name" + : "Login with Password"; } @Override diff --git a/src/main/java/net/wurstclient/clickgui/ClickGui.java b/src/main/java/net/wurstclient/clickgui/ClickGui.java index a41a16e3d8..5f1fe29ad6 100644 --- a/src/main/java/net/wurstclient/clickgui/ClickGui.java +++ b/src/main/java/net/wurstclient/clickgui/ClickGui.java @@ -471,6 +471,8 @@ public void render(DrawContext context, int mouseX, int mouseY, GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); // GL11.glShadeModel(GL11.GL_SMOOTH); RenderSystem.lineWidth(1); + MatrixStack matrixStack = context.getMatrices(); + matrixStack.push(); tooltip = ""; for(Window window : windows) @@ -495,12 +497,14 @@ public void render(DrawContext context, int mouseX, int mouseY, else window.stopDraggingScrollbar(); + matrixStack.translate(0, 0, 300); renderWindow(context, window, mouseX, mouseY, partialTicks); } renderPopups(context, mouseX, mouseY); renderTooltip(context, mouseX, mouseY); + matrixStack.pop(); GL11.glEnable(GL11.GL_CULL_FACE); GL11.glDisable(GL11.GL_BLEND); } @@ -598,12 +602,18 @@ public void renderPinnedWindows(DrawContext context, float partialTicks) GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); RenderSystem.lineWidth(1); + MatrixStack matrixStack = context.getMatrices(); + matrixStack.push(); for(Window window : windows) if(window.isPinned() && !window.isInvisible()) + { + matrixStack.translate(0, 0, 300); renderWindow(context, window, Integer.MIN_VALUE, Integer.MIN_VALUE, partialTicks); - + } + + matrixStack.pop(); GL11.glEnable(GL11.GL_CULL_FACE); GL11.glDisable(GL11.GL_BLEND); } diff --git a/src/main/java/net/wurstclient/clickgui/components/BlockListEditButton.java b/src/main/java/net/wurstclient/clickgui/components/BlockListEditButton.java index 5bc07e29d1..e7a70a99ca 100644 --- a/src/main/java/net/wurstclient/clickgui/components/BlockListEditButton.java +++ b/src/main/java/net/wurstclient/clickgui/components/BlockListEditButton.java @@ -33,7 +33,7 @@ protected void openScreen() @Override protected String getText() { - return setting.getName() + ": " + setting.getBlockNames().size(); + return setting.getName() + ": " + setting.size(); } @Override diff --git a/src/main/java/net/wurstclient/commands/BlockListCmd.java b/src/main/java/net/wurstclient/commands/BlockListCmd.java index f4ef45a4b2..66eeca75cd 100644 --- a/src/main/java/net/wurstclient/commands/BlockListCmd.java +++ b/src/main/java/net/wurstclient/commands/BlockListCmd.java @@ -7,14 +7,9 @@ */ package net.wurstclient.commands; -import java.util.Collections; import java.util.List; import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.registry.Registries; -import net.minecraft.util.Identifier; -import net.minecraft.util.InvalidIdentifierException; import net.wurstclient.DontBlock; import net.wurstclient.Feature; import net.wurstclient.command.CmdError; @@ -84,15 +79,13 @@ private void add(Feature feature, BlockListSetting setting, String[] args) throw new CmdSyntaxError(); String inputBlockName = args[3]; - Block block = getBlockFromNameOrID(inputBlockName); + Block block = BlockUtils.getBlockFromNameOrID(inputBlockName); if(block == null) throw new CmdSyntaxError( "\"" + inputBlockName + "\" is not a valid block."); String blockName = BlockUtils.getName(block); - int index = - Collections.binarySearch(setting.getBlockNames(), blockName); - if(index >= 0) + if(setting.contains(blockName)) throw new CmdError(feature.getName() + " " + setting.getName() + " already contains " + blockName); @@ -106,14 +99,13 @@ private void remove(Feature feature, BlockListSetting setting, throw new CmdSyntaxError(); String inputBlockName = args[3]; - Block block = getBlockFromNameOrID(inputBlockName); + Block block = BlockUtils.getBlockFromNameOrID(inputBlockName); if(block == null) throw new CmdSyntaxError( "\"" + inputBlockName + "\" is not a valid block."); String blockName = BlockUtils.getName(block); - int index = - Collections.binarySearch(setting.getBlockNames(), blockName); + int index = setting.indexOf(blockName); if(index < 0) throw new CmdError(feature.getName() + " " + setting.getName() + " does not contain " + blockName); @@ -168,26 +160,4 @@ private BlockListSetting getAsBlockListSetting(Feature feature, return (BlockListSetting)setting; } - - private Block getBlockFromNameOrID(String nameOrId) - { - if(MathUtils.isInteger(nameOrId)) - { - BlockState state = Block.STATE_IDS.get(Integer.parseInt(nameOrId)); - if(state == null) - return null; - - return state.getBlock(); - } - - try - { - return Registries.BLOCK.getOrEmpty(Identifier.of(nameOrId)) - .orElse(null); - - }catch(InvalidIdentifierException e) - { - return null; - } - } } diff --git a/src/main/java/net/wurstclient/commands/SetBlockCmd.java b/src/main/java/net/wurstclient/commands/SetBlockCmd.java index 644e945585..dbd48308a9 100644 --- a/src/main/java/net/wurstclient/commands/SetBlockCmd.java +++ b/src/main/java/net/wurstclient/commands/SetBlockCmd.java @@ -8,10 +8,6 @@ package net.wurstclient.commands; import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.registry.Registries; -import net.minecraft.util.Identifier; -import net.minecraft.util.InvalidIdentifierException; import net.wurstclient.DontBlock; import net.wurstclient.Feature; import net.wurstclient.command.CmdError; @@ -20,8 +16,8 @@ import net.wurstclient.command.Command; import net.wurstclient.settings.BlockSetting; import net.wurstclient.settings.Setting; +import net.wurstclient.util.BlockUtils; import net.wurstclient.util.CmdUtils; -import net.wurstclient.util.MathUtils; @DontBlock public final class SetBlockCmd extends Command @@ -67,32 +63,10 @@ private void setBlock(BlockSetting setting, String value) return; } - Block block = getBlockFromNameOrID(value); + Block block = BlockUtils.getBlockFromNameOrID(value); if(block == null) throw new CmdSyntaxError("\"" + value + "\" is not a valid block."); setting.setBlock(block); } - - private Block getBlockFromNameOrID(String nameOrId) - { - if(MathUtils.isInteger(nameOrId)) - { - BlockState state = Block.STATE_IDS.get(Integer.parseInt(nameOrId)); - if(state == null) - return null; - - return state.getBlock(); - } - - try - { - return Registries.BLOCK.getOrEmpty(Identifier.of(nameOrId)) - .orElse(null); - - }catch(InvalidIdentifierException e) - { - return null; - } - } } diff --git a/src/main/java/net/wurstclient/events/HandleBlockBreakingListener.java b/src/main/java/net/wurstclient/events/HandleBlockBreakingListener.java new file mode 100644 index 0000000000..61bcf8f936 --- /dev/null +++ b/src/main/java/net/wurstclient/events/HandleBlockBreakingListener.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014-2024 Wurst-Imperium and contributors. + * + * This source code is subject to the terms of the GNU General Public + * License, version 3. If a copy of the GPL was not distributed with this + * file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt + */ +package net.wurstclient.events; + +import java.util.ArrayList; + +import net.minecraft.client.MinecraftClient; +import net.wurstclient.event.CancellableEvent; +import net.wurstclient.event.Listener; + +/** + * Fired at the beginning of + * {@link MinecraftClient#handleBlockBreaking(boolean)}. + * Allows you to cancel vanilla block breaking and replace it with your own. + */ +public interface HandleBlockBreakingListener extends Listener +{ + /** + * Fired at the beginning of + * {@link MinecraftClient#handleBlockBreaking(boolean)}. + * Allows you to cancel vanilla block breaking and replace it with your own. + */ + public void onHandleBlockBreaking(HandleBlockBreakingEvent event); + + /** + * Fired at the beginning of + * {@link MinecraftClient#handleBlockBreaking(boolean)}. + * Allows you to cancel vanilla block breaking and replace it with your own. + */ + public static class HandleBlockBreakingEvent + extends CancellableEvent + { + @Override + public void fire(ArrayList listeners) + { + for(HandleBlockBreakingListener listener : listeners) + { + listener.onHandleBlockBreaking(this); + + if(isCancelled()) + break; + } + } + + @Override + public Class getListenerType() + { + return HandleBlockBreakingListener.class; + } + } +} diff --git a/src/main/java/net/wurstclient/hack/HackList.java b/src/main/java/net/wurstclient/hack/HackList.java index d750429540..34c21a6b3c 100644 --- a/src/main/java/net/wurstclient/hack/HackList.java +++ b/src/main/java/net/wurstclient/hack/HackList.java @@ -185,6 +185,7 @@ public final class HackList implements UpdateListener public final TrollPotionHack trollPotionHack = new TrollPotionHack(); public final TrueSightHack trueSightHack = new TrueSightHack(); public final TunnellerHack tunnellerHack = new TunnellerHack(); + public final VeinMinerHack veinMinerHack = new VeinMinerHack(); public final XRayHack xRayHack = new XRayHack(); private final TreeMap hax = diff --git a/src/main/java/net/wurstclient/hacks/AnchorAuraHack.java b/src/main/java/net/wurstclient/hacks/AnchorAuraHack.java index 2e5b3d8894..79c4dd4900 100644 --- a/src/main/java/net/wurstclient/hacks/AnchorAuraHack.java +++ b/src/main/java/net/wurstclient/hacks/AnchorAuraHack.java @@ -64,10 +64,8 @@ public final class AnchorAuraHack extends Hack implements UpdateListener new CheckboxSetting("Check line of sight", "description.wurst.setting.anchoraura.check_line_of_sight", false); - private final SwingHandSetting swingHand = new SwingHandSetting( - "How AnchorAura should swing your hand when placing, charging and" - + " detonating respawn anchors.", - SwingHand.CLIENT); + private final SwingHandSetting swingHand = + new SwingHandSetting(this, SwingHand.CLIENT); private final EnumSetting takeItemsFrom = new EnumSetting<>("Take items from", diff --git a/src/main/java/net/wurstclient/hacks/AutoFarmHack.java b/src/main/java/net/wurstclient/hacks/AutoFarmHack.java index 59707fc6cb..46b0c35d9b 100644 --- a/src/main/java/net/wurstclient/hacks/AutoFarmHack.java +++ b/src/main/java/net/wurstclient/hacks/AutoFarmHack.java @@ -7,7 +7,11 @@ */ package net.wurstclient.hacks; -import java.util.*; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -15,7 +19,6 @@ import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.Item; import net.minecraft.item.Items; -import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket; import net.minecraft.registry.tag.BlockTags; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; @@ -30,7 +33,9 @@ import net.wurstclient.settings.CheckboxSetting; import net.wurstclient.settings.SliderSetting; import net.wurstclient.settings.SliderSetting.ValueDisplay; +import net.wurstclient.settings.SwingHandSetting.SwingHand; import net.wurstclient.util.BlockBreaker; +import net.wurstclient.util.BlockBreakingCache; import net.wurstclient.util.BlockPlacer; import net.wurstclient.util.BlockPlacer.BlockPlacingParams; import net.wurstclient.util.BlockUtils; @@ -61,7 +66,7 @@ public final class AutoFarmHack extends Hack } private final HashMap plants = new HashMap<>(); - private final ArrayDeque> prevBlocks = new ArrayDeque<>(); + private final BlockBreakingCache cache = new BlockBreakingCache(); private BlockPos currentlyHarvesting; private final AutoFarmRenderer renderer = new AutoFarmRenderer(); @@ -100,7 +105,7 @@ protected void onDisable() currentlyHarvesting = null; } - prevBlocks.clear(); + cache.reset(); overlay.resetProgress(); busy = false; @@ -111,17 +116,17 @@ protected void onDisable() public void onUpdate() { currentlyHarvesting = null; - Vec3d eyesVec = RotationUtils.getEyesPos().subtract(0.5, 0.5, 0.5); - BlockPos eyesBlock = BlockPos.ofFloored(RotationUtils.getEyesPos()); + Vec3d eyesVec = RotationUtils.getEyesPos(); + BlockPos eyesBlock = BlockPos.ofFloored(eyesVec); double rangeSq = range.getValueSq(); int blockRange = range.getValueCeil(); // get nearby, non-empty blocks - ArrayList blocks = BlockUtils - .getAllInBoxStream(eyesBlock, blockRange) - .filter(pos -> eyesVec.squaredDistanceTo(Vec3d.of(pos)) <= rangeSq) - .filter(BlockUtils::canBeClicked) - .collect(Collectors.toCollection(ArrayList::new)); + ArrayList blocks = + BlockUtils.getAllInBoxStream(eyesBlock, blockRange) + .filter(pos -> pos.getSquaredDistance(eyesVec) <= rangeSq) + .filter(BlockUtils::canBeClicked) + .collect(Collectors.toCollection(ArrayList::new)); // check for any new plants and add them to the map updatePlants(blocks); @@ -146,9 +151,9 @@ public void onUpdate() // if we can't replant, harvest instead if(!replanting) - harvest(blocksToHarvest); + harvest(blocksToHarvest.stream()); - // upate busy state + // update busy state busy = replanting || currentlyHarvesting != null; // update renderer @@ -187,8 +192,8 @@ private ArrayList getBlocksToHarvest(Vec3d eyesVec, ArrayList blocks) { return blocks.parallelStream().filter(this::shouldBeHarvested) - .sorted(Comparator.comparingDouble( - pos -> eyesVec.squaredDistanceTo(Vec3d.of(pos)))) + .sorted(Comparator + .comparingDouble(pos -> pos.getSquaredDistance(eyesVec))) .collect(Collectors.toCollection(ArrayList::new)); } @@ -234,11 +239,11 @@ private ArrayList getBlocksToReplant(Vec3d eyesVec, BlockPos eyesBlock, double rangeSq, int blockRange) { return BlockUtils.getAllInBoxStream(eyesBlock, blockRange) - .filter(pos -> eyesVec.squaredDistanceTo(Vec3d.of(pos)) <= rangeSq) + .filter(pos -> pos.getSquaredDistance(eyesVec) <= rangeSq) .filter(pos -> BlockUtils.getState(pos).isReplaceable()) .filter(pos -> plants.containsKey(pos)).filter(this::canBeReplanted) - .sorted(Comparator.comparingDouble( - pos -> eyesVec.squaredDistanceTo(Vec3d.of(pos)))) + .sorted(Comparator + .comparingDouble(pos -> pos.getSquaredDistance(eyesVec))) .collect(Collectors.toCollection(ArrayList::new)); } @@ -303,8 +308,7 @@ private boolean replant(List blocksToReplant) // swing arm if(result.isAccepted() && result.shouldSwingHand()) - MC.player.networkHandler - .sendPacket(new HandSwingC2SPacket(hand)); + SwingHand.SERVER.swing(hand); // reset cooldown MC.itemUseCooldown = 4; @@ -330,42 +334,34 @@ private boolean replant(List blocksToReplant) return false; } - private void harvest(List blocksToHarvest) + private void harvest(Stream stream) { + // Break all blocks in creative mode if(MC.player.getAbilities().creativeMode) { - Stream stream = blocksToHarvest.parallelStream(); - for(Set set : prevBlocks) - stream = stream.filter(pos -> !set.contains(pos)); - List filteredBlocks = stream.collect(Collectors.toList()); - - prevBlocks.addLast(new HashSet<>(filteredBlocks)); - while(prevBlocks.size() > 5) - prevBlocks.removeFirst(); - - if(!filteredBlocks.isEmpty()) - currentlyHarvesting = filteredBlocks.get(0); - MC.interactionManager.cancelBlockBreaking(); overlay.resetProgress(); - BlockBreaker.breakBlocksWithPacketSpam(filteredBlocks); + + ArrayList blocks = cache.filterOutRecentBlocks(stream); + if(blocks.isEmpty()) + return; + + currentlyHarvesting = blocks.get(0); + BlockBreaker.breakBlocksWithPacketSpam(blocks); return; } - for(BlockPos pos : blocksToHarvest) - if(BlockBreaker.breakOneBlock(pos)) - { - currentlyHarvesting = pos; - break; - } + // Break the first valid block in survival mode + currentlyHarvesting = + stream.filter(BlockBreaker::breakOneBlock).findFirst().orElse(null); if(currentlyHarvesting == null) + { MC.interactionManager.cancelBlockBreaking(); - - if(currentlyHarvesting != null - && BlockUtils.getHardness(currentlyHarvesting) < 1) - overlay.updateProgress(); - else overlay.resetProgress(); + return; + } + + overlay.updateProgress(); } } diff --git a/src/main/java/net/wurstclient/hacks/AutoFishHack.java b/src/main/java/net/wurstclient/hacks/AutoFishHack.java index c0f290589a..81bdedfc0f 100644 --- a/src/main/java/net/wurstclient/hacks/AutoFishHack.java +++ b/src/main/java/net/wurstclient/hacks/AutoFishHack.java @@ -9,7 +9,9 @@ import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.projectile.FishingBobberEntity; import net.minecraft.item.Items; +import net.minecraft.network.packet.s2c.play.EntityTrackerUpdateS2CPacket; import net.minecraft.network.packet.s2c.play.PlaySoundS2CPacket; import net.minecraft.sound.SoundEvents; import net.minecraft.util.math.Vec3d; @@ -23,6 +25,7 @@ import net.wurstclient.hacks.autofish.AutoFishRodSelector; import net.wurstclient.hacks.autofish.FishingSpotManager; import net.wurstclient.hacks.autofish.ShallowWaterWarningCheckbox; +import net.wurstclient.settings.EnumSetting; import net.wurstclient.settings.SliderSetting; import net.wurstclient.settings.SliderSetting.ValueDisplay; @@ -32,10 +35,21 @@ public final class AutoFishHack extends Hack implements UpdateListener, PacketInputListener, RenderListener { + private final EnumSetting biteMode = + new EnumSetting<>("Bite mode", + "\u00a7lSound\u00a7r mode detects bites by listening for the bite sound." + + " This method is less accurate, but is more resilient against" + + " anti-cheats. See the \"Valid range\" setting.\n\n" + + "\u00a7lEntity\u00a7r mode detects bites by checking for the" + + " fishing hook's entity update packet. It's more accurate than" + + " the sound method, but is less resilient against anti-cheats.", + AutoFishHack.BiteMode.values(), AutoFishHack.BiteMode.SOUND); + private final SliderSetting validRange = new SliderSetting("Valid range", "Any bites that occur outside of this range will be ignored.\n\n" + "Increase your range if bites are not being detected, decrease it" - + " if other people's bites are being detected as yours.", + + " if other people's bites are being detected as yours.\n\n" + + "This setting has no effect when \"Bite mode\" is set to \"Entity\".", 1.5, 0.25, 8, 0.25, ValueDisplay.DECIMAL); private final SliderSetting catchDelay = new SliderSetting("Catch delay", @@ -69,6 +83,7 @@ public AutoFishHack() { super("AutoFish"); setCategory(Category.OTHER); + addSetting(biteMode); addSetting(validRange); addSetting(catchDelay); addSetting(retryDelay); @@ -166,6 +181,15 @@ public void onUpdate() @Override public void onReceivedPacket(PacketInputEvent event) + { + switch(biteMode.getSelected()) + { + case SOUND -> processSoundUpdate(event); + case ENTITY -> processEntityUpdate(event); + } + } + + private void processSoundUpdate(PacketInputEvent event) { // check packet type if(!(event.getPacket() instanceof PlaySoundS2CPacket sound)) @@ -193,6 +217,28 @@ public void onReceivedPacket(PacketInputEvent event) biteDetected = true; } + private void processEntityUpdate(PacketInputEvent event) + { + // check packet type + if(!(event.getPacket() instanceof EntityTrackerUpdateS2CPacket update)) + return; + + // check if the entity is a bobber + if(!(MC.world + .getEntityById(update.id()) instanceof FishingBobberEntity bobber)) + return; + + // check if it's our bobber + if(bobber != MC.player.fishHook) + return; + + // check if player is fishing + if(!isFishing()) + return; + + biteDetected = true; + } + @Override public void onRender(MatrixStack matrixStack, float partialTicks) { @@ -206,4 +252,23 @@ private boolean isFishing() && !player.fishHook.isRemoved() && player.getMainHandStack().isOf(Items.FISHING_ROD); } + + private enum BiteMode + { + SOUND("Sound"), + ENTITY("Entity"); + + private final String name; + + private BiteMode(String name) + { + this.name = name; + } + + @Override + public String toString() + { + return name; + } + } } diff --git a/src/main/java/net/wurstclient/hacks/AutoLibrarianHack.java b/src/main/java/net/wurstclient/hacks/AutoLibrarianHack.java index fe14587f45..97f1292ef8 100644 --- a/src/main/java/net/wurstclient/hacks/AutoLibrarianHack.java +++ b/src/main/java/net/wurstclient/hacks/AutoLibrarianHack.java @@ -56,6 +56,7 @@ import net.wurstclient.settings.SliderSetting; import net.wurstclient.settings.SliderSetting.ValueDisplay; import net.wurstclient.settings.SwingHandSetting; +import net.wurstclient.settings.SwingHandSetting.SwingHand; import net.wurstclient.util.*; import net.wurstclient.util.BlockBreaker.BlockBreakingParams; import net.wurstclient.util.BlockPlacer.BlockPlacingParams; @@ -95,8 +96,8 @@ public final class AutoLibrarianHack extends Hack private final SliderSetting range = new SliderSetting("Range", 5, 1, 6, 0.05, ValueDisplay.DECIMAL); - private final FacingSetting facing = FacingSetting - .withoutPacketSpam("How to face the villager and job site.\n\n" + private final FacingSetting facing = FacingSetting.withoutPacketSpam( + "How AutoLibrarian should face the villager and job site.\n\n" + "\u00a7lOff\u00a7r - Don't face the villager at all. Will be" + " detected by anti-cheat plugins.\n\n" + "\u00a7lServer-side\u00a7r - Face the villager on the" @@ -107,8 +108,7 @@ public final class AutoLibrarianHack extends Hack + " can be disorienting to look at."); private final SwingHandSetting swingHand = - new SwingHandSetting("How to swing your hand when interacting with the" - + " villager and job site."); + new SwingHandSetting(this, SwingHand.SERVER); private final SliderSetting repairMode = new SliderSetting("Repair mode", "Prevents AutoLibrarian from using your axe when its durability reaches" diff --git a/src/main/java/net/wurstclient/hacks/AutoMineHack.java b/src/main/java/net/wurstclient/hacks/AutoMineHack.java index 3b9ba5a696..cd0ba71177 100644 --- a/src/main/java/net/wurstclient/hacks/AutoMineHack.java +++ b/src/main/java/net/wurstclient/hacks/AutoMineHack.java @@ -16,17 +16,27 @@ import net.minecraft.util.math.Direction; import net.wurstclient.Category; import net.wurstclient.SearchTags; +import net.wurstclient.events.HandleBlockBreakingListener; import net.wurstclient.events.UpdateListener; import net.wurstclient.hack.Hack; import net.wurstclient.mixinterface.IKeyBinding; +import net.wurstclient.settings.CheckboxSetting; @SearchTags({"auto mine", "AutoBreak", "auto break"}) -public final class AutoMineHack extends Hack implements UpdateListener +public final class AutoMineHack extends Hack + implements UpdateListener, HandleBlockBreakingListener { + private final CheckboxSetting superFastMode = + new CheckboxSetting("Super fast mode", + "Breaks blocks faster than you normally could. May get detected by" + + " anti-cheat plugins.", + false); + public AutoMineHack() { super("AutoMine"); setCategory(Category.BLOCKS); + addSetting(superFastMode); } @Override @@ -37,14 +47,17 @@ protected void onEnable() WURST.getHax().nukerLegitHack.setEnabled(false); WURST.getHax().speedNukerHack.setEnabled(false); WURST.getHax().tunnellerHack.setEnabled(false); + WURST.getHax().veinMinerHack.setEnabled(false); EVENTS.add(UpdateListener.class, this); + EVENTS.add(HandleBlockBreakingListener.class, this); } @Override protected void onDisable() { EVENTS.remove(UpdateListener.class, this); + EVENTS.remove(HandleBlockBreakingListener.class, this); IKeyBinding.get(MC.options.attackKey).resetPressedState(); MC.interactionManager.cancelBlockBreaking(); } @@ -86,6 +99,9 @@ public void onUpdate() // This case doesn't cancel block breaking in vanilla Minecraft. return; + if(!im.isBreakingBlock()) + im.attackBlock(pos, side); + if(im.updateBlockBreakingProgress(pos, side)) { MC.particleManager.addBlockBreakingParticles(pos, side); @@ -93,4 +109,12 @@ public void onUpdate() MC.options.attackKey.setPressed(true); } } + + @Override + public void onHandleBlockBreaking(HandleBlockBreakingEvent event) + { + // Cancel vanilla block breaking so we don't send the packets twice. + if(!superFastMode.isChecked()) + event.cancel(); + } } diff --git a/src/main/java/net/wurstclient/hacks/BonemealAuraHack.java b/src/main/java/net/wurstclient/hacks/BonemealAuraHack.java index a01e758479..7817e2cc81 100644 --- a/src/main/java/net/wurstclient/hacks/BonemealAuraHack.java +++ b/src/main/java/net/wurstclient/hacks/BonemealAuraHack.java @@ -19,7 +19,7 @@ import net.minecraft.util.math.Vec3d; import net.wurstclient.Category; import net.wurstclient.SearchTags; -import net.wurstclient.events.PostMotionListener; +import net.wurstclient.events.HandleInputListener; import net.wurstclient.hack.Hack; import net.wurstclient.settings.CheckboxSetting; import net.wurstclient.settings.EnumSetting; @@ -35,7 +35,7 @@ @SearchTags({"bonemeal aura", "bone meal aura", "AutoBonemeal", "auto bonemeal", "auto bone meal", "fertilizer"}) -public final class BonemealAuraHack extends Hack implements PostMotionListener +public final class BonemealAuraHack extends Hack implements HandleInputListener { private final SliderSetting range = new SliderSetting("Range", 4.25, 1, 6, 0.05, ValueDisplay.DECIMAL); @@ -83,22 +83,25 @@ public BonemealAuraHack() @Override protected void onEnable() { - EVENTS.add(PostMotionListener.class, this); + EVENTS.add(HandleInputListener.class, this); } @Override protected void onDisable() { - EVENTS.remove(PostMotionListener.class, this); + EVENTS.remove(HandleInputListener.class, this); } @Override - public void onPostMotion() + public void onHandleInput() { // wait for right click timer if(MC.itemUseCooldown > 0) return; + if(MC.interactionManager.isBreakingBlock() || MC.player.isRiding()) + return; + // get valid blocks ArrayList validBlocks = getValidBlocks(); diff --git a/src/main/java/net/wurstclient/hacks/BuildRandomHack.java b/src/main/java/net/wurstclient/hacks/BuildRandomHack.java index 0629ab9e8b..c1cd5da600 100644 --- a/src/main/java/net/wurstclient/hacks/BuildRandomHack.java +++ b/src/main/java/net/wurstclient/hacks/BuildRandomHack.java @@ -27,6 +27,7 @@ import net.wurstclient.settings.SliderSetting; import net.wurstclient.settings.SliderSetting.ValueDisplay; import net.wurstclient.settings.SwingHandSetting; +import net.wurstclient.settings.SwingHandSetting.SwingHand; import net.wurstclient.util.BlockPlacer; import net.wurstclient.util.BlockPlacer.BlockPlacingParams; import net.wurstclient.util.BlockUtils; @@ -74,8 +75,8 @@ public final class BuildRandomHack extends Hack + " camera on the client-side. This is the most legit option, but" + " can be VERY disorienting to look at."); - private final SwingHandSetting swingHand = new SwingHandSetting( - "How BuildRandom should swing your hand when placing blocks."); + private final SwingHandSetting swingHand = + new SwingHandSetting(this, SwingHand.SERVER); private final CheckboxSetting fastPlace = new CheckboxSetting("Always FastPlace", diff --git a/src/main/java/net/wurstclient/hacks/CaveFinderHack.java b/src/main/java/net/wurstclient/hacks/CaveFinderHack.java index 0b8eda8088..11406f18c2 100644 --- a/src/main/java/net/wurstclient/hacks/CaveFinderHack.java +++ b/src/main/java/net/wurstclient/hacks/CaveFinderHack.java @@ -44,11 +44,11 @@ import net.wurstclient.settings.SliderSetting.ValueDisplay; import net.wurstclient.util.BlockVertexCompiler; import net.wurstclient.util.ChatUtils; -import net.wurstclient.util.ChunkSearcher; -import net.wurstclient.util.ChunkSearcherCoordinator; import net.wurstclient.util.RegionPos; import net.wurstclient.util.RenderUtils; import net.wurstclient.util.RotationUtils; +import net.wurstclient.util.chunk.ChunkSearcher; +import net.wurstclient.util.chunk.ChunkSearcherCoordinator; @SearchTags({"cave finder"}) public final class CaveFinderHack extends Hack diff --git a/src/main/java/net/wurstclient/hacks/ChestEspHack.java b/src/main/java/net/wurstclient/hacks/ChestEspHack.java index 62f4ed3888..e2b2438f76 100644 --- a/src/main/java/net/wurstclient/hacks/ChestEspHack.java +++ b/src/main/java/net/wurstclient/hacks/ChestEspHack.java @@ -36,8 +36,8 @@ import net.wurstclient.settings.CheckboxSetting; import net.wurstclient.settings.ColorSetting; import net.wurstclient.settings.EspStyleSetting; -import net.wurstclient.util.ChunkUtils; import net.wurstclient.util.RenderUtils; +import net.wurstclient.util.chunk.ChunkUtils; public class ChestEspHack extends Hack implements UpdateListener, CameraTransformViewBobbingListener, RenderListener diff --git a/src/main/java/net/wurstclient/hacks/CrystalAuraHack.java b/src/main/java/net/wurstclient/hacks/CrystalAuraHack.java index 223ee71f11..7217854736 100644 --- a/src/main/java/net/wurstclient/hacks/CrystalAuraHack.java +++ b/src/main/java/net/wurstclient/hacks/CrystalAuraHack.java @@ -70,10 +70,8 @@ public final class CrystalAuraHack extends Hack implements UpdateListener + "Slower but can help with anti-cheat plugins.", false); - private final SwingHandSetting swingHand = new SwingHandSetting( - "How CrystalAura should swing your hand when placing and detonating" - + " end crystals.", - SwingHand.CLIENT); + private final SwingHandSetting swingHand = + new SwingHandSetting(this, SwingHand.CLIENT); private final EnumSetting takeItemsFrom = new EnumSetting<>("Take items from", "Where to look for end crystals.", diff --git a/src/main/java/net/wurstclient/hacks/ExcavatorHack.java b/src/main/java/net/wurstclient/hacks/ExcavatorHack.java index acc2eaa8ee..d27c9a36f2 100644 --- a/src/main/java/net/wurstclient/hacks/ExcavatorHack.java +++ b/src/main/java/net/wurstclient/hacks/ExcavatorHack.java @@ -104,6 +104,7 @@ protected void onEnable() WURST.getHax().speedNukerHack.setEnabled(false); WURST.getHax().templateToolHack.setEnabled(false); WURST.getHax().tunnellerHack.setEnabled(false); + WURST.getHax().veinMinerHack.setEnabled(false); step = Step.START_POS; diff --git a/src/main/java/net/wurstclient/hacks/FeedAuraHack.java b/src/main/java/net/wurstclient/hacks/FeedAuraHack.java index c4b1de4b81..c8a0e2126d 100644 --- a/src/main/java/net/wurstclient/hacks/FeedAuraHack.java +++ b/src/main/java/net/wurstclient/hacks/FeedAuraHack.java @@ -33,7 +33,7 @@ import net.minecraft.util.math.Vec3d; import net.wurstclient.Category; import net.wurstclient.SearchTags; -import net.wurstclient.events.PostMotionListener; +import net.wurstclient.events.HandleInputListener; import net.wurstclient.events.RenderListener; import net.wurstclient.events.UpdateListener; import net.wurstclient.hack.Hack; @@ -49,7 +49,7 @@ @SearchTags({"feed aura", "BreedAura", "breed aura", "AutoBreeder", "auto breeder"}) public final class FeedAuraHack extends Hack - implements UpdateListener, PostMotionListener, RenderListener + implements UpdateListener, HandleInputListener, RenderListener { private final SliderSetting range = new SliderSetting("Range", "Determines how far FeedAura will reach to feed animals.\n" @@ -98,7 +98,7 @@ protected void onEnable() WURST.getHax().tpAuraHack.setEnabled(false); EVENTS.add(UpdateListener.class, this); - EVENTS.add(PostMotionListener.class, this); + EVENTS.add(HandleInputListener.class, this); EVENTS.add(RenderListener.class, this); } @@ -106,7 +106,7 @@ protected void onEnable() protected void onDisable() { EVENTS.remove(UpdateListener.class, this); - EVENTS.remove(PostMotionListener.class, this); + EVENTS.remove(HandleInputListener.class, this); EVENTS.remove(RenderListener.class, this); target = null; @@ -151,7 +151,7 @@ public void onUpdate() } @Override - public void onPostMotion() + public void onHandleInput() { if(target == null) return; @@ -160,6 +160,9 @@ public void onPostMotion() ClientPlayerEntity player = MC.player; Hand hand = Hand.MAIN_HAND; + if(im.isBreakingBlock() || player.isRiding()) + return; + // create realistic hit result Box box = target.getBoundingBox(); Vec3d start = RotationUtils.getEyesPos(); diff --git a/src/main/java/net/wurstclient/hacks/FightBotHack.java b/src/main/java/net/wurstclient/hacks/FightBotHack.java index 1346b591e1..8f38241a15 100644 --- a/src/main/java/net/wurstclient/hacks/FightBotHack.java +++ b/src/main/java/net/wurstclient/hacks/FightBotHack.java @@ -51,8 +51,7 @@ public final class FightBotHack extends Hack new AttackSpeedSliderSetting(); private final SwingHandSetting swingHand = new SwingHandSetting( - "How FightBot should swing your hand when attacking.", - SwingHand.CLIENT); + SwingHandSetting.genericCombatDescription(this), SwingHand.CLIENT); private final SliderSetting distance = new SliderSetting("Distance", "How closely to follow the target.\n" diff --git a/src/main/java/net/wurstclient/hacks/HandNoClipHack.java b/src/main/java/net/wurstclient/hacks/HandNoClipHack.java index 0bc6b03082..2c2e323117 100644 --- a/src/main/java/net/wurstclient/hacks/HandNoClipHack.java +++ b/src/main/java/net/wurstclient/hacks/HandNoClipHack.java @@ -42,7 +42,7 @@ public HandNoClipHack() public boolean isBlockInList(BlockPos pos) { - return blocks.getBlockNames().contains(BlockUtils.getName(pos)); + return blocks.contains(BlockUtils.getName(pos)); } // See AbstractBlockStateMixin.onGetOutlineShape() diff --git a/src/main/java/net/wurstclient/hacks/InstantBunkerHack.java b/src/main/java/net/wurstclient/hacks/InstantBunkerHack.java index 4eda9fdad9..aee4657f28 100644 --- a/src/main/java/net/wurstclient/hacks/InstantBunkerHack.java +++ b/src/main/java/net/wurstclient/hacks/InstantBunkerHack.java @@ -17,7 +17,6 @@ import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.BlockItem; import net.minecraft.item.ItemStack; -import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; @@ -29,6 +28,7 @@ import net.wurstclient.events.RenderListener; import net.wurstclient.events.UpdateListener; import net.wurstclient.hack.Hack; +import net.wurstclient.settings.SwingHandSetting.SwingHand; import net.wurstclient.util.BlockUtils; import net.wurstclient.util.ChatUtils; import net.wurstclient.util.RenderUtils; @@ -236,8 +236,7 @@ private void placeBlockSimple(BlockPos pos) side.getOpposite(), hitVec); // swing arm - MC.player.networkHandler - .sendPacket(new HandSwingC2SPacket(Hand.MAIN_HAND)); + SwingHand.SERVER.swing(Hand.MAIN_HAND); // reset timer MC.itemUseCooldown = 4; diff --git a/src/main/java/net/wurstclient/hacks/KaboomHack.java b/src/main/java/net/wurstclient/hacks/KaboomHack.java index 9646e43fa1..5c3d462588 100644 --- a/src/main/java/net/wurstclient/hacks/KaboomHack.java +++ b/src/main/java/net/wurstclient/hacks/KaboomHack.java @@ -11,12 +11,16 @@ import java.util.Comparator; import java.util.stream.Collectors; +import net.minecraft.particle.ParticleTypes; +import net.minecraft.sound.SoundCategory; +import net.minecraft.sound.SoundEvents; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; -import net.minecraft.world.explosion.Explosion; +import net.minecraft.util.math.random.Random; import net.wurstclient.Category; import net.wurstclient.events.UpdateListener; import net.wurstclient.hack.Hack; +import net.wurstclient.settings.CheckboxSetting; import net.wurstclient.settings.SliderSetting; import net.wurstclient.settings.SliderSetting.ValueDisplay; import net.wurstclient.util.BlockBreaker; @@ -26,14 +30,24 @@ public final class KaboomHack extends Hack implements UpdateListener { private final SliderSetting power = - new SliderSetting("Power", 128, 32, 512, 32, ValueDisplay.INTEGER); + new SliderSetting("Power", "description.wurst.setting.kaboom.power", + 128, 32, 512, 32, ValueDisplay.INTEGER); + + private final CheckboxSetting sound = new CheckboxSetting("Sound", + "description.wurst.setting.kaboom.sound", true); + + private final CheckboxSetting particles = new CheckboxSetting("Particles", + "description.wurst.setting.kaboom.particles", true); + + private final Random random = Random.create(); public KaboomHack() { super("Kaboom"); - setCategory(Category.BLOCKS); addSetting(power); + addSetting(sound); + addSetting(particles); } @Override @@ -51,40 +65,47 @@ protected void onDisable() @Override public void onUpdate() { - // check fly-kick + // Abort if flying to prevent getting kicked if(!MC.player.getAbilities().creativeMode && !MC.player.isOnGround()) return; - // do explosion particles - new Explosion(MC.world, MC.player, MC.player.getX(), MC.player.getY(), - MC.player.getZ(), 6F, false, Explosion.DestructionType.KEEP) - .affectWorld(true); + double x = MC.player.getX(); + double y = MC.player.getY(); + double z = MC.player.getZ(); - // get valid blocks - ArrayList blocks = getBlocksByDistanceReversed(6); + // Do explosion effect + if(sound.isChecked()) + { + float soundPitch = + (1F + (random.nextFloat() - random.nextFloat()) * 0.2F) * 0.7F; + MC.world.playSound(x, y, z, + SoundEvents.ENTITY_GENERIC_EXPLODE.value(), + SoundCategory.BLOCKS, 4, soundPitch, false); + } + if(particles.isChecked()) + MC.world.addParticle(ParticleTypes.EXPLOSION_EMITTER, x, y, z, 1, 0, + 0); - // break all blocks + // Break all blocks + ArrayList blocks = getBlocksByDistanceReversed(); for(int i = 0; i < power.getValueI(); i++) BlockBreaker.breakBlocksWithPacketSpam(blocks); - // disable setEnabled(false); } - private ArrayList getBlocksByDistanceReversed(double range) + private ArrayList getBlocksByDistanceReversed() { - Vec3d eyesVec = RotationUtils.getEyesPos().subtract(0.5, 0.5, 0.5); - double rangeSq = Math.pow(range + 0.5, 2); - int rangeI = (int)Math.ceil(range); - - BlockPos center = BlockPos.ofFloored(RotationUtils.getEyesPos()); - BlockPos min = center.add(-rangeI, -rangeI, -rangeI); - BlockPos max = center.add(rangeI, rangeI, rangeI); + Vec3d eyesVec = RotationUtils.getEyesPos(); + BlockPos eyesBlock = BlockPos.ofFloored(eyesVec); + double rangeSq = 36; + int blockRange = 6; - return BlockUtils.getAllInBox(min, max).stream() - .filter(pos -> eyesVec.squaredDistanceTo(Vec3d.of(pos)) <= rangeSq) - .sorted(Comparator.comparingDouble( - pos -> -eyesVec.squaredDistanceTo(Vec3d.of(pos)))) + // farthest blocks first + return BlockUtils.getAllInBoxStream(eyesBlock, blockRange) + .filter(pos -> pos.getSquaredDistance(eyesVec) <= rangeSq) + .sorted(Comparator + .comparingDouble(pos -> -pos.getSquaredDistance(eyesVec))) .collect(Collectors.toCollection(ArrayList::new)); } } diff --git a/src/main/java/net/wurstclient/hacks/KillauraHack.java b/src/main/java/net/wurstclient/hacks/KillauraHack.java index c3fafc5d03..8331bf995d 100644 --- a/src/main/java/net/wurstclient/hacks/KillauraHack.java +++ b/src/main/java/net/wurstclient/hacks/KillauraHack.java @@ -77,8 +77,7 @@ public final class KillauraHack extends Hack new SliderSetting("FOV", 360, 30, 360, 10, ValueDisplay.DEGREES); private final SwingHandSetting swingHand = new SwingHandSetting( - "How Killaura should swing your hand when attacking.", - SwingHand.CLIENT); + SwingHandSetting.genericCombatDescription(this), SwingHand.CLIENT); private final CheckboxSetting damageIndicator = new CheckboxSetting( "Damage indicator", diff --git a/src/main/java/net/wurstclient/hacks/KillauraLegitHack.java b/src/main/java/net/wurstclient/hacks/KillauraLegitHack.java index d1eca3cb79..b10e4c4964 100644 --- a/src/main/java/net/wurstclient/hacks/KillauraLegitHack.java +++ b/src/main/java/net/wurstclient/hacks/KillauraLegitHack.java @@ -83,8 +83,7 @@ public final class KillauraLegitHack extends Hack implements UpdateListener, private final SwingHandSetting swingHand = SwingHandSetting.withoutOffOption( - "How KillauraLegit should swing your hand when attacking.", - SwingHand.CLIENT); + SwingHandSetting.genericCombatDescription(this), SwingHand.CLIENT); private final CheckboxSetting damageIndicator = new CheckboxSetting( "Damage indicator", diff --git a/src/main/java/net/wurstclient/hacks/MobSpawnEspHack.java b/src/main/java/net/wurstclient/hacks/MobSpawnEspHack.java index bc10af12f7..12e6b66d17 100644 --- a/src/main/java/net/wurstclient/hacks/MobSpawnEspHack.java +++ b/src/main/java/net/wurstclient/hacks/MobSpawnEspHack.java @@ -7,16 +7,8 @@ */ package net.wurstclient.hacks; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.ConcurrentModificationException; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; -import java.util.stream.Collectors; +import java.awt.Color; +import java.util.Map.Entry; import org.joml.Matrix4f; import org.lwjgl.opengl.GL11; @@ -33,13 +25,11 @@ import net.minecraft.client.render.VertexFormat; import net.minecraft.client.render.VertexFormats; import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.EntityType; +import net.minecraft.entity.SpawnRestriction; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import net.minecraft.world.LightType; -import net.minecraft.world.chunk.Chunk; -import net.minecraft.world.dimension.DimensionType; import net.wurstclient.Category; import net.wurstclient.SearchTags; import net.wurstclient.events.PacketInputListener; @@ -49,142 +39,86 @@ import net.wurstclient.settings.CheckboxSetting; import net.wurstclient.settings.ChunkAreaSetting; import net.wurstclient.settings.ChunkAreaSetting.ChunkArea; +import net.wurstclient.settings.ColorSetting; import net.wurstclient.settings.SliderSetting; import net.wurstclient.settings.SliderSetting.ValueDisplay; -import net.wurstclient.util.ChunkUtils; -import net.wurstclient.util.MinPriorityThreadFactory; import net.wurstclient.util.RegionPos; import net.wurstclient.util.RenderUtils; +import net.wurstclient.util.chunk.ChunkSearcher; +import net.wurstclient.util.chunk.ChunkSearcher.Result; +import net.wurstclient.util.chunk.ChunkVertexBufferCoordinator; @SearchTags({"mob spawn esp", "LightLevelESP", "light level esp", "LightLevelOverlay", "light level overlay"}) public final class MobSpawnEspHack extends Hack - implements UpdateListener, PacketInputListener, RenderListener + implements UpdateListener, RenderListener { private final ChunkAreaSetting drawDistance = new ChunkAreaSetting("Draw distance", "", ChunkArea.A9); - private final SliderSetting loadingSpeed = new SliderSetting( - "Loading speed", 1, 1, 5, 1, ValueDisplay.INTEGER.withSuffix("x")); + private final ColorSetting nightColor = new ColorSetting("Night color", + "description.wurst.setting.mobspawnesp.night_color", Color.YELLOW); + + private final ColorSetting dayColor = new ColorSetting("Day color", + "description.wurst.setting.mobspawnesp.day_color", Color.RED); + + private final SliderSetting opacity = + new SliderSetting("Opacity", 0.5, 0, 1, 0.01, ValueDisplay.PERCENTAGE); private final CheckboxSetting depthTest = new CheckboxSetting("Depth test", true); - private final HashMap scanners = new HashMap<>(); - private ExecutorService pool; + private final ChunkVertexBufferCoordinator coordinator = + new ChunkVertexBufferCoordinator(this::isSpawnable, this::buildBuffer, + drawDistance); + + private int cachedDayColor; + private int cachedNightColor; public MobSpawnEspHack() { super("MobSpawnESP"); setCategory(Category.RENDER); addSetting(drawDistance); - addSetting(loadingSpeed); + addSetting(nightColor); + addSetting(dayColor); + addSetting(opacity); addSetting(depthTest); } @Override protected void onEnable() { - pool = MinPriorityThreadFactory.newFixedThreadPool(); - EVENTS.add(UpdateListener.class, this); - EVENTS.add(PacketInputListener.class, this); + EVENTS.add(PacketInputListener.class, coordinator); EVENTS.add(RenderListener.class, this); + + cachedDayColor = dayColor.getColorI(); + cachedNightColor = nightColor.getColorI(); } @Override protected void onDisable() { EVENTS.remove(UpdateListener.class, this); - EVENTS.remove(PacketInputListener.class, this); + EVENTS.remove(PacketInputListener.class, coordinator); EVENTS.remove(RenderListener.class, this); - for(ChunkScanner scanner : new ArrayList<>(scanners.values())) - { - scanner.reset(); - scanners.remove(scanner.chunk.getPos()); - } - - pool.shutdownNow(); + coordinator.reset(); } @Override public void onUpdate() { - DimensionType dimension = MC.world.getDimension(); - - // remove old scanners that are out of range - for(ChunkScanner scanner : new ArrayList<>(scanners.values())) + if(dayColor.getColorI() != cachedDayColor + || nightColor.getColorI() != cachedNightColor) { - if(drawDistance.isInRange(scanner.chunk.getPos()) - && dimension == scanner.dimension) - continue; - - scanner.reset(); - scanners.remove(scanner.chunk.getPos()); + cachedDayColor = dayColor.getColorI(); + cachedNightColor = nightColor.getColorI(); + coordinator.reset(); } - // create & start scanners for new chunks - for(Chunk chunk : drawDistance.getChunksInRange()) - { - ChunkPos chunkPos = chunk.getPos(); - if(scanners.containsKey(chunkPos)) - continue; - - ChunkScanner scanner = new ChunkScanner(chunk, dimension); - scanners.put(chunkPos, scanner); - scanner.future = pool.submit(() -> scanner.scan()); - } - - // generate vertex buffers - ChunkPos center = MC.player.getChunkPos(); - Comparator c = Comparator.comparingInt( - s -> ChunkUtils.getManhattanDistance(center, s.chunk.getPos())); - List sortedScanners = scanners.values().stream() - .filter(s -> s.doneScanning).filter(s -> !s.doneCompiling).sorted(c) - .limit(loadingSpeed.getValueI()).collect(Collectors.toList()); - - for(ChunkScanner scanner : sortedScanners) - try - { - scanner.compileBuffer(); - - }catch(ConcurrentModificationException e) - { - System.out.println( - "WARNING! ChunkScanner.compileDisplayList(); failed with the following exception:"); - e.printStackTrace(); - - if(scanner.vertexBuffer != null) - scanner.vertexBuffer.close(); - } - } - - @Override - public void onReceivedPacket(PacketInputEvent event) - { - ClientWorld world = MC.world; - if(MC.player == null || world == null) - return; - - ChunkPos center = ChunkUtils.getAffectedChunk(event.getPacket()); - if(center == null) - return; - - ArrayList chunks = new ArrayList<>(); - for(int x = center.x - 1; x <= center.x + 1; x++) - for(int z = center.z - 1; z <= center.z + 1; z++) - chunks.add(new ChunkPos(x, z)); - - for(ChunkPos chunkPos : chunks) - { - ChunkScanner scanner = scanners.get(chunkPos); - if(scanner == null) - return; - - scanner.reset(); - scanner.future = pool.submit(() -> scanner.scan()); - } + coordinator.update(); } @Override @@ -193,180 +127,91 @@ public void onRender(MatrixStack matrixStack, float partialTicks) // GL settings GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GL11.glEnable(GL11.GL_CULL_FACE); boolean depthTest = this.depthTest.isChecked(); if(!depthTest) GL11.glDisable(GL11.GL_DEPTH_TEST); - RenderSystem.setShaderColor(1, 1, 1, 1); RenderSystem.setShader(GameRenderer::getPositionColorProgram); + RenderSystem.setShaderColor(1, 1, 1, opacity.getValueF()); - for(ChunkScanner scanner : new ArrayList<>(scanners.values())) + for(Entry entry : coordinator.getBuffers()) { - if(scanner.vertexBuffer == null) - continue; + RegionPos region = RegionPos.of(entry.getKey()); + VertexBuffer vertexBuffer = entry.getValue(); matrixStack.push(); - RenderUtils.applyRegionalRenderOffset(matrixStack, scanner.chunk); + RenderUtils.applyRegionalRenderOffset(matrixStack, region); Matrix4f viewMatrix = matrixStack.peek().getPositionMatrix(); Matrix4f projMatrix = RenderSystem.getProjectionMatrix(); ShaderProgram shader = RenderSystem.getShader(); - scanner.vertexBuffer.bind(); - scanner.vertexBuffer.draw(viewMatrix, projMatrix, shader); + vertexBuffer.bind(); + vertexBuffer.draw(viewMatrix, projMatrix, shader); VertexBuffer.unbind(); matrixStack.pop(); } - if(!depthTest) - GL11.glEnable(GL11.GL_DEPTH_TEST); - // GL resets RenderSystem.setShaderColor(1, 1, 1, 1); + if(!depthTest) + GL11.glEnable(GL11.GL_DEPTH_TEST); GL11.glDisable(GL11.GL_BLEND); } - private static class ChunkScanner + private boolean isSpawnable(BlockPos pos, BlockState state) { - public Future future; - private final Chunk chunk; - private final DimensionType dimension; - private final Set red = new HashSet<>(); - private final Set yellow = new HashSet<>(); - private VertexBuffer vertexBuffer; - - private boolean doneScanning; - private boolean doneCompiling; - - public ChunkScanner(Chunk chunk, DimensionType dimension) - { - this.chunk = chunk; - this.dimension = dimension; - } - - @SuppressWarnings("deprecation") - private void scan() - { - ClientWorld world = MC.world; - ArrayList blocks = new ArrayList<>(); - - int minX = chunk.getPos().getStartX(); - int minY = world.getBottomY(); - int minZ = chunk.getPos().getStartZ(); - int maxX = chunk.getPos().getEndX(); - int maxY = world.getTopY(); - int maxZ = chunk.getPos().getEndZ(); - - for(int x = minX; x <= maxX; x++) - for(int y = minY; y <= maxY; y++) - for(int z = minZ; z <= maxZ; z++) - { - BlockPos pos = new BlockPos(x, y, z); - BlockState state = world.getBlockState(pos); - - if(state.blocksMovement()) - continue; - if(!state.getFluidState().isEmpty()) - continue; - - BlockState stateDown = world.getBlockState(pos.down()); - if(!stateDown.allowsSpawning(world, pos.down(), - EntityType.ZOMBIE)) - continue; - - blocks.add(pos); - } - - if(Thread.interrupted()) - return; - - red.addAll(blocks.stream() - .filter(pos -> world.getLightLevel(LightType.BLOCK, pos) < 1) - .filter(pos -> world.getLightLevel(LightType.SKY, pos) < 8) - .collect(Collectors.toList())); - - if(Thread.interrupted()) - return; - - yellow.addAll(blocks.stream().filter(pos -> !red.contains(pos)) - .filter(pos -> world.getLightLevel(LightType.BLOCK, pos) < 1) - .collect(Collectors.toList())); - doneScanning = true; - } + // Check for solid blocks, fluids, redstone, prevent_spawning tags, etc. + // See SpawnLocationTypes.ON_GROUND + if(!SpawnRestriction.isSpawnPosAllowed(EntityType.CREEPER, MC.world, + pos)) + return false; + + // Check for hitbox collisions + // (using a creeper because it's shorter than a zombie) + if(!MC.world.isSpaceEmpty(EntityType.CREEPER + .getSpawnBox(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5))) + return false; + + // Check block light level + return MC.world.getLightLevel(LightType.BLOCK, pos) < 1; + } + + private BuiltBuffer buildBuffer(ChunkSearcher searcher, + Iterable results) + { + RegionPos region = RegionPos.of(searcher.getPos()); + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferBuilder = tessellator.begin( + VertexFormat.DrawMode.DEBUG_LINES, VertexFormats.POSITION_COLOR); - private void compileBuffer() + for(Result result : results) { - RegionPos region = RegionPos.of(chunk.getPos()); - - if(vertexBuffer != null) - { - vertexBuffer.close(); - vertexBuffer = null; - } - - Tessellator tessellator = RenderSystem.renderThreadTesselator(); - BufferBuilder bufferBuilder = - tessellator.begin(VertexFormat.DrawMode.DEBUG_LINES, - VertexFormats.POSITION_COLOR); - - new ArrayList<>(red).stream() - .map(pos -> new BlockPos(pos.getX() - region.x(), pos.getY(), - pos.getZ() - region.z())) - .forEach(pos -> { - bufferBuilder - .vertex(pos.getX(), pos.getY() + 0.01F, pos.getZ()) - .color(1, 0, 0, 0.5F); - bufferBuilder.vertex(pos.getX() + 1, pos.getY() + 0.01F, - pos.getZ() + 1).color(1, 0, 0, 0.5F); - bufferBuilder - .vertex(pos.getX() + 1, pos.getY() + 0.01F, pos.getZ()) - .color(1, 0, 0, 0.5F); - bufferBuilder - .vertex(pos.getX(), pos.getY() + 0.01F, pos.getZ() + 1) - .color(1, 0, 0, 0.5F); - }); - - new ArrayList<>(yellow).stream() - .map(pos -> new BlockPos(pos.getX() - region.x(), pos.getY(), - pos.getZ() - region.z())) - .forEach(pos -> { - bufferBuilder - .vertex(pos.getX(), pos.getY() + 0.01F, pos.getZ()) - .color(1, 1, 0, 0.5F); - bufferBuilder.vertex(pos.getX() + 1, pos.getY() + 0.01F, - pos.getZ() + 1).color(1, 1, 0, 0.5F); - bufferBuilder - .vertex(pos.getX() + 1, pos.getY() + 0.01F, pos.getZ()) - .color(1, 1, 0, 0.5F); - bufferBuilder - .vertex(pos.getX(), pos.getY() + 0.01F, pos.getZ() + 1) - .color(1, 1, 0, 0.5F); - }); - - BuiltBuffer buffer = bufferBuilder.endNullable(); - if(buffer != null) - { - vertexBuffer = new VertexBuffer(VertexBuffer.Usage.STATIC); - vertexBuffer.bind(); - vertexBuffer.upload(buffer); - VertexBuffer.unbind(); - } + if(searcher.isInterrupted()) + return null; - doneCompiling = true; + drawCross(bufferBuilder, result.pos(), region); } - private void reset() - { - if(future != null) - future.cancel(true); - - red.clear(); - yellow.clear(); - - doneScanning = false; - doneCompiling = false; - } + return bufferBuilder.endNullable(); + } + + private void drawCross(BufferBuilder bufferBuilder, BlockPos pos, + RegionPos region) + { + float x1 = pos.getX() - region.x(); + float x2 = x1 + 1; + float y = pos.getY() + 0.01F; + float z1 = pos.getZ() - region.z(); + float z2 = z1 + 1; + + int color = MC.world.getLightLevel(LightType.SKY, pos) < 8 + ? cachedDayColor : cachedNightColor; + + bufferBuilder.vertex(x1, y, z1).color(color); + bufferBuilder.vertex(x2, y, z2).color(color); + bufferBuilder.vertex(x2, y, z1).color(color); + bufferBuilder.vertex(x1, y, z2).color(color); } } diff --git a/src/main/java/net/wurstclient/hacks/MultiAuraHack.java b/src/main/java/net/wurstclient/hacks/MultiAuraHack.java index a1b836fd7e..2931d07d57 100644 --- a/src/main/java/net/wurstclient/hacks/MultiAuraHack.java +++ b/src/main/java/net/wurstclient/hacks/MultiAuraHack.java @@ -40,8 +40,7 @@ public final class MultiAuraHack extends Hack implements UpdateListener new SliderSetting("FOV", 360, 30, 360, 10, ValueDisplay.DEGREES); private final SwingHandSetting swingHand = new SwingHandSetting( - "How MultiAura should swing your hand when attacking.", - SwingHand.CLIENT); + SwingHandSetting.genericCombatDescription(this), SwingHand.CLIENT); private final PauseAttackOnContainersSetting pauseOnContainers = new PauseAttackOnContainersSetting(false); diff --git a/src/main/java/net/wurstclient/hacks/NewChunksHack.java b/src/main/java/net/wurstclient/hacks/NewChunksHack.java index 75838bb029..46ab153701 100644 --- a/src/main/java/net/wurstclient/hacks/NewChunksHack.java +++ b/src/main/java/net/wurstclient/hacks/NewChunksHack.java @@ -33,9 +33,9 @@ import net.wurstclient.settings.SliderSetting; import net.wurstclient.settings.SliderSetting.ValueDisplay; import net.wurstclient.util.BlockUtils; -import net.wurstclient.util.ChunkUtils; import net.wurstclient.util.RegionPos; import net.wurstclient.util.RenderUtils; +import net.wurstclient.util.chunk.ChunkUtils; public final class NewChunksHack extends Hack implements UpdateListener, RenderListener diff --git a/src/main/java/net/wurstclient/hacks/NukerHack.java b/src/main/java/net/wurstclient/hacks/NukerHack.java index 52ed87ddc0..ab542c8391 100644 --- a/src/main/java/net/wurstclient/hacks/NukerHack.java +++ b/src/main/java/net/wurstclient/hacks/NukerHack.java @@ -7,21 +7,12 @@ */ package net.wurstclient.hacks; -import java.util.ArrayDeque; import java.util.ArrayList; -import java.util.Comparator; -import java.util.HashSet; -import java.util.Set; -import java.util.function.BiPredicate; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.stream.Collectors; +import java.util.Objects; import java.util.stream.Stream; -import net.minecraft.block.Blocks; import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.hit.HitResult; +import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.wurstclient.Category; @@ -29,55 +20,32 @@ import net.wurstclient.events.RenderListener; import net.wurstclient.events.UpdateListener; import net.wurstclient.hack.Hack; -import net.wurstclient.settings.BlockListSetting; -import net.wurstclient.settings.BlockSetting; -import net.wurstclient.settings.CheckboxSetting; -import net.wurstclient.settings.EnumSetting; +import net.wurstclient.hacks.nukers.CommonNukerSettings; import net.wurstclient.settings.SliderSetting; import net.wurstclient.settings.SliderSetting.ValueDisplay; +import net.wurstclient.settings.SwingHandSetting; +import net.wurstclient.settings.SwingHandSetting.SwingHand; import net.wurstclient.util.BlockBreaker; +import net.wurstclient.util.BlockBreaker.BlockBreakingParams; +import net.wurstclient.util.BlockBreakingCache; import net.wurstclient.util.BlockUtils; import net.wurstclient.util.OverlayRenderer; import net.wurstclient.util.RotationUtils; public final class NukerHack extends Hack - implements UpdateListener, LeftClickListener, RenderListener + implements UpdateListener, RenderListener { private final SliderSetting range = new SliderSetting("Range", 5, 1, 6, 0.05, ValueDisplay.DECIMAL); - private final EnumSetting mode = new EnumSetting<>("Mode", - "\u00a7lNormal\u00a7r mode simply breaks everything around you.\n" - + "\u00a7lID\u00a7r mode only breaks the selected block type. Left-click on a block to select it.\n" - + "\u00a7lMultiID\u00a7r mode only breaks the block types in your MultiID List.\n" - + "\u00a7lFlat\u00a7r mode flattens the area around you, but won't dig down.\n" - + "\u00a7lSmash\u00a7r mode only breaks blocks that can be destroyed instantly (e.g. tall grass).", - Mode.values(), Mode.NORMAL); + private final CommonNukerSettings commonSettings = + new CommonNukerSettings(); - private final BlockSetting id = - new BlockSetting("ID", "The type of block to break in ID mode.\n" - + "air = won't break anything", "minecraft:air", true); + private final SwingHandSetting swingHand = new SwingHandSetting( + SwingHandSetting.genericMiningDescription(this), SwingHand.SERVER); - private final CheckboxSetting lockId = new CheckboxSetting("Lock ID", - "Prevents changing the ID by clicking on blocks or restarting Nuker.", - false); - - private final BlockListSetting multiIdList = new BlockListSetting( - "MultiID List", "The types of blocks to break in MultiID mode.", - "minecraft:ancient_debris", "minecraft:bone_block", - "minecraft:coal_ore", "minecraft:copper_ore", - "minecraft:deepslate_coal_ore", "minecraft:deepslate_copper_ore", - "minecraft:deepslate_diamond_ore", "minecraft:deepslate_emerald_ore", - "minecraft:deepslate_gold_ore", "minecraft:deepslate_iron_ore", - "minecraft:deepslate_lapis_ore", "minecraft:deepslate_redstone_ore", - "minecraft:diamond_ore", "minecraft:emerald_ore", "minecraft:glowstone", - "minecraft:gold_ore", "minecraft:iron_ore", "minecraft:lapis_ore", - "minecraft:nether_gold_ore", "minecraft:nether_quartz_ore", - "minecraft:raw_copper_block", "minecraft:raw_gold_block", - "minecraft:raw_iron_block", "minecraft:redstone_ore"); - - private final ArrayDeque> prevBlocks = new ArrayDeque<>(); - private final OverlayRenderer renderer = new OverlayRenderer(); + private final BlockBreakingCache cache = new BlockBreakingCache(); + private final OverlayRenderer overlay = new OverlayRenderer(); private BlockPos currentBlock; public NukerHack() @@ -85,16 +53,14 @@ public NukerHack() super("Nuker"); setCategory(Category.BLOCKS); addSetting(range); - addSetting(mode); - addSetting(id); - addSetting(lockId); - addSetting(multiIdList); + commonSettings.getSettings().forEach(this::addSetting); + addSetting(swingHand); } @Override public String getRenderName() { - return mode.getSelected().getRenderName(this); + return getName() + commonSettings.getRenderNameSuffix(); } @Override @@ -105,9 +71,10 @@ protected void onEnable() WURST.getHax().nukerLegitHack.setEnabled(false); WURST.getHax().speedNukerHack.setEnabled(false); WURST.getHax().tunnellerHack.setEnabled(false); + WURST.getHax().veinMinerHack.setEnabled(false); EVENTS.add(UpdateListener.class, this); - EVENTS.add(LeftClickListener.class, this); + EVENTS.add(LeftClickListener.class, commonSettings); EVENTS.add(RenderListener.class, this); } @@ -115,7 +82,7 @@ protected void onEnable() protected void onDisable() { EVENTS.remove(UpdateListener.class, this); - EVENTS.remove(LeftClickListener.class, this); + EVENTS.remove(LeftClickListener.class, commonSettings); EVENTS.remove(RenderListener.class, this); if(currentBlock != null) @@ -125,11 +92,9 @@ protected void onDisable() currentBlock = null; } - prevBlocks.clear(); - renderer.resetProgress(); - - if(!lockId.isChecked()) - id.setBlock(Blocks.AIR); + cache.reset(); + overlay.resetProgress(); + commonSettings.reset(); } @Override @@ -137,12 +102,7 @@ public void onUpdate() { currentBlock = null; - // abort if user is mining manually - if(MC.options.attackKey.isPressed()) - return; - - // abort if using IDNuker without an ID being set - if(mode.getSelected() == Mode.ID && id.getBlock() == Blocks.AIR) + if(MC.options.attackKey.isPressed() || commonSettings.isIdModeWithAir()) return; Vec3d eyesVec = RotationUtils.getEyesPos(); @@ -150,137 +110,62 @@ public void onUpdate() double rangeSq = range.getValueSq(); int blockRange = range.getValueCeil(); - Stream stream = - BlockUtils.getAllInBoxStream(eyesBlock, blockRange) - .filter(pos -> pos.getSquaredDistance(eyesVec) <= rangeSq) - .filter(BlockUtils::canBeClicked) - .filter(mode.getSelected().getValidator(this)).sorted(Comparator - .comparingDouble(pos -> pos.getSquaredDistance(eyesVec))); + Stream stream = BlockUtils + .getAllInBoxStream(eyesBlock, blockRange) + .filter(commonSettings::shouldBreakBlock) + .map(BlockBreaker::getBlockBreakingParams).filter(Objects::nonNull); + + if(commonSettings.isSphereShape()) + stream = stream.filter(params -> params.distanceSq() <= rangeSq); + + stream = stream.sorted(BlockBreaker.comparingParams()); // Break all blocks in creative mode if(MC.player.getAbilities().creativeMode) { MC.interactionManager.cancelBlockBreaking(); - renderer.resetProgress(); + overlay.resetProgress(); - ArrayList blocks = filterOutRecentBlocks(stream); + ArrayList blocks = cache + .filterOutRecentBlocks(stream.map(BlockBreakingParams::pos)); if(blocks.isEmpty()) return; currentBlock = blocks.get(0); BlockBreaker.breakBlocksWithPacketSpam(blocks); + swingHand.swing(Hand.MAIN_HAND); return; } // Break the first valid block in survival mode - currentBlock = - stream.filter(BlockBreaker::breakOneBlock).findFirst().orElse(null); + currentBlock = stream.filter(this::breakOneBlock) + .map(BlockBreakingParams::pos).findFirst().orElse(null); if(currentBlock == null) { MC.interactionManager.cancelBlockBreaking(); - renderer.resetProgress(); + overlay.resetProgress(); return; } - if(BlockUtils.getHardness(currentBlock) < 1) - renderer.updateProgress(); - else - renderer.resetProgress(); + overlay.updateProgress(); } - /* - * Waits 5 ticks before trying to break the same block again, which - * makes it much more likely that the server will accept the block - * breaking packets. - */ - private ArrayList filterOutRecentBlocks(Stream stream) + private boolean breakOneBlock(BlockBreakingParams params) { - for(Set set : prevBlocks) - stream = stream.filter(pos -> !set.contains(pos)); - - ArrayList blocks = - stream.collect(Collectors.toCollection(ArrayList::new)); + WURST.getRotationFaker().faceVectorPacket(params.hitVec()); - prevBlocks.addLast(new HashSet<>(blocks)); - while(prevBlocks.size() > 5) - prevBlocks.removeFirst(); + if(!MC.interactionManager.updateBlockBreakingProgress(params.pos(), + params.side())) + return false; - return blocks; - } - - @Override - public void onLeftClick(LeftClickEvent event) - { - if(mode.getSelected() != Mode.ID) - return; - - if(lockId.isChecked()) - return; - - if(MC.crosshairTarget == null - || MC.crosshairTarget.getType() != HitResult.Type.BLOCK) - return; - - BlockHitResult blockHitResult = (BlockHitResult)MC.crosshairTarget; - BlockPos pos = new BlockPos(blockHitResult.getBlockPos()); - id.setBlockName(BlockUtils.getName(pos)); + swingHand.swing(Hand.MAIN_HAND); + return true; } @Override public void onRender(MatrixStack matrixStack, float partialTicks) { - renderer.render(matrixStack, partialTicks, currentBlock); - } - - private enum Mode - { - NORMAL("Normal", NukerHack::getName, (n, p) -> true), - - ID("ID", - n -> "IDNuker [" + n.id.getBlockName().replace("minecraft:", "") - + "]", - (n, p) -> BlockUtils.getName(p).equals(n.id.getBlockName())), - - MULTI_ID("MultiID", - n -> "MultiIDNuker [" + n.multiIdList.getBlockNames().size() - + (n.multiIdList.getBlockNames().size() == 1 ? " ID]" - : " IDs]"), - (n, p) -> n.multiIdList.getBlockNames() - .contains(BlockUtils.getName(p))), - - FLAT("Flat", n -> "FlatNuker", - (n, p) -> p.getY() >= MC.player.getPos().getY()), - - SMASH("Smash", n -> "SmashNuker", - (n, p) -> BlockUtils.getHardness(p) >= 1); - - private final String name; - private final Function renderName; - private final BiPredicate validator; - - private Mode(String name, Function renderName, - BiPredicate validator) - { - this.name = name; - this.renderName = renderName; - this.validator = validator; - } - - @Override - public String toString() - { - return name; - } - - public String getRenderName(NukerHack n) - { - return renderName.apply(n); - } - - public Predicate getValidator(NukerHack n) - { - return p -> validator.test(n, p); - } + overlay.render(matrixStack, partialTicks, currentBlock); } } diff --git a/src/main/java/net/wurstclient/hacks/NukerLegitHack.java b/src/main/java/net/wurstclient/hacks/NukerLegitHack.java index 1b027bf3b5..e04d972126 100644 --- a/src/main/java/net/wurstclient/hacks/NukerLegitHack.java +++ b/src/main/java/net/wurstclient/hacks/NukerLegitHack.java @@ -7,30 +7,32 @@ */ package net.wurstclient.hacks; -import java.util.ArrayList; import java.util.Comparator; -import java.util.function.BiPredicate; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.stream.Collectors; +import java.util.Objects; +import java.util.stream.Stream; -import net.minecraft.block.Blocks; +import net.minecraft.block.BlockState; +import net.minecraft.client.network.ClientPlayerInteractionManager; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.hit.HitResult; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import net.wurstclient.Category; import net.wurstclient.SearchTags; +import net.wurstclient.events.HandleBlockBreakingListener; import net.wurstclient.events.LeftClickListener; import net.wurstclient.events.RenderListener; import net.wurstclient.events.UpdateListener; import net.wurstclient.hack.Hack; -import net.wurstclient.settings.BlockListSetting; -import net.wurstclient.settings.BlockSetting; -import net.wurstclient.settings.CheckboxSetting; -import net.wurstclient.settings.EnumSetting; +import net.wurstclient.hacks.nukers.CommonNukerSettings; +import net.wurstclient.mixinterface.IKeyBinding; import net.wurstclient.settings.SliderSetting; import net.wurstclient.settings.SliderSetting.ValueDisplay; +import net.wurstclient.settings.SwingHandSetting; +import net.wurstclient.settings.SwingHandSetting.SwingHand; import net.wurstclient.util.BlockBreaker; import net.wurstclient.util.BlockBreaker.BlockBreakingParams; import net.wurstclient.util.BlockUtils; @@ -39,116 +41,66 @@ @SearchTags({"LegitNuker", "nuker legit", "legit nuker"}) public final class NukerLegitHack extends Hack - implements LeftClickListener, RenderListener, UpdateListener + implements UpdateListener, HandleBlockBreakingListener, RenderListener { private final SliderSetting range = - new SliderSetting("Range", 4.25, 1, 4.25, 0.05, ValueDisplay.DECIMAL); + new SliderSetting("Range", 4.25, 1, 4.5, 0.05, ValueDisplay.DECIMAL); - private final EnumSetting mode = new EnumSetting<>("Mode", - "\u00a7lNormal\u00a7r mode simply breaks everything around you.\n" - + "\u00a7lID\u00a7r mode only breaks the selected block type. Left-click on a block to select it.\n" - + "\u00a7lMultiID\u00a7r mode only breaks the block types in your MultiID List.\n" - + "\u00a7lFlat\u00a7r mode flattens the area around you, but won't dig down.\n" - + "\u00a7lSmash\u00a7r mode only breaks blocks that can be destroyed instantly (e.g. tall grass).", - Mode.values(), Mode.NORMAL); + private final CommonNukerSettings commonSettings = + new CommonNukerSettings(); - private final BlockSetting id = - new BlockSetting("ID", "The type of block to break in ID mode.\n" - + "air = won't break anything", "minecraft:air", true); + private final SwingHandSetting swingHand = + SwingHandSetting.withoutOffOption( + SwingHandSetting.genericMiningDescription(this), SwingHand.CLIENT); - private final CheckboxSetting lockId = new CheckboxSetting("Lock ID", - "Prevents changing the ID by clicking on blocks or restarting NukerLegit.", - false); - - private final BlockListSetting multiIdList = new BlockListSetting( - "MultiID List", "The types of blocks to break in MultiID mode.", - "minecraft:ancient_debris", "minecraft:bone_block", - "minecraft:coal_ore", "minecraft:copper_ore", - "minecraft:deepslate_coal_ore", "minecraft:deepslate_copper_ore", - "minecraft:deepslate_diamond_ore", "minecraft:deepslate_emerald_ore", - "minecraft:deepslate_gold_ore", "minecraft:deepslate_iron_ore", - "minecraft:deepslate_lapis_ore", "minecraft:deepslate_redstone_ore", - "minecraft:diamond_ore", "minecraft:emerald_ore", "minecraft:glowstone", - "minecraft:gold_ore", "minecraft:iron_ore", "minecraft:lapis_ore", - "minecraft:nether_gold_ore", "minecraft:nether_quartz_ore", - "minecraft:raw_copper_block", "minecraft:raw_gold_block", - "minecraft:raw_iron_block", "minecraft:redstone_ore"); - - private final OverlayRenderer renderer = new OverlayRenderer(); + private final OverlayRenderer overlay = new OverlayRenderer(); private BlockPos currentBlock; public NukerLegitHack() { super("NukerLegit"); - setCategory(Category.BLOCKS); addSetting(range); - addSetting(mode); - addSetting(id); - addSetting(lockId); - addSetting(multiIdList); + commonSettings.getSettings().forEach(this::addSetting); + addSetting(swingHand); } @Override public String getRenderName() { - return mode.getSelected().getRenderName(this); + return getName() + commonSettings.getRenderNameSuffix(); } @Override protected void onEnable() { - // disable other nukers WURST.getHax().autoMineHack.setEnabled(false); WURST.getHax().excavatorHack.setEnabled(false); WURST.getHax().nukerHack.setEnabled(false); WURST.getHax().speedNukerHack.setEnabled(false); WURST.getHax().tunnellerHack.setEnabled(false); + WURST.getHax().veinMinerHack.setEnabled(false); - // add listeners - EVENTS.add(LeftClickListener.class, this); EVENTS.add(UpdateListener.class, this); + EVENTS.add(LeftClickListener.class, commonSettings); + EVENTS.add(HandleBlockBreakingListener.class, this); EVENTS.add(RenderListener.class, this); } @Override protected void onDisable() { - // remove listeners - EVENTS.remove(LeftClickListener.class, this); EVENTS.remove(UpdateListener.class, this); + EVENTS.remove(LeftClickListener.class, commonSettings); + EVENTS.remove(HandleBlockBreakingListener.class, this); EVENTS.remove(RenderListener.class, this); // resets - MC.options.attackKey.setPressed(false); - renderer.resetProgress(); + IKeyBinding.get(MC.options.attackKey).resetPressedState(); + MC.interactionManager.cancelBlockBreaking(); + overlay.resetProgress(); currentBlock = null; - if(!lockId.isChecked()) - id.setBlock(Blocks.AIR); - } - - @Override - public void onLeftClick(LeftClickEvent event) - { - // check mode - if(mode.getSelected() != Mode.ID) - return; - - if(lockId.isChecked()) - return; - - // check hitResult - if(MC.crosshairTarget == null - || !(MC.crosshairTarget instanceof BlockHitResult)) - return; - - // check pos - BlockPos pos = ((BlockHitResult)MC.crosshairTarget).getBlockPos(); - if(pos == null || BlockUtils.getBlock(pos) == Blocks.AIR) - return; - - // set id - id.setBlockName(BlockUtils.getName(pos)); + commonSettings.reset(); } @Override @@ -156,134 +108,104 @@ public void onUpdate() { currentBlock = null; - // abort if using IDNuker without an ID being set - if(mode.getSelected() == Mode.ID && id.getBlock() == Blocks.AIR) + if(commonSettings.isIdModeWithAir()) { - renderer.resetProgress(); + overlay.resetProgress(); return; } - // get valid blocks - Iterable validBlocks = getValidBlocks(range.getValueI(), - mode.getSelected().getValidator(this)); + // Ignore the attack cooldown because opening any screen + // will set it to 10k ticks. - // find closest valid block - for(BlockPos pos : validBlocks) + if(MC.player.isRiding()) { - // break block - if(!breakBlockExtraLegit(pos)) - continue; - - // set currentBlock if successful - currentBlock = pos; - break; + overlay.resetProgress(); + MC.interactionManager.cancelBlockBreaking(); + return; } + Vec3d eyesVec = RotationUtils.getEyesPos(); + BlockPos eyesBlock = BlockPos.ofFloored(eyesVec); + double maxRange = MC.player.getBlockInteractionRange() + 1; + double rangeSq = commonSettings.isSphereShape() ? range.getValueSq() + : maxRange * maxRange; + int blockRange = range.getValueCeil(); + + Stream stream = BlockUtils + .getAllInBoxStream(eyesBlock, blockRange) + .filter(commonSettings::shouldBreakBlock) + .map(BlockBreaker::getBlockBreakingParams).filter(Objects::nonNull) + .filter(BlockBreakingParams::lineOfSight) + .filter(params -> params.distanceSq() <= rangeSq).sorted( + Comparator.comparingDouble(BlockBreakingParams::distanceSq)); + + // Break the first valid block + currentBlock = stream.filter(this::breakBlock) + .map(BlockBreakingParams::pos).findFirst().orElse(null); + // reset if no block was found if(currentBlock == null) { - MC.options.attackKey.setPressed(false); - renderer.resetProgress(); + IKeyBinding.get(MC.options.attackKey).resetPressedState(); + overlay.resetProgress(); } - renderer.updateProgress(); + overlay.updateProgress(); } - private ArrayList getValidBlocks(int range, - Predicate validator) + private boolean breakBlock(BlockBreakingParams params) { - Vec3d eyesVec = RotationUtils.getEyesPos(); - BlockPos center = BlockPos.ofFloored(eyesVec); + ClientPlayerInteractionManager im = MC.interactionManager; - return BlockUtils.getAllInBoxStream(center, range) - .filter(BlockUtils::canBeClicked).filter(validator) - .sorted(Comparator.comparingDouble( - pos -> eyesVec.squaredDistanceTo(Vec3d.ofCenter(pos)))) - .collect(Collectors.toCollection(ArrayList::new)); - } - - private boolean breakBlockExtraLegit(BlockPos pos) - { - BlockBreakingParams params = BlockBreaker.getBlockBreakingParams(pos); - if(!params.lineOfSight() || params.distanceSq() > range.getValueSq()) - return false; - - // face block WURST.getRotationFaker().faceVectorClient(params.hitVec()); + HitResult hitResult = MC.crosshairTarget; + if(hitResult == null || hitResult.getType() != HitResult.Type.BLOCK + || !(hitResult instanceof BlockHitResult bHitResult)) + { + im.cancelBlockBreaking(); + return true; + } - WURST.getHax().autoToolHack.equipIfEnabled(pos); - - if(!MC.interactionManager.isBreakingBlock()) - MC.interactionManager.attackBlock(pos, params.side()); - - // if attack key is down but nothing happens, - // release it for one tick - if(MC.options.attackKey.isPressed() - && !MC.interactionManager.isBreakingBlock()) + BlockPos pos = bHitResult.getBlockPos(); + BlockState state = MC.world.getBlockState(pos); + Direction side = bHitResult.getSide(); + if(state.isAir() || !params.pos().equals(pos) + || !params.side().equals(side)) { - MC.options.attackKey.setPressed(false); + im.cancelBlockBreaking(); return true; } - // damage block - MC.options.attackKey.setPressed(true); + WURST.getHax().autoToolHack.equipIfEnabled(params.pos()); + + if(MC.player.isUsingItem()) + // This case doesn't cancel block breaking in vanilla Minecraft. + return true; + + if(!im.isBreakingBlock()) + im.attackBlock(pos, side); + + if(im.updateBlockBreakingProgress(pos, side)) + { + MC.particleManager.addBlockBreakingParticles(pos, side); + swingHand.swing(Hand.MAIN_HAND); + MC.options.attackKey.setPressed(true); + } + return true; } @Override - public void onRender(MatrixStack matrixStack, float partialTicks) + public void onHandleBlockBreaking(HandleBlockBreakingEvent event) { - renderer.render(matrixStack, partialTicks, currentBlock); + // Cancel vanilla block breaking so we don't send the packets twice. + if(currentBlock != null) + event.cancel(); } - private enum Mode + @Override + public void onRender(MatrixStack matrixStack, float partialTicks) { - NORMAL("Normal", n -> "NukerLegit", (n, p) -> true), - - ID("ID", - n -> "IDNukerLegit [" - + n.id.getBlockName().replace("minecraft:", "") + "]", - (n, p) -> BlockUtils.getName(p).equals(n.id.getBlockName())), - - MULTI_ID("MultiID", - n -> "MultiIDNuker [" + n.multiIdList.getBlockNames().size() - + (n.multiIdList.getBlockNames().size() == 1 ? " ID]" - : " IDs]"), - (n, p) -> n.multiIdList.getBlockNames() - .contains(BlockUtils.getName(p))), - - FLAT("Flat", n -> "FlatNukerLegit", - (n, p) -> p.getY() >= MC.player.getPos().getY()), - - SMASH("Smash", n -> "SmashNukerLegit", - (n, p) -> BlockUtils.getHardness(p) >= 1); - - private final String name; - private final Function renderName; - private final BiPredicate validator; - - private Mode(String name, Function renderName, - BiPredicate validator) - { - this.name = name; - this.renderName = renderName; - this.validator = validator; - } - - @Override - public String toString() - { - return name; - } - - public String getRenderName(NukerLegitHack n) - { - return renderName.apply(n); - } - - public Predicate getValidator(NukerLegitHack n) - { - return p -> validator.test(n, p); - } + overlay.render(matrixStack, partialTicks, currentBlock); } } diff --git a/src/main/java/net/wurstclient/hacks/PortalEspHack.java b/src/main/java/net/wurstclient/hacks/PortalEspHack.java index 4e691814e8..2480ebb0b7 100644 --- a/src/main/java/net/wurstclient/hacks/PortalEspHack.java +++ b/src/main/java/net/wurstclient/hacks/PortalEspHack.java @@ -33,9 +33,9 @@ import net.wurstclient.settings.ChunkAreaSetting; import net.wurstclient.settings.ColorSetting; import net.wurstclient.settings.EspStyleSetting; -import net.wurstclient.util.ChunkSearcher.Result; -import net.wurstclient.util.ChunkSearcherCoordinator; import net.wurstclient.util.RenderUtils; +import net.wurstclient.util.chunk.ChunkSearcher.Result; +import net.wurstclient.util.chunk.ChunkSearcherCoordinator; public final class PortalEspHack extends Hack implements UpdateListener, CameraTransformViewBobbingListener, RenderListener diff --git a/src/main/java/net/wurstclient/hacks/ProtectHack.java b/src/main/java/net/wurstclient/hacks/ProtectHack.java index 7e1fe6d782..17a14ecbb8 100644 --- a/src/main/java/net/wurstclient/hacks/ProtectHack.java +++ b/src/main/java/net/wurstclient/hacks/ProtectHack.java @@ -45,7 +45,7 @@ public final class ProtectHack extends Hack new AttackSpeedSliderSetting(); private final SwingHandSetting swingHand = new SwingHandSetting( - "How Protect should swing your hand when attacking.", SwingHand.CLIENT); + SwingHandSetting.genericCombatDescription(this), SwingHand.CLIENT); private final CheckboxSetting useAi = new CheckboxSetting("Use AI (experimental)", false); diff --git a/src/main/java/net/wurstclient/hacks/ReachHack.java b/src/main/java/net/wurstclient/hacks/ReachHack.java index 28f90cb258..c7580933c7 100644 --- a/src/main/java/net/wurstclient/hacks/ReachHack.java +++ b/src/main/java/net/wurstclient/hacks/ReachHack.java @@ -13,7 +13,6 @@ import net.wurstclient.settings.SliderSetting; import net.wurstclient.settings.SliderSetting.ValueDisplay; -// TODO: Remove this hack in 1.20.5, as it seems to be patched. @SearchTags({"range"}) public final class ReachHack extends Hack { @@ -32,6 +31,6 @@ public double getReachDistance() return range.getValue(); } - // See ClientPlayerEntityMixin.method_55754() and - // ClientPlayerEntityMixin.method_55755() + // See ClientPlayerEntityMixin.getBlockInteractionRange() and + // ClientPlayerEntityMixin.getEntityInteractionRange() } diff --git a/src/main/java/net/wurstclient/hacks/SearchHack.java b/src/main/java/net/wurstclient/hacks/SearchHack.java index fb09198019..41464ee2c6 100644 --- a/src/main/java/net/wurstclient/hacks/SearchHack.java +++ b/src/main/java/net/wurstclient/hacks/SearchHack.java @@ -42,11 +42,11 @@ import net.wurstclient.settings.SliderSetting.ValueDisplay; import net.wurstclient.util.BlockVertexCompiler; import net.wurstclient.util.ChatUtils; -import net.wurstclient.util.ChunkSearcher; -import net.wurstclient.util.ChunkSearcherCoordinator; import net.wurstclient.util.RegionPos; import net.wurstclient.util.RenderUtils; import net.wurstclient.util.RotationUtils; +import net.wurstclient.util.chunk.ChunkSearcher; +import net.wurstclient.util.chunk.ChunkSearcherCoordinator; @SearchTags({"BlockESP", "block esp"}) public final class SearchHack extends Hack diff --git a/src/main/java/net/wurstclient/hacks/SpeedNukerHack.java b/src/main/java/net/wurstclient/hacks/SpeedNukerHack.java index 4d656a26b2..0ecb8a0a7d 100644 --- a/src/main/java/net/wurstclient/hacks/SpeedNukerHack.java +++ b/src/main/java/net/wurstclient/hacks/SpeedNukerHack.java @@ -9,14 +9,10 @@ import java.util.ArrayList; import java.util.Comparator; -import java.util.Iterator; -import java.util.function.BiPredicate; -import java.util.function.Function; -import java.util.function.Predicate; import java.util.stream.Collectors; +import java.util.stream.Stream; -import net.minecraft.block.Blocks; -import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.wurstclient.Category; @@ -25,199 +21,96 @@ import net.wurstclient.events.UpdateListener; import net.wurstclient.hack.DontSaveState; import net.wurstclient.hack.Hack; -import net.wurstclient.settings.BlockListSetting; -import net.wurstclient.settings.BlockSetting; -import net.wurstclient.settings.CheckboxSetting; -import net.wurstclient.settings.EnumSetting; +import net.wurstclient.hacks.nukers.CommonNukerSettings; import net.wurstclient.settings.SliderSetting; import net.wurstclient.settings.SliderSetting.ValueDisplay; +import net.wurstclient.settings.SwingHandSetting; +import net.wurstclient.settings.SwingHandSetting.SwingHand; import net.wurstclient.util.BlockBreaker; import net.wurstclient.util.BlockUtils; import net.wurstclient.util.RotationUtils; @SearchTags({"speed nuker", "FastNuker", "fast nuker"}) @DontSaveState -public final class SpeedNukerHack extends Hack - implements LeftClickListener, UpdateListener +public final class SpeedNukerHack extends Hack implements UpdateListener { private final SliderSetting range = new SliderSetting("Range", 5, 1, 6, 0.05, ValueDisplay.DECIMAL); - private final EnumSetting mode = new EnumSetting<>("Mode", - "\u00a7lNormal\u00a7r mode simply breaks everything around you.\n" - + "\u00a7lID\u00a7r mode only breaks the selected block type. Left-click on a block to select it.\n" - + "\u00a7lMultiID\u00a7r mode only breaks the block types in your MultiID List.\n" - + "\u00a7lFlat\u00a7r mode flattens the area around you, but won't dig down.\n" - + "\u00a7lSmash\u00a7r mode only breaks blocks that can be destroyed instantly (e.g. tall grass).", - Mode.values(), Mode.NORMAL); + private final CommonNukerSettings commonSettings = + new CommonNukerSettings(); - private final BlockSetting id = - new BlockSetting("ID", "The type of block to break in ID mode.\n" - + "air = won't break anything", "minecraft:air", true); - - private final CheckboxSetting lockId = new CheckboxSetting("Lock ID", - "Prevents changing the ID by clicking on blocks or restarting SpeedNuker.", - false); - - private final BlockListSetting multiIdList = new BlockListSetting( - "MultiID List", "The types of blocks to break in MultiID mode.", - "minecraft:ancient_debris", "minecraft:bone_block", - "minecraft:coal_ore", "minecraft:copper_ore", - "minecraft:deepslate_coal_ore", "minecraft:deepslate_copper_ore", - "minecraft:deepslate_diamond_ore", "minecraft:deepslate_emerald_ore", - "minecraft:deepslate_gold_ore", "minecraft:deepslate_iron_ore", - "minecraft:deepslate_lapis_ore", "minecraft:deepslate_redstone_ore", - "minecraft:diamond_ore", "minecraft:emerald_ore", "minecraft:glowstone", - "minecraft:gold_ore", "minecraft:iron_ore", "minecraft:lapis_ore", - "minecraft:nether_gold_ore", "minecraft:nether_quartz_ore", - "minecraft:raw_copper_block", "minecraft:raw_gold_block", - "minecraft:raw_iron_block", "minecraft:redstone_ore"); + private final SwingHandSetting swingHand = new SwingHandSetting( + SwingHandSetting.genericMiningDescription(this), SwingHand.OFF); public SpeedNukerHack() { super("SpeedNuker"); - setCategory(Category.BLOCKS); addSetting(range); - addSetting(mode); - addSetting(id); - addSetting(lockId); - addSetting(multiIdList); + commonSettings.getSettings().forEach(this::addSetting); + addSetting(swingHand); } @Override public String getRenderName() { - return mode.getSelected().renderName.apply(this); + return getName() + commonSettings.getRenderNameSuffix(); } @Override protected void onEnable() { - // disable other nukers WURST.getHax().autoMineHack.setEnabled(false); WURST.getHax().excavatorHack.setEnabled(false); WURST.getHax().nukerHack.setEnabled(false); WURST.getHax().nukerLegitHack.setEnabled(false); WURST.getHax().tunnellerHack.setEnabled(false); + WURST.getHax().veinMinerHack.setEnabled(false); - // add listeners - EVENTS.add(LeftClickListener.class, this); + EVENTS.add(LeftClickListener.class, commonSettings); EVENTS.add(UpdateListener.class, this); } @Override protected void onDisable() { - // remove listeners - EVENTS.remove(LeftClickListener.class, this); + EVENTS.remove(LeftClickListener.class, commonSettings); EVENTS.remove(UpdateListener.class, this); - // resets - if(!lockId.isChecked()) - id.setBlock(Blocks.AIR); + commonSettings.reset(); } @Override public void onUpdate() { - // abort if using IDNuker without an ID being set - if(mode.getSelected() == Mode.ID && id.getBlock() == Blocks.AIR) + if(commonSettings.isIdModeWithAir()) return; - // get valid blocks - Iterable validBlocks = getValidBlocks(range.getValue(), - pos -> mode.getSelected().validator.test(this, pos)); - - Iterator autoToolIterator = validBlocks.iterator(); - if(autoToolIterator.hasNext()) - WURST.getHax().autoToolHack.equipIfEnabled(autoToolIterator.next()); + Vec3d eyesVec = RotationUtils.getEyesPos(); + BlockPos eyesBlock = BlockPos.ofFloored(eyesVec); + double rangeSq = range.getValueSq(); + int blockRange = range.getValueCeil(); - // break all blocks - BlockBreaker.breakBlocksWithPacketSpam(validBlocks); - } - - private ArrayList getValidBlocks(double range, - Predicate validator) - { - Vec3d eyesVec = RotationUtils.getEyesPos().subtract(0.5, 0.5, 0.5); - double rangeSq = Math.pow(range + 0.5, 2); - int rangeI = (int)Math.ceil(range); + Stream stream = + BlockUtils.getAllInBoxStream(eyesBlock, blockRange) + .filter(BlockUtils::canBeClicked) + .filter(commonSettings::shouldBreakBlock); - BlockPos center = BlockPos.ofFloored(RotationUtils.getEyesPos()); - BlockPos min = center.add(-rangeI, -rangeI, -rangeI); - BlockPos max = center.add(rangeI, rangeI, rangeI); + if(commonSettings.isSphereShape()) + stream = stream + .filter(pos -> pos.getSquaredDistance(eyesVec) <= rangeSq); - return BlockUtils.getAllInBox(min, max).stream() - .filter(pos -> eyesVec.squaredDistanceTo(Vec3d.of(pos)) <= rangeSq) - .filter(BlockUtils::canBeClicked).filter(validator) - .sorted(Comparator.comparingDouble( - pos -> eyesVec.squaredDistanceTo(Vec3d.of(pos)))) + ArrayList blocks = stream + .sorted(Comparator + .comparingDouble(pos -> pos.getSquaredDistance(eyesVec))) .collect(Collectors.toCollection(ArrayList::new)); - } - - @Override - public void onLeftClick(LeftClickEvent event) - { - // check mode - if(mode.getSelected() != Mode.ID) - return; - - if(lockId.isChecked()) - return; - - // check hitResult - if(MC.crosshairTarget == null - || !(MC.crosshairTarget instanceof BlockHitResult)) - return; - // check pos - BlockPos pos = ((BlockHitResult)MC.crosshairTarget).getBlockPos(); - if(pos == null || BlockUtils.getBlock(pos) == Blocks.AIR) + if(blocks.isEmpty()) return; - // set id - id.setBlockName(BlockUtils.getName(pos)); - } - - private enum Mode - { - NORMAL("Normal", n -> "SpeedNuker", (n, pos) -> true), - - ID("ID", - n -> "IDSpeedNuker [" - + n.id.getBlockName().replace("minecraft:", "") + "]", - (n, pos) -> BlockUtils.getName(pos).equals(n.id.getBlockName())), - - MULTI_ID("MultiID", - n -> "MultiIDNuker [" + n.multiIdList.getBlockNames().size() - + (n.multiIdList.getBlockNames().size() == 1 ? " ID]" - : " IDs]"), - (n, p) -> n.multiIdList.getBlockNames() - .contains(BlockUtils.getName(p))), - - FLAT("Flat", n -> "FlatSpeedNuker", - (n, pos) -> pos.getY() >= MC.player.getY()), - - SMASH("Smash", n -> "SmashSpeedNuker", - (n, pos) -> BlockUtils.getHardness(pos) >= 1); - - private final String name; - private final Function renderName; - private final BiPredicate validator; - - private Mode(String name, Function renderName, - BiPredicate validator) - { - this.name = name; - this.renderName = renderName; - this.validator = validator; - } - - @Override - public String toString() - { - return name; - } + WURST.getHax().autoToolHack.equipIfEnabled(blocks.get(0)); + BlockBreaker.breakBlocksWithPacketSpam(blocks); + swingHand.swing(Hand.MAIN_HAND); } } diff --git a/src/main/java/net/wurstclient/hacks/TillauraHack.java b/src/main/java/net/wurstclient/hacks/TillauraHack.java index a30be4f474..4425369dad 100644 --- a/src/main/java/net/wurstclient/hacks/TillauraHack.java +++ b/src/main/java/net/wurstclient/hacks/TillauraHack.java @@ -20,7 +20,7 @@ import net.minecraft.util.math.Vec3d; import net.wurstclient.Category; import net.wurstclient.SearchTags; -import net.wurstclient.events.PostMotionListener; +import net.wurstclient.events.HandleInputListener; import net.wurstclient.hack.Hack; import net.wurstclient.settings.CheckboxSetting; import net.wurstclient.settings.SliderSetting; @@ -35,7 +35,7 @@ @SearchTags({"till aura", "HoeAura", "hoe aura", "FarmlandAura", "farmland aura", "farm land aura", "AutoTill", "auto till", "AutoHoe", "auto hoe"}) -public final class TillauraHack extends Hack implements PostMotionListener +public final class TillauraHack extends Hack implements HandleInputListener { private final SliderSetting range = new SliderSetting("Range", "How far Tillaura will reach to till blocks.", 5, 1, 6, 0.05, @@ -67,17 +67,17 @@ public TillauraHack() @Override protected void onEnable() { - EVENTS.add(PostMotionListener.class, this); + EVENTS.add(HandleInputListener.class, this); } @Override protected void onDisable() { - EVENTS.remove(PostMotionListener.class, this); + EVENTS.remove(HandleInputListener.class, this); } @Override - public void onPostMotion() + public void onHandleInput() { // wait for right click timer if(MC.itemUseCooldown > 0) diff --git a/src/main/java/net/wurstclient/hacks/TpAuraHack.java b/src/main/java/net/wurstclient/hacks/TpAuraHack.java index cec37a0578..6c428b74f5 100644 --- a/src/main/java/net/wurstclient/hacks/TpAuraHack.java +++ b/src/main/java/net/wurstclient/hacks/TpAuraHack.java @@ -50,7 +50,7 @@ public final class TpAuraHack extends Hack implements UpdateListener Priority.values(), Priority.ANGLE); private final SwingHandSetting swingHand = new SwingHandSetting( - "How TP-Aura should swing your hand when attacking.", SwingHand.CLIENT); + SwingHandSetting.genericCombatDescription(this), SwingHand.CLIENT); private final PauseAttackOnContainersSetting pauseOnContainers = new PauseAttackOnContainersSetting(true); diff --git a/src/main/java/net/wurstclient/hacks/TreeBotHack.java b/src/main/java/net/wurstclient/hacks/TreeBotHack.java index e198b585c1..c3c6d56afe 100644 --- a/src/main/java/net/wurstclient/hacks/TreeBotHack.java +++ b/src/main/java/net/wurstclient/hacks/TreeBotHack.java @@ -40,6 +40,7 @@ import net.wurstclient.settings.SliderSetting; import net.wurstclient.settings.SliderSetting.ValueDisplay; import net.wurstclient.settings.SwingHandSetting; +import net.wurstclient.settings.SwingHandSetting.SwingHand; import net.wurstclient.util.BlockBreaker; import net.wurstclient.util.BlockBreaker.BlockBreakingParams; import net.wurstclient.util.BlockUtils; @@ -55,7 +56,7 @@ public final class TreeBotHack extends Hack ValueDisplay.DECIMAL); private final FacingSetting facing = FacingSetting.withoutPacketSpam( - "How to face the logs and leaves when breaking them.\n\n" + "How TreeBot should face the logs and leaves when breaking them.\n\n" + "\u00a7lOff\u00a7r - Don't face the blocks at all. Will be" + " detected by anti-cheat plugins.\n\n" + "\u00a7lServer-side\u00a7r - Face the blocks on the" @@ -65,8 +66,8 @@ public final class TreeBotHack extends Hack + " camera on the client-side. This is the most legit option, but" + " can be disorienting to look at."); - private final SwingHandSetting swingHand = new SwingHandSetting( - "How TreeBot should swing your hand when breaking logs and leaves."); + private final SwingHandSetting swingHand = + new SwingHandSetting(this, SwingHand.SERVER); private TreeFinder treeFinder; private AngleFinder angleFinder; diff --git a/src/main/java/net/wurstclient/hacks/TriggerBotHack.java b/src/main/java/net/wurstclient/hacks/TriggerBotHack.java index 8bc275585c..814507736c 100644 --- a/src/main/java/net/wurstclient/hacks/TriggerBotHack.java +++ b/src/main/java/net/wurstclient/hacks/TriggerBotHack.java @@ -47,11 +47,8 @@ public final class TriggerBotHack extends Hack 100, 0, 1000, 50, ValueDisplay.INTEGER.withPrefix("\u00b1") .withSuffix("ms").withLabel(0, "off")); - private final SwingHandSetting swingHand = new SwingHandSetting( - "How TriggerBot should swing your hand when attacking.\n\n" - + "This setting will be ignored if \"Simulate mouse click\" is" - + " enabled.", - SwingHand.CLIENT); + private final SwingHandSetting swingHand = + new SwingHandSetting(this, SwingHand.CLIENT); private final CheckboxSetting attackWhileBlocking = new CheckboxSetting("Attack while blocking", diff --git a/src/main/java/net/wurstclient/hacks/TunnellerHack.java b/src/main/java/net/wurstclient/hacks/TunnellerHack.java index f3e05f885e..d18f2ece1d 100644 --- a/src/main/java/net/wurstclient/hacks/TunnellerHack.java +++ b/src/main/java/net/wurstclient/hacks/TunnellerHack.java @@ -37,7 +37,6 @@ import net.minecraft.entity.FallingBlockEntity; import net.minecraft.item.BlockItem; import net.minecraft.item.ItemStack; -import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; @@ -56,6 +55,7 @@ import net.wurstclient.settings.EnumSetting; import net.wurstclient.settings.SliderSetting; import net.wurstclient.settings.SliderSetting.ValueDisplay; +import net.wurstclient.settings.SwingHandSetting.SwingHand; import net.wurstclient.util.BlockUtils; import net.wurstclient.util.ChatUtils; import net.wurstclient.util.RegionPos; @@ -123,6 +123,7 @@ protected void onEnable() WURST.getHax().nukerLegitHack.setEnabled(false); WURST.getHax().protectHack.setEnabled(false); WURST.getHax().speedNukerHack.setEnabled(false); + WURST.getHax().veinMinerHack.setEnabled(false); // add listeners EVENTS.add(UpdateListener.class, this); @@ -890,8 +891,7 @@ private void placeBlockSimple(BlockPos pos) side.getOpposite(), hitVec); // swing arm - MC.player.networkHandler - .sendPacket(new HandSwingC2SPacket(Hand.MAIN_HAND)); + SwingHand.SERVER.swing(Hand.MAIN_HAND); // reset timer MC.itemUseCooldown = 4; @@ -956,8 +956,7 @@ private boolean breakBlock(BlockPos pos) return false; // swing arm - MC.player.networkHandler - .sendPacket(new HandSwingC2SPacket(Hand.MAIN_HAND)); + SwingHand.SERVER.swing(Hand.MAIN_HAND); return true; } diff --git a/src/main/java/net/wurstclient/hacks/VeinMinerHack.java b/src/main/java/net/wurstclient/hacks/VeinMinerHack.java new file mode 100644 index 0000000000..f30f36c7af --- /dev/null +++ b/src/main/java/net/wurstclient/hacks/VeinMinerHack.java @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2014-2024 Wurst-Imperium and contributors. + * + * This source code is subject to the terms of the GNU General Public + * License, version 3. If a copy of the GPL was not distributed with this + * file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt + */ +package net.wurstclient.hacks; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Objects; +import java.util.stream.Stream; + +import org.lwjgl.opengl.GL11; + +import com.mojang.blaze3d.systems.RenderSystem; + +import net.minecraft.block.Block; +import net.minecraft.client.render.GameRenderer; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.hit.HitResult; +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 net.wurstclient.Category; +import net.wurstclient.events.LeftClickListener; +import net.wurstclient.events.RenderListener; +import net.wurstclient.events.UpdateListener; +import net.wurstclient.hack.Hack; +import net.wurstclient.hacks.nukers.NukerMultiIdListSetting; +import net.wurstclient.settings.CheckboxSetting; +import net.wurstclient.settings.SliderSetting; +import net.wurstclient.settings.SliderSetting.ValueDisplay; +import net.wurstclient.settings.SwingHandSetting; +import net.wurstclient.settings.SwingHandSetting.SwingHand; +import net.wurstclient.util.BlockBreaker; +import net.wurstclient.util.BlockBreaker.BlockBreakingParams; +import net.wurstclient.util.BlockBreakingCache; +import net.wurstclient.util.BlockUtils; +import net.wurstclient.util.OverlayRenderer; +import net.wurstclient.util.RegionPos; +import net.wurstclient.util.RenderUtils; +import net.wurstclient.util.RotationUtils; + +public final class VeinMinerHack extends Hack + implements UpdateListener, LeftClickListener, RenderListener +{ + private final SliderSetting range = + new SliderSetting("Range", 5, 1, 6, 0.05, ValueDisplay.DECIMAL); + + private final CheckboxSetting flat = new CheckboxSetting("Flat mode", + "Won't break any blocks below your feet.", false); + + private final NukerMultiIdListSetting multiIdList = + new NukerMultiIdListSetting("The types of blocks to mine as veins."); + + private final SwingHandSetting swingHand = new SwingHandSetting( + SwingHandSetting.genericMiningDescription(this), SwingHand.SERVER); + + private final BlockBreakingCache cache = new BlockBreakingCache(); + private final OverlayRenderer overlay = new OverlayRenderer(); + private final HashSet currentVein = new HashSet<>(); + private BlockPos currentBlock; + + private final SliderSetting maxVeinSize = new SliderSetting("Max vein size", + "Maximum number of blocks to mine in a single vein.", 64, 1, 1000, 1, + ValueDisplay.INTEGER); + + private final CheckboxSetting checkLOS = new CheckboxSetting( + "Check line of sight", + "Makes sure that you don't reach through walls when breaking blocks.", + false); + + public VeinMinerHack() + { + super("VeinMiner"); + setCategory(Category.BLOCKS); + addSetting(range); + addSetting(flat); + addSetting(multiIdList); + addSetting(swingHand); + addSetting(maxVeinSize); + addSetting(checkLOS); + } + + @Override + protected void onEnable() + { + WURST.getHax().autoMineHack.setEnabled(false); + WURST.getHax().excavatorHack.setEnabled(false); + WURST.getHax().nukerHack.setEnabled(false); + WURST.getHax().nukerLegitHack.setEnabled(false); + WURST.getHax().speedNukerHack.setEnabled(false); + WURST.getHax().tunnellerHack.setEnabled(false); + + EVENTS.add(UpdateListener.class, this); + EVENTS.add(LeftClickListener.class, this); + EVENTS.add(RenderListener.class, this); + } + + @Override + protected void onDisable() + { + EVENTS.remove(UpdateListener.class, this); + EVENTS.remove(LeftClickListener.class, this); + EVENTS.remove(RenderListener.class, this); + + currentVein.clear(); + if(currentBlock != null) + { + MC.interactionManager.breakingBlock = true; + MC.interactionManager.cancelBlockBreaking(); + currentBlock = null; + } + + cache.reset(); + overlay.resetProgress(); + } + + @Override + public void onUpdate() + { + currentBlock = null; + currentVein.removeIf(pos -> BlockUtils.getState(pos).isReplaceable()); + + if(MC.options.attackKey.isPressed()) + return; + + Vec3d eyesVec = RotationUtils.getEyesPos(); + BlockPos eyesBlock = BlockPos.ofFloored(eyesVec); + double rangeSq = range.getValueSq(); + int blockRange = range.getValueCeil(); + + Stream stream = BlockUtils + .getAllInBoxStream(eyesBlock, blockRange) + .filter(this::shouldBreakBlock) + .map(BlockBreaker::getBlockBreakingParams).filter(Objects::nonNull) + .filter(params -> params.distanceSq() <= rangeSq); + + if(checkLOS.isChecked()) + stream = stream.filter(BlockBreakingParams::lineOfSight); + + stream = stream.sorted(BlockBreaker.comparingParams()); + + // Break all blocks in creative mode + if(MC.player.getAbilities().creativeMode) + { + MC.interactionManager.cancelBlockBreaking(); + overlay.resetProgress(); + + ArrayList blocks = cache + .filterOutRecentBlocks(stream.map(BlockBreakingParams::pos)); + if(blocks.isEmpty()) + return; + + currentBlock = blocks.get(0); + BlockBreaker.breakBlocksWithPacketSpam(blocks); + swingHand.swing(Hand.MAIN_HAND); + return; + } + + // Break the first valid block in survival mode + currentBlock = stream.filter(this::breakOneBlock) + .map(BlockBreakingParams::pos).findFirst().orElse(null); + + if(currentBlock == null) + { + MC.interactionManager.cancelBlockBreaking(); + overlay.resetProgress(); + return; + } + + overlay.updateProgress(); + } + + private boolean shouldBreakBlock(BlockPos pos) + { + if(flat.isChecked() && pos.getY() < MC.player.getY()) + return false; + + return currentVein.contains(pos); + } + + private boolean breakOneBlock(BlockBreakingParams params) + { + WURST.getRotationFaker().faceVectorPacket(params.hitVec()); + + if(!MC.interactionManager.updateBlockBreakingProgress(params.pos(), + params.side())) + return false; + + swingHand.swing(Hand.MAIN_HAND); + return true; + } + + @Override + public void onLeftClick(LeftClickEvent event) + { + if(!currentVein.isEmpty()) + return; + + if(!(MC.crosshairTarget instanceof BlockHitResult bHitResult) + || bHitResult.getType() != HitResult.Type.BLOCK) + return; + + if(!multiIdList.contains(BlockUtils.getBlock(bHitResult.getBlockPos()))) + return; + + buildVein(bHitResult.getBlockPos()); + } + + private void buildVein(BlockPos pos) + { + ArrayDeque queue = new ArrayDeque<>(); + Block targetBlock = BlockUtils.getBlock(pos); + int maxSize = maxVeinSize.getValueI(); + + queue.offer(pos); + currentVein.add(pos); + + while(!queue.isEmpty() && currentVein.size() < maxSize) + { + BlockPos current = queue.poll(); + + for(Direction direction : Direction.values()) + { + BlockPos neighbor = current.offset(direction); + if(!currentVein.contains(neighbor) + && BlockUtils.getBlock(neighbor) == targetBlock) + { + queue.offer(neighbor); + currentVein.add(neighbor); + } + } + } + } + + @Override + public void onRender(MatrixStack matrixStack, float partialTicks) + { + overlay.render(matrixStack, partialTicks, currentBlock); + if(currentVein.isEmpty()) + return; + + // GL settings + GL11.glEnable(GL11.GL_BLEND); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GL11.glDisable(GL11.GL_CULL_FACE); + GL11.glDisable(GL11.GL_DEPTH_TEST); + + matrixStack.push(); + RegionPos region = RenderUtils.getCameraRegion(); + RenderUtils.applyRegionalRenderOffset(matrixStack, region); + + double boxMin = 1 / 16.0; + double boxMax = 15 / 16.0; + Box box = new Box(boxMin, boxMin, boxMin, boxMax, boxMax, boxMax) + .offset(region.negate().toVec3d()); + + RenderSystem.setShader(GameRenderer::getPositionProgram); + RenderSystem.setShaderColor(0, 0, 0, 0.5F); + for(BlockPos pos : currentVein) + RenderUtils.drawOutlinedBox(box.offset(pos), matrixStack); + + matrixStack.pop(); + + // GL resets + RenderSystem.setShaderColor(1, 1, 1, 1); + GL11.glEnable(GL11.GL_DEPTH_TEST); + GL11.glEnable(GL11.GL_CULL_FACE); + GL11.glDisable(GL11.GL_BLEND); + } +} diff --git a/src/main/java/net/wurstclient/hacks/XRayHack.java b/src/main/java/net/wurstclient/hacks/XRayHack.java index 19c160ba76..82698d5717 100644 --- a/src/main/java/net/wurstclient/hacks/XRayHack.java +++ b/src/main/java/net/wurstclient/hacks/XRayHack.java @@ -18,6 +18,7 @@ import net.minecraft.block.Block; import net.minecraft.client.gui.screen.Screen; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; import net.wurstclient.Category; import net.wurstclient.SearchTags; import net.wurstclient.clickgui.screens.EditBlockListScreen; @@ -30,6 +31,8 @@ import net.wurstclient.mixinterface.ISimpleOption; import net.wurstclient.settings.BlockListSetting; import net.wurstclient.settings.CheckboxSetting; +import net.wurstclient.settings.SliderSetting; +import net.wurstclient.settings.SliderSetting.ValueDisplay; import net.wurstclient.util.BlockUtils; import net.wurstclient.util.ChatUtils; @@ -46,32 +49,32 @@ public final class XRayHack extends Hack implements UpdateListener, "minecraft:anvil", "minecraft:beacon", "minecraft:bone_block", "minecraft:bookshelf", "minecraft:brewing_stand", "minecraft:budding_amethyst", "minecraft:chain_command_block", - "minecraft:chest", "minecraft:clay", "minecraft:coal_block", - "minecraft:coal_ore", "minecraft:command_block", "minecraft:copper_ore", - "minecraft:crafter", "minecraft:crafting_table", - "minecraft:decorated_pot", "minecraft:deepslate_coal_ore", - "minecraft:deepslate_copper_ore", "minecraft:deepslate_diamond_ore", - "minecraft:deepslate_emerald_ore", "minecraft:deepslate_gold_ore", - "minecraft:deepslate_iron_ore", "minecraft:deepslate_lapis_ore", - "minecraft:deepslate_redstone_ore", "minecraft:diamond_block", - "minecraft:diamond_ore", "minecraft:dispenser", "minecraft:dropper", - "minecraft:emerald_block", "minecraft:emerald_ore", - "minecraft:enchanting_table", "minecraft:end_portal", - "minecraft:end_portal_frame", "minecraft:ender_chest", - "minecraft:furnace", "minecraft:glowstone", "minecraft:gold_block", - "minecraft:gold_ore", "minecraft:hopper", "minecraft:iron_block", - "minecraft:iron_ore", "minecraft:ladder", "minecraft:lapis_block", - "minecraft:lapis_ore", "minecraft:lava", "minecraft:lodestone", - "minecraft:mossy_cobblestone", "minecraft:nether_gold_ore", - "minecraft:nether_portal", "minecraft:nether_quartz_ore", - "minecraft:raw_copper_block", "minecraft:raw_gold_block", - "minecraft:raw_iron_block", "minecraft:redstone_block", - "minecraft:redstone_ore", "minecraft:repeating_command_block", - "minecraft:sculk_catalyst", "minecraft:sculk_sensor", - "minecraft:sculk_shrieker", "minecraft:spawner", - "minecraft:suspicious_gravel", "minecraft:suspicious_sand", - "minecraft:tnt", "minecraft:torch", "minecraft:trapped_chest", - "minecraft:trial_spawner", "minecraft:vault", "minecraft:water"); + "minecraft:chest", "minecraft:coal_block", "minecraft:coal_ore", + "minecraft:command_block", "minecraft:copper_ore", "minecraft:crafter", + "minecraft:crafting_table", "minecraft:decorated_pot", + "minecraft:deepslate_coal_ore", "minecraft:deepslate_copper_ore", + "minecraft:deepslate_diamond_ore", "minecraft:deepslate_emerald_ore", + "minecraft:deepslate_gold_ore", "minecraft:deepslate_iron_ore", + "minecraft:deepslate_lapis_ore", "minecraft:deepslate_redstone_ore", + "minecraft:diamond_block", "minecraft:diamond_ore", + "minecraft:dispenser", "minecraft:dropper", "minecraft:emerald_block", + "minecraft:emerald_ore", "minecraft:enchanting_table", + "minecraft:end_portal", "minecraft:end_portal_frame", + "minecraft:ender_chest", "minecraft:furnace", "minecraft:glowstone", + "minecraft:gold_block", "minecraft:gold_ore", "minecraft:hopper", + "minecraft:iron_block", "minecraft:iron_ore", "minecraft:ladder", + "minecraft:lapis_block", "minecraft:lapis_ore", "minecraft:lava", + "minecraft:lodestone", "minecraft:mossy_cobblestone", + "minecraft:nether_gold_ore", "minecraft:nether_portal", + "minecraft:nether_quartz_ore", "minecraft:raw_copper_block", + "minecraft:raw_gold_block", "minecraft:raw_iron_block", + "minecraft:redstone_block", "minecraft:redstone_ore", + "minecraft:repeating_command_block", "minecraft:sculk_catalyst", + "minecraft:sculk_sensor", "minecraft:sculk_shrieker", + "minecraft:spawner", "minecraft:suspicious_gravel", + "minecraft:suspicious_sand", "minecraft:tnt", "minecraft:torch", + "minecraft:trapped_chest", "minecraft:trial_spawner", "minecraft:vault", + "minecraft:water"); private final CheckboxSetting onlyExposed = new CheckboxSetting( "Only show exposed", @@ -80,11 +83,19 @@ public final class XRayHack extends Hack implements UpdateListener, + "Remember to restart X-Ray when changing this setting.", false); + private final SliderSetting opacity = new SliderSetting("Opacity", + "Opacity of non-ore blocks when X-Ray is enabled.\n\n" + + "Does not work when Sodium is installed.\n\n" + + "Remember to restart X-Ray when changing this setting.", + 0, 0, 0.99, 0.01, ValueDisplay.PERCENTAGE.withLabel(0, "off")); + private final String optiFineWarning; private final String renderName = Math.random() < 0.01 ? "X-Wurst" : getName(); private ArrayList oreNamesCache; + private final ThreadLocal mutablePosForExposedCheck = + ThreadLocal.withInitial(BlockPos.Mutable::new); public XRayHack() { @@ -92,6 +103,7 @@ public XRayHack() setCategory(Category.RENDER); addSetting(ores); addSetting(onlyExposed); + addSetting(opacity); optiFineWarning = checkOptiFine(); } @@ -165,8 +177,12 @@ public void onGetAmbientOcclusionLightLevel( @Override public void onShouldDrawSide(ShouldDrawSideEvent event) { - event.setRendered( - isVisible(event.getState().getBlock(), event.getPos())); + boolean visible = + isVisible(event.getState().getBlock(), event.getPos()); + if(!visible && opacity.getValue() > 0) + return; + + event.setRendered(visible); } @Override @@ -177,23 +193,38 @@ public void onRenderBlockEntity(RenderBlockEntityEvent event) event.cancel(); } - private boolean isVisible(Block block, BlockPos pos) + public boolean isVisible(Block block, BlockPos pos) { String name = BlockUtils.getName(block); int index = Collections.binarySearch(oreNamesCache, name); boolean visible = index >= 0; if(visible && onlyExposed.isChecked() && pos != null) - return !BlockUtils.isOpaqueFullCube(pos.up()) - || !BlockUtils.isOpaqueFullCube(pos.down()) - || !BlockUtils.isOpaqueFullCube(pos.east()) - || !BlockUtils.isOpaqueFullCube(pos.west()) - || !BlockUtils.isOpaqueFullCube(pos.north()) - || !BlockUtils.isOpaqueFullCube(pos.south()); + return isExposed(pos); return visible; } + private boolean isExposed(BlockPos pos) + { + BlockPos.Mutable mutablePos = mutablePosForExposedCheck.get(); + for(Direction direction : Direction.values()) + if(!BlockUtils.isOpaqueFullCube(mutablePos.set(pos, direction))) + return true; + + return false; + } + + public boolean isOpacityMode() + { + return isEnabled() && opacity.getValue() > 0; + } + + public int getOpacityColorMask() + { + return (int)(opacity.getValue() * 255) << 24 | 0xFFFFFF; + } + /** * Checks if OptiFine/OptiFabric is installed and returns a warning message * if it is. @@ -215,4 +246,6 @@ public void openBlockListEditor(Screen prevScreen) { MC.setScreen(new EditBlockListScreen(prevScreen, ores)); } + + // See AbstractBlockRenderContextMixin, RenderLayersMixin } diff --git a/src/main/java/net/wurstclient/hacks/nukers/CommonNukerSettings.java b/src/main/java/net/wurstclient/hacks/nukers/CommonNukerSettings.java new file mode 100644 index 0000000000..7daa8d9a2e --- /dev/null +++ b/src/main/java/net/wurstclient/hacks/nukers/CommonNukerSettings.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2014-2024 Wurst-Imperium and contributors. + * + * This source code is subject to the terms of the GNU General Public + * License, version 3. If a copy of the GPL was not distributed with this + * file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt + */ +package net.wurstclient.hacks.nukers; + +import java.util.stream.Stream; + +import net.minecraft.block.Blocks; +import net.minecraft.client.MinecraftClient; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.hit.HitResult; +import net.minecraft.util.math.BlockPos; +import net.wurstclient.WurstClient; +import net.wurstclient.events.LeftClickListener; +import net.wurstclient.hacks.nukers.NukerModeSetting.NukerMode; +import net.wurstclient.hacks.nukers.NukerShapeSetting.NukerShape; +import net.wurstclient.settings.BlockSetting; +import net.wurstclient.settings.CheckboxSetting; +import net.wurstclient.settings.Setting; +import net.wurstclient.util.BlockUtils; + +public final class CommonNukerSettings implements LeftClickListener +{ + private static final MinecraftClient MC = WurstClient.MC; + + private final NukerShapeSetting shape = new NukerShapeSetting(); + + private final CheckboxSetting flat = new CheckboxSetting("Flat mode", + "Won't break any blocks below your feet.", false); + + private final NukerModeSetting mode = new NukerModeSetting(); + + private final BlockSetting id = + new BlockSetting("ID", "The type of block to break in ID mode.\n" + + "air = won't break anything", "minecraft:air", true); + + private final CheckboxSetting lockId = new CheckboxSetting("Lock ID", + "Prevents changing the ID by clicking on blocks or restarting the hack.", + false); + + private final NukerMultiIdListSetting multiIdList = + new NukerMultiIdListSetting(); + + public Stream getSettings() + { + return Stream.of(shape, flat, mode, id, lockId, multiIdList); + } + + public void reset() + { + if(!lockId.isChecked()) + id.setBlock(Blocks.AIR); + } + + public String getRenderNameSuffix() + { + return switch(mode.getSelected()) + { + case ID -> " [ID:" + id.getShortBlockName() + "]"; + case MULTI_ID -> " [MultiID:" + multiIdList.size() + "]"; + case SMASH -> " [Smash]"; + default -> ""; + }; + } + + public boolean isIdModeWithAir() + { + return mode.getSelected() == NukerMode.ID + && id.getBlock() == Blocks.AIR; + } + + public boolean isSphereShape() + { + return shape.getSelected() == NukerShape.SPHERE; + } + + public boolean shouldBreakBlock(BlockPos pos) + { + if(flat.isChecked() && pos.getY() < MC.player.getY()) + return false; + + switch(mode.getSelected()) + { + default: + case NORMAL: + return true; + + case ID: + return BlockUtils.getName(pos).equals(id.getBlockName()); + + case MULTI_ID: + return multiIdList.contains(BlockUtils.getBlock(pos)); + + case SMASH: + return BlockUtils.getHardness(pos) >= 1; + } + } + + @Override + public void onLeftClick(LeftClickEvent event) + { + if(lockId.isChecked() || mode.getSelected() != NukerMode.ID) + return; + + if(!(MC.crosshairTarget instanceof BlockHitResult bHitResult) + || bHitResult.getType() != HitResult.Type.BLOCK) + return; + + id.setBlockName(BlockUtils.getName(bHitResult.getBlockPos())); + } +} diff --git a/src/main/java/net/wurstclient/hacks/nukers/NukerModeSetting.java b/src/main/java/net/wurstclient/hacks/nukers/NukerModeSetting.java new file mode 100644 index 0000000000..2e709f9116 --- /dev/null +++ b/src/main/java/net/wurstclient/hacks/nukers/NukerModeSetting.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014-2024 Wurst-Imperium and contributors. + * + * This source code is subject to the terms of the GNU General Public + * License, version 3. If a copy of the GPL was not distributed with this + * file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt + */ +package net.wurstclient.hacks.nukers; + +import net.wurstclient.settings.EnumSetting; + +public final class NukerModeSetting + extends EnumSetting +{ + public NukerModeSetting() + { + super("Mode", + "\u00a7lNormal\u00a7r mode simply breaks everything around you.\n\n" + + "\u00a7lID\u00a7r mode only breaks the selected block type." + + " Left-click on a block to select it.\n\n" + + "\u00a7lMultiID\u00a7r mode only breaks the block types in" + + " your MultiID List.\n\n" + + "\u00a7lSmash\u00a7r mode only breaks blocks that can be" + + " destroyed instantly (e.g. tall grass).", + NukerMode.values(), NukerMode.NORMAL); + } + + public enum NukerMode + { + NORMAL("Normal"), + ID("ID"), + MULTI_ID("MultiID"), + SMASH("Smash"); + + private final String name; + + private NukerMode(String name) + { + this.name = name; + } + + @Override + public String toString() + { + return name; + } + } +} diff --git a/src/main/java/net/wurstclient/hacks/nukers/NukerMultiIdListSetting.java b/src/main/java/net/wurstclient/hacks/nukers/NukerMultiIdListSetting.java new file mode 100644 index 0000000000..9826780655 --- /dev/null +++ b/src/main/java/net/wurstclient/hacks/nukers/NukerMultiIdListSetting.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2014-2024 Wurst-Imperium and contributors. + * + * This source code is subject to the terms of the GNU General Public + * License, version 3. If a copy of the GPL was not distributed with this + * file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt + */ +package net.wurstclient.hacks.nukers; + +import net.wurstclient.hacks.NukerHack; +import net.wurstclient.hacks.NukerLegitHack; +import net.wurstclient.hacks.SpeedNukerHack; +import net.wurstclient.settings.BlockListSetting; + +/** + * A {@link BlockListSetting} named "MultiID List" containing all of Minecraft's + * ores by default. Used by {@link NukerHack}, {@link NukerLegitHack}, and + * {@link SpeedNukerHack}. + */ +public final class NukerMultiIdListSetting extends BlockListSetting +{ + public NukerMultiIdListSetting(String descriptionKey) + { + super("MultiID List", descriptionKey, "minecraft:ancient_debris", + "minecraft:bone_block", "minecraft:coal_ore", + "minecraft:copper_ore", "minecraft:deepslate_coal_ore", + "minecraft:deepslate_copper_ore", "minecraft:deepslate_diamond_ore", + "minecraft:deepslate_emerald_ore", "minecraft:deepslate_gold_ore", + "minecraft:deepslate_iron_ore", "minecraft:deepslate_lapis_ore", + "minecraft:deepslate_redstone_ore", "minecraft:diamond_ore", + "minecraft:emerald_ore", "minecraft:glowstone", + "minecraft:gold_ore", "minecraft:iron_ore", "minecraft:lapis_ore", + "minecraft:nether_gold_ore", "minecraft:nether_quartz_ore", + "minecraft:raw_copper_block", "minecraft:raw_gold_block", + "minecraft:raw_iron_block", "minecraft:redstone_ore"); + } + + public NukerMultiIdListSetting() + { + this("The types of blocks to break in MultiID mode."); + } +} diff --git a/src/main/java/net/wurstclient/hacks/nukers/NukerShapeSetting.java b/src/main/java/net/wurstclient/hacks/nukers/NukerShapeSetting.java new file mode 100644 index 0000000000..5b098f5ca4 --- /dev/null +++ b/src/main/java/net/wurstclient/hacks/nukers/NukerShapeSetting.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2014-2024 Wurst-Imperium and contributors. + * + * This source code is subject to the terms of the GNU General Public + * License, version 3. If a copy of the GPL was not distributed with this + * file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt + */ +package net.wurstclient.hacks.nukers; + +import net.wurstclient.settings.EnumSetting; + +public final class NukerShapeSetting + extends EnumSetting +{ + public NukerShapeSetting() + { + super("Shape", + "\u00a7lNote:\u00a7r If your range is set too high, the cube shape" + + " will start to look like a sphere because you can't reach" + + " the corners. Ranges 1-3 work best for the cube shape.", + NukerShape.values(), NukerShape.SPHERE); + } + + public enum NukerShape + { + SPHERE("Sphere"), + CUBE("Cube"); + + private final String name; + + private NukerShape(String name) + { + this.name = name; + } + + @Override + public String toString() + { + return name; + } + } +} diff --git a/src/main/java/net/wurstclient/hud/HackListHUD.java b/src/main/java/net/wurstclient/hud/HackListHUD.java index 1554fe4fc1..b21ce2b7af 100644 --- a/src/main/java/net/wurstclient/hud/HackListHUD.java +++ b/src/main/java/net/wurstclient/hud/HackListHUD.java @@ -49,11 +49,11 @@ public void render(DrawContext context, float partialTicks) if(WurstClient.INSTANCE.getHax().rainbowUiHack.isEnabled()) { float[] acColor = WurstClient.INSTANCE.getGui().getAcColor(); - textColor = 0x04 << 24 | (int)(acColor[0] * 256) << 16 - | (int)(acColor[1] * 256) << 8 | (int)(acColor[2] * 256); + textColor = 0x04 << 24 | (int)(acColor[0] * 0xFF) << 16 + | (int)(acColor[1] * 0xFF) << 8 | (int)(acColor[2] * 0xFF); }else - textColor = 0x04000000 | otf.getColor(); + textColor = otf.getColor(0x04); int height = posY + activeHax.size() * 9; Window sr = WurstClient.MC.getWindow(); diff --git a/src/main/java/net/wurstclient/mixin/AbstractBlockRenderContextMixin.java b/src/main/java/net/wurstclient/mixin/AbstractBlockRenderContextMixin.java new file mode 100644 index 0000000000..d0cd5d270a --- /dev/null +++ b/src/main/java/net/wurstclient/mixin/AbstractBlockRenderContextMixin.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014-2024 Wurst-Imperium and contributors. + * + * This source code is subject to the terms of the GNU General Public + * License, version 3. If a copy of the GPL was not distributed with this + * file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt + */ +package net.wurstclient.mixin; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.MutableQuadViewImpl; +import net.fabricmc.fabric.impl.client.indigo.renderer.render.AbstractBlockRenderContext; +import net.fabricmc.fabric.impl.client.indigo.renderer.render.BlockRenderInfo; +import net.wurstclient.WurstClient; +import net.wurstclient.hacks.XRayHack; + +@Mixin(value = AbstractBlockRenderContext.class, remap = false) +public abstract class AbstractBlockRenderContextMixin +{ + @Shadow + @Final + private BlockRenderInfo blockInfo; + + /** + * Applies X-Ray's opacity mask to the block color after all the normal + * coloring and shading is done. + */ + @Inject(at = @At("RETURN"), + method = "shadeQuad(Lnet/fabricmc/fabric/impl/client/indigo/renderer/mesh/MutableQuadViewImpl;ZZZ)V") + private void onShadeQuad(MutableQuadViewImpl quad, boolean ao, + boolean emissive, boolean vanillaShade, CallbackInfo ci) + { + XRayHack xray = WurstClient.INSTANCE.getHax().xRayHack; + if(!xray.isOpacityMode() || xray + .isVisible(blockInfo.blockState.getBlock(), blockInfo.blockPos)) + return; + + for(int i = 0; i < 4; i++) + quad.color(i, quad.color(i) & xray.getOpacityColorMask()); + } +} diff --git a/src/main/java/net/wurstclient/mixin/ClientPlayerEntityMixin.java b/src/main/java/net/wurstclient/mixin/ClientPlayerEntityMixin.java index 5800c942a3..2c3ab2e4c6 100644 --- a/src/main/java/net/wurstclient/mixin/ClientPlayerEntityMixin.java +++ b/src/main/java/net/wurstclient/mixin/ClientPlayerEntityMixin.java @@ -315,7 +315,6 @@ public float getStepHeight() .adjustStepHeight(super.getStepHeight()); } - // getter for GENERIC_BLOCK_INTERACTION_RANGE @Override public double getBlockInteractionRange() { @@ -326,7 +325,6 @@ public double getBlockInteractionRange() return hax.reachHack.getReachDistance(); } - // getter for GENERIC_ENTITY_INTERACTION_RANGE @Override public double getEntityInteractionRange() { diff --git a/src/main/java/net/wurstclient/mixin/KeyBindingMixin.java b/src/main/java/net/wurstclient/mixin/KeyBindingMixin.java index 9078a93fa4..dc4e3e2424 100644 --- a/src/main/java/net/wurstclient/mixin/KeyBindingMixin.java +++ b/src/main/java/net/wurstclient/mixin/KeyBindingMixin.java @@ -31,7 +31,11 @@ public void wurst_resetPressedState() { long handle = WurstClient.MC.getWindow().getHandle(); int code = boundKey.getCode(); - setPressed(InputUtil.isKeyPressed(handle, code)); + + if(boundKey.getCategory() == InputUtil.Type.MOUSE) + setPressed(GLFW.glfwGetMouseButton(handle, code) == 1); + else + setPressed(InputUtil.isKeyPressed(handle, code)); } @Override diff --git a/src/main/java/net/wurstclient/mixin/MinecraftClientMixin.java b/src/main/java/net/wurstclient/mixin/MinecraftClientMixin.java index 3afc973fb5..50c6320935 100644 --- a/src/main/java/net/wurstclient/mixin/MinecraftClientMixin.java +++ b/src/main/java/net/wurstclient/mixin/MinecraftClientMixin.java @@ -34,6 +34,7 @@ import net.minecraft.util.thread.ReentrantThreadExecutor; import net.wurstclient.WurstClient; import net.wurstclient.event.EventManager; +import net.wurstclient.events.HandleBlockBreakingListener.HandleBlockBreakingEvent; import net.wurstclient.events.HandleInputListener.HandleInputEvent; import net.wurstclient.events.LeftClickListener.LeftClickEvent; import net.wurstclient.events.RightClickListener.RightClickEvent; @@ -122,6 +123,22 @@ private void onDoItemPick(CallbackInfo ci) WurstClient.INSTANCE.getFriends().middleClick(eHitResult.getEntity()); } + /** + * Allows hacks to cancel vanilla block breaking and replace it with their + * own. Useful for Nuker-like hacks. + */ + @Inject(at = @At("HEAD"), + method = "handleBlockBreaking(Z)V", + cancellable = true) + private void onHandleBlockBreaking(boolean breaking, CallbackInfo ci) + { + HandleBlockBreakingEvent event = new HandleBlockBreakingEvent(); + EventManager.fire(event); + + if(event.isCancelled()) + ci.cancel(); + } + @Inject(at = @At("HEAD"), method = "getSession()Lnet/minecraft/client/session/Session;", cancellable = true) diff --git a/src/main/java/net/wurstclient/mixin/RenderLayersMixin.java b/src/main/java/net/wurstclient/mixin/RenderLayersMixin.java new file mode 100644 index 0000000000..1b4b0f66de --- /dev/null +++ b/src/main/java/net/wurstclient/mixin/RenderLayersMixin.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014-2024 Wurst-Imperium and contributors. + * + * This source code is subject to the terms of the GNU General Public + * License, version 3. If a copy of the GPL was not distributed with this + * file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt + */ +package net.wurstclient.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.block.BlockState; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.RenderLayers; +import net.wurstclient.WurstClient; + +@Mixin(RenderLayers.class) +public abstract class RenderLayersMixin +{ + /** + * Puts all blocks on the translucent layer if Opacity X-Ray is enabled. + */ + @Inject(at = @At("HEAD"), + method = "getBlockLayer(Lnet/minecraft/block/BlockState;)Lnet/minecraft/client/render/RenderLayer;", + cancellable = true) + private static void onGetBlockLayer(BlockState state, + CallbackInfoReturnable cir) + { + if(!WurstClient.INSTANCE.getHax().xRayHack.isOpacityMode()) + return; + + cir.setReturnValue(RenderLayer.getTranslucent()); + } +} diff --git a/src/main/java/net/wurstclient/other_features/HackListOtf.java b/src/main/java/net/wurstclient/other_features/HackListOtf.java index 8aa8c23e5c..ef7b220c97 100644 --- a/src/main/java/net/wurstclient/other_features/HackListOtf.java +++ b/src/main/java/net/wurstclient/other_features/HackListOtf.java @@ -115,9 +115,9 @@ public boolean shouldSort() } } - public int getColor() + public int getColor(int alpha) { - return color.getColorI() & 0x00FFFFFF; + return color.getColorI(alpha); } public static enum Mode diff --git a/src/main/java/net/wurstclient/settings/BlockListSetting.java b/src/main/java/net/wurstclient/settings/BlockListSetting.java index 597200eadd..017e6d5133 100644 --- a/src/main/java/net/wurstclient/settings/BlockListSetting.java +++ b/src/main/java/net/wurstclient/settings/BlockListSetting.java @@ -30,13 +30,14 @@ import net.wurstclient.util.BlockUtils; import net.wurstclient.util.json.JsonException; import net.wurstclient.util.json.JsonUtils; +import net.wurstclient.util.text.WText; -public final class BlockListSetting extends Setting +public class BlockListSetting extends Setting { private final ArrayList blockNames = new ArrayList<>(); private final String[] defaultNames; - public BlockListSetting(String name, String description, String... blocks) + public BlockListSetting(String name, WText description, String... blocks) { super(name, description); @@ -47,11 +48,42 @@ public BlockListSetting(String name, String description, String... blocks) defaultNames = blockNames.toArray(new String[0]); } + public BlockListSetting(String name, String descriptionKey, + String... blocks) + { + this(name, WText.translated(descriptionKey), blocks); + } + public List getBlockNames() { return Collections.unmodifiableList(blockNames); } + public int indexOf(String name) + { + return Collections.binarySearch(blockNames, name); + } + + public int indexOf(Block block) + { + return indexOf(BlockUtils.getName(block)); + } + + public boolean contains(String name) + { + return indexOf(name) >= 0; + } + + public boolean contains(Block block) + { + return indexOf(block) >= 0; + } + + public int size() + { + return blockNames.size(); + } + public void add(Block block) { String name = BlockUtils.getName(block); @@ -130,7 +162,7 @@ public JsonObject exportWikiData() JsonObject json = new JsonObject(); json.addProperty("name", getName()); - json.addProperty("descriptionKey", getDescriptionKey()); + json.addProperty("description", getDescription()); json.addProperty("type", "BlockList"); JsonArray defaultBlocksJson = new JsonArray(); diff --git a/src/main/java/net/wurstclient/settings/BlockSetting.java b/src/main/java/net/wurstclient/settings/BlockSetting.java index d52e9e9069..7103a3caaf 100644 --- a/src/main/java/net/wurstclient/settings/BlockSetting.java +++ b/src/main/java/net/wurstclient/settings/BlockSetting.java @@ -24,6 +24,7 @@ import net.wurstclient.util.BlockUtils; import net.wurstclient.util.json.JsonException; import net.wurstclient.util.json.JsonUtils; +import net.wurstclient.util.text.WText; public final class BlockSetting extends Setting { @@ -31,7 +32,7 @@ public final class BlockSetting extends Setting private final String defaultName; private final boolean allowAir; - public BlockSetting(String name, String description, String blockName, + public BlockSetting(String name, WText description, String blockName, boolean allowAir) { super(name, description); @@ -44,9 +45,15 @@ public BlockSetting(String name, String description, String blockName, this.allowAir = allowAir; } + public BlockSetting(String name, String descriptionKey, String blockName, + boolean allowAir) + { + this(name, WText.translated(descriptionKey), blockName, allowAir); + } + public BlockSetting(String name, String blockName, boolean allowAir) { - this(name, "", blockName, allowAir); + this(name, WText.empty(), blockName, allowAir); } /** @@ -62,6 +69,11 @@ public String getBlockName() return blockName; } + public String getShortBlockName() + { + return blockName.replace("minecraft:", ""); + } + public void setBlock(Block block) { if(block == null) @@ -133,7 +145,7 @@ public JsonObject exportWikiData() { JsonObject json = new JsonObject(); json.addProperty("name", getName()); - json.addProperty("descriptionKey", getDescriptionKey()); + json.addProperty("description", getDescription()); json.addProperty("type", "Block"); json.addProperty("defaultValue", defaultName); json.addProperty("allowAir", allowAir); diff --git a/src/main/java/net/wurstclient/settings/BookOffersSetting.java b/src/main/java/net/wurstclient/settings/BookOffersSetting.java index 6a2c6a4a2f..5258680d99 100644 --- a/src/main/java/net/wurstclient/settings/BookOffersSetting.java +++ b/src/main/java/net/wurstclient/settings/BookOffersSetting.java @@ -28,13 +28,14 @@ import net.wurstclient.util.json.JsonException; import net.wurstclient.util.json.JsonUtils; import net.wurstclient.util.json.WsonObject; +import net.wurstclient.util.text.WText; public final class BookOffersSetting extends Setting { private final ArrayList offers = new ArrayList<>(); private final BookOffer[] defaultOffers; - public BookOffersSetting(String name, String description, + public BookOffersSetting(String name, WText description, String... enchantments) { super(name, description); @@ -47,6 +48,12 @@ public BookOffersSetting(String name, String description, defaultOffers = offers.toArray(new BookOffer[0]); } + public BookOffersSetting(String name, String descriptionKey, + String... enchantments) + { + this(name, WText.translated(descriptionKey), enchantments); + } + public List getOffers() { return Collections.unmodifiableList(offers); @@ -214,7 +221,7 @@ public JsonObject exportWikiData() { JsonObject json = new JsonObject(); json.addProperty("name", getName()); - json.addProperty("descriptionKey", getDescriptionKey()); + json.addProperty("description", getDescription()); json.addProperty("type", "BookOffers"); JsonArray jsonDefaultOffers = new JsonArray(); diff --git a/src/main/java/net/wurstclient/settings/CheckboxSetting.java b/src/main/java/net/wurstclient/settings/CheckboxSetting.java index f420adac9f..4f9b06c831 100644 --- a/src/main/java/net/wurstclient/settings/CheckboxSetting.java +++ b/src/main/java/net/wurstclient/settings/CheckboxSetting.java @@ -19,6 +19,7 @@ import net.wurstclient.clickgui.components.CheckboxComponent; import net.wurstclient.keybinds.PossibleKeybind; import net.wurstclient.util.json.JsonUtils; +import net.wurstclient.util.text.WText; public class CheckboxSetting extends Setting implements CheckboxLock { @@ -26,16 +27,21 @@ public class CheckboxSetting extends Setting implements CheckboxLock private final boolean checkedByDefault; private CheckboxLock lock; - public CheckboxSetting(String name, String description, boolean checked) + public CheckboxSetting(String name, WText description, boolean checked) { super(name, description); this.checked = checked; checkedByDefault = checked; } + public CheckboxSetting(String name, String descriptionKey, boolean checked) + { + this(name, WText.translated(descriptionKey), checked); + } + public CheckboxSetting(String name, boolean checked) { - this(name, "", checked); + this(name, WText.empty(), checked); } @Override @@ -108,7 +114,7 @@ public JsonObject exportWikiData() { JsonObject json = new JsonObject(); json.addProperty("name", getName()); - json.addProperty("descriptionKey", getDescriptionKey()); + json.addProperty("description", getDescription()); json.addProperty("type", "Checkbox"); json.addProperty("checkedByDefault", checkedByDefault); return json; diff --git a/src/main/java/net/wurstclient/settings/ColorSetting.java b/src/main/java/net/wurstclient/settings/ColorSetting.java index e56fd1ae54..d2e7e82b63 100644 --- a/src/main/java/net/wurstclient/settings/ColorSetting.java +++ b/src/main/java/net/wurstclient/settings/ColorSetting.java @@ -24,22 +24,28 @@ import net.wurstclient.util.ColorUtils; import net.wurstclient.util.json.JsonException; import net.wurstclient.util.json.JsonUtils; +import net.wurstclient.util.text.WText; public final class ColorSetting extends Setting { private Color color; private final Color defaultColor; - public ColorSetting(String name, String description, Color color) + public ColorSetting(String name, WText description, Color color) { super(name, description); this.color = Objects.requireNonNull(color); defaultColor = color; } + public ColorSetting(String name, String descriptionKey, Color color) + { + this(name, WText.translated(descriptionKey), color); + } + public ColorSetting(String name, Color color) { - this(name, "", color); + this(name, WText.empty(), color); } public Color getColor() @@ -63,7 +69,12 @@ public void setAsShaderColor(float opacity) public int getColorI() { - return color.getRGB(); + return color.getRGB() | 0xFF000000; + } + + public int getColorI(int alpha) + { + return color.getRGB() & 0x00FFFFFF | alpha << 24; } public int getRed() @@ -126,7 +137,7 @@ public JsonObject exportWikiData() { JsonObject json = new JsonObject(); json.addProperty("name", getName()); - json.addProperty("descriptionKey", getDescriptionKey()); + json.addProperty("description", getDescription()); json.addProperty("type", "Color"); json.addProperty("defaultColor", ColorUtils.toHex(defaultColor)); return json; diff --git a/src/main/java/net/wurstclient/settings/EnumSetting.java b/src/main/java/net/wurstclient/settings/EnumSetting.java index 2b3b84be47..4c07308157 100644 --- a/src/main/java/net/wurstclient/settings/EnumSetting.java +++ b/src/main/java/net/wurstclient/settings/EnumSetting.java @@ -20,6 +20,7 @@ import net.wurstclient.clickgui.components.ComboBoxComponent; import net.wurstclient.keybinds.PossibleKeybind; import net.wurstclient.util.json.JsonUtils; +import net.wurstclient.util.text.WText; public class EnumSetting> extends Setting { @@ -27,7 +28,7 @@ public class EnumSetting> extends Setting private T selected; private final T defaultSelected; - public EnumSetting(String name, String description, T[] values, T selected) + public EnumSetting(String name, WText description, T[] values, T selected) { super(name, description); this.values = Objects.requireNonNull(values); @@ -35,9 +36,15 @@ public EnumSetting(String name, String description, T[] values, T selected) defaultSelected = selected; } + public EnumSetting(String name, String descriptionKey, T[] values, + T selected) + { + this(name, WText.translated(descriptionKey), values, selected); + } + public EnumSetting(String name, T[] values, T selected) { - this(name, "", values, selected); + this(name, WText.empty(), values, selected); } public T[] getValues() @@ -119,7 +126,7 @@ public JsonObject exportWikiData() { JsonObject json = new JsonObject(); json.addProperty("name", getName()); - json.addProperty("descriptionKey", getDescriptionKey()); + json.addProperty("description", getDescription()); json.addProperty("type", "Enum"); JsonArray values = new JsonArray(); diff --git a/src/main/java/net/wurstclient/settings/FileSetting.java b/src/main/java/net/wurstclient/settings/FileSetting.java index e68ef23666..7f95ce27c2 100644 --- a/src/main/java/net/wurstclient/settings/FileSetting.java +++ b/src/main/java/net/wurstclient/settings/FileSetting.java @@ -28,6 +28,7 @@ import net.wurstclient.keybinds.PossibleKeybind; import net.wurstclient.util.json.JsonException; import net.wurstclient.util.json.JsonUtils; +import net.wurstclient.util.text.WText; public final class FileSetting extends Setting { @@ -35,7 +36,7 @@ public final class FileSetting extends Setting private String selectedFile = ""; private final Consumer createDefaultFiles; - public FileSetting(String name, String description, String folderName, + public FileSetting(String name, WText description, String folderName, Consumer createDefaultFiles) { super(name, description); @@ -44,6 +45,13 @@ public FileSetting(String name, String description, String folderName, setSelectedFileToDefault(); } + public FileSetting(String name, String descriptionKey, String folderName, + Consumer createDefaultFiles) + { + this(name, WText.translated(descriptionKey), folderName, + createDefaultFiles); + } + public Path getFolder() { return folder; @@ -169,7 +177,7 @@ public JsonObject exportWikiData() { JsonObject json = new JsonObject(); json.addProperty("name", getName()); - json.addProperty("descriptionKey", getDescriptionKey()); + json.addProperty("description", getDescription()); json.addProperty("type", "File"); Path mcFolder = WurstClient.INSTANCE.getWurstFolder().getParent(); diff --git a/src/main/java/net/wurstclient/settings/ItemListSetting.java b/src/main/java/net/wurstclient/settings/ItemListSetting.java index 87221b49b7..d6b895a047 100644 --- a/src/main/java/net/wurstclient/settings/ItemListSetting.java +++ b/src/main/java/net/wurstclient/settings/ItemListSetting.java @@ -29,13 +29,14 @@ import net.wurstclient.keybinds.PossibleKeybind; import net.wurstclient.util.json.JsonException; import net.wurstclient.util.json.JsonUtils; +import net.wurstclient.util.text.WText; public final class ItemListSetting extends Setting { private final ArrayList itemNames = new ArrayList<>(); private final String[] defaultNames; - public ItemListSetting(String name, String description, String... items) + public ItemListSetting(String name, WText description, String... items) { super(name, description); @@ -47,6 +48,11 @@ public ItemListSetting(String name, String description, String... items) defaultNames = itemNames.toArray(new String[0]); } + public ItemListSetting(String name, String descriptionKey, String... items) + { + this(name, WText.translated(descriptionKey), items); + } + public List getItemNames() { return Collections.unmodifiableList(itemNames); @@ -130,7 +136,7 @@ public JsonObject exportWikiData() { JsonObject json = new JsonObject(); json.addProperty("name", getName()); - json.addProperty("descriptionKey", getDescriptionKey()); + json.addProperty("description", getDescription()); json.addProperty("type", "ItemList"); JsonArray defaultItems = new JsonArray(); diff --git a/src/main/java/net/wurstclient/settings/Setting.java b/src/main/java/net/wurstclient/settings/Setting.java index 0cafa98912..7733212aa0 100644 --- a/src/main/java/net/wurstclient/settings/Setting.java +++ b/src/main/java/net/wurstclient/settings/Setting.java @@ -13,17 +13,17 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import net.wurstclient.WurstClient; import net.wurstclient.clickgui.Component; import net.wurstclient.keybinds.PossibleKeybind; import net.wurstclient.util.ChatUtils; +import net.wurstclient.util.text.WText; public abstract class Setting { private final String name; - private final String description; + private final WText description; - public Setting(String name, String description) + public Setting(String name, WText description) { this.name = Objects.requireNonNull(name); this.description = Objects.requireNonNull(description); @@ -36,7 +36,7 @@ public final String getName() public final String getDescription() { - return WurstClient.INSTANCE.translate(description); + return description.toString(); } public final String getWrappedDescription(int width) @@ -44,11 +44,6 @@ public final String getWrappedDescription(int width) return ChatUtils.wrapText(getDescription(), width); } - public final String getDescriptionKey() - { - return description; - } - public abstract Component getComponent(); public abstract void fromJson(JsonElement json); @@ -60,7 +55,7 @@ public final String getDescriptionKey() * Wurst Wiki. Must always specify the following properties: *
    *
  • name - *
  • descriptionKey + *
  • description *
  • type *
*/ diff --git a/src/main/java/net/wurstclient/settings/SliderSetting.java b/src/main/java/net/wurstclient/settings/SliderSetting.java index a9ff5c5c53..b68b406b4b 100644 --- a/src/main/java/net/wurstclient/settings/SliderSetting.java +++ b/src/main/java/net/wurstclient/settings/SliderSetting.java @@ -21,6 +21,7 @@ import net.wurstclient.keybinds.PossibleKeybind; import net.wurstclient.util.MathUtils; import net.wurstclient.util.json.JsonUtils; +import net.wurstclient.util.text.WText; public class SliderSetting extends Setting implements SliderLock { @@ -36,7 +37,7 @@ public class SliderSetting extends Setting implements SliderLock private double usableMin; private double usableMax; - public SliderSetting(String name, String description, double value, + public SliderSetting(String name, WText description, double value, double minimum, double maximum, double increment, ValueDisplay display) { super(name, description); @@ -53,10 +54,17 @@ public SliderSetting(String name, String description, double value, this.display = display; } + public SliderSetting(String name, String descriptionKey, double value, + double minimum, double maximum, double increment, ValueDisplay display) + { + this(name, WText.translated(descriptionKey), value, minimum, maximum, + increment, display); + } + public SliderSetting(String name, double value, double minimum, double maximum, double increment, ValueDisplay display) { - this(name, "", value, minimum, maximum, increment, display); + this(name, WText.empty(), value, minimum, maximum, increment, display); } @Override @@ -272,7 +280,7 @@ public JsonObject exportWikiData() { JsonObject json = new JsonObject(); json.addProperty("name", getName()); - json.addProperty("descriptionKey", getDescriptionKey()); + json.addProperty("description", getDescription()); json.addProperty("type", "Slider"); json.addProperty("defaultValue", defaultValue); diff --git a/src/main/java/net/wurstclient/settings/SwingHandSetting.java b/src/main/java/net/wurstclient/settings/SwingHandSetting.java index 65264430a9..6924673a78 100644 --- a/src/main/java/net/wurstclient/settings/SwingHandSetting.java +++ b/src/main/java/net/wurstclient/settings/SwingHandSetting.java @@ -13,50 +13,67 @@ import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket; import net.minecraft.util.Hand; import net.wurstclient.WurstClient; +import net.wurstclient.hack.Hack; +import net.wurstclient.util.text.WText; public final class SwingHandSetting extends EnumSetting { private static final MinecraftClient MC = WurstClient.MC; - private static final String FULL_DESCRIPTION_SUFFIX = + private static final WText FULL_DESCRIPTION_SUFFIX = buildDescriptionSuffix(true); - private static final String REDUCED_DESCRIPTION_SUFFIX = + private static final WText REDUCED_DESCRIPTION_SUFFIX = buildDescriptionSuffix(false); - private SwingHandSetting(String name, String description, - SwingHand[] values, SwingHand selected) + private SwingHandSetting(String name, WText description, SwingHand[] values, + SwingHand selected) { super(name, description, values, selected); } - public SwingHandSetting(String name, String description, SwingHand selected) + public SwingHandSetting(WText description, SwingHand selected) { - this(name, description + FULL_DESCRIPTION_SUFFIX, SwingHand.values(), - selected); + this("Swing hand", description.append(FULL_DESCRIPTION_SUFFIX), + SwingHand.values(), selected); } - public SwingHandSetting(String description, SwingHand selected) + public SwingHandSetting(Hack hack, SwingHand selected) { - this("Swing hand", description, selected); + this(hackDescription(hack), selected); } - public SwingHandSetting(String description) + public static SwingHandSetting withoutOffOption(WText description, + SwingHand selected) { - this(description, SwingHand.SERVER); + SwingHand[] values = {SwingHand.SERVER, SwingHand.CLIENT}; + return new SwingHandSetting("Swing hand", + description.append(REDUCED_DESCRIPTION_SUFFIX), values, selected); } - public static SwingHandSetting withoutOffOption(String name, - String description, SwingHand selected) + public static SwingHandSetting withoutOffOption(Hack hack, + SwingHand selected) { - SwingHand[] values = {SwingHand.SERVER, SwingHand.CLIENT}; - return new SwingHandSetting(name, - description + REDUCED_DESCRIPTION_SUFFIX, values, selected); + return withoutOffOption(hackDescription(hack), selected); } - public static SwingHandSetting withoutOffOption(String description, - SwingHand selected) + public static WText genericMiningDescription(Hack hack) { - return withoutOffOption("Swing hand", description, selected); + return WText.translated( + "description.wurst.setting.generic.swing_hand_mining", + hack.getName()); + } + + public static WText genericCombatDescription(Hack hack) + { + return WText.translated( + "description.wurst.setting.generic.swing_hand_combat", + hack.getName()); + } + + private static WText hackDescription(Hack hack) + { + return WText.translated("description.wurst.setting." + + hack.getName().toLowerCase() + ".swing_hand"); } public void swing(Hand hand) @@ -64,44 +81,41 @@ public void swing(Hand hand) getSelected().swing(hand); } - private static String buildDescriptionSuffix(boolean includeOff) + private static WText buildDescriptionSuffix(boolean includeOff) { - StringBuilder builder = new StringBuilder("\n\n"); + WText text = WText.literal("\n\n"); SwingHand[] values = includeOff ? SwingHand.values() : new SwingHand[]{SwingHand.SERVER, SwingHand.CLIENT}; for(SwingHand value : values) - builder.append("\u00a7l").append(value.name).append("\u00a7r - ") + text.append("\u00a7l" + value.name + "\u00a7r - ") .append(value.description).append("\n\n"); - return builder.toString(); + return text; } public enum SwingHand { - OFF("Off", - "Don't swing your hand at all. Will be detected by anti-cheat" - + " plugins.", - hand -> {}), + OFF("Off", hand -> {}), SERVER("Server-side", - "Swing your hand on the server-side, without playing the animation" - + " on the client-side.", hand -> MC.player.networkHandler .sendPacket(new HandSwingC2SPacket(hand))), - CLIENT("Client-side", - "Swing your hand on the client-side. This is the most legit option.", - hand -> MC.player.swingHand(hand)); + CLIENT("Client-side", hand -> MC.player.swingHand(hand)); + + private static final String TRANSLATION_KEY_PREFIX = + "description.wurst.setting.generic.swing_hand."; private final String name; - private final String description; + private final WText description; private final Consumer swing; - private SwingHand(String name, String description, Consumer swing) + private SwingHand(String name, Consumer swing) { this.name = name; - this.description = description; + description = + WText.translated(TRANSLATION_KEY_PREFIX + name().toLowerCase()); this.swing = swing; } diff --git a/src/main/java/net/wurstclient/settings/TextFieldSetting.java b/src/main/java/net/wurstclient/settings/TextFieldSetting.java index 590ac30f76..a1e33571ec 100644 --- a/src/main/java/net/wurstclient/settings/TextFieldSetting.java +++ b/src/main/java/net/wurstclient/settings/TextFieldSetting.java @@ -22,6 +22,7 @@ import net.wurstclient.keybinds.PossibleKeybind; import net.wurstclient.util.json.JsonException; import net.wurstclient.util.json.JsonUtils; +import net.wurstclient.util.text.WText; public final class TextFieldSetting extends Setting { @@ -29,8 +30,8 @@ public final class TextFieldSetting extends Setting private final String defaultValue; private final Predicate validator; - public TextFieldSetting(String name, String description, - String defaultValue, Predicate validator) + public TextFieldSetting(String name, WText description, String defaultValue, + Predicate validator) { super(name, description); @@ -45,21 +46,32 @@ public TextFieldSetting(String name, String description, this.validator = validator; } + public TextFieldSetting(String name, String descriptionKey, + String defaultValue, Predicate validator) + { + this(name, WText.translated(descriptionKey), defaultValue, validator); + } + public TextFieldSetting(String name, String defaultValue, Predicate validator) { - this(name, "", defaultValue, validator); + this(name, WText.empty(), defaultValue, validator); } - public TextFieldSetting(String name, String description, - String defaultValue) + public TextFieldSetting(String name, WText description, String defaultValue) { this(name, description, defaultValue, s -> true); } + public TextFieldSetting(String name, String descriptionKey, + String defaultValue) + { + this(name, WText.translated(descriptionKey), defaultValue, s -> true); + } + public TextFieldSetting(String name, String defaultValue) { - this(name, "", defaultValue, s -> true); + this(name, WText.empty(), defaultValue, s -> true); } /** @@ -134,7 +146,7 @@ public JsonObject exportWikiData() { JsonObject json = new JsonObject(); json.addProperty("name", getName()); - json.addProperty("descriptionKey", getDescriptionKey()); + json.addProperty("description", getDescription()); json.addProperty("type", "TextField"); json.addProperty("defaultValue", defaultValue); return json; diff --git a/src/main/java/net/wurstclient/util/BlockBreaker.java b/src/main/java/net/wurstclient/util/BlockBreaker.java index c1c28ec328..daab4a7f03 100644 --- a/src/main/java/net/wurstclient/util/BlockBreaker.java +++ b/src/main/java/net/wurstclient/util/BlockBreaker.java @@ -7,10 +7,12 @@ */ package net.wurstclient.util; +import java.util.Comparator; +import java.util.function.Function; + import net.minecraft.block.BlockState; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket; import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket; import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket.Action; import net.minecraft.util.Hand; @@ -22,6 +24,7 @@ import net.minecraft.util.math.Vec3i; import net.minecraft.util.shape.VoxelShape; import net.wurstclient.WurstClient; +import net.wurstclient.settings.SwingHandSetting.SwingHand; public enum BlockBreaker { @@ -36,17 +39,21 @@ public static boolean breakOneBlock(BlockPos pos) if(params == null) return false; + return breakOneBlock(params); + } + + public static boolean breakOneBlock(BlockBreakingParams params) + { // face block WURST.getRotationFaker().faceVectorPacket(params.hitVec); // damage block - if(!MC.interactionManager.updateBlockBreakingProgress(pos, params.side)) + if(!MC.interactionManager.updateBlockBreakingProgress(params.pos, + params.side)) return false; // swing arm - MC.player.networkHandler - .sendPacket(new HandSwingC2SPacket(Hand.MAIN_HAND)); - + SwingHand.SERVER.swing(Hand.MAIN_HAND); return true; } @@ -140,6 +147,27 @@ public BlockHitResult toHitResult() } } + /** + * Returns a comparator that compares BlockBreakingParams by line of sight + * first, then by distance. + */ + public static Comparator comparingParams() + { + return Comparator.comparing(BlockBreakingParams::lineOfSight).reversed() + .thenComparing(params -> params.distanceSq); + } + + /** + * Returns a comparator that compares BlockBreakingParams by line of sight + * first, then by distance. + */ + public static Comparator comparingParams( + Function keyExtractor) + { + return Comparator. comparing(keyExtractor, + comparingParams()); + } + public static void breakBlocksWithPacketSpam(Iterable blocks) { Vec3d eyesPos = RotationUtils.getEyesPos(); diff --git a/src/main/java/net/wurstclient/util/BlockBreakingCache.java b/src/main/java/net/wurstclient/util/BlockBreakingCache.java new file mode 100644 index 0000000000..cf2ecb07fc --- /dev/null +++ b/src/main/java/net/wurstclient/util/BlockBreakingCache.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014-2024 Wurst-Imperium and contributors. + * + * This source code is subject to the terms of the GNU General Public + * License, version 3. If a copy of the GPL was not distributed with this + * file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt + */ +package net.wurstclient.util; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import net.minecraft.util.math.BlockPos; + +public final class BlockBreakingCache +{ + private final ArrayDeque> prevBlocks = new ArrayDeque<>(); + + /** + * Waits 5 ticks before trying to break the same block again, which + * makes it much more likely that the server will accept the block + * breaking packets. + */ + public ArrayList filterOutRecentBlocks(Stream stream) + { + for(Set set : prevBlocks) + stream = stream.filter(pos -> !set.contains(pos)); + + ArrayList blocks = + stream.collect(Collectors.toCollection(ArrayList::new)); + + prevBlocks.addLast(new HashSet<>(blocks)); + while(prevBlocks.size() > 5) + prevBlocks.removeFirst(); + + return blocks; + } + + public void reset() + { + prevBlocks.clear(); + } +} diff --git a/src/main/java/net/wurstclient/util/ChunkSearcherCoordinator.java b/src/main/java/net/wurstclient/util/chunk/AbstractChunkCoordinator.java similarity index 74% rename from src/main/java/net/wurstclient/util/ChunkSearcherCoordinator.java rename to src/main/java/net/wurstclient/util/chunk/AbstractChunkCoordinator.java index bf0f7bdb73..f27c2bcc54 100644 --- a/src/main/java/net/wurstclient/util/ChunkSearcherCoordinator.java +++ b/src/main/java/net/wurstclient/util/chunk/AbstractChunkCoordinator.java @@ -5,7 +5,7 @@ * License, version 3. If a copy of the GPL was not distributed with this * file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt */ -package net.wurstclient.util; +package net.wurstclient.util.chunk; import java.util.ArrayList; import java.util.Collections; @@ -14,7 +14,6 @@ import java.util.Objects; import java.util.Set; import java.util.function.BiPredicate; -import java.util.stream.Stream; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -25,38 +24,24 @@ import net.wurstclient.WurstClient; import net.wurstclient.events.PacketInputListener; import net.wurstclient.settings.ChunkAreaSetting; -import net.wurstclient.util.ChunkSearcher.Result; -public final class ChunkSearcherCoordinator implements PacketInputListener +public abstract class AbstractChunkCoordinator implements PacketInputListener { - private final HashMap searchers = new HashMap<>(); - private final ChunkAreaSetting area; + protected final HashMap searchers = + new HashMap<>(); + protected final ChunkAreaSetting area; private BiPredicate query; - private final Set chunksToUpdate = + protected final Set chunksToUpdate = Collections.synchronizedSet(new HashSet<>()); - public ChunkSearcherCoordinator(ChunkAreaSetting area) - { - this((pos, state) -> false, area); - } - - public ChunkSearcherCoordinator(BiPredicate query, + public AbstractChunkCoordinator(BiPredicate query, ChunkAreaSetting area) { this.query = Objects.requireNonNull(query); this.area = Objects.requireNonNull(area); } - @Override - public void onReceivedPacket(PacketInputEvent event) - { - ChunkPos chunkPos = ChunkUtils.getAffectedChunk(event.getPacket()); - - if(chunkPos != null) - chunksToUpdate.add(chunkPos); - } - public boolean update() { DimensionType dimension = WurstClient.MC.world.getDimension(); @@ -85,6 +70,7 @@ else if(chunkUpdates.contains(searcherPos)) { searchers.remove(searcherPos); searcher.cancel(); + onRemove(searcher); searchersChanged = true; } } @@ -105,6 +91,11 @@ else if(chunkUpdates.contains(searcherPos)) return searchersChanged; } + protected void onRemove(ChunkSearcher searcher) + { + // Overridden in ChunkVertexBufferCoordinator + } + public void reset() { searchers.values().forEach(ChunkSearcher::cancel); @@ -117,9 +108,11 @@ public boolean isDone() return searchers.values().stream().allMatch(ChunkSearcher::isDone); } - public Stream getMatches() + public void setQuery(BiPredicate query) { - return searchers.values().stream().flatMap(ChunkSearcher::getMatches); + this.query = Objects.requireNonNull(query); + searchers.values().forEach(ChunkSearcher::cancel); + searchers.clear(); } public void setTargetBlock(Block block) @@ -127,14 +120,7 @@ public void setTargetBlock(Block block) setQuery((pos, state) -> block == state.getBlock()); } - public void setQuery(BiPredicate query) - { - this.query = Objects.requireNonNull(query); - searchers.values().forEach(ChunkSearcher::cancel); - searchers.clear(); - } - - private HashSet clearChunksToUpdate() + protected HashSet clearChunksToUpdate() { synchronized(chunksToUpdate) { diff --git a/src/main/java/net/wurstclient/util/ChunkSearcher.java b/src/main/java/net/wurstclient/util/chunk/ChunkSearcher.java similarity index 84% rename from src/main/java/net/wurstclient/util/ChunkSearcher.java rename to src/main/java/net/wurstclient/util/chunk/ChunkSearcher.java index 30f8310b92..e2e1f749a9 100644 --- a/src/main/java/net/wurstclient/util/ChunkSearcher.java +++ b/src/main/java/net/wurstclient/util/chunk/ChunkSearcher.java @@ -5,20 +5,22 @@ * License, version 3. If a copy of the GPL was not distributed with this * file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt */ -package net.wurstclient.util; +package net.wurstclient.util.chunk; import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.function.BiPredicate; import java.util.stream.Stream; -import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.dimension.DimensionType; +import net.wurstclient.util.MinPriorityThreadFactory; /** * Searches the given {@link Chunk} for blocks matching the given query. @@ -35,11 +37,6 @@ public final class ChunkSearcher private CompletableFuture> future; private boolean interrupted; - public ChunkSearcher(Block block, Chunk chunk, DimensionType dimension) - { - this((pos, state) -> block == state.getBlock(), chunk, dimension); - } - public ChunkSearcher(BiPredicate query, Chunk chunk, DimensionType dimension) { @@ -96,6 +93,11 @@ public void cancel() future.cancel(false); } + public boolean isInterrupted() + { + return interrupted; + } + public ChunkPos getPos() { return chunk.getPos(); @@ -114,6 +116,14 @@ public Stream getMatches() return future.join().stream(); } + public List getMatchesList() + { + if(future == null || future.isCancelled()) + return List.of(); + + return Collections.unmodifiableList(future.join()); + } + public boolean isDone() { return future != null && future.isDone(); diff --git a/src/main/java/net/wurstclient/util/chunk/ChunkSearcherCoordinator.java b/src/main/java/net/wurstclient/util/chunk/ChunkSearcherCoordinator.java new file mode 100644 index 0000000000..6735d3751e --- /dev/null +++ b/src/main/java/net/wurstclient/util/chunk/ChunkSearcherCoordinator.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014-2024 Wurst-Imperium and contributors. + * + * This source code is subject to the terms of the GNU General Public + * License, version 3. If a copy of the GPL was not distributed with this + * file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt + */ +package net.wurstclient.util.chunk; + +import java.util.function.BiPredicate; +import java.util.stream.Stream; + +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.wurstclient.settings.ChunkAreaSetting; +import net.wurstclient.util.chunk.ChunkSearcher.Result; + +public final class ChunkSearcherCoordinator extends AbstractChunkCoordinator +{ + public ChunkSearcherCoordinator(ChunkAreaSetting area) + { + this((pos, state) -> false, area); + } + + public ChunkSearcherCoordinator(BiPredicate query, + ChunkAreaSetting area) + { + super(query, area); + } + + @Override + public void onReceivedPacket(PacketInputEvent event) + { + ChunkPos chunkPos = ChunkUtils.getAffectedChunk(event.getPacket()); + + if(chunkPos != null) + chunksToUpdate.add(chunkPos); + } + + public Stream getMatches() + { + return searchers.values().stream().flatMap(ChunkSearcher::getMatches); + } +} diff --git a/src/main/java/net/wurstclient/util/ChunkUtils.java b/src/main/java/net/wurstclient/util/chunk/ChunkUtils.java similarity index 95% rename from src/main/java/net/wurstclient/util/ChunkUtils.java rename to src/main/java/net/wurstclient/util/chunk/ChunkUtils.java index 12b13e71b7..ce629a35d7 100644 --- a/src/main/java/net/wurstclient/util/ChunkUtils.java +++ b/src/main/java/net/wurstclient/util/chunk/ChunkUtils.java @@ -5,7 +5,7 @@ * License, version 3. If a copy of the GPL was not distributed with this * file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt */ -package net.wurstclient.util; +package net.wurstclient.util.chunk; import java.util.Objects; import java.util.stream.Stream; diff --git a/src/main/java/net/wurstclient/util/chunk/ChunkVertexBufferCoordinator.java b/src/main/java/net/wurstclient/util/chunk/ChunkVertexBufferCoordinator.java new file mode 100644 index 0000000000..9c1748a200 --- /dev/null +++ b/src/main/java/net/wurstclient/util/chunk/ChunkVertexBufferCoordinator.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2014-2024 Wurst-Imperium and contributors. + * + * This source code is subject to the terms of the GNU General Public + * License, version 3. If a copy of the GPL was not distributed with this + * file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt + */ +package net.wurstclient.util.chunk; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.Set; +import java.util.function.BiFunction; +import java.util.function.BiPredicate; + +import net.minecraft.block.BlockState; +import net.minecraft.client.gl.VertexBuffer; +import net.minecraft.client.render.BuiltBuffer; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.wurstclient.settings.ChunkAreaSetting; +import net.wurstclient.util.chunk.ChunkSearcher.Result; + +public final class ChunkVertexBufferCoordinator extends AbstractChunkCoordinator +{ + private final HashMap buffers = new HashMap<>(); + private final BiFunction, BuiltBuffer> renderer; + + public ChunkVertexBufferCoordinator(BiPredicate query, + BiFunction, BuiltBuffer> renderer, + ChunkAreaSetting area) + { + super(query, area); + this.renderer = Objects.requireNonNull(renderer); + } + + @Override + public void onReceivedPacket(PacketInputEvent event) + { + ChunkPos center = ChunkUtils.getAffectedChunk(event.getPacket()); + if(center == null) + return; + + for(int x = center.x - 1; x <= center.x + 1; x++) + for(int z = center.z - 1; z <= center.z + 1; z++) + chunksToUpdate.add(new ChunkPos(x, z)); + } + + @Override + protected void onRemove(ChunkSearcher searcher) + { + @SuppressWarnings("resource") + VertexBuffer buffer = buffers.remove(searcher.getPos()); + if(buffer != null) + buffer.close(); + } + + @Override + public void reset() + { + super.reset(); + buffers.values().forEach(VertexBuffer::close); + buffers.clear(); + } + + public Set> getBuffers() + { + for(ChunkSearcher searcher : searchers.values()) + buildBuffer(searcher); + + return Collections.unmodifiableSet(buffers.entrySet()); + } + + private void buildBuffer(ChunkSearcher searcher) + { + if(buffers.containsKey(searcher.getPos())) + return; + + BuiltBuffer buffer = + renderer.apply(searcher, searcher.getMatchesList()); + if(buffer == null) + return; + + VertexBuffer vertexBuffer = new VertexBuffer(VertexBuffer.Usage.STATIC); + vertexBuffer.bind(); + vertexBuffer.upload(buffer); + VertexBuffer.unbind(); + buffers.put(searcher.getPos(), vertexBuffer); + } +} diff --git a/src/main/java/net/wurstclient/util/text/WLiteralTextContent.java b/src/main/java/net/wurstclient/util/text/WLiteralTextContent.java new file mode 100644 index 0000000000..2785bbe0f0 --- /dev/null +++ b/src/main/java/net/wurstclient/util/text/WLiteralTextContent.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014-2024 Wurst-Imperium and contributors. + * + * This source code is subject to the terms of the GNU General Public + * License, version 3. If a copy of the GPL was not distributed with this + * file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt + */ +package net.wurstclient.util.text; + +import java.util.Objects; + +public final class WLiteralTextContent implements WTextContent +{ + public static final WLiteralTextContent EMPTY = new WLiteralTextContent(""); + + private final String text; + + public WLiteralTextContent(String text) + { + this.text = Objects.requireNonNull(text); + } + + @Override + public String toString() + { + return text; + } +} diff --git a/src/main/java/net/wurstclient/util/text/WText.java b/src/main/java/net/wurstclient/util/text/WText.java new file mode 100644 index 0000000000..04d7a34ae7 --- /dev/null +++ b/src/main/java/net/wurstclient/util/text/WText.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2014-2024 Wurst-Imperium and contributors. + * + * This source code is subject to the terms of the GNU General Public + * License, version 3. If a copy of the GPL was not distributed with this + * file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt + */ +package net.wurstclient.util.text; + +import java.util.ArrayList; + +import com.google.common.collect.Lists; + +import net.minecraft.text.Text; + +/** + * Allows you to build more complex text out of multiple Wurst translations and + * have everything update automatically when the user's language changes. + * + *

+ * This is necessary because Minecraft's {@link Text} does not have access to + * Wurst's translations for security reasons. + */ +public final class WText +{ + private final ArrayList contents; + + private WText(WTextContent... contents) + { + this.contents = Lists.newArrayList(contents); + } + + public static WText literal(String text) + { + return new WText(new WLiteralTextContent(text)); + } + + public static WText translated(String key, Object... args) + { + return new WText(new WTranslatedTextContent(key, args)); + } + + public static WText empty() + { + return new WText(WLiteralTextContent.EMPTY); + } + + public WText append(WText text) + { + contents.addAll(text.contents); + return this; + } + + public WText append(String text) + { + return append(literal(text)); + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + for(WTextContent content : contents) + builder.append(content); + return builder.toString(); + } +} diff --git a/src/main/java/net/wurstclient/util/text/WTextContent.java b/src/main/java/net/wurstclient/util/text/WTextContent.java new file mode 100644 index 0000000000..2098c6fdab --- /dev/null +++ b/src/main/java/net/wurstclient/util/text/WTextContent.java @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2014-2024 Wurst-Imperium and contributors. + * + * This source code is subject to the terms of the GNU General Public + * License, version 3. If a copy of the GPL was not distributed with this + * file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt + */ +package net.wurstclient.util.text; + +public interface WTextContent +{ + +} diff --git a/src/main/java/net/wurstclient/util/text/WTranslatedTextContent.java b/src/main/java/net/wurstclient/util/text/WTranslatedTextContent.java new file mode 100644 index 0000000000..36fafebb70 --- /dev/null +++ b/src/main/java/net/wurstclient/util/text/WTranslatedTextContent.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014-2024 Wurst-Imperium and contributors. + * + * This source code is subject to the terms of the GNU General Public + * License, version 3. If a copy of the GPL was not distributed with this + * file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt + */ +package net.wurstclient.util.text; + +import java.util.Map; +import java.util.Objects; + +import net.wurstclient.WurstClient; +import net.wurstclient.WurstTranslator; + +public final class WTranslatedTextContent implements WTextContent +{ + private final String key; + private final Object[] args; + private String translation; + private Map lastLanguage; + + public WTranslatedTextContent(String key, Object... args) + { + this.key = Objects.requireNonNull(key); + this.args = args; + } + + private void update() + { + WurstTranslator translator = WurstClient.INSTANCE.getTranslator(); + Map language = translator.getWurstsCurrentLanguage(); + if(language == lastLanguage) + return; + + translation = translator.translate(key, args); + lastLanguage = language; + } + + @Override + public String toString() + { + update(); + return translation; + } +} diff --git a/src/main/resources/assets/wurst/translations/cs_cz.json b/src/main/resources/assets/wurst/translations/cs_cz.json index cd9f1bbf72..955beed352 100644 --- a/src/main/resources/assets/wurst/translations/cs_cz.json +++ b/src/main/resources/assets/wurst/translations/cs_cz.json @@ -98,7 +98,7 @@ "description.wurst.hack.masstpa": "Odešle požadavek na TPA všem hráčům.", "description.wurst.hack.mileycyrus": "Neustálé twerkování.", "description.wurst.hack.mobesp": "Zvýrazní moby v okolí.", - "description.wurst.hack.mobspawnesp": "Zvýrazní oblasti, kde se mohou mobové objevovat.\n§ežlutá§r - mobové se mohou oběvovat v noci\n§cred§r - mobové se mohou oběvovat vždy", + "description.wurst.hack.mobspawnesp": "Zvýrazní oblasti, kde se mohou mobové objevovat.", "description.wurst.hack.multiaura": "Rychlejší Killaura, která útočí na více entit najednou.", "description.wurst.hack.nameprotect": "Skryje jména všech hráčů.", "description.wurst.hack.nametags": "Změní měřítko jmenovek tak, abyste je mohli vždy číst. Také vám umožní vidět jmenovky krčících se hráčů.", diff --git a/src/main/resources/assets/wurst/translations/de_de.json b/src/main/resources/assets/wurst/translations/de_de.json index 39bfd0d514..5d3cbe92e3 100644 --- a/src/main/resources/assets/wurst/translations/de_de.json +++ b/src/main/resources/assets/wurst/translations/de_de.json @@ -106,7 +106,7 @@ "description.wurst.hack.masstpa": "Sendet TPA-Requests an alle Spieler.", "description.wurst.hack.mileycyrus": "Lässt dich twerken.", "description.wurst.hack.mobesp": "Markiert Mobs in deiner Umgebung.", - "description.wurst.hack.mobspawnesp": "Markiert Orte, an denen Mobs spawnen können.\n§eGelb§r - Mobs können nachts spawnen\n§cRot§r - Mobs können jederzeit spawnen", + "description.wurst.hack.mobspawnesp": "Markiert Orte, an denen Mobs spawnen können.", "description.wurst.hack.multiaura": "Schnellere Killaura, die mehrere Mobs und Spieler gleichzeitig angreifen kann.", "description.wurst.hack.nameprotect": "Verbirgt alle Spielernamen.", "description.wurst.hack.nametags": "Ändert die Größe der Name-Tags, sodass du sie immer gut lesen kannst. Ermöglicht dir außerdem, die Name-Tags von schleichenden Spielern zu sehen.", diff --git a/src/main/resources/assets/wurst/translations/en_us.json b/src/main/resources/assets/wurst/translations/en_us.json index f7aec70c3b..3b81bbd6a6 100644 --- a/src/main/resources/assets/wurst/translations/en_us.json +++ b/src/main/resources/assets/wurst/translations/en_us.json @@ -12,6 +12,7 @@ "description.wurst.setting.anchoraura.auto-place_anchors": "When enabled, AnchorAura will automatically place anchors near valid entities.\nWhen disabled, AnchorAura will only charge and detonate manually placed anchors.", "description.wurst.setting.anchoraura.face_anchors": "Whether or not AnchorAura should face the correct direction when placing and right-clicking respawn anchors.\n\nSlower but can help with anti-cheat plugins.", "description.wurst.setting.anchoraura.check_line_of_sight": "Ensures that you don't reach through blocks when placing or right-clicking respawn anchors.\n\nSlower but can help with anti-cheat plugins.", + "description.wurst.setting.anchoraura.swing_hand": "How AnchorAura should swing your hand when placing, charging and detonating respawn anchors.", "description.wurst.setting.anchoraura.take_items_from": "Where to look for respawn anchors and glowstone.", "description.wurst.hack.antiafk": "Walks around randomly to hide you from AFK detectors.", "description.wurst.setting.antiafk.use_ai": "Uses a pathfinding AI to move around naturally and avoid hazards.\nCan sometimes get stuck.", @@ -37,6 +38,7 @@ "description.wurst.hack.autodrop": "Automatically drops unwanted items.", "description.wurst.hack.autoleave": "Automatically leaves the server when your health is low.", "description.wurst.hack.autolibrarian": "Automatically trains a villager to become a librarian that sells a specific enchanted book. You can set up an entire trading hall in no time by using this hack.", + "description.wurst.setting.autolibrarian.swing_hand": "How AutoLibrarian should swing your hand when interacting with the villager and job site.", "description.wurst.hack.autoeat": "Automatically eats food when necessary.", "description.wurst.setting.autoeat.target_hunger": "Tries to keep the hunger bar at or above this level, but only if it doesn't waste any hunger points.", "description.wurst.setting.autoeat.min_hunger": "Always keeps the hunger bar at or above this level, even if it wastes some hunger points.\n6.5 - Cannot cause any waste with vanilla food items.\n10.0 - Completely ignores waste and just keeps the hunger bar full.", @@ -70,6 +72,7 @@ "description.wurst.hack.bonemealaura": "Automatically uses bone meal on specific types of plants.\nUse the checkboxes to specify the types of plants.", "description.wurst.hack.bowaimbot": "Automatically aims your bow or crossbow.", "description.wurst.hack.buildrandom": "Randomly places blocks around you.", + "description.wurst.setting.buildrandom.swing_hand": "How BuildRandom should swing your hand when placing blocks.", "description.wurst.hack.bunnyhop": "Makes you jump automatically.", "description.wurst.hack.cameradistance": "Allows you to change the camera distance in 3rd person.", "description.wurst.hack.cameranoclip": "Allows the camera in 3rd person to go through walls.", @@ -87,6 +90,7 @@ "description.wurst.hack.creativeflight": "Allows you to fly like in Creative Mode.\n\n§c§lWARNING:§r You will take fall damage if you don't use NoFall.", "description.wurst.hack.criticals": "Changes all your hits to critical hits.", "description.wurst.hack.crystalaura": "Automatically places (optional) and detonates end crystals to kill entities around you.", + "description.wurst.setting.crystalaura.swing_hand": "How CrystalAura should swing your hand when placing and detonating end crystals.", "description.wurst.hack.derp": "Randomly moves your head around.\nOnly visible to other players.", "description.wurst.hack.dolphin": "Makes you bob up in water automatically.\n(just like a dolphin)", "description.wurst.hack.excavator": "Automatically breaks all blocks in the selected area.", @@ -133,7 +137,10 @@ "description.wurst.hack.itemgenerator": "Generates random items and drops them on the ground.\n§oCreative mode only.§r", "description.wurst.hack.jesus": "Allows you to walk on water.\nJesus used this hack ~2000 years ago.", "description.wurst.hack.jetpack": "Allows you to fly as if you had a jetpack.\n\n§c§lWARNING:§r You will take fall damage if you don't use NoFall.", - "description.wurst.hack.kaboom": "Breaks blocks around you like an explosion.\nThis can be a lot faster than Nuker if the server doesn't have NoCheat+. It works best with fast tools and weak blocks.\nNote: This is not an actual explosion.", + "description.wurst.hack.kaboom": "Breaks blocks around you like an explosion.\n\nCan be a lot faster than Nuker if the server doesn't have an anti-cheat plugin. It works best with fast tools and weak blocks.\n\nNote: This is not an actual explosion.", + "description.wurst.setting.kaboom.power": "Determines how many sets of block breaking packets will be sent for each block.\n\nHigher values increase your odds of breaking more blocks, but also place additional load on the server. Small servers are likely to crash at the higher values.", + "description.wurst.setting.kaboom.sound": "Whether or not to play an explosion sound. Does not affect block breaking. Only you can hear the sound.", + "description.wurst.setting.kaboom.particles": "Whether or not to display explosion particles. Does not affect block breaking. Only you can see the particles.", "description.wurst.hack.killauralegit": "Slower Killaura that is harder to detect.\nNot required on normal NoCheat+ servers!", "description.wurst.hack.killaura": "Automatically attacks entities around you.", "description.wurst.hack.killpotion": "Generates a potion that can kill almost anything, including players in Creative mode. Does not work on undead mobs, since they are already dead.\n\nRequires Creative mode.", @@ -143,7 +150,9 @@ "description.wurst.hack.masstpa": "Sends a TPA request to all players.", "description.wurst.hack.mileycyrus": "Makes you twerk.", "description.wurst.hack.mobesp": "Highlights nearby mobs.", - "description.wurst.hack.mobspawnesp": "Highlights areas where mobs can spawn.\n§eyellow§r - mobs can spawn at night\n§cred§r - mobs can always spawn", + "description.wurst.hack.mobspawnesp": "Highlights areas where mobs can spawn.", + "description.wurst.setting.mobspawnesp.night_color": "Color of the X at positions where mobs can spawn at night.", + "description.wurst.setting.mobspawnesp.day_color": "Color of the X at positions where mobs can always spawn.", "description.wurst.hack.multiaura": "Faster Killaura that attacks multiple entities at once.", "description.wurst.hack.nameprotect": "Hides all player names.", "description.wurst.hack.nametags": "Changes the scale of the nametags so you can always read them. Also allows you to see the nametags of sneaking players.", @@ -166,7 +175,7 @@ "description.wurst.hack.noweather": "Allows you to alter the client-side weather, time and moon phase.", "description.wurst.hack.noweb": "Prevents you from getting slowed down by cobwebs.", "description.wurst.hack.nuker": "Automatically breaks blocks around you.", - "description.wurst.hack.nukerlegit": "Slower Nuker that bypasses all AntiCheat plugins.\nNot required on normal NoCheat+ servers!", + "description.wurst.hack.nukerlegit": "Slower Nuker that's much harder for anti-cheat plugins to detect.\nNot required on normal NoCheat+ servers!", "description.wurst.hack.openwateresp": "Shows whether or not you are fishing in 'open water' and draws a box around the area used for the open water calculation.", "description.wurst.hack.overlay": "Renders the Nuker animation whenever you mine a block.", "description.wurst.hack.panic": "Instantly turns off all enabled hacks.\nBe careful with this one!", @@ -216,10 +225,13 @@ "description.wurst.hack.tp-aura": "Automatically attacks the closest valid entity while teleporting around it.", "description.wurst.hack.trajectories": "Predicts the flight path of arrows and throwable items.", "description.wurst.hack.treebot": "An experimental bot that automatically walks around and chops down trees.\nLimited to small trees for now.", + "description.wurst.setting.treebot.swing_hand": "How TreeBot should swing your hand when breaking logs and leaves.", "description.wurst.hack.triggerbot": "Automatically attacks the entity you're looking at.", + "description.wurst.setting.triggerbot.swing_hand": "How TriggerBot should swing your hand when attacking. (This setting will be ignored if \"Simulate mouse click\" is enabled.)", "description.wurst.hack.trollpotion": "Generates a potion with many annoying effects on it.", "description.wurst.hack.truesight": "Allows you to see invisible entities.", "description.wurst.hack.tunneller": "Automatically digs a tunnel.\n\n§c§lWARNING:§r Although this bot will try to avoid lava and other dangers, there is no guarantee that it won't die. Only send it out with gear that you don't mind losing.", + "description.wurst.hack.veinminer": "Automatically mines ore veins for you.", "description.wurst.hack.x-ray": "Allows you to see ores through walls.", "description.wurst.other_feature.nochatreports": "Disables the cryptographic signatures that since 1.19 are attached to your chat messages.\n\n§c§lWARNING: §cIf §cyou §csend §cchat §cmessages §cwith §csignatures, §cyour §cMinecraft §caccount §ccan §cget §creported §cand §cglobally §cbanned §cfrom §cmultiplayer!§r\n\nEven if you only say harmless things in chat, your signed messages can be abused to create a fake chat report that gets your account banned unfairly.\n\nIf you have to re-enable chat signatures to chat on a server, consider playing on an alt account that you don't mind losing.", "button.wurst.nochatreports.disable_signatures": "Disable Signatures", @@ -259,6 +271,11 @@ "description.wurst.setting.generic.filter_zombie_villagers_combat": "Won't attack zombified villagers.", "description.wurst.setting.generic.filter_zombie_villagers_vision": "Won't show zombified villagers.", "description.wurst.setting.generic.pause_attack_on_containers": "Won't attack while a container screen (chest, hopper, etc.) is open.\nUseful for minigame servers that display chest-like menus.", + "description.wurst.setting.generic.swing_hand_mining": "How %s should swing your hand when mining.", + "description.wurst.setting.generic.swing_hand_combat": "How %s should swing your hand when attacking.", + "description.wurst.setting.generic.swing_hand.off": "Don't swing your hand at all. Will be detected by anti-cheat plugins.", + "description.wurst.setting.generic.swing_hand.server": "Swing your hand on the server-side, without playing the animation on the client-side.", + "description.wurst.setting.generic.swing_hand.client": "Swing your hand on the client-side. This is the most legit option.", "description.wurst.altmanager.premium": "This alt has a password and can join all servers.", "description.wurst.altmanager.cracked": "This alt has no password and will only work on cracked servers.", "description.wurst.altmanager.failed": "Last time you tried to log in with this alt, it didn't work.", diff --git a/src/main/resources/assets/wurst/translations/fr_fr.json b/src/main/resources/assets/wurst/translations/fr_fr.json index 1468dd7217..60658b9f8c 100644 --- a/src/main/resources/assets/wurst/translations/fr_fr.json +++ b/src/main/resources/assets/wurst/translations/fr_fr.json @@ -95,7 +95,7 @@ "description.wurst.hack.masstpa": "Envoie une requête TPA à tous les joueurs.", "description.wurst.hack.mileycyrus": "Vous fait twerker.", "description.wurst.hack.mobesp": "Met en évidence les monstres à proximité.", - "description.wurst.hack.mobspawnesp": "Met en évidence les zones où les monstres peuvent apparaître.\n§ejaune§r - les monstres peuvent apparaître la nuit\n§crouge§r - les monstres peuvent toujours apparaître", + "description.wurst.hack.mobspawnesp": "Met en évidence les zones où les monstres peuvent apparaître.", "description.wurst.hack.multiaura": "Killaura plus rapide qui attaque plusieurs entités à la fois.", "description.wurst.hack.nameprotect": "Masque tous les noms de joueurs.", "description.wurst.hack.nametags": "Modifie l'échelle des nametags de nom afin que vous puissiez toujours les lire. Vous permet également de voir les nametags des joueurs accroupis.", diff --git a/src/main/resources/assets/wurst/translations/it_it.json b/src/main/resources/assets/wurst/translations/it_it.json index b7718c10b9..9f4c2f6f68 100644 --- a/src/main/resources/assets/wurst/translations/it_it.json +++ b/src/main/resources/assets/wurst/translations/it_it.json @@ -98,7 +98,7 @@ "description.wurst.hack.masstpa": "Manda una richiesta di teletrasporto a tutti i giocatori.", "description.wurst.hack.mileycyrus": "Ti fa twerkare.", "description.wurst.hack.mobesp": "Evidenzia i mob vicini.", - "description.wurst.hack.mobspawnesp": "Evidenzia le aree dove i mob possono spawnare.\n§egiallo§r - I mob possono nascere durante la notte\n§crosso§r - i mob possono nascere sempre", + "description.wurst.hack.mobspawnesp": "Evidenzia le aree dove i mob possono spawnare.", "description.wurst.hack.multiaura": "Killaura più veloce che attacca più entità in una sola volta.", "description.wurst.hack.nameprotect": "Nasconde i nomi dei giocatori.", "description.wurst.hack.nametags": "Modifica la scala delle targhette in modo da poterle leggere sempre. Ti permette anche di vedere le targhette dei giocatori piegati.", diff --git a/src/main/resources/assets/wurst/translations/ja_jp.json b/src/main/resources/assets/wurst/translations/ja_jp.json index 5062944dcc..1226869957 100644 --- a/src/main/resources/assets/wurst/translations/ja_jp.json +++ b/src/main/resources/assets/wurst/translations/ja_jp.json @@ -119,7 +119,7 @@ "description.wurst.hack.masstpa": "すべてのプレイヤーにTPA(テレポート)リクエストを送信する。", "description.wurst.hack.mileycyrus": "腰振りダンスをする。", "description.wurst.hack.mobesp": "付近のモブをハイライト表示する。", - "description.wurst.hack.mobspawnesp": "モブがスポーンする可能性のあるエリアをハイライト表示する。\n§e黄色§r - モブが夜にスポーンする可能性あり\n§c赤色§r - モブが常時スポーンする可能性あり", + "description.wurst.hack.mobspawnesp": "モブがスポーンする可能性のあるエリアをハイライト表示する。", "description.wurst.hack.multiaura": "同時に複数のエンティティを攻撃する早いKillaura。", "description.wurst.hack.nameprotect": "すべてのプレイヤーの名前を隠す。", "description.wurst.hack.nametags": "いつでも読めるようネームタグのサイズを変更し、それに加えしゃがんでいるプレイヤーのネームタグも見えるようになる。", diff --git a/src/main/resources/assets/wurst/translations/pl_pl.json b/src/main/resources/assets/wurst/translations/pl_pl.json index 7e77d905a7..abfa342d2e 100644 --- a/src/main/resources/assets/wurst/translations/pl_pl.json +++ b/src/main/resources/assets/wurst/translations/pl_pl.json @@ -98,7 +98,7 @@ "description.wurst.hack.masstpa": "Wysyła prośbę TPA do wszystkich graczy.", "description.wurst.hack.mileycyrus": "Sprawia, że twerkujesz.", "description.wurst.hack.mobesp": "Podświetla pobliskie moby.", - "description.wurst.hack.mobspawnesp": "Podświetla obszary, w których moby mogą się odradzać.\n§eżółty§r - moby mogą odradzać się w nocy\n§cczerwony§r - moby mogą zawsze się odradzać", + "description.wurst.hack.mobspawnesp": "Podświetla obszary, w których moby mogą się odradzać.", "description.wurst.hack.multiaura": "Szybsza Killaura, atakująca wiele bytów jednocześnie.", "description.wurst.hack.nameprotect": "Ukrywa wszystkie nazwy graczy.", "description.wurst.hack.nametags": "Zmienia skalę nametagów, abyś zawsze mógł je przeczytać. Pozwala również zobaczyć nazwy skradających się graczy.", diff --git a/src/main/resources/assets/wurst/translations/ro_ro.json b/src/main/resources/assets/wurst/translations/ro_ro.json index 5aaa6c164f..6d08ce2e5c 100644 --- a/src/main/resources/assets/wurst/translations/ro_ro.json +++ b/src/main/resources/assets/wurst/translations/ro_ro.json @@ -95,7 +95,7 @@ "description.wurst.hack.masstpa": "Trimite TPA request la toti playerii.", "description.wurst.hack.mileycyrus": "Faci twerk.", "description.wurst.hack.mobesp": "Contureaza mobii din apropiere.", - "description.wurst.hack.mobspawnesp": "Contureaza zonele in care mobii se pot spawna.\n§egalben§r - mobii se pot spawna noaptea\n§crosu§r - mobii se pot spawna mereu", + "description.wurst.hack.mobspawnesp": "Contureaza zonele in care mobii se pot spawna.", "description.wurst.hack.multiaura": "Killaura care ataca multiple entitati deodata.", "description.wurst.hack.nameprotect": "Ascunde toate numele jucatorilor.", "description.wurst.hack.nametags": "Schimba marimea name tagurilor pentru a le putea vedea de la orice distanta. Poti vedea name tagurile jucatorilor pe crouch.", diff --git a/src/main/resources/assets/wurst/translations/ru_ru.json b/src/main/resources/assets/wurst/translations/ru_ru.json index fc0a6f95d5..760e596838 100644 --- a/src/main/resources/assets/wurst/translations/ru_ru.json +++ b/src/main/resources/assets/wurst/translations/ru_ru.json @@ -98,7 +98,7 @@ "description.wurst.hack.masstpa": "Отправляет запрос на телепортацию всем игрокам.", "description.wurst.hack.mileycyrus": "Заставляет Вас тверкать.", "description.wurst.hack.mobesp": "Подсвечивает мобов неподалеку.", - "description.wurst.hack.mobspawnesp": "Показывает места в которых могут заспавниться мобы.\n§eжёлтым§r - мобы могут заспавниться ночью\n§cкрасным§r - мобы могут заспавниться когда угодно", + "description.wurst.hack.mobspawnesp": "Показывает места в которых могут заспавниться мобы.", "description.wurst.hack.multiaura": "Более быстрая Killaura которая атакует сразу несколько сущностей одновременно.", "description.wurst.hack.nameprotect": "Скрывает ники всех игроков.", "description.wurst.hack.nametags": "Увеличивает размер ников игроков чтобы их всегда можно было прочесть. Также позволяет видеть ники прячущихся приседанием игроков.", diff --git a/src/main/resources/assets/wurst/translations/uk_ua.json b/src/main/resources/assets/wurst/translations/uk_ua.json index 19e19b426f..2a27615902 100644 --- a/src/main/resources/assets/wurst/translations/uk_ua.json +++ b/src/main/resources/assets/wurst/translations/uk_ua.json @@ -94,7 +94,7 @@ "description.wurst.hack.masstpa": "Надсилає запит на телепортацію всім гравцям.", "description.wurst.hack.mileycyrus": "Примушує вас тверкати.", "description.wurst.hack.mobesp": "Підсвічує мобів знову.", - "description.wurst.hack.mobspawnesp": "Показує місця, у яких можуть народитися моби.\n§eжовтим§r - моби можуть народитися вночі\n§cчервоним§r - моби можуть народиться коли завгодно", + "description.wurst.hack.mobspawnesp": "Показує місця, у яких можуть народитися моби.", "description.wurst.hack.multiaura": "Швидша Killaura, яка атакує відразу кілька сутностей одночасно.", "description.wurst.hack.nameprotect": "Приховує ніки всіх гравців.", "description.wurst.hack.nametags": "Збільшує розмір ників гравців, щоб їх завжди було можливо прочитати. Також дозволяє бачити ніки гравців, що шифтять.", diff --git a/src/main/resources/assets/wurst/translations/zh_cn.json b/src/main/resources/assets/wurst/translations/zh_cn.json index 94eaaf71fe..e6e5b925ff 100644 --- a/src/main/resources/assets/wurst/translations/zh_cn.json +++ b/src/main/resources/assets/wurst/translations/zh_cn.json @@ -103,7 +103,7 @@ "description.wurst.hack.masstpa": "给每个人发送 TPA 请求。\n\n§c§l警告:§r当在国内服务器使用会因为 Wurst 无法判断中文返回消息而导致 TPA 请求继续。", "description.wurst.hack.mileycyrus": "类似疯狂按 Shift 潜行。", "description.wurst.hack.mobesp": "高亮附近的生物。", - "description.wurst.hack.mobspawnesp": "高亮生物可以生成的区域。\n§e黄色§r 可以在夜间生成\n§c红色§r - 可以在任意时候生成", + "description.wurst.hack.mobspawnesp": "高亮生物可以生成的区域。", "description.wurst.hack.multiaura": "比 Killaura 更高级,能同时攻击多个实体。", "description.wurst.hack.nameprotect": "隐藏所有玩家的名字。", "description.wurst.hack.nametags": "改变名字大小使你更容易看到他们,同时也能让你看到那些潜行玩家的名字。", diff --git a/src/main/resources/assets/wurst/translations/zh_hk.json b/src/main/resources/assets/wurst/translations/zh_hk.json index a858936dce..213fb0cf8b 100644 --- a/src/main/resources/assets/wurst/translations/zh_hk.json +++ b/src/main/resources/assets/wurst/translations/zh_hk.json @@ -94,7 +94,7 @@ "description.wurst.hack.masstpa": "畀每個人發送 傳送申請。\n\n§c§l警告:§r中文伺服器使用會因為 Wurst 判斷嘅係英文而導致 傳送申請 仍喺繼續。", "description.wurst.hack.mileycyrus": "類似瘋狂按 Shift 潛行。", "description.wurst.hack.mobesp": "高亮附近嘅生物。", - "description.wurst.hack.mobspawnesp": "高亮生物可以生成嘅區域。\n§e黃色§r 可以喺夜間生成\n§c紅色§r - 可以喺任意時候生成", + "description.wurst.hack.mobspawnesp": "高亮生物可以生成嘅區域。", "description.wurst.hack.multiaura": "比 Killaura 更高級,能同一時間攻擊多個實體。", "description.wurst.hack.nameprotect": "隱藏所有玩家嘅名字。", "description.wurst.hack.nametags": "改變名字標簽大小使你可以經常可以睇到佢哋,同時都可以令你睇到啲正潛行嘅玩家名字標簽。", diff --git a/src/main/resources/assets/wurst/translations/zh_tw.json b/src/main/resources/assets/wurst/translations/zh_tw.json index e189a0ecf4..fdd5596fa0 100644 --- a/src/main/resources/assets/wurst/translations/zh_tw.json +++ b/src/main/resources/assets/wurst/translations/zh_tw.json @@ -98,7 +98,7 @@ "description.wurst.hack.masstpa": "給每個人發送TPA請求。\n\n§c§l警告:§r國內服務器使用會因為Wurst判斷的是英文而導致TPA仍在繼續。", "description.wurst.hack.mileycyrus": "類似全自動Shift蹲起。", "description.wurst.hack.mobesp": "高亮附近的生物。", - "description.wurst.hack.mobspawnesp": "高亮那些生物可以生成的區域。\n§e黃色§r - 可以在夜間生成\n§c紅色§r - 可以在任意時候生成", + "description.wurst.hack.mobspawnesp": "高亮那些生物可以生成的區域。", "description.wurst.hack.multiaura": "比Killaura更高級,能同一時間攻擊多個實體。", "description.wurst.hack.nameprotect": "隱藏所有玩家的名字。", "description.wurst.hack.nametags": "改變名字標籤大小使你可以經常可以看到他們,同時也能讓你看到那些正潜行的玩家名字標籤。", diff --git a/src/main/resources/wurst.mixins.json b/src/main/resources/wurst.mixins.json index 3fd19ae356..342c496fe1 100644 --- a/src/main/resources/wurst.mixins.json +++ b/src/main/resources/wurst.mixins.json @@ -5,6 +5,7 @@ "compatibilityLevel": "JAVA_21", "mixins": [], "client": [ + "AbstractBlockRenderContextMixin", "AbstractBlockStateMixin", "AbstractSignEditScreenMixin", "AllowedAddressResolverMixin", @@ -52,6 +53,7 @@ "PlayerInventoryMixin", "PlayerSkinProviderMixin", "PowderSnowBlockMixin", + "RenderLayersMixin", "RenderTickCounterDynamicMixin", "ScreenMixin", "ShulkerBoxScreenMixin",