diff --git a/README.md b/README.md index df21b268..c2c6e069 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,9 @@ In no particular order - **ActivatedSpawnerDetector** Detects if a player was ever near a spawner or trial spawner block. The intended use for this module would be on anarchy servers where people try to hide their items within chests in dungeons, mineshafts, and trial chambers. (Credits to etianl :D) - **Airstrike+:** Rains down whatever entities you desire. It used to only rain fireballs, and I also changed the positioning of the spawning. (Credits to Allah-Hack for the original) - **AnHero:** Become An Hero! (A quick way back to spawn.) (Credits to etianl :D) +- **Attribute Swap:** Swaps the current main hand item with another item on the hotbar for a single tick when you attack an entity. This cause the attributes from the target item you are swapping to be applied to the first item.Thank you to [DonKisser](https://github.com/DonKisser) for making this module for us! + Their inspiration was this Youtube video by @scilangaming: + https://www.youtube.com/watch?v=q99eqD_fBqo - **AutoCommand:** Automates a list of commands you set in it's options at the push of a button! Credits to [aaaasdfghjkllll](https://github.com/aaaasdfghjkllll). I only added a full auto option because who doesn't love full auto? - **AutoDisplays:** Automatically spams block displays around all player's heads to blind them or text displays around them for trolling and advertising. Requires operator access. (Credits to etianl :D) - **AutoDrop:** Drops the stack in your selected slot automatically, or you can choose a slot to dump. You can shift click your inventory items to dump your trash easily. (Credits to etianl :D) @@ -68,6 +71,12 @@ In no particular order - **AutoNames** Automatically change player name colors, prefix, suffix in tab and chat. Requires OP status. Credits to [DedicateDev](https://github.com/DedicateDev) - **AutoScoreboard:** Automates the creation of a custom scoreboard. Useful for advertising on griefed servers. Requires OP status. Credits to [aaaasdfghjkllll](https://github.com/aaaasdfghjkllll) - **AutoStaircase:** Builds stairs upward in the direction you are facing by running forward and jumping. (Credits to etianl for bringing it to life! As well as Credits to [majorsopa](https://github.com/majorsopa) for writing the original. <3) I just had to fix up some stuff for this one but Frostburn Client had the base code there. I believe this is the first publicly available automatic staircase builder in a Meteor addon, correct me if I'm wrong maybe I didn't have to learn some Java to do this. +- **AutoTexts:** Automatically spawns words around you by creating invisible armor stands with names. You can specify the text you want to spawn in, and the color of the text. Thank you to [DedicateDev](https://github.com/DedicateDev)! +- **TextCommand:** Very similar to the **AutoTexts** module. The difference with this one is that it can display many lines one after the other. Thank you to [DedicateDev](https://github.com/DedicateDev)! +- The command is accessed by typing .text followed by one of the subcommands. You can choose load or save a preset set of text. +- The saved presets for the .text command will be saved in the .minecraft/TrouserStreak/TextPresets folder. +- Some example commands would be ".text load mountains" or ".text save mountains #green [ #dark_red Trolled! #green ]|#gold Mountains of Lava Inc.|#red Youtube: #blue www.youtube.com/@mountainsoflavainc.6913" +- Individual lines are seperated by a | (pipe character) and you can also use #red "wordhere" to format the color of the text. - **AutoTitles:** Displays text (such as advertisements) across the screen of all the individuals who are online on a server at the time. Requires OP status. Credits to [ogmur](https://www.youtube.com/@Ogmur) for figuring out these commands, and to etianl for writing a module for it. - **AutoVclipCommand** Automatically selects the nearest two block gap going either up or down to vclip into. (Credits to etianl, and credits to the original [AutoVclip](https://github.com/kittenvr/AutoVclip) for minecraft 1.19.2 which inspired me to make this one. :D) - **BaseFinder:** Automatically detects if a Base or Build could be in a chunk by checking every block and entity in each chunk to see if there are "Un-natural" things within them. (Credits to etianl :D, and to Meteor-Rejects for some code from newchunks.) @@ -103,6 +112,7 @@ In no particular order - **LavaAura:** Automatically places and picks up lava buckets at an entity's position on a tick delay, or sets the entity on fire using flint and steel or fire charges. Also has the option of placing lavabuckets or fire on every block face which may be useful in creative mode. (Credits to etianl :D) - **LecternCrash:** Crash 1.18.X vanilla servers and possibly below. (Credits to Coderx-Gamer) - **MaceKill:** Exploits Mace mechanics to make the Mace super OP everytime you swing it instead of just when you drop from a height. (Credits to etianl :D) +- **MultiUse:** Allows you to do the item use action more than once per item use. Essentially a strange form of the FastUse module and may work well combined with it. Initially created by [maytrixc](https://github.com/maytrixc), modified by etianl to use doItemUse. - **NbtEditor:** Requires Creative mode. Generates custom entities in the form of a custom spawn egg, generate items with custom enchantments (Only in Minecraft 1.20.4 and below), and potions with custom effects all based on the settings you configure. It can also copy the Nbt data from one item to another. (Credits to etianl :D) - **NewerNewChunks:** NewChunks module with new newchunk estimation exploits, and the ability to save chunk data for later! Comes with several new homebrewed newchunks methods made by yours truly. (Credits to Meteor Rejects, and BleachHack from where it was ported, and etianl for updating :D.) diff --git a/gradle.properties b/gradle.properties index d7119258..056a3c60 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ yarn_mappings=1.20.4+build.3 loader_version=0.15.3 # Mod Properties -mod_version=1.3.7-1.20.4 +mod_version=1.3.8-1.20.4 maven_group=pwn.noobs archives_base_name=3trouser-streak diff --git a/src/main/java/pwn/noobs/trouserstreak/Trouser.java b/src/main/java/pwn/noobs/trouserstreak/Trouser.java index c4688aa3..ea459e9a 100644 --- a/src/main/java/pwn/noobs/trouserstreak/Trouser.java +++ b/src/main/java/pwn/noobs/trouserstreak/Trouser.java @@ -40,6 +40,14 @@ public void onInitialize() { Modules.get().add(new BetterScaffold()); Modules.get().add(new RedstoneNuker()); + //Modules.get().add(new -----> Create Illegal things with Creative mode! <-----()); + Modules.get().add(new ForceOPSign()); + Modules.get().add(new ForceOPBook()); + Modules.get().add(new NbtEditor()); + Modules.get().add(new AirstrikePlus()); + Modules.get().add(new BoomPlus()); + Modules.get().add(new ExplosionAura()); + //Modules.get().add(new -----> Overpowered OP mode modules! <-----()); Modules.get().add(new BungeeSpoofer()); Modules.get().add(new HandOfGod()); @@ -50,17 +58,11 @@ public void onInitialize() { Modules.get().add(new AutoScoreboard()); Modules.get().add(new AutoTitles()); Modules.get().add(new AutoDisplays()); + Modules.get().add(new AutoTexts()); + Commands.add(new TextCommand()); Modules.get().add(new AutoNames()); Modules.get().add(new OPplayerTPmodule()); - //Modules.get().add(new -----> Create Illegal things with Creative mode! <-----()); - Modules.get().add(new ForceOPSign()); - Modules.get().add(new ForceOPBook()); - Modules.get().add(new NbtEditor()); - Modules.get().add(new AirstrikePlus()); - Modules.get().add(new BoomPlus()); - Modules.get().add(new ExplosionAura()); - //Modules.get().add(new -----> Exploits for old versions! <-----()); Modules.get().add(new ShulkerDupe()); Modules.get().add(new InvDupeModule()); @@ -70,13 +72,15 @@ public void onInitialize() { //Modules.get().add(new -----> And much more <-----()); Modules.get().add(new BookAndQuillDupe()); - Modules.get().add(new BetterAutoSign()); + Modules.get().add(new AttributeSwap()); Modules.get().add(new Teleport()); Modules.get().add(new TPFly()); Modules.get().add(new FlightAntikick()); + Modules.get().add(new BetterAutoSign()); Modules.get().add(new InstaSafetyBox()); Modules.get().add(new TrouserBuild()); Modules.get().add(new TrailMaker()); + Modules.get().add(new MultiUse()); Modules.get().add(new AutoDrop()); Modules.get().add(new AnHero()); Commands.add(new WorldInfoCommand()); diff --git a/src/main/java/pwn/noobs/trouserstreak/commands/TextCommand.java b/src/main/java/pwn/noobs/trouserstreak/commands/TextCommand.java new file mode 100644 index 00000000..aeb21d1c --- /dev/null +++ b/src/main/java/pwn/noobs/trouserstreak/commands/TextCommand.java @@ -0,0 +1,276 @@ +//Credits to DedicateDev for making this! I (etianl) only added functions for deleting presets and regenerating the default presets. +package pwn.noobs.trouserstreak.commands; + +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import meteordevelopment.meteorclient.commands.Command; +import net.minecraft.command.CommandSource; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtDouble; +import net.minecraft.nbt.NbtList; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3d; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.Arrays; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Stream; + +import static com.mojang.brigadier.Command.SINGLE_SUCCESS; +import static meteordevelopment.meteorclient.MeteorClient.mc; + +public class TextCommand extends Command { + private static final double LINE_SPACING = 0.3; + private static final double INITIAL_HEIGHT_OFFSET = 1.0; + private static final String PRESETS_DIRECTORY = "TrouserStreak/TextPresets"; + + public enum ColorModes { + aqua, black, blue, dark_aqua, dark_blue, dark_gray, dark_green, + dark_purple, dark_red, gold, gray, green, italic, light_purple, + red, white, yellow + } + + public TextCommand() { + super("text", "Spawns a text hologram with custom text in front of you. Use | for new lines and #color for text color."); + createDefaultPresets(); + } + + @Override + public void build(LiteralArgumentBuilder builder) { + builder + .then(argument("message", StringArgumentType.greedyString()) + .executes(context -> { + spawnTextLines(context.getArgument("message", String.class)); + return SINGLE_SUCCESS; + })) + .then(literal("save") + .then(argument("presetName", StringArgumentType.word()) + .then(argument("text", StringArgumentType.greedyString()) + .executes(context -> { + String presetName = context.getArgument("presetName", String.class); + String text = context.getArgument("text", String.class); + savePreset(presetName, text); + info("Saved preset: " + presetName); + return SINGLE_SUCCESS; + })))) + .then(literal("load") + .then(argument("presetName", StringArgumentType.word()) + .suggests((context, suggestionsBuilder) -> suggestPresets(suggestionsBuilder)) + .executes(context -> { + String presetName = context.getArgument("presetName", String.class); + String text = loadPreset(presetName); + if (text != null) { + spawnTextLines(text); + info("Loaded preset: " + presetName); + } else { + error("Preset not found: " + presetName); + } + return SINGLE_SUCCESS; + }))) + .then(literal("regeneratedefaults") + .executes(context -> { + regenDefaultPresets(); + info("Default presets regenerated."); + return SINGLE_SUCCESS; + })) + .then(literal("delete") + .then(argument("presetName", StringArgumentType.word()) + .suggests((context, suggestionsBuilder) -> suggestPresets(suggestionsBuilder)) + .executes(context -> { + String presetName = context.getArgument("presetName", String.class); + deletePreset(presetName); + return SINGLE_SUCCESS; + }))); + } + + private CompletableFuture suggestPresets(SuggestionsBuilder builder) { + try { + Path presetsDir = Paths.get(PRESETS_DIRECTORY); + if (Files.exists(presetsDir)) { + try (Stream files = Files.list(presetsDir)) { + files.filter(path -> path.toString().endsWith(".txt")) + .map(path -> path.getFileName().toString().replace(".txt", "")) + .forEach(builder::suggest); + } + } + } catch (IOException ignored) {} + return builder.buildFuture(); + } + + private void spawnTextLines(String text) { + String[] lines = text.split("\\|"); + for (int i = lines.length - 1; i >= 0; i--) { + String line = lines[i].trim(); + String formattedText = formatTextWithColors(line); + double heightOffset = ((lines.length - 1 - i) * LINE_SPACING) + INITIAL_HEIGHT_OFFSET; + spawnText(formattedText, heightOffset, true); + } + } + + private String formatTextWithColors(String line) { + StringBuilder formattedText = new StringBuilder(); + String currentColor = "white"; + String[] words = line.split(" "); + + for (String word : words) { + if (word.startsWith("#")) { + try { + ColorModes.valueOf(word.substring(1).toLowerCase()); + currentColor = word.substring(1).toLowerCase(); + } catch (IllegalArgumentException ignored) { + formattedText.append(word).append(" "); + } + } else { + formattedText.append("{\"text\":\"").append(word).append(" \",\"color\":\"") + .append(currentColor).append("\"},"); + } + } + + return "[" + formattedText.substring(0, formattedText.length() - 1) + "]"; + } + + private void savePreset(String presetName, String text) { + try { + Path dirPath = Paths.get(PRESETS_DIRECTORY); + Files.createDirectories(dirPath); + Path filePath = dirPath.resolve(presetName + ".txt"); + Files.write(filePath, text.getBytes(StandardCharsets.UTF_8), + StandardOpenOption.CREATE, + StandardOpenOption.TRUNCATE_EXISTING); + } catch (IOException e) { + error("Failed to save preset: " + e.getMessage()); + } + } + + private String loadPreset(String presetName) { + try { + Path filePath = Paths.get(PRESETS_DIRECTORY, presetName + ".txt"); + if (Files.exists(filePath)) { + return Files.readString(filePath); + } + } catch (IOException e) { + error("Failed to load preset: " + e.getMessage()); + } + return null; + } + private void deletePreset(String presetName) { + Path filePath = Paths.get(PRESETS_DIRECTORY, presetName + ".txt"); + try { + if (Files.exists(filePath)) { + Files.delete(filePath); + info("Deleted preset: " + presetName); + } else { + error("Preset not found: " + presetName); + } + } catch (IOException e) { + error("Failed to delete preset: " + e.getMessage()); + } + } + private void createDefaultPresets() { + String[] defaultPresets = { + "trolled=#green [ #dark_red Trolled! #green ]|#gold Mountains of Lava Inc.|#red Youtube: #blue www.youtube.com/@mountainsoflavainc.6913|#green [ #dark_red Trolled! #green ]", + "mountains=#red Mountains Of Lava Inc.|#gold youtube.com/@mountainsoflavainc.6913", + "genesis=#gold THE BOOK OF GENESIS|#gold Chapter 1|#green [1:1] In the beginning when God created the heavens and the earth,|#green [1:2] the earth was a formless void and darkness covered the face of the deep, while a wind from God swept over the face of the waters.|#green [1:3] Then God said, 'Let there be light'; and there was light.|#green [1:4] And God saw that the light was good; and God separated the light from the darkness.|#green [1:5] God called the light Day, and the darkness he called Night. And there was evening and there was morning, the first day.|#green [1:6] And God said, 'Let there be a dome in the midst of the waters, and let it separate the waters from the waters.'|#green [1:7] So God made the dome and separated the waters that were under the dome from the waters that were above the dome. And it was so.|#green [1:8] God called the dome Sky. And there was evening and there was morning, the second day.|#green [1:9] And God said, 'Let the waters under the sky be gathered together into one place, and let the dry land appear.' And it was so.|#green [1:10] God called the dry land Earth, and the waters that were gathered together he called Seas. And God saw that it was good.|#gold Chapter 2|#green [2:1] Thus the heavens and the earth were finished, and all their multitude.|#green [2:2] And on the seventh day God finished the work that he had done, and he rested on the seventh day from all the work that he had done.", + }; + + for (String preset : defaultPresets) { + String[] parts = preset.split("=", 2); + if (!Files.exists(Paths.get(PRESETS_DIRECTORY, parts[0] + ".txt"))) { + savePreset(parts[0], parts[1]); + } + } + } + private void regenDefaultPresets() { + String[] defaultPresetNames = { + "trolled", + "mountains", + "genesis" + }; + + try { + Path dirPath = Paths.get(PRESETS_DIRECTORY); + if (Files.exists(dirPath)) { + try (Stream files = Files.list(dirPath)) { + files.filter(path -> { + String fileName = path.getFileName().toString(); + return Arrays.stream(defaultPresetNames) + .anyMatch(name -> fileName.equals(name + ".txt")); + }).forEach(path -> { + try { + Files.delete(path); + } catch (IOException e) { + error("Failed to delete preset: " + path + " - " + e.getMessage()); + } + }); + } catch (IOException e) { + error("Failed to list directory: " + e.getMessage()); + } + } + Files.createDirectories(dirPath); + + String[] defaultPresets = { + "trolled=#green [ #dark_red Trolled! #green ]|#gold Mountains of Lava Inc.|#red Youtube: #blue www.youtube.com/@mountainsoflavainc.6913|#green [ #dark_red Trolled! #green ]", + "mountains=#red Mountains Of Lava Inc.|#gold youtube.com/@mountainsoflavainc.6913", + "genesis=#gold THE BOOK OF GENESIS|#gold Chapter 1|#green [1:1] In the beginning when God created the heavens and the earth,|#green [1:2] the earth was a formless void and darkness covered the face of the deep, while a wind from God swept over the face of the waters.|#green [1:3] Then God said, 'Let there be light'; and there was light.|#green [1:4] And God saw that the light was good; and God separated the light from the darkness.|#green [1:5] God called the light Day, and the darkness he called Night. And there was evening and there was morning, the first day.|#green [1:6] And God said, 'Let there be a dome in the midst of the waters, and let it separate the waters from the waters.'|#green [1:7] So God made the dome and separated the waters that were under the dome from the waters that were above the dome. And it was so.|#green [1:8] God called the dome Sky. And there was evening and there was morning, the second day.|#green [1:9] And God said, 'Let the waters under the sky be gathered together into one place, and let the dry land appear.' And it was so.|#green [1:10] God called the dry land Earth, and the waters that were gathered together he called Seas. And God saw that it was good.|#gold Chapter 2|#green [2:1] Thus the heavens and the earth were finished, and all their multitude.|#green [2:2] And on the seventh day God finished the work that he had done, and he rested on the seventh day from all the work that he had done.", + }; + + for (String preset : defaultPresets) { + String[] parts = preset.split("=", 2); + savePreset(parts[0], parts[1]); + } + } catch (IOException e) { + error("Failed to regenerate presets: " + e.getMessage()); + } + } + + private void spawnText(String message, double yOffset, boolean isJson) { + if (!mc.player.getAbilities().creativeMode) { + error("Creative mode required!"); + return; + } + + ItemStack armorStand = new ItemStack(Items.ARMOR_STAND); + ItemStack current = mc.player.getMainHandStack(); + Vec3d pos = mc.player.getPos().add(mc.player.getRotationVector().multiply(2)).add(0, yOffset, 0); + + NbtCompound tag = new NbtCompound(); + + NbtCompound entityTag = new NbtCompound(); + + entityTag.putString("id", "minecraft:armor_stand"); + + NbtList positionList = new NbtList(); + positionList.add(NbtDouble.of(pos.x)); + positionList.add(NbtDouble.of(pos.y)); + positionList.add(NbtDouble.of(pos.z)); + + entityTag.put("Pos", positionList); + entityTag.putBoolean("Invisible", true); + entityTag.putBoolean("Marker", true); + entityTag.putBoolean("NoGravity", true); + entityTag.putBoolean("CustomNameVisible",true); + entityTag.putString("CustomName", message); + + tag.put("EntityTag", entityTag); + + armorStand.setNbt(tag); + + + BlockHitResult bhr = new BlockHitResult(pos, Direction.UP, BlockPos.ofFloored(pos), false); + mc.interactionManager.clickCreativeStack(armorStand, 36 + mc.player.getInventory().selectedSlot); + mc.interactionManager.interactBlock(mc.player, Hand.MAIN_HAND, bhr); + mc.interactionManager.clickCreativeStack(current, 36 + mc.player.getInventory().selectedSlot); + } +} \ No newline at end of file diff --git a/src/main/java/pwn/noobs/trouserstreak/modules/AttributeSwap.java b/src/main/java/pwn/noobs/trouserstreak/modules/AttributeSwap.java new file mode 100644 index 00000000..47774220 --- /dev/null +++ b/src/main/java/pwn/noobs/trouserstreak/modules/AttributeSwap.java @@ -0,0 +1,49 @@ +/*Thank you to [DonKisser](https://github.com/DonKisser) for making this module for us! + Their inspiration was this Youtube video by @scilangaming: + https://www.youtube.com/watch?v=q99eqD_fBqo*/ + +package pwn.noobs.trouserstreak.modules; + +import pwn.noobs.trouserstreak.Trouser; +import meteordevelopment.meteorclient.events.entity.player.AttackEntityEvent; +import meteordevelopment.meteorclient.events.world.TickEvent; +import meteordevelopment.meteorclient.settings.BoolSetting; +import meteordevelopment.meteorclient.settings.IntSetting; +import meteordevelopment.meteorclient.settings.Setting; +import meteordevelopment.meteorclient.settings.SettingGroup; +import meteordevelopment.meteorclient.systems.modules.Module; +import meteordevelopment.meteorclient.utils.player.InvUtils; +import meteordevelopment.orbit.EventHandler; + +public class AttributeSwap extends Module { + private final SettingGroup sgGeneral = settings.getDefaultGroup(); + private final Setting targetSlot = sgGeneral.add(new IntSetting.Builder().name("target-slot").description("The hotbar slot to swap to when attacking.").sliderRange(1, 9).defaultValue(1).min(1).build()); + private final Setting swapBack = sgGeneral.add(new BoolSetting.Builder().name("swap-back").description("Swap back to the original slot after a short delay.").defaultValue(true).build()); + private final Setting delay = sgGeneral.add(new IntSetting.Builder().name("swap-back-delay").description("Delay in ticks before swapping back to the previous slot.").sliderRange(1, 20).defaultValue(1).min(1).visible(swapBack::get).build()); + private int prevSlot = -1; + private int dDelay = 0; + public AttributeSwap() { + super(Trouser.Main, "attribute-swap", "Swaps attributes of the main hand item with the target slot on attack"); + } + @EventHandler + private void onAttack(AttackEntityEvent event) { + if (mc.player == null || mc.world == null) return; + if (swapBack.get()) { + prevSlot = mc.player.getInventory().selectedSlot; + } + InvUtils.swap(targetSlot.get()-1, false); + if (swapBack.get() && prevSlot != -1) { + dDelay = delay.get(); + } + } + @EventHandler + private void onTick(TickEvent.Pre event) { + if (dDelay > 0) { + dDelay--; + if (dDelay == 0 && prevSlot != -1) { + InvUtils.swap(prevSlot, false); + prevSlot = -1; + } + } + } +} \ No newline at end of file diff --git a/src/main/java/pwn/noobs/trouserstreak/modules/AutoTexts.java b/src/main/java/pwn/noobs/trouserstreak/modules/AutoTexts.java new file mode 100644 index 00000000..fdd6f54f --- /dev/null +++ b/src/main/java/pwn/noobs/trouserstreak/modules/AutoTexts.java @@ -0,0 +1,211 @@ +//Credits to DedicateDev for making this! +package pwn.noobs.trouserstreak.modules; + +import meteordevelopment.meteorclient.events.game.GameLeftEvent; +import meteordevelopment.meteorclient.events.game.OpenScreenEvent; +import meteordevelopment.meteorclient.events.world.PlaySoundEvent; +import meteordevelopment.meteorclient.events.world.TickEvent; +import meteordevelopment.meteorclient.settings.*; +import meteordevelopment.meteorclient.systems.modules.Module; +import meteordevelopment.orbit.EventHandler; +import net.minecraft.client.gui.screen.DisconnectedScreen; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtDouble; +import net.minecraft.nbt.NbtList; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3d; +import pwn.noobs.trouserstreak.Trouser; + +import java.util.List; +import java.util.Random; + +public class AutoTexts extends Module { + public enum ColorModes { + aqua, black, blue, dark_aqua, dark_blue, dark_gray, dark_green, + dark_purple, dark_red, gold, gray, green, italic, light_purple, + red, white, yellow + } + + private final SettingGroup sgGeneral = settings.getDefaultGroup(); + private final SettingGroup sgText = settings.createGroup("Text Options"); + private final SettingGroup sgSpawning = settings.createGroup("Spawn Settings"); + private final SettingGroup sgMisc = settings.createGroup("Miscellaneous"); + + private final Setting disconnectdisable = sgGeneral.add(new BoolSetting.Builder() + .name("Disable on Disconnect") + .description("Disables module on disconnecting") + .defaultValue(false) + .build()); + + private final Setting> texts = sgText.add(new StringListSetting.Builder() + .name("Texts") + .description("Text lines to display") + .defaultValue(List.of("Trolled by Mountains of Lava Inc", "www.youtube.com/@mountainsoflavainc.6913")) + .build()); + + private final Setting rainbow = sgText.add(new BoolSetting.Builder() + .name("Rainbow") + .description("Randomly cycles through all available colors") + .defaultValue(false) + .build()); + + private final Setting textColor = sgText.add(new EnumSetting.Builder() + .name("Text Color") + .description("Color of the text") + .defaultValue(ColorModes.red) + .visible(() -> !rainbow.get()) + .build()); + + private final Setting radius = sgSpawning.add(new IntSetting.Builder() + .name("Radius") + .description("Spawn radius") + .defaultValue(8) + .min(1) + .sliderMax(8) + .build()); + + private final Setting height = sgSpawning.add(new IntSetting.Builder() + .name("Height") + .description("Base spawn height relative to player") + .defaultValue(0) + .sliderRange(-8, 8) + .build()); + + private final Setting heightVariation = sgSpawning.add(new BoolSetting.Builder() + .name("Height Variation") + .description("Enable random height variation") + .defaultValue(false) + .build()); + + private final Setting spawnDelay = sgSpawning.add(new IntSetting.Builder() + .name("Spawn Delay") + .description("Delay between spawns in ticks") + .defaultValue(2) + .min(0) + .sliderMax(20) + .build()); + + private final Setting spawnCount = sgSpawning.add(new IntSetting.Builder() + .name("Spawn Count") + .description("How many to spawn per tick") + .defaultValue(1) + .min(1) + .sliderMax(100) + .build()); + + private final Setting muteSounds = sgMisc.add(new BoolSetting.Builder() + .name("Mute Sounds") + .description("Prevents playing armor stand placement sounds") + .defaultValue(true) + .build()); + + private final Random random = new Random(); + private int ticks; + private Vec3d origin; + private String namecolour; + + public AutoTexts() { + super(Trouser.Main, "auto-texts", "Spawns invisible armor stands with custom text. Requires creative mode."); + } + + @Override + public void onActivate() { + if (!mc.player.getAbilities().creativeMode) { + error("Creative mode required!"); + toggle(); + return; + } + ticks = 0; + origin = null; + namecolour = ""; + } + + @EventHandler + private void onScreenOpen(OpenScreenEvent event) { + if (disconnectdisable.get() && event.screen instanceof DisconnectedScreen) toggle(); + } + + @EventHandler + private void onGameLeft(GameLeftEvent event) { + if (disconnectdisable.get()) toggle(); + } + + @EventHandler + private void onPlaySound(PlaySoundEvent event) { + if (muteSounds.get() && event.sound.getId().getPath().contains("entity.armor_stand.place")) { + event.cancel(); + } + } + + @EventHandler + public void onTick(TickEvent.Pre event) { + origin = mc.player.getPos(); + } + + @EventHandler + private void onTick(TickEvent.Post event) { + if (ticks >= spawnDelay.get()) { + updateNameColor(); + for (int i = 0; i < spawnCount.get(); i++) { + spawnArmorStand(); + } + ticks = 0; + } + ticks++; + } + + private void updateNameColor() { + if (rainbow.get()) { + ColorModes[] colors = ColorModes.values(); + namecolour = colors[random.nextInt(colors.length)].toString(); + } else { + namecolour = textColor.get().toString(); + } + } + + private Vec3d pickRandomPos() { + double x = random.nextDouble(radius.get() * 2) - radius.get() + origin.x; + double y = mc.player.getY() + height.get() + (heightVariation.get() ? random.nextDouble(8) - 4 : 0); + double z = random.nextDouble(radius.get() * 2) - radius.get() + origin.z; + return new Vec3d(x, y, z); + } + + private void spawnArmorStand() { + ItemStack armorStand = new ItemStack(Items.ARMOR_STAND); + ItemStack current = mc.player.getMainHandStack(); + Vec3d pos = pickRandomPos(); + String selectedText = texts.get().get(random.nextInt(texts.get().size())); + + NbtCompound tag = new NbtCompound(); + + NbtCompound entityTag = new NbtCompound(); + + entityTag.putString("id", "minecraft:armor_stand"); + + NbtList positionList = new NbtList(); + positionList.add(NbtDouble.of(pos.x)); + positionList.add(NbtDouble.of(pos.y)); + positionList.add(NbtDouble.of(pos.z)); + + entityTag.put("Pos", positionList); + entityTag.putBoolean("Invisible", true); + entityTag.putBoolean("Marker", true); + entityTag.putBoolean("NoGravity", true); + entityTag.putBoolean("CustomNameVisible",true); + entityTag.putString("CustomName", "{\"text\":\"" + selectedText + "\",\"color\":\"" + namecolour + "\"}"); + + tag.put("EntityTag", entityTag); + + armorStand.setNbt(tag); + + BlockHitResult bhr = new BlockHitResult(pos, Direction.UP, BlockPos.ofFloored(pos), false); + mc.interactionManager.clickCreativeStack(armorStand, 36 + mc.player.getInventory().selectedSlot); + mc.interactionManager.interactBlock(mc.player, Hand.MAIN_HAND, bhr); + mc.interactionManager.clickCreativeStack(current, 36 + mc.player.getInventory().selectedSlot); + } +} \ No newline at end of file diff --git a/src/main/java/pwn/noobs/trouserstreak/modules/BaseFinder.java b/src/main/java/pwn/noobs/trouserstreak/modules/BaseFinder.java index 521c9162..304d60f6 100644 --- a/src/main/java/pwn/noobs/trouserstreak/modules/BaseFinder.java +++ b/src/main/java/pwn/noobs/trouserstreak/modules/BaseFinder.java @@ -124,7 +124,7 @@ public class BaseFinder extends Module { .min(-64) .sliderRange(-64, 319) .defaultValue(260) - .visible(() -> skybuildfind.get()) + .visible(skybuildfind::get) .build()); private final Setting bedrockfind = sgDetectors.add(new BoolSetting.Builder() .name("Bedrock Finder") @@ -137,7 +137,7 @@ public class BaseFinder extends Module { .min(0) .sliderRange(0, 384) .defaultValue(4) - .visible(() -> bedrockfind.get()) + .visible(bedrockfind::get) .build()); private final Setting spawner = sgDetectors.add(new BoolSetting.Builder() .name("Unnatural Spawner Finder") @@ -215,6 +215,11 @@ private Set> getDefaultCreatures() { .sliderRange(0,300) .defaultValue(5) .build()); + private final Setting list1Activar = sglists.add(new BoolSetting.Builder() + .name("List #1 Activate") + .description("Activates checks for List #1") + .defaultValue(true) + .build()); private final Setting> Blawcks1 = sglists.add(new BlockListSetting.Builder() .name("Block List #1 (Default)") .description("If the total amount of any of these found is greater than the Number specified, throw a base location.") @@ -248,48 +253,85 @@ private Set> getDefaultCreatures() { Blocks.PIGLIN_HEAD, Blocks.PIGLIN_WALL_HEAD, Blocks.CREEPER_HEAD, Blocks.CREEPER_WALL_HEAD, Blocks.DRAGON_WALL_HEAD, Blocks.DRAGON_HEAD, Blocks.PLAYER_HEAD, Blocks.PLAYER_WALL_HEAD, Blocks.ZOMBIE_HEAD, Blocks.ZOMBIE_WALL_HEAD, Blocks.SKELETON_WALL_SKULL, Blocks.WITHER_SKELETON_SKULL, Blocks.WITHER_SKELETON_WALL_SKULL, Blocks.HONEY_BLOCK, Blocks.HONEYCOMB_BLOCK, Blocks.HOPPER, Blocks.JUKEBOX, Blocks.LIGHTNING_ROD, Blocks.LODESTONE, Blocks.OBSERVER, Blocks.POWERED_RAIL, Blocks.HEAVY_WEIGHTED_PRESSURE_PLATE, Blocks.LIGHT_WEIGHTED_PRESSURE_PLATE, Blocks.POLISHED_BLACKSTONE_PRESSURE_PLATE, Blocks.BIRCH_PRESSURE_PLATE, Blocks.JUNGLE_PRESSURE_PLATE, Blocks.DARK_OAK_PRESSURE_PLATE, Blocks.MANGROVE_PRESSURE_PLATE, Blocks.CRIMSON_PRESSURE_PLATE, Blocks.WARPED_PRESSURE_PLATE, Blocks.RESPAWN_ANCHOR, Blocks.CALIBRATED_SCULK_SENSOR, Blocks.SNIFFER_EGG ) + .visible(list1Activar::get) .filter(this::filterBlocks) .build() ); + private final Setting list2Activar = sglists.add(new BoolSetting.Builder() + .name("List #2 Activate") + .description("Activates checks for List #2") + .defaultValue(true) + .build()); private final Setting> Blawcks2 = sglists.add(new BlockListSetting.Builder() .name("Block List #2 (Default)") .description("If the total amount of any of these found is greater than the Number specified, throw a base location.") .defaultValue(Blocks.SPRUCE_WALL_SIGN, Blocks.POLISHED_DIORITE, Blocks.NOTE_BLOCK) + .visible(list2Activar::get) .filter(this::filterBlocks) .build() ); + private final Setting list3Activar = sglists.add(new BoolSetting.Builder() + .name("List #3 Activate") + .description("Activates checks for List #3") + .defaultValue(true) + .build()); private final Setting> Blawcks3 = sglists.add(new BlockListSetting.Builder() .name("Block List #3 (Default)") .description("If the total amount of any of these found is greater than the Number specified, throw a base location.") .defaultValue(Blocks.CRAFTING_TABLE, Blocks.BREWING_STAND, Blocks.ENDER_CHEST, Blocks.SMOOTH_QUARTZ, Blocks.REDSTONE_BLOCK, Blocks.DIAMOND_BLOCK, Blocks.BROWN_STAINED_GLASS) + .visible(list3Activar::get) .filter(this::filterBlocks) .build() ); + private final Setting list4Activar = sglists.add(new BoolSetting.Builder() + .name("List #4 Activate") + .description("Activates checks for List #4") + .defaultValue(true) + .build()); private final Setting> Blawcks4 = sglists.add(new BlockListSetting.Builder() .name("Block List #4 (Default)") .description("If the total amount of any of these found is greater than the Number specified, throw a base location.") .defaultValue(Blocks.OAK_WALL_SIGN, Blocks.TRAPPED_CHEST, Blocks.IRON_TRAPDOOR, Blocks.LAPIS_BLOCK) + .visible(list4Activar::get) .filter(this::filterBlocks) .build() ); + private final Setting list5Activar = sglists.add(new BoolSetting.Builder() + .name("List #5 Activate") + .description("Activates checks for List #5") + .defaultValue(true) + .build()); private final Setting> Blawcks5 = sglists.add(new BlockListSetting.Builder() .name("Block List #5 (Default)") .description("If the total amount of any of these found is greater than the Number specified, throw a base location.") .defaultValue(Blocks.QUARTZ_BLOCK, Blocks.RED_BED, Blocks.WHITE_BED, Blocks.YELLOW_BED, Blocks.ORANGE_BED, Blocks.BLUE_BED, Blocks.CYAN_BED, Blocks.GREEN_BED, Blocks.LIME_BED, Blocks.PURPLE_BED) + .visible(list5Activar::get) .filter(this::filterBlocks) .build() ); + private final Setting list6Activar = sglists.add(new BoolSetting.Builder() + .name("List #6 Activate") + .description("Activates checks for List #6") + .defaultValue(true) + .build()); private final Setting> Blawcks6 = sglists.add(new BlockListSetting.Builder() .name("Block List #6 (Default)") .description("If the total amount of any of these found is greater than the Number specified, throw a base location.") .defaultValue(Blocks.REDSTONE_TORCH, Blocks.REDSTONE_WALL_TORCH, Blocks.FURNACE) + .visible(list6Activar::get) .filter(this::filterBlocks) .build() ); + private final Setting list7Activar = sglists.add(new BoolSetting.Builder() + .name("List #7 Activate") + .description("Activates checks for List #7") + .defaultValue(true) + .build()); private final Setting> Blawcks7 = sglists.add(new BlockListSetting.Builder() .name("Block List #7 (Extra Custom)") .description("If the total amount of any of these found is greater than the Number specified, throw a base location.") .defaultValue() + .visible(list7Activar::get) .filter(this::filterBlocks) .build() ); @@ -299,6 +341,7 @@ private Set> getDefaultCreatures() { .min(1) .sliderRange(1,100) .defaultValue(1) + .visible(list1Activar::get) .build()); private final Setting blowkfind2 = sglists.add(new IntSetting.Builder() .name("(List #2) Number Of Blocks to Find") @@ -306,6 +349,7 @@ private Set> getDefaultCreatures() { .min(1) .sliderRange(1,100) .defaultValue(5) + .visible(list2Activar::get) .build()); private final Setting blowkfind3 = sglists.add(new IntSetting.Builder() .name("(List #3) Number Of Blocks to Find") @@ -313,6 +357,7 @@ private Set> getDefaultCreatures() { .min(1) .sliderRange(1,100) .defaultValue(4) + .visible(list3Activar::get) .build()); private final Setting blowkfind4 = sglists.add(new IntSetting.Builder() .name("(List #4) Number Of Blocks to Find") @@ -320,6 +365,7 @@ private Set> getDefaultCreatures() { .min(1) .sliderRange(1,100) .defaultValue(2) + .visible(list4Activar::get) .build()); private final Setting blowkfind5 = sglists.add(new IntSetting.Builder() .name("(List #5) Number Of Blocks to Find") @@ -327,6 +373,7 @@ private Set> getDefaultCreatures() { .min(1) .sliderRange(1,100) .defaultValue(12) + .visible(list5Activar::get) .build()); private final Setting blowkfind6 = sglists.add(new IntSetting.Builder() .name("(List #6) Number Of Blocks to Find") @@ -334,6 +381,7 @@ private Set> getDefaultCreatures() { .min(1) .sliderRange(1,100) .defaultValue(12) + .visible(list6Activar::get) .build()); private final Setting blowkfind7 = sglists.add(new IntSetting.Builder() .name("(List #7) Number Of Blocks to Find") @@ -341,6 +389,7 @@ private Set> getDefaultCreatures() { .min(1) .sliderRange(1,100) .defaultValue(1) + .visible(list7Activar::get) .build()); private final Setting remove = sgcacheCdata.add(new BoolSetting.Builder() .name("RemoveOnModuleDisabled") @@ -376,7 +425,7 @@ private Set> getDefaultCreatures() { .name("AutoReloadBases") .description("Reloads the bases automatically from your savefiles on a delay.") .defaultValue(false) - .visible(() -> load.get()) + .visible(load::get) .build() ); private final Setting removedelay = sgCdata.add(new IntSetting.Builder() @@ -532,7 +581,7 @@ public WWidget getWidget(GuiTheme theme) { .description("How far from the base chunk to still render a tracer.") .defaultValue(32) .sliderRange(1,1024) - .visible(() -> trcr.get()) + .visible(trcr::get) .build() ); private final Setting baseChunksSideColor = sgRender.add(new ColorSetting.Builder() @@ -545,7 +594,7 @@ public WWidget getWidget(GuiTheme theme) { .name("Base-chunks-tracer-color") .description("Color of tracers to the chunks that may contain bases or builds.") .defaultValue(new SettingColor(255, 127, 0, 255, true)) - .visible(() -> trcr.get()) + .visible(trcr::get) .build() ); private static final ExecutorService taskExecutor = Executors.newCachedThreadPool(); @@ -613,7 +662,7 @@ public void onActivate() { clearChunkData(); } if (save.get() || load.get()) { - if (mc.isInSingleplayer()==true){ + if (mc.isInSingleplayer()){ String[] array = mc.getServer().getSavePath(WorldSavePath.ROOT).toString().replace(':', '_').split("/|\\\\"); serverip=array[array.length-2]; world= mc.world.getRegistryKey().getValue().toString().replace(':', '_'); @@ -670,10 +719,7 @@ private void onGameLeft(GameLeftEvent event) { private void onPreTick(TickEvent.Pre event) { world = mc.world.getRegistryKey().getValue().toString().replace(':', '_'); - if (mc.player.getHealth() == 0) { - worldchange = true; - } - if (basefound == true && basefoundspamTicks < bsefndtickdelay.get()) basefoundspamTicks++; + if (basefound && basefoundspamTicks < bsefndtickdelay.get()) basefoundspamTicks++; else if (basefoundspamTicks >= bsefndtickdelay.get()) { basefound = false; basefoundspamTicks = 0; @@ -728,7 +774,7 @@ else if (basefoundspamTicks >= bsefndtickdelay.get()) { } if (save.get() || load.get()) { - if (mc.isInSingleplayer() == true) { + if (mc.isInSingleplayer()) { String[] array = mc.getServer().getSavePath(WorldSavePath.ROOT).toString().replace(':', '_').split("/|\\\\"); serverip = array[array.length - 2]; world = mc.world.getRegistryKey().getValue().toString().replace(':', '_'); @@ -750,7 +796,7 @@ else if (basefoundspamTicks >= bsefndtickdelay.get()) { } } //autoreload when entering different dimensions - if (load.get() && worldchange == true) { + if (load.get() && worldchange) { if (worldleaveremove.get()) { clearChunkData(); } @@ -758,7 +804,7 @@ else if (basefoundspamTicks >= bsefndtickdelay.get()) { worldchange = false; } if (!save.get()) saveDataWasOn = false; - if (save.get() && justenabledsavedata <= 2 && saveDataWasOn == false) { + if (save.get() && justenabledsavedata <= 2 && !saveDataWasOn) { justenabledsavedata++; if (justenabledsavedata == 1) { synchronized (baseChunks) { @@ -908,8 +954,7 @@ private void render2(Box box, Color sides, Color lines, ShapeMode shapeMode, Ren @EventHandler private void onReadPacket(PacketEvent.Receive event) { if (event.packet instanceof PlayerMoveC2SPacket) return; //this keeps getting cast to the chunkdata for no reason - if (!(event.packet instanceof PlayerMoveC2SPacket) && event.packet instanceof ChunkDataS2CPacket && mc.world != null) { - ChunkDataS2CPacket packet = (ChunkDataS2CPacket) event.packet; + if (!(event.packet instanceof PlayerMoveC2SPacket) && event.packet instanceof ChunkDataS2CPacket packet && mc.world != null) { basepos = new ChunkPos(packet.getChunkX(), packet.getChunkZ()); @@ -923,7 +968,7 @@ private void onReadPacket(PacketEvent.Receive event) { future.join(); } catch (CompletionException e) {} - if (bubblesFinder.get() || spawner.get() || signFinder.get() || portalFinder.get() || roofDetector.get() || bedrockfind.get() || skybuildfind.get() || Blawcks1.get().size()>0 || Blawcks2.get().size()>0 || Blawcks3.get().size()>0 || Blawcks4.get().size()>0 || Blawcks5.get().size()>0 || Blawcks6.get().size()>0 || Blawcks7.get().size()>0){ + if (bubblesFinder.get() || spawner.get() || signFinder.get() || portalFinder.get() || roofDetector.get() || bedrockfind.get() || skybuildfind.get() || !Blawcks1.get().isEmpty() || !Blawcks2.get().isEmpty() || !Blawcks3.get().isEmpty() || !Blawcks4.get().isEmpty() || !Blawcks5.get().isEmpty() || !Blawcks6.get().isEmpty() || !Blawcks7.get().isEmpty()){ int Ymin = mc.world.getBottomY()+minY.get(); int Ymax = mc.world.getTopY()-maxY.get(); try { @@ -962,15 +1007,15 @@ private void onReadPacket(PacketEvent.Receive event) { for (Text line : lines) { if (line.getLiteralString().length() != 0 && (line.getString() != "<----" && i == 1) && (line.getString() != "---->" && i == 2)){ //handling for arrows is for igloos signtextfound = true; - if (signtextfound == true) break; + if (signtextfound) break; } i++; } for (Text line2 : lines2) { - if (signtextfound == true) break; + if (signtextfound) break; if (line2.getLiteralString().length() != 0){ signtextfound = true; - if (signtextfound == true) break; + if (signtextfound) break; } } } else if (blockEntity instanceof HangingSignBlockEntity) { @@ -981,18 +1026,18 @@ private void onReadPacket(PacketEvent.Receive event) { for (Text line : lines) { if (line.getLiteralString().length() != 0){ //handling for arrows is for igloos signtextfound = true; - if (signtextfound == true) break; + if (signtextfound) break; } } for (Text line2 : lines2) { - if (signtextfound == true) break; + if (signtextfound) break; if (line2.getLiteralString().length() != 0){ signtextfound = true; - if (signtextfound == true) break; + if (signtextfound) break; } } } - if (signtextfound == true && !baseChunks.contains(basepos)){ + if (signtextfound && !baseChunks.contains(basepos)){ baseChunks.add(basepos); if (save.get()) { saveBaseChunkData(basepos); @@ -1018,7 +1063,7 @@ private void onReadPacket(PacketEvent.Receive event) { } } } - if (bubblesFinder.get() && blerks.getBlock() instanceof BubbleColumnBlock && blerks.get(BubbleColumnBlock.DRAG) == false) { + if (bubblesFinder.get() && blerks.getBlock() instanceof BubbleColumnBlock && !blerks.get(BubbleColumnBlock.DRAG)) { if (!baseChunks.contains(basepos)){ baseChunks.add(basepos); if (save.get()) { @@ -1079,49 +1124,49 @@ private void onReadPacket(PacketEvent.Receive event) { if (mc.world.getRegistryKey() == World.OVERWORLD && (blerks.getBlock()==Blocks.MOSSY_COBBLESTONE || blerks.getBlock()==Blocks.COBWEB || blerks.getBlock()==Blocks.STONE_BRICK_STAIRS || blerks.getBlock()==Blocks.BUDDING_AMETHYST))spawnernaturalblocks=true; else if (mc.world.getRegistryKey() == World.NETHER && (blerks.getBlock()==Blocks.NETHER_BRICK_FENCE || blerks.getBlock()==Blocks.CHAIN))spawnernaturalblocks=true; } - if (Blawcks1.get().size()>0){ + if (list1Activar.get() && !Blawcks1.get().isEmpty()){ if (Blawcks1.get().contains(blerks.getBlock())) { blockpositions1.add(blockposi); found1= blockpositions1.size(); lastblockfound1=blerks.getBlock().toString(); } } - if (Blawcks2.get().size()>0){ + if (list2Activar.get() && !Blawcks2.get().isEmpty()){ if (Blawcks2.get().contains(blerks.getBlock())) { blockpositions2.add(blockposi); found2= blockpositions2.size(); lastblockfound2=blerks.getBlock().toString(); } } - if (Blawcks3.get().size()>0){ + if (list3Activar.get() && !Blawcks3.get().isEmpty()){ if (Blawcks3.get().contains(blerks.getBlock())) { blockpositions3.add(blockposi); found3= blockpositions3.size(); lastblockfound3=blerks.getBlock().toString(); } } - if (Blawcks4.get().size()>0){ + if (list4Activar.get() && !Blawcks4.get().isEmpty()){ if (Blawcks4.get().contains(blerks.getBlock())) { blockpositions4.add(blockposi); found4= blockpositions4.size(); lastblockfound4=blerks.getBlock().toString(); } } - if (Blawcks5.get().size()>0){ + if (list5Activar.get() && !Blawcks5.get().isEmpty()){ if (Blawcks5.get().contains(blerks.getBlock())) { blockpositions5.add(blockposi); found5= blockpositions5.size(); lastblockfound5=blerks.getBlock().toString(); } } - if (Blawcks6.get().size()>0){ + if (list6Activar.get() && !Blawcks6.get().isEmpty()){ if (Blawcks6.get().contains(blerks.getBlock())) { blockpositions6.add(blockposi); found6= blockpositions6.size(); lastblockfound6=blerks.getBlock().toString(); } } - if (Blawcks7.get().size()>0){ + if (list7Activar.get() && !Blawcks7.get().isEmpty()){ if (Blawcks7.get().contains(blerks.getBlock())) { blockpositions7.add(blockposi); found7= blockpositions7.size(); @@ -1130,21 +1175,21 @@ private void onReadPacket(PacketEvent.Receive event) { } } } - if (Blawcks1.get().size()>0)checkingchunk1=true; - if (Blawcks2.get().size()>0)checkingchunk2=true; - if (Blawcks3.get().size()>0)checkingchunk3=true; - if (Blawcks4.get().size()>0)checkingchunk4=true; - if (Blawcks5.get().size()>0)checkingchunk5=true; - if (Blawcks6.get().size()>0)checkingchunk6=true; - if (Blawcks7.get().size()>0)checkingchunk7=true; + if (!Blawcks1.get().isEmpty())checkingchunk1=true; + if (!Blawcks2.get().isEmpty())checkingchunk2=true; + if (!Blawcks3.get().isEmpty())checkingchunk3=true; + if (!Blawcks4.get().isEmpty())checkingchunk4=true; + if (!Blawcks5.get().isEmpty())checkingchunk5=true; + if (!Blawcks6.get().isEmpty())checkingchunk6=true; + if (!Blawcks7.get().isEmpty())checkingchunk7=true; } } } Y+=16; } //CheckList 1 - if (Blawcks1.get().size()>0){ - if (checkingchunk1==true && found1>=blowkfind1.get()) { + if (!Blawcks1.get().isEmpty()){ + if (checkingchunk1 && found1>=blowkfind1.get()) { if (!baseChunks.contains(basepos)){ baseChunks.add(basepos); if (save.get()) { @@ -1159,7 +1204,7 @@ private void onReadPacket(PacketEvent.Receive event) { blockpositions1.clear(); found1 = 0; checkingchunk1=false; - } else if (checkingchunk1==true && found10){ - if (checkingchunk2==true && found2>=blowkfind2.get()) { + if (!Blawcks2.get().isEmpty()){ + if (checkingchunk2 && found2>=blowkfind2.get()) { if (!baseChunks.contains(basepos)){ baseChunks.add(basepos); if (save.get()) { @@ -1183,7 +1228,7 @@ private void onReadPacket(PacketEvent.Receive event) { blockpositions2.clear(); found2 = 0; checkingchunk2=false; - } else if (checkingchunk2==true && found20){ - if (checkingchunk3==true && found3>=blowkfind3.get()) { + if (!Blawcks3.get().isEmpty()){ + if (checkingchunk3 && found3>=blowkfind3.get()) { if (!baseChunks.contains(basepos)){ baseChunks.add(basepos); if (save.get()) { @@ -1207,7 +1252,7 @@ private void onReadPacket(PacketEvent.Receive event) { blockpositions3.clear(); found3 = 0; checkingchunk3=false; - } else if (checkingchunk3==true && found30){ - if (checkingchunk4==true && found4>=blowkfind4.get()) { + if (!Blawcks4.get().isEmpty()){ + if (checkingchunk4 && found4>=blowkfind4.get()) { if (!baseChunks.contains(basepos)){ baseChunks.add(basepos); if (save.get()) { @@ -1231,7 +1276,7 @@ private void onReadPacket(PacketEvent.Receive event) { blockpositions4.clear(); found4 = 0; checkingchunk4=false; - } else if (checkingchunk4==true && found40){ - if (checkingchunk5==true && found5>=blowkfind5.get()) { + if (!Blawcks5.get().isEmpty()){ + if (checkingchunk5 && found5>=blowkfind5.get()) { if (!baseChunks.contains(basepos)){ baseChunks.add(basepos); if (save.get()) { @@ -1255,7 +1300,7 @@ private void onReadPacket(PacketEvent.Receive event) { blockpositions5.clear(); found5 = 0; checkingchunk5=false; - } else if (checkingchunk5==true && found50){ - if (checkingchunk6==true && found6>=blowkfind6.get()) { + if (!Blawcks6.get().isEmpty()){ + if (checkingchunk6 && found6>=blowkfind6.get()) { if (!baseChunks.contains(basepos)){ baseChunks.add(basepos); if (save.get()) { @@ -1279,7 +1324,7 @@ private void onReadPacket(PacketEvent.Receive event) { blockpositions6.clear(); found6 = 0; checkingchunk6=false; - } else if (checkingchunk6==true && found60){ - if (checkingchunk7==true && found7>=blowkfind7.get()) { + if (!Blawcks7.get().isEmpty()){ + if (checkingchunk7 && found7>=blowkfind7.get()) { if (!baseChunks.contains(basepos)){ baseChunks.add(basepos); if (save.get()) { @@ -1303,7 +1348,7 @@ private void onReadPacket(PacketEvent.Receive event) { blockpositions7.clear(); found7 = 0; checkingchunk7=false; - } else if (checkingchunk7==true && found7 uses = sgGeneral.add(new IntSetting.Builder() + .name("Extra uses per use") + .description("Amount of extra uses per use") + .defaultValue(1) + .min(1) + .sliderMax(10) + .build() + ); + public MultiUse() { + super(Trouser.Main, "multi-use", "Uses an item multiple times per item use"); + } + @EventHandler + private void onMouseButton(MouseButtonEvent event) { + if (mc.options.useKey.isPressed()) { + for (int i = 0; i < uses.get(); i++) { + mc.doItemUse(); + } + } + } + @EventHandler + private void onPreTick(TickEvent.Pre event) { + if (mc.options.useKey.isPressed()) { + for (int i = 0; i < uses.get(); i++) { + mc.doItemUse(); + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index ca59eaea..b070a7cf 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,7 +1,7 @@ { "schemaVersion": 1, "id": "streak-addon", - "version": "1.3.7", + "version": "1.3.8", "name": "TrouserStreak", "description": "Trouser-Streak is a compilation of modules, updated to the latest version and optimized for maximum grief. I did not make all of these.", "authors": [ diff --git a/src/main/resources/streak-addon.accesswidener b/src/main/resources/streak-addon.accesswidener index 691ecb5f..d15897af 100644 --- a/src/main/resources/streak-addon.accesswidener +++ b/src/main/resources/streak-addon.accesswidener @@ -6,4 +6,5 @@ accessible method net/minecraft/world/chunk/PalettedContainer$Data palette ()Lne accessible method net/minecraft/client/network/ClientPlayerEntity getPermissionLevel ()I accessible field net/minecraft/block/spawner/MobSpawnerLogic spawnDelay I accessible field net/minecraft/block/spawner/MobSpawnerLogic spawnEntry Lnet/minecraft/block/spawner/MobSpawnerEntry; -accessible field net/minecraft/block/entity/DecoratedPotBlockEntity stack Lnet/minecraft/item/ItemStack; \ No newline at end of file +accessible field net/minecraft/block/entity/DecoratedPotBlockEntity stack Lnet/minecraft/item/ItemStack; +accessible method net/minecraft/client/MinecraftClient doItemUse ()V \ No newline at end of file