From 85ec5de48b1b312d98a7be85c4b705a26cfe0601 Mon Sep 17 00:00:00 2001 From: wuritz Date: Tue, 22 Jul 2025 13:22:34 +0200 Subject: [PATCH 01/14] fixed timer --- gradle.properties | 2 +- src/main/java/com/genyo/addon/modules/GenyoAutoEZ.java | 5 +++-- src/main/java/com/genyo/addon/modules/GenyoGoodbye.java | 3 ++- src/main/java/com/genyo/addon/modules/GenyoWelcome.java | 3 ++- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/gradle.properties b/gradle.properties index 8fbe06d..f6795f0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ yarn_mappings=1.21.4+build.8 loader_version=0.16.14 # Mod Properties -mod_version=0.7.3 +mod_version=0.7.4 maven_group=com.genyo archives_base_name=genyo-addon diff --git a/src/main/java/com/genyo/addon/modules/GenyoAutoEZ.java b/src/main/java/com/genyo/addon/modules/GenyoAutoEZ.java index 832adba..b7cf9d3 100644 --- a/src/main/java/com/genyo/addon/modules/GenyoAutoEZ.java +++ b/src/main/java/com/genyo/addon/modules/GenyoAutoEZ.java @@ -40,7 +40,7 @@ public GenyoAutoEZ() { .description("How many ticks to wait between sending messages.") .defaultValue(10) .min(0) - .sliderRange(0, 100) + .max(100) .build() ); @@ -102,7 +102,8 @@ public void onActivate() { @EventHandler(priority = EventPriority.HIGHEST) private void onTick(TickEvent.Pre event) { if (mc.player == null && mc.world == null) return; - timer++; + + if (!messageQueue.isEmpty()) timer++; if (timer >= tickDelay.get() && !messageQueue.isEmpty()) { Message msg = messageQueue.get(0); diff --git a/src/main/java/com/genyo/addon/modules/GenyoGoodbye.java b/src/main/java/com/genyo/addon/modules/GenyoGoodbye.java index 2bbe556..adee730 100644 --- a/src/main/java/com/genyo/addon/modules/GenyoGoodbye.java +++ b/src/main/java/com/genyo/addon/modules/GenyoGoodbye.java @@ -53,7 +53,8 @@ public GenyoGoodbye() { @EventHandler(priority = EventPriority.HIGHEST) private void onTick(TickEvent.Pre event) { if (mc.player == null && mc.world == null) return; - timer++; + + if (!messageQueue.isEmpty()) timer++; if (timer >= tickDelay.get() && !messageQueue.isEmpty()) { Message msg = messageQueue.get(0); diff --git a/src/main/java/com/genyo/addon/modules/GenyoWelcome.java b/src/main/java/com/genyo/addon/modules/GenyoWelcome.java index 7fcc1e3..10f4e32 100644 --- a/src/main/java/com/genyo/addon/modules/GenyoWelcome.java +++ b/src/main/java/com/genyo/addon/modules/GenyoWelcome.java @@ -72,7 +72,8 @@ private void onGameLeft(GameLeftEvent event) { @EventHandler(priority = EventPriority.HIGHEST) private void onTick(TickEvent.Pre event) { if (mc.player == null && mc.world == null) return; - timer++; + + if (!messageQueue.isEmpty()) timer++; if (timer >= tickDelay.get() && !messageQueue.isEmpty()) { Message msg = messageQueue.get(0); From b908a532bdb605081b66541f2784abdfe5812f06 Mon Sep 17 00:00:00 2001 From: wuritz Date: Tue, 22 Jul 2025 14:27:04 +0200 Subject: [PATCH 02/14] szebb --- .../com/genyo/addon/modules/GenyoGoodbye.java | 22 ------------------- .../genyo/addon/screens/ListGroupScreen.java | 22 ++++++++++++++----- .../settings/playerlist/ListGroupSetting.java | 12 +++++++--- .../com/genyo/addon/utils/GenyoChatUtils.java | 8 +++++++ 4 files changed, 33 insertions(+), 31 deletions(-) diff --git a/src/main/java/com/genyo/addon/modules/GenyoGoodbye.java b/src/main/java/com/genyo/addon/modules/GenyoGoodbye.java index adee730..c65a923 100644 --- a/src/main/java/com/genyo/addon/modules/GenyoGoodbye.java +++ b/src/main/java/com/genyo/addon/modules/GenyoGoodbye.java @@ -3,8 +3,6 @@ import com.genyo.addon.GenyoAddon; import com.genyo.addon.settings.playerlist.ListGroupSetting; import com.genyo.addon.settings.playerlist.PLGroup; -import meteordevelopment.meteorclient.events.game.GameJoinedEvent; -import meteordevelopment.meteorclient.events.game.GameLeftEvent; import meteordevelopment.meteorclient.events.packets.PacketEvent; import meteordevelopment.meteorclient.events.world.TickEvent; import meteordevelopment.meteorclient.settings.IntSetting; @@ -24,7 +22,6 @@ public class GenyoGoodbye extends GenyoModule { private final List messageQueue = new LinkedList<>(); private int timer; - private Set onlinePlayers = new HashSet<>(); private ArrayList groupsList = new ArrayList<>(); private ArrayList namesList = new ArrayList<>(); @@ -66,11 +63,6 @@ private void onTick(TickEvent.Pre event) { } } - @Override - public void onActivate() { - onlinePlayers.clear(); - } - @EventHandler private void onReceivePacket(PacketEvent.Receive event) { if (event.packet instanceof PlayerRemoveS2CPacket pac) { @@ -84,20 +76,6 @@ private void onReceivePacket(PacketEvent.Receive event) { } } - @EventHandler - private void onGameJoined(GameJoinedEvent event) { - if (mc.player == null && mc.world == null) return; - onlinePlayers.clear(); - mc.getNetworkHandler().getPlayerList().iterator().forEachRemaining(p -> { - if (p.getProfile() != null) onlinePlayers.add(p.getProfile().getId()); - }); - } - - @EventHandler - private void onGameLeft(GameLeftEvent event) { - onlinePlayers.clear(); - } - public void refreshList(List newGroups) { groupsList.clear(); groupsList.addAll(newGroups); diff --git a/src/main/java/com/genyo/addon/screens/ListGroupScreen.java b/src/main/java/com/genyo/addon/screens/ListGroupScreen.java index f32bfb6..4b51567 100644 --- a/src/main/java/com/genyo/addon/screens/ListGroupScreen.java +++ b/src/main/java/com/genyo/addon/screens/ListGroupScreen.java @@ -3,6 +3,7 @@ import com.genyo.addon.settings.playerlist.ListGroupSetting; import com.genyo.addon.settings.playerlist.ListPlayer; import com.genyo.addon.settings.playerlist.PLGroup; +import com.genyo.addon.utils.GenyoChatUtils; import meteordevelopment.meteorclient.gui.GuiTheme; import meteordevelopment.meteorclient.gui.WindowScreen; import meteordevelopment.meteorclient.gui.widgets.WWidget; @@ -13,6 +14,7 @@ import meteordevelopment.meteorclient.gui.widgets.pressable.WMinus; import meteordevelopment.meteorclient.gui.widgets.pressable.WPlus; import meteordevelopment.meteorclient.utils.network.MeteorExecutor; +import meteordevelopment.meteorclient.utils.render.color.Color; import net.minecraft.client.gui.screen.Screen; import static meteordevelopment.meteorclient.MeteorClient.mc; @@ -38,7 +40,11 @@ public ListGroupScreen(GuiTheme theme, ListGroupSetting setting, int index, Scre public void initWidgets() { table = add(theme.table()).expandX().minWidth(400).widget(); - table.add(theme.label("Group Name")).widget(); + table.add(theme.label("Status")); + table.add(theme.label((currentGroup.isEnabled() ? "Enabled" : "Disabled")).color(currentGroup.isEnabled() ? Color.GREEN : Color.RED)); + table.row(); + + table.add(theme.label("Name")).widget(); WTextBox textBox = table.add(theme.textBox(currentGroup.getGroupName())).expandX().widget(); textBox.action = () -> currentGroup.setGroupName(textBox.get()); textBox.actionOnUnfocused = this::confirmChanges; @@ -54,24 +60,22 @@ public void initWidgets() { table.add(theme.horizontalSeparator()).expandX(); table.row(); - initTable(table); - // New WHorizontalList list = table.add(theme.horizontalList()).expandX().widget(); WTextBox nameW = list.add(theme.textBox("", (text, c) -> c != ' ')).expandX().widget(); - nameW.setFocused(true); + //nameW.setFocused(true); WPlus add = list.add(theme.plus()).widget(); add.action = () -> { String name = nameW.get().trim(); if (name.equalsIgnoreCase("")) return; - //PLGroup currentGroup = setting.get().get(index); - ListPlayer player = new ListPlayer(name); if (currentGroup.containsPlayer(player)) { // it already exists nameW.set(""); + nameW.setFocused(true); + GenyoChatUtils.sendError("Player '" + name + "' already exists in '" + currentGroup.getGroupName() + "'!"); return; } @@ -82,8 +86,14 @@ public void initWidgets() { confirmChanges(); }; + table.row(); + + initTable(table); + enterAction = add.action; + table.row(); + table.add(theme.horizontalSeparator()).expandX(); table.row(); WButton save = table.add(theme.button("Save")).expandX().widget(); diff --git a/src/main/java/com/genyo/addon/settings/playerlist/ListGroupSetting.java b/src/main/java/com/genyo/addon/settings/playerlist/ListGroupSetting.java index fd2ffe4..b11d34c 100644 --- a/src/main/java/com/genyo/addon/settings/playerlist/ListGroupSetting.java +++ b/src/main/java/com/genyo/addon/settings/playerlist/ListGroupSetting.java @@ -34,17 +34,23 @@ public static void fillTable(GuiTheme theme, WTable table, ListGroupSetting sett for (int i = 0; i < setting.get().size(); i++) { int currentIndex = i; PLGroup currentGroup = groups.get(currentIndex); + WCheckbox toggle = table.add(theme.checkbox(currentGroup.isEnabled())).widget(); toggle.action = () -> { currentGroup.setEnabled(toggle.checked); GenyoChatUtils.sendInfo("Set group '" + currentGroup.getGroupName() + "' to " + (toggle.checked ? "enabled" : "disabled.")); }; - table.add(theme.label(groups.get(i).getGroupName())); - WButton button = table.add(theme.button("Edit")).expandX().widget(); - button.action = () -> { + + //table.add(theme.tooltip(currentGroup.getGroupName())).expandX(); + table.add(theme.label(currentGroup.getGroupName())).padHorizontal(20); + //table.add(theme.verticalSeparator()); + + WButton edit = table.add(theme.button("Edit")).expandX().widget(); + edit.action = () -> { mc.setScreen(new ListGroupScreen(theme, setting, currentIndex, mc.currentScreen)); }; + WMinus delete = table.add(theme.minus()).widget(); delete.action = () -> { groups.remove(currentIndex); diff --git a/src/main/java/com/genyo/addon/utils/GenyoChatUtils.java b/src/main/java/com/genyo/addon/utils/GenyoChatUtils.java index 33f8d77..8459b8d 100644 --- a/src/main/java/com/genyo/addon/utils/GenyoChatUtils.java +++ b/src/main/java/com/genyo/addon/utils/GenyoChatUtils.java @@ -21,6 +21,14 @@ public static void sendInfo(String text) { sendMessage(Text.of(msg), Objects.hash("genyo-info")); } + public static void sendError(String text) { + if (mc.world == null) return; + + ChatUtils.forceNextPrefixClass(GenyoChatUtils.class); + String msg = prefix + " " + Formatting.RED + text; + sendMessage(Text.of(msg), Objects.hash("genyo-error")); + } + public static void sendMessage(Text text, int id) { ((IChatHud) mc.inGameHud.getChatHud()).meteor$add(text, id); } From 98adda211074bbf36e09b42e01ad05d60235d89b Mon Sep 17 00:00:00 2001 From: wuritz Date: Wed, 23 Jul 2025 15:30:57 +0200 Subject: [PATCH 03/14] =?UTF-8?q?auto=20mine=20m=C5=B1kszik=20csak=20nem?= =?UTF-8?q?=20auto=20double?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/genyo/addon/GenyoAddon.java | 1 + .../genyo/addon/events/AttackBlockEvent.java | 27 + .../com/genyo/addon/hud/PvPNeccessaryHud.java | 4 +- .../ClientPlayerInteractionManagerMixin.java | 30 + .../DefaultSettingsWidgetFactoryMixin.java | 21 + .../genyo/addon/modules/GenyoAutoMine.java | 1139 +++++++++++++++++ .../com/genyo/addon/modules/GenyoModule.java | 34 +- .../genyo/addon/modules/GenyoSurround.java | 42 + .../com/genyo/addon/render/RenderBuffers.java | 177 +++ .../addon/render/animation/Animation.java | 65 + .../genyo/addon/render/animation/Easing.java | 213 +++ .../genyo/addon/screens/ListGroupScreen.java | 3 + .../genyo/addon/settings/FloatSetting.java | 125 ++ .../com/genyo/addon/utils/GEntityUtils.java | 17 + .../{InventoryUtils.java => GInvUtils.java} | 2 +- .../addon/utils/math/GPositionUtils.java | 62 + .../genyo/addon/utils/render/ColorUtil.java | 23 + .../utils/world/BlastResistantBlocks.java | 44 + src/main/resources/genyo.mixins.json | 3 +- 19 files changed, 2017 insertions(+), 15 deletions(-) create mode 100644 src/main/java/com/genyo/addon/events/AttackBlockEvent.java create mode 100644 src/main/java/com/genyo/addon/mixin/ClientPlayerInteractionManagerMixin.java create mode 100644 src/main/java/com/genyo/addon/modules/GenyoAutoMine.java create mode 100644 src/main/java/com/genyo/addon/render/RenderBuffers.java create mode 100644 src/main/java/com/genyo/addon/render/animation/Animation.java create mode 100644 src/main/java/com/genyo/addon/render/animation/Easing.java create mode 100644 src/main/java/com/genyo/addon/settings/FloatSetting.java create mode 100644 src/main/java/com/genyo/addon/utils/GEntityUtils.java rename src/main/java/com/genyo/addon/utils/{InventoryUtils.java => GInvUtils.java} (97%) create mode 100644 src/main/java/com/genyo/addon/utils/math/GPositionUtils.java create mode 100644 src/main/java/com/genyo/addon/utils/render/ColorUtil.java create mode 100644 src/main/java/com/genyo/addon/utils/world/BlastResistantBlocks.java diff --git a/src/main/java/com/genyo/addon/GenyoAddon.java b/src/main/java/com/genyo/addon/GenyoAddon.java index ffc8433..3e9e2a7 100644 --- a/src/main/java/com/genyo/addon/GenyoAddon.java +++ b/src/main/java/com/genyo/addon/GenyoAddon.java @@ -62,6 +62,7 @@ private void initModules(Modules modules) { modules.add(new GenyoWelcome()); modules.add(new GenyoSkinBlink()); modules.add(new GenyoGoodbye()); + modules.add(new GenyoAutoMine()); } private void initHUD(Hud hud) { diff --git a/src/main/java/com/genyo/addon/events/AttackBlockEvent.java b/src/main/java/com/genyo/addon/events/AttackBlockEvent.java new file mode 100644 index 0000000..27c5e5a --- /dev/null +++ b/src/main/java/com/genyo/addon/events/AttackBlockEvent.java @@ -0,0 +1,27 @@ +package com.genyo.addon.events; + +import meteordevelopment.meteorclient.events.Cancellable; +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; + +public class AttackBlockEvent extends Cancellable { + private static final AttackBlockEvent INSTANCE = new AttackBlockEvent(); + + public BlockPos pos; + public BlockState state; + public Direction direction; + + /** + * @param pos + * @param state + * @param direction + */ + public static AttackBlockEvent get(BlockPos pos, BlockState state, Direction direction) { + INSTANCE.pos = pos; + INSTANCE.state = state; + INSTANCE.direction = direction; + + return INSTANCE; + } +} diff --git a/src/main/java/com/genyo/addon/hud/PvPNeccessaryHud.java b/src/main/java/com/genyo/addon/hud/PvPNeccessaryHud.java index b1d4ae0..e27a8ff 100644 --- a/src/main/java/com/genyo/addon/hud/PvPNeccessaryHud.java +++ b/src/main/java/com/genyo/addon/hud/PvPNeccessaryHud.java @@ -1,8 +1,8 @@ package com.genyo.addon.hud; import com.genyo.addon.GenyoAddon; +import com.genyo.addon.utils.GInvUtils; import com.genyo.addon.utils.HudUtils; -import com.genyo.addon.utils.InventoryUtils; import meteordevelopment.meteorclient.settings.*; import meteordevelopment.meteorclient.systems.hud.HudElement; import meteordevelopment.meteorclient.systems.hud.HudElementInfo; @@ -105,7 +105,7 @@ public void render(HudRenderer renderer) { for (int i = 0; i < itemsLength; i++) { Item item = items.get().get(i); - ItemStack itemStack = new ItemStack(item, InventoryUtils.find(item).count()); + ItemStack itemStack = new ItemStack(item, GInvUtils.find(item).count()); int scaleOffset = (int) (getScale() * 10); int intScale = (int) (getScale()); diff --git a/src/main/java/com/genyo/addon/mixin/ClientPlayerInteractionManagerMixin.java b/src/main/java/com/genyo/addon/mixin/ClientPlayerInteractionManagerMixin.java new file mode 100644 index 0000000..276fcfb --- /dev/null +++ b/src/main/java/com/genyo/addon/mixin/ClientPlayerInteractionManagerMixin.java @@ -0,0 +1,30 @@ +package com.genyo.addon.mixin; + +import com.genyo.addon.events.AttackBlockEvent; +import meteordevelopment.meteorclient.MeteorClient; +import net.minecraft.block.BlockState; +import net.minecraft.client.network.ClientPlayerInteractionManager; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +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 static meteordevelopment.meteorclient.MeteorClient.mc; + +@Mixin(ClientPlayerInteractionManager.class) +public class ClientPlayerInteractionManagerMixin { + + /** + * @param pos + * @param direction + * @param cir + */ + @Inject(method = "attackBlock", at = @At(value = "HEAD"), cancellable = true) + private void hookAttackBlock(BlockPos pos, Direction direction, CallbackInfoReturnable cir) { + BlockState state = mc.world.getBlockState(pos); + if (MeteorClient.EVENT_BUS.post(AttackBlockEvent.get(pos, state, direction)).isCancelled()) cir.cancel(); + } + +} diff --git a/src/main/java/com/genyo/addon/mixin/DefaultSettingsWidgetFactoryMixin.java b/src/main/java/com/genyo/addon/mixin/DefaultSettingsWidgetFactoryMixin.java index 1bf5507..82dff8f 100644 --- a/src/main/java/com/genyo/addon/mixin/DefaultSettingsWidgetFactoryMixin.java +++ b/src/main/java/com/genyo/addon/mixin/DefaultSettingsWidgetFactoryMixin.java @@ -1,11 +1,13 @@ package com.genyo.addon.mixin; +import com.genyo.addon.settings.FloatSetting; import com.genyo.addon.settings.playerlist.ListGroupSetting; import meteordevelopment.meteorclient.gui.DefaultSettingsWidgetFactory; import meteordevelopment.meteorclient.gui.GuiTheme; import meteordevelopment.meteorclient.gui.utils.SettingsWidgetFactory; import meteordevelopment.meteorclient.gui.widgets.containers.WContainer; import meteordevelopment.meteorclient.gui.widgets.containers.WTable; +import meteordevelopment.meteorclient.gui.widgets.input.WDoubleEdit; import meteordevelopment.meteorclient.settings.Setting; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -20,6 +22,9 @@ public abstract class DefaultSettingsWidgetFactoryMixin extends SettingsWidgetFa @Shadow private void selectW(WContainer c, Setting setting, Runnable action) {} + @Shadow + private void reset(WContainer c, Setting setting, Runnable action) {} + public DefaultSettingsWidgetFactoryMixin(GuiTheme theme) { super(theme); } @@ -27,6 +32,7 @@ public DefaultSettingsWidgetFactoryMixin(GuiTheme theme) { @Inject(method = "", at = @At("TAIL")) protected void genyo(CallbackInfo info) { factories.put(ListGroupSetting.class, (table, setting) -> listGroupW(table, (ListGroupSetting) setting)); + factories.put(FloatSetting.class, (table, setting) -> floatW(table, (FloatSetting) setting)); } @Unique @@ -34,4 +40,19 @@ private void listGroupW(WTable table, ListGroupSetting setting) { WTable wtable = table.add(theme.table()).expandX().widget(); ListGroupSetting.fillTable(theme, wtable, setting); } + + @Unique + private void floatW(WTable table, FloatSetting setting) { + WDoubleEdit edit = theme.doubleEdit(setting.get(), setting.min, setting.max, setting.sliderMin, setting.sliderMax, setting.decimalPlaces, setting.noSlider); + table.add(edit).expandX(); + + Runnable action = () -> { + if (!setting.set((float) edit.get())) edit.set(setting.get()); + }; + + if (setting.onSliderRelease) edit.actionOnRelease = action; + else edit.action = action; + + reset(table, setting, () -> edit.set(setting.get())); + } } diff --git a/src/main/java/com/genyo/addon/modules/GenyoAutoMine.java b/src/main/java/com/genyo/addon/modules/GenyoAutoMine.java new file mode 100644 index 0000000..920035e --- /dev/null +++ b/src/main/java/com/genyo/addon/modules/GenyoAutoMine.java @@ -0,0 +1,1139 @@ +package com.genyo.addon.modules; + +import com.genyo.addon.GenyoAddon; +import com.genyo.addon.events.AttackBlockEvent; +import com.genyo.addon.render.animation.Animation; +import com.genyo.addon.settings.FloatSetting; +import com.genyo.addon.utils.GEntityUtils; +import com.genyo.addon.utils.math.GPositionUtils; +import com.genyo.addon.utils.render.ColorUtil; +import com.genyo.addon.utils.world.BlastResistantBlocks; +import meteordevelopment.meteorclient.events.packets.PacketEvent; +import meteordevelopment.meteorclient.events.render.Render3DEvent; +import meteordevelopment.meteorclient.events.world.TickEvent; +import meteordevelopment.meteorclient.mixininterface.IClientPlayerInteractionManager; +import meteordevelopment.meteorclient.renderer.Renderer3D; +import meteordevelopment.meteorclient.renderer.ShapeMode; +import meteordevelopment.meteorclient.settings.*; +import meteordevelopment.meteorclient.systems.modules.Modules; +import meteordevelopment.meteorclient.utils.player.InvUtils; +import meteordevelopment.meteorclient.utils.render.color.Color; +import meteordevelopment.meteorclient.utils.render.color.SettingColor; +import meteordevelopment.orbit.EventHandler; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.ShapeContext; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.EntityPose; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket; +import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket; +import net.minecraft.network.packet.c2s.play.UpdateSelectedSlotC2SPacket; +import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket; +import net.minecraft.util.Hand; +import net.minecraft.util.math.*; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.util.shape.VoxelShapes; + +import java.util.*; + +public class GenyoAutoMine extends GenyoModule{ + + public GenyoAutoMine() { + super(GenyoAddon.GENYO, "genyo-auto-mine", "dábül"); + } + + private final SettingGroup sgGeneral = settings.getDefaultGroup(); + private final SettingGroup sgSelection = settings.createGroup("Selection"); + + private final Setting multitask = sgGeneral.add(new BoolSetting.Builder() + .name("Allow Multitask") + .description("Allows actions while using items") + .defaultValue(false) + .build() + ); + + private final Setting auto = sgSelection.add(new BoolSetting.Builder() + .name("Auto") + .description("Automatically mines nearby players feet") + .defaultValue(false) + .build() + ); + + private final Setting selection = sgSelection.add(new EnumSetting.Builder() + .name("Selection") + .description("The selection of blocks mine") + .visible(auto::get) + .defaultValue(Selection.ALL) + .build() + ); + + private final Setting avoidSelf = sgSelection.add(new BoolSetting.Builder() + .name("Avoid Self") + .description("Avoids mining blocks in your surround") + .defaultValue(false) + .visible(auto::get) + .build() + ); + + private final Setting> whitelist = sgSelection.add(new BlockListSetting.Builder() + .name("Block Whitelist") + .description("Valid block whitelist") + .defaultValue(Blocks.OBSIDIAN, Blocks.ENDER_CHEST) + .build() + ); + + private final Setting> blacklist = sgSelection.add(new BlockListSetting.Builder() + .name("Block Blacklist") + .description("Valid block blacklist") + .defaultValue(Blocks.SHULKER_BOX) + .build() + ); + + private final Setting enemyRange = sgSelection.add(new FloatSetting.Builder() + .name("Enemy Range") + .description("Only mines on visible faces") + .defaultValue(5.0f) + .min(1.0f) + .max(10.0f) + .visible(auto::get) + .build() + ); + + private final Setting strictDirection = sgSelection.add(new BoolSetting.Builder() + .name("Strict Direction") + .description("Only mines on visible faces") + .visible(auto::get) + .defaultValue(false) + .build() + ); + + private final Setting antiCrawl = sgGeneral.add(new BoolSetting.Builder() + .name("Anti Crawl") + .description("Attempts to stop player from crawling") + .defaultValue(false) + .build() + ); + + private final Setting head = sgGeneral.add(new BoolSetting.Builder() + .name("Target Body") + .description("Attempts to mine players face blocks") + .defaultValue(false) + .visible(auto::get) + .build() + ); + + private final Setting aboveHead = sgGeneral.add(new BoolSetting.Builder() + .name("Target Head") + .description("Attempts to mine above players head") + .defaultValue(false) + .visible(auto::get) + .build() + ); + + private final Setting doubleBreak = sgGeneral.add(new BoolSetting.Builder() + .name("Double Break") + .description("Allows you to mine two blocks at once") + .defaultValue(false) + .build() + ); + + private final Setting mineTicks = sgGeneral.add(new IntSetting.Builder() + .name("Mining Ticks") + .description("The max number of ticks to hold a pickaxe for the packet mine") + .min(5) + .max(60) + .defaultValue(20) + .visible(doubleBreak::get) + .build() + ); + + private final Setting remine = sgGeneral.add(new EnumSetting.Builder() + .name("Remine") + .description("Remines already mined blocks") + .defaultValue(RemineMode.NORMAL) + .build() + ); + + private final Setting packetInstant = sgGeneral.add(new BoolSetting.Builder() + .name("Fast") + .description("Instant mines on packet") + .defaultValue(false) + .visible(() -> remine.get() == RemineMode.INSTANT) + .build() + ); + + private final Setting range = sgGeneral.add(new FloatSetting.Builder() + .name("Range") + .description("The range to mine blocks") + .min(0.1f) + .defaultValue(4.0f) + .max(6.0f) + .build() + ); + + private final Setting speed = sgGeneral.add(new FloatSetting.Builder() + .name("Speed") + .description("The speed to mine blocks") + .min(0.1f) + .defaultValue(1.0f) + .max(1.0f) + .build() + ); + + private final Setting swap = sgGeneral.add(new EnumSetting.Builder() + .name("Auto Swap") + .description("Swaps to the best tool once the mining is complete") + .defaultValue(Swap.SILENT) + .build() + ); + + private final Setting swapBefore = sgGeneral.add(new BoolSetting.Builder() + .name("Swap Before") + .description("Swaps before fully done mining") + .defaultValue(false) + .visible(() -> swap.get() != Swap.OFF) + .build() + ); + + private final Setting rotate = sgGeneral.add(new BoolSetting.Builder() + .name("Rotate") + .description("Rotates when mining the block") + .defaultValue(true) + .build() + ); + + private final Setting switchReset = sgGeneral.add(new BoolSetting.Builder() + .name("Switch Reset") + .description("Resets mining after switching items") + .defaultValue(false) + .build() + ); + + private final Setting grim = sgGeneral.add(new BoolSetting.Builder() + .name("Grim") + .description("Uses grim block breaking speeds") + .defaultValue(false) + .build() + ); + + private final Setting grimNew = sgGeneral.add(new BoolSetting.Builder() + .name("Grim V3") + .description("Allows mining on new grim servers") + .defaultValue(false) + .visible(grim::get) + .build() + ); + + private final Setting anticheat = sgGeneral.add(new BoolSetting.Builder() + .name("Anti Cheat") + .description("grim anti cheat genyo fasz") + .defaultValue(false) + .build() + ); + + private final Setting color = sgGeneral.add(new ColorSetting.Builder() + .name("Mine Color") + .description("The mine render color") + .defaultValue(new SettingColor(255, 0, 0, 45)) + .build() + ); + + private final Setting colorDone = sgGeneral.add(new ColorSetting.Builder() + .name("Done Color") + .description("The done render color") + .defaultValue(new SettingColor(0, 255, 0, 45)) + .build() + ); + + private final Setting fadeTime = sgGeneral.add(new IntSetting.Builder() + .name("Fade Time") + .description("Time to fade") + .min(0) + .defaultValue(250) + .max(1000) + .visible(() -> false) // ?????????? + .build() + ); + + private final Setting smoothColor = sgGeneral.add(new BoolSetting.Builder() + .name("Smooth Color") + .description("Interpolates from start to done color") + .defaultValue(false) + .visible(() -> false) // ?????????? + .build() + ); + + private PlayerEntity playerTarget; + private MineData packetMine, instantMine; // mining2 should always be the instant mine + private boolean packetSwapBack; + private boolean manualOverride; + private int remineTimer = 0; // TODO: tick timer + + private boolean changedInstantMine; + private boolean waitForPacketMine; + private boolean packetMineStuck; + + private boolean antiCrawlOverride; + private int antiCrawlTicks; + + private final Queue autoMineQueue = new ArrayDeque<>(); + private int autoMineTickDelay; + + private MineAnimation packetMineAnim = new MineAnimation(MineData.empty(), new Animation(true, 200)); + private MineAnimation instantMineAnim = new MineAnimation(MineData.empty(), new Animation(true, 200)); + + @Override + public void onDeactivate() { + autoMineQueue.clear(); + playerTarget = null; + packetMine = null; + + if (instantMine != null) { + abortMining(instantMine); + instantMine = null; + } + + packetMineAnim = new MineAnimation(MineData.empty(), new Animation(true, 200)); + instantMineAnim = new MineAnimation(MineData.empty(), new Animation(true, 200)); + + autoMineTickDelay = 0; + antiCrawlTicks = 0; + manualOverride = false; + antiCrawlOverride = false; + waitForPacketMine = false; + packetMineStuck = false; + if (packetSwapBack) { + ((IClientPlayerInteractionManager) mc.interactionManager).meteor$syncSelected(); + packetSwapBack = false; + } + } + + @EventHandler + public void onTick(TickEvent.Pre event) { + if (mc.player == null) return; + if (mc.player.isCreative() || mc.player.isSpectator()) return; + + remineTimer++; + + PlayerEntity currentTarget = getClosestPlayer((double) enemyRange.get()); + boolean targetChanged = playerTarget != null && playerTarget != currentTarget; + playerTarget = currentTarget; + + if (isInstantMineComplete()) { + if (changedInstantMine) changedInstantMine = false; + if (waitForPacketMine) waitForPacketMine = false; + } + + autoMineTickDelay--; + antiCrawlTicks--; + + // Mining packet handling + if (packetMine != null && packetMine.getTicksMining() > mineTicks.get()) { + packetMineStuck = true; + packetMineAnim.animation.setState(false); + if (packetSwapBack) { + ((IClientPlayerInteractionManager) mc.interactionManager).meteor$syncSelected(); + packetSwapBack = false; + } + packetMine = null; + if (!isInstantMineComplete()) { + waitForPacketMine = true; + } + } + + if (packetMine != null) { + final float damageDelta = mc.world.getBlockState(packetMine.getPos()).calcBlockBreakingDelta(mc.player, mc.world, packetMine.getPos()); + + packetMine.addBlockDamage(damageDelta); + + int slot = packetMine.getBestSlot(); + float damageDone = packetMine.getBlockDamage() + (swapBefore.get() + || packetMineStuck ? damageDelta : 0.0f); + if (damageDone >= 1.0f && slot != -1 && !checkMultitask()) + { + //Managers.INVENTORY.setSlot(slot); + InvUtils.move().slot(slot); + packetSwapBack = true; + if (packetMineStuck) + { + packetMineStuck = false; + } + } + } + + if (packetSwapBack) + { + if (packetMine != null && canMine(packetMine.getState())) + { + packetMine.markAttemptedMine(); + } + else + { + ((IClientPlayerInteractionManager) mc.interactionManager).meteor$syncSelected(); + packetSwapBack = false; + packetMineAnim.animation.setState(false); + packetMine = null; + if (!isInstantMineComplete()) + { + waitForPacketMine = true; + } + } + } + + if (instantMine != null) + { + final double distance = mc.player.getEyePos().squaredDistanceTo(instantMine.getPos().toCenterPos()); + if (distance > square(range.get()) || instantMine.getTicksMining() > mineTicks.get()) { + abortMining(instantMine); + instantMineAnim.animation.setState(false); + instantMine = null; + } + } + + if (instantMine != null) { + final float damageDelta = mc.world.getBlockState(instantMine.getPos()).calcBlockBreakingDelta(mc.player, mc.world, instantMine.getPos()); + + instantMine.addBlockDamage(damageDelta); + + if (instantMine.getBlockDamage() >= speed.get()) { + boolean canMine = canMine(instantMine.getState()); + boolean canPlace = mc.world.canPlace(instantMine.getState(), instantMine.getPos(), ShapeContext.absent()); + if (canMine) { + instantMine.markAttemptedMine(); + } else { + instantMine.resetMiningTicks(); + if (remine.get() == RemineMode.NORMAL || remine.get() == RemineMode.FAST) { + instantMine.setTotalBlockDamage(0.0f, 0.0f); + } + + if (manualOverride) { + manualOverride = false; + // Clear our old manual mine + abortMining(instantMine); + instantMineAnim.animation.setState(false); + instantMine = null; + } + } + + boolean passedRemine = remine.get() == RemineMode.INSTANT || (remineTimer >= 500); + + if (instantMine != null && (remine.get() == RemineMode.INSTANT + && packetInstant.get() && packetMine == null && canPlace || canMine && passedRemine) + && (!checkMultitask() || multitask.get() || swap.get() == Swap.OFF)) { + stopMining(instantMine); + remineTimer = 0; + + if (remine.get() == RemineMode.FAST) { + startMining(instantMine); + } + } + } + } + + // Clear overrides + if (manualOverride && (instantMine == null || instantMine.getGoal() != MiningGoal.MANUAL)) { + manualOverride = false; + } + + if (antiCrawlOverride && (instantMine == null || instantMine.getGoal() != MiningGoal.PREVENT_CRAWL)) { + antiCrawlOverride = false; + } + + if (auto.get()) { + if (!autoMineQueue.isEmpty() && autoMineTickDelay <= 0) { + MineData nextMine = autoMineQueue.poll(); + if (nextMine != null) { + startMining(nextMine); + autoMineTickDelay = 5; + } + } + + BlockPos antiCrawlPos = getAntiCrawlPos(playerTarget); + if (antiCrawlOverride) { + if (mc.player.getPose().equals(EntityPose.SWIMMING)) { + antiCrawlTicks = 10; + } + + if (antiCrawlTicks <= 0 || !isInstantMineComplete() && antiCrawlPos != null + && !instantMine.getPos().equals(antiCrawlPos)) + { + antiCrawlOverride = false; + } + } + + if (autoMineQueue.isEmpty() && !manualOverride && !antiCrawlOverride) { + if (antiCrawl.get() && mc.player.getPose().equals(EntityPose.SWIMMING) && antiCrawlPos != null) + { + MineData data = new MineData(antiCrawlPos, strictDirection.get() ? + mc.player.getHorizontalFacing() : Direction.UP, MiningGoal.PREVENT_CRAWL); + if (isInstantMineComplete() || !instantMine.equals(data)) + { + startAutoMine(data); + antiCrawlOverride = true; + } + } else if (playerTarget != null && !targetChanged) { + BlockPos targetPos = GEntityUtils.getRoundedBlockPos(playerTarget); + boolean bedrockPhased = GPositionUtils.isBedrock(playerTarget.getBoundingBox(), targetPos) && !playerTarget.isCrawling(); + + if (!isInstantMineComplete() && checkDataY(instantMine, targetPos, bedrockPhased)) + { + abortMining(instantMine); + instantMineAnim.animation.setState(false); + instantMine = null; + } + + else if (packetMine != null && checkDataY(packetMine, targetPos, bedrockPhased)) + { + packetMineAnim.animation.setState(false); + if (packetSwapBack) + { + ((IClientPlayerInteractionManager) mc.interactionManager).meteor$syncSelected(); + packetSwapBack = false; + } + packetMine = null; + waitForPacketMine = false; + } + + else + { + List phasedBlocks = getPhaseBlocks(playerTarget, targetPos, bedrockPhased); + + MineData bestMine; + if (!phasedBlocks.isEmpty()) + { + BlockPos pos1 = phasedBlocks.removeFirst(); + bestMine = new MineData(pos1, strictDirection.get() ? mc.player.getHorizontalFacing() : Direction.UP); + + if (packetMine == null && doubleBreak.get() || isInstantMineComplete()) { + startAutoMine(bestMine); + } + } + + else + { + List miningBlocks = getMiningBlocks(playerTarget, targetPos, bedrockPhased); + bestMine = getInstantMine(miningBlocks, bedrockPhased); + + if (bestMine != null && (packetMine == null && !changedInstantMine + && doubleBreak.get() || isInstantMineComplete())) + { + startAutoMine(bestMine); + } + } + } + } + + else + { + if (!isInstantMineComplete() && instantMine.getGoal() == MiningGoal.MINING_ENEMY) { + abortMining(instantMine); + instantMineAnim.animation.setState(false); + instantMine = null; + } + + if (packetMine != null && packetMine.getGoal() == MiningGoal.MINING_ENEMY) { + packetMineAnim.animation.setState(false); + if (packetSwapBack) { + ((IClientPlayerInteractionManager) mc.interactionManager).meteor$syncSelected(); + packetSwapBack = false; + } + packetMine = null; + waitForPacketMine = false; + } + } + } + } + } + + @EventHandler + public void onAttackBlock(AttackBlockEvent event) { + if (mc.player == null && mc.world == null) return; + if (mc.player.isCreative() || mc.player.isSpectator()) return; + + event.cancel(); + + // Do not try to break unbreakable blocks + if (event.state.getBlock().getHardness() == -1.0f || !canMine(event.state) || isMining(event.pos)) return; + + MineData data = new MineData(event.pos, event.direction, MiningGoal.MANUAL); + + if (instantMine != null && instantMine.getGoal() == MiningGoal.MINING_ENEMY + || packetMine != null && packetMine.getGoal() == MiningGoal.MINING_ENEMY) + { + manualOverride = true; + } + + if (!doubleBreak.get()) { + instantMine = data; + startMining(instantMine); + mc.player.swingHand(Hand.MAIN_HAND, false); + return; + } + + boolean updateChanged = false; + if (!isInstantMineComplete() && !changedInstantMine) { + if (packetMine == null) { + packetMine = instantMine.copy(); + packetMineAnim = new MineAnimation(packetMine, + new Animation(true, fadeTime.get())); + } else { + updateChanged = true; + } + } + + instantMine = data; + startMining(instantMine); + mc.player.swingHand(Hand.MAIN_HAND, false); + if (updateChanged) changedInstantMine = true; + } + + @EventHandler + public void onPacketSent(PacketEvent.Sent event) { + if (event.packet instanceof UpdateSelectedSlotC2SPacket && switchReset.get() && instantMine != null) { + instantMine.setTotalBlockDamage(0.0f, 0.0f); + } + } + + @EventHandler + public void onPacketReceive(PacketEvent.Receive event) { + if (event.packet instanceof BlockUpdateS2CPacket packet && canMine(packet.getState())) { + if (antiCrawlOverride && packet.getPos().equals(getAntiCrawlPos(playerTarget))) { + antiCrawlTicks = 10; + } + } + } + + public void startAutoMine(MineData data) { + if (!canMine(data.getState()) || isMining(data.getPos())) return; + + if (!doubleBreak.get()) { + instantMine = data; + autoMineQueue.offer(data); + return; + } + + if (changedInstantMine && !isInstantMineComplete() || waitForPacketMine) return; + + boolean updateChanged = false; + if (!isInstantMineComplete() && !changedInstantMine) { + if (packetMine == null) { + packetMine = instantMine.copy(); + packetMineAnim = new MineAnimation(packetMine, + new Animation(true, fadeTime.get())); + } else { + updateChanged = true; + } + } + + instantMine = data; + autoMineQueue.offer(data); + + if (updateChanged) { + changedInstantMine = true; + } + } + + public MineData getInstantMine(List miningBlocks, boolean bedrockPhased) { + PriorityQueue validInstantMines = new PriorityQueue<>(); + for (BlockPos blockPos : miningBlocks) { + BlockState state1 = mc.world.getBlockState(blockPos); + if (!isAutoMineBlock(state1.getBlock())) // bedrock mine exploit!! + { + continue; + } + + double dist = mc.player.getEyePos().squaredDistanceTo(blockPos.toCenterPos()); + if (dist > square(range.get())) continue; + + BlockState state2 = mc.world.getBlockState(blockPos.down()); + if (bedrockPhased || state2.isOf(Blocks.OBSIDIAN) || state2.isOf(Blocks.BEDROCK)) { + Direction direction = strictDirection.get() ? mc.player.getHorizontalFacing() : Direction.UP; + + validInstantMines.add(new MineData(blockPos, direction)); + } + } + + if (validInstantMines.isEmpty()) return null; + + return validInstantMines.peek(); + } + + public List getPhaseBlocks(PlayerEntity player, BlockPos playerPos, boolean targetBedrockPhased) + { + List phaseBlocks = GPositionUtils.getAllInBox(player.getBoundingBox(), + targetBedrockPhased && head.get() ? playerPos.up() : playerPos); + + phaseBlocks.removeIf(p -> { + BlockState state = mc.world.getBlockState(p); + if (!isAutoMineBlock(state.getBlock()) || !canMine(state) || isMining(p)) return true; + + double dist = mc.player.getEyePos().squaredDistanceTo(p.toCenterPos()); + if (dist > square(range.get())) return true; + + return avoidSelf.get() && intersectsPlayer(p); + }); + + if (targetBedrockPhased && aboveHead.get()) phaseBlocks.add(playerPos.up(2)); + + return phaseBlocks; + } + + /** + * + * @param player + * @return A {@link Set} of potential blocks to mine for an enemy player + */ + public List getMiningBlocks(PlayerEntity player, BlockPos playerPos, boolean bedrockPhased) + { + List surroundingBlocks = Modules.get().get(GenyoSurround.class).getSurroundNoDown(player, range.get()); + List miningBlocks; + if (bedrockPhased) + { + List facePlaceBlocks = new ArrayList<>(); + if (head.get()) { + facePlaceBlocks.addAll(surroundingBlocks.stream().map(BlockPos::up).toList()); + } + + BlockState belowFeet = mc.world.getBlockState(playerPos.down()); + if (canMine(belowFeet)) + { + facePlaceBlocks.add(playerPos.down()); + } + miningBlocks = facePlaceBlocks; + } + else + { + miningBlocks = surroundingBlocks; + } + + miningBlocks.removeIf(p -> avoidSelf.get() && intersectsPlayer(p)); + return miningBlocks; + } + + private BlockPos getAntiCrawlPos(PlayerEntity playerTarget) + { + if (!mc.player.isOnGround()) + { + return null; + } + BlockPos crawlingPos = GEntityUtils.getRoundedBlockPos(mc.player); + boolean playerBelow = playerTarget != null && GEntityUtils.getRoundedBlockPos(playerTarget).getY() < crawlingPos.getY(); + // We want to be same level as our opponent + if (playerBelow) + { + BlockState state = mc.world.getBlockState(crawlingPos.down()); + if (isAutoMineBlock(state.getBlock()) && canMine(state)) + { + return crawlingPos.down(); + } + } + else + { + BlockState state = mc.world.getBlockState(crawlingPos.up()); + if (isAutoMineBlock(state.getBlock()) && canMine(state)) + { + return crawlingPos.up(); + } + } + return null; + } + + private boolean checkDataY(MineData data, BlockPos targetPos, boolean bedrockPhased) + { + return data.getGoal() == MiningGoal.MINING_ENEMY && !bedrockPhased && data.getPos().getY() != targetPos.getY(); + } + + private boolean intersectsPlayer(BlockPos pos) + { + List playerBlocks = Modules.get().get(GenyoSurround.class).getPlayerBlocks(mc.player); + List surroundingBlocks = Modules.get().get(GenyoSurround.class).getSurroundNoDown(mc.player); + return playerBlocks.contains(pos) || surroundingBlocks.contains(pos); + } + + @EventHandler + public void onRender3D(Render3DEvent event) { + if (mc.player == null && mc.world == null) return; + if (mc.player.isCreative() || mc.player.isSpectator()) return; + + if (instantMineAnim != null && instantMineAnim.animation().getFactor() > 0.01f) + { + renderMiningData(event.matrices, event.tickDelta, instantMineAnim, true, event.renderer); + } + + if (doubleBreak.get() && packetMineAnim != null && packetMineAnim.animation().getFactor() > 0.01f) + { + renderMiningData(event.matrices, event.tickDelta, packetMineAnim, false, event.renderer); + } + } + + public void renderMiningData(MatrixStack matrixStack, float tickDelta, MineAnimation mineAnimation, boolean instantMine, Renderer3D renderer) + { + MineData data = mineAnimation.data(); + Animation animation = mineAnimation.animation(); + int boxAlpha = (int) (40 * animation.getFactor()); + int lineAlpha = (int) (100 * animation.getFactor()); + + Color boxColor; + Color lineColor; + if (smoothColor.get()) { + boxColor = !canMine(data.getState()) ? colorDone.get() : ColorUtil.interpolateColor(Math.min(data.getBlockDamage(), 1.0f), colorDone.get(), color.get()); + lineColor = !canMine(data.getState()) ? colorDone.get() : ColorUtil.interpolateColor(Math.min(data.getBlockDamage(), 1.0f), colorDone.get(), color.get()); + } else { + boxColor = data.getBlockDamage() >= 0.95f || !canMine(data.getState()) ? colorDone.get() : color.get(); + lineColor = data.getBlockDamage() >= 0.95f || !canMine(data.getState()) ? colorDone.get() : color.get(); + } + + BlockPos mining = data.getPos(); + VoxelShape outlineShape = VoxelShapes.fullCube(); + + if (!instantMine || data.getBlockDamage() < speed.get()) { + outlineShape = data.getState().getOutlineShape(mc.world, mining); + outlineShape = outlineShape.isEmpty() ? VoxelShapes.fullCube() : outlineShape; + } + Box render1 = outlineShape.getBoundingBox(); + Vec3d center = render1.offset(mining).getCenter(); + float total = instantMine ? speed.get() : 1.0f; + float scale = (instantMine && data.getBlockDamage() >= speed.get()) || !canMine(data.getState()) ? 1.0f : + MathHelper.clamp((data.getBlockDamage() + (data.getBlockDamage() - data.getLastDamage()) * tickDelta) / total, 0.0f, 1.0f); + double dx = (render1.maxX - render1.minX) / 2.0; + double dy = (render1.maxY - render1.minY) / 2.0; + double dz = (render1.maxZ - render1.minZ) / 2.0; + final Box scaled = new Box(center, center).expand(dx * scale, dy * scale, dz * scale); + + renderer.box(scaled, boxColor, lineColor, ShapeMode.Both, 0); + //RenderManager.renderBox(matrixStack, scaled, boxColor); + //RenderManager.renderBoundingBox(matrixStack, scaled, 1.5f, lineColor); + } + + public void startMining(MineData data) + { + /*if (rotate.get()) + { + float[] rotations = RotationUtil.getRotationsTo(mc.player.getEyePos(), data.getPos().toCenterPos()); + if (grim.get()) + { + setRotationSilent(rotations[0], rotations[1]); + } + else + { + setRotation(rotations[0], rotations[1]); + } + }*/ + + if (doubleBreak.get()) + { + // https://github.com/GrimAnticheat/Grim/blob/2.0/src/main/java/ac/grim/grimac/checks/impl/misc/FastBreak.java#L76 + // https://github.com/GrimAnticheat/Grim/blob/2.0/src/main/java/ac/grim/grimac/checks/impl/misc/FastBreak.java#L98 + if (grimNew.get()) + { + if (anticheat.get()) { + mc.getNetworkHandler().sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK, data.getPos(), data.getDirection())); + mc.getNetworkHandler().sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.START_DESTROY_BLOCK, data.getPos(), data.getDirection())); + mc.getNetworkHandler().sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.ABORT_DESTROY_BLOCK, data.getPos(), data.getDirection())); + } else { + mc.getNetworkHandler().sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.START_DESTROY_BLOCK, data.getPos(), data.getDirection())); + } + + mc.getNetworkHandler().sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK, data.getPos(), data.getDirection())); + mc.getNetworkHandler().sendPacket(new HandSwingC2SPacket(Hand.MAIN_HAND)); + mc.getNetworkHandler().sendPacket(new HandSwingC2SPacket(Hand.MAIN_HAND)); + mc.getNetworkHandler().sendPacket(new HandSwingC2SPacket(Hand.MAIN_HAND)); + } else { + mc.getNetworkHandler().sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK, data.getPos(), data.getDirection())); + mc.getNetworkHandler().sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.START_DESTROY_BLOCK, data.getPos(), data.getDirection())); + mc.getNetworkHandler().sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK, data.getPos(), data.getDirection())); + mc.getNetworkHandler().sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK, data.getPos(), data.getDirection())); + mc.getNetworkHandler().sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.START_DESTROY_BLOCK, data.getPos(), data.getDirection())); + mc.getNetworkHandler().sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK, data.getPos(), data.getDirection())); + mc.getNetworkHandler().sendPacket(new HandSwingC2SPacket(Hand.MAIN_HAND)); + } + } else { + mc.getNetworkHandler().sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.START_DESTROY_BLOCK, data.getPos(), data.getDirection())); + } + + /*if (rotate.get() && grim.get()) + { + Managers.ROTATION.setRotationSilentSync(); + }*/ + + instantMineAnim = new MineAnimation(data, new Animation(true, fadeTime.get())); + } + + public void abortMining(MineData data) + { + mc.getNetworkHandler().sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.ABORT_DESTROY_BLOCK, data.getPos(), data.getDirection())); + } + + public void stopMining(MineData data) + { + /*if (rotate.get()) + { + float[] rotations = RotationUtil.getRotationsTo(mc.player.getEyePos(), data.getPos().toCenterPos()); + if (grim.get()) + { + setRotationSilent(rotations[0], rotations[1]); + } + else + { + setRotation(rotations[0], rotations[1]); + } + }*/ + + int slot = data.getBestSlot(); + if (slot != -1) + { + swapTo(slot); + } + + stopMiningInternal(data); + + if (slot != -1) + { + swapSync(slot); + } + + /*if (rotate.get() && grim.get()) + { + Managers.ROTATION.setRotationSilentSync(); + }*/ + } + + private void stopMiningInternal(MineData data) + { + mc.getNetworkHandler().sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK, data.getPos(), data.getDirection())); + mc.getNetworkHandler().sendPacket(new PlayerActionC2SPacket( + PlayerActionC2SPacket.Action.ABORT_DESTROY_BLOCK, data.getPos(), data.getDirection())); + } + + public boolean isInstantMineComplete() + { + return instantMine == null || instantMine.getBlockDamage() >= speed.get() && !canMine(instantMine.getState()); + } + + public BlockPos getMiningBlock() + { + if (instantMine != null) + { + double damage = instantMine.getBlockDamage() / speed.get(); + if (damage > 0.75) + { + return instantMine.getPos(); + } + } + return null; + } + + private void swapTo(int slot) + { + switch (swap.get()) + { + //case NORMAL -> Managers.INVENTORY.setClientSlot(slot); + case NORMAL -> InvUtils.swap(slot, false); + //case SILENT -> Managers.INVENTORY.setSlot(slot); + case SILENT -> InvUtils.swap(slot, true); + } + } + + private void swapSync(int slot) + { + switch (swap.get()) + { + case SILENT -> ((IClientPlayerInteractionManager) mc.interactionManager).meteor$syncSelected(); + } + } + + public boolean isSilentSwapping() + { + return packetSwapBack; + } + + private boolean isMining(BlockPos blockPos) + { + return instantMine != null && instantMine.getPos().equals(blockPos) || + packetMine != null && packetMine.getPos().equals(blockPos); + } + + private boolean isAutoMineBlock(Block block) + { + if (BlastResistantBlocks.isUnbreakable(block)) + { + return false; + } + return switch (selection.get()) + { + case WHITELIST -> whitelist.get().contains(block); + case BLACKLIST -> !blacklist.get().contains(block); + case ALL -> true; + }; + } + + public boolean canMine(BlockState state) + { + return !state.isAir() && state.getFluidState().isEmpty(); + } + + public static class MineData implements Comparable + { + private final MinecraftClient mc = MinecraftClient.getInstance(); + + private final BlockPos pos; + private final Direction direction; + private final MiningGoal goal; + // + private int ticksMining; + private float blockDamage, lastDamage; + + public MineData(BlockPos pos, Direction direction) + { + this.pos = pos; + this.direction = direction; + this.goal = MiningGoal.MINING_ENEMY; + } + + public MineData(BlockPos pos, Direction direction, MiningGoal goal) + { + this.pos = pos; + this.direction = direction; + this.goal = goal; + } + + private double getPriority() + { + double dist = mc.player.getEyePos().squaredDistanceTo(pos.down().toCenterPos()); + return 0.0f; + } + + @Override + public int compareTo(MineData o) + { + return Double.compare(getPriority(), o.getPriority()); + } + + @Override + public boolean equals(Object obj) + { + return obj instanceof MineData d && d.getPos().equals(pos); + } + + public void resetMiningTicks() + { + ticksMining = 0; + } + + public void markAttemptedMine() + { + ticksMining++; + } + + public void addBlockDamage(float blockDamage) + { + this.lastDamage = this.blockDamage; + this.blockDamage += blockDamage; + } + + public void setTotalBlockDamage(float blockDamage, float lastDamage) + { + this.blockDamage = blockDamage; + this.lastDamage = lastDamage; + } + + public BlockPos getPos() + { + return pos; + } + + public Direction getDirection() + { + return direction; + } + + public MiningGoal getGoal() + { + return goal; + } + + public int getTicksMining() + { + return ticksMining; + } + + public float getBlockDamage() + { + return blockDamage; + } + + public float getLastDamage() + { + return lastDamage; + } + + public static MineData empty() + { + return new MineData(BlockPos.ORIGIN, Direction.UP); + } + + public MineData copy() + { + final MineData data = new MineData(pos, direction, goal); + data.setTotalBlockDamage(blockDamage, lastDamage); + return data; + } + + public BlockState getState() + { + return mc.world.getBlockState(pos); + } + + public int getBestSlot() + { + return InvUtils.findFastestTool(getState()).slot(); + } + } + + private float square(float value) { + return value*value; + } + + public record MineAnimation(MineData data, Animation animation) {} + + public enum MiningGoal { + MANUAL, + MINING_ENEMY, + PREVENT_CRAWL + } + + public enum RemineMode { + INSTANT, + NORMAL, + FAST + } + + public enum Selection { + WHITELIST, + BLACKLIST, + ALL + } + + public enum Swap { + NORMAL, + SILENT, + OFF + } +} diff --git a/src/main/java/com/genyo/addon/modules/GenyoModule.java b/src/main/java/com/genyo/addon/modules/GenyoModule.java index a41f15f..42adb48 100644 --- a/src/main/java/com/genyo/addon/modules/GenyoModule.java +++ b/src/main/java/com/genyo/addon/modules/GenyoModule.java @@ -5,29 +5,22 @@ import meteordevelopment.meteorclient.settings.Setting; import meteordevelopment.meteorclient.settings.SettingGroup; import meteordevelopment.meteorclient.systems.config.Config; +import meteordevelopment.meteorclient.systems.friends.Friends; import meteordevelopment.meteorclient.systems.modules.Category; import meteordevelopment.meteorclient.systems.modules.Module; -import meteordevelopment.meteorclient.systems.modules.Modules; -import meteordevelopment.meteorclient.systems.modules.player.Rotation; import meteordevelopment.meteorclient.utils.player.ChatUtils; +import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.network.PendingUpdateManager; import net.minecraft.client.network.SequencedPacketCreator; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.packet.Packet; -import net.minecraft.network.packet.c2s.play.PlayerInteractBlockC2SPacket; -import net.minecraft.network.packet.c2s.play.PlayerInteractItemC2SPacket; import net.minecraft.text.Text; import net.minecraft.util.Formatting; 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.MathHelper; -import net.minecraft.util.math.Vec3d; +import java.util.Comparator; import java.util.Objects; -import static meteordevelopment.meteorclient.MeteorClient.mc; - public class GenyoModule extends Module { private final String prefix = Formatting.GOLD + "" + Formatting.BOLD + "[Genyo]"; @@ -158,4 +151,23 @@ public Setting addPauseEat(SettingGroup group) { .build() ); } + + public PlayerEntity getClosestPlayer(double range) { + return mc.world.getPlayers().stream().filter(e -> !(e instanceof ClientPlayerEntity) && !e.isSpectator()) + .filter(e -> mc.player.squaredDistanceTo(e) <= range * range) + //.filter(e -> !Managers.SOCIAL.isFriend(e.getName().getString())) + .filter(e -> !Friends.get().isFriend(e)) + .min(Comparator.comparingDouble(e -> mc.player.squaredDistanceTo(e))).orElse(null); + } + + public boolean checkMultitask() { + return checkMultitask(false); + } + + public boolean checkMultitask(boolean checkOffhand) { + if (checkOffhand && mc.player.getActiveHand() != Hand.MAIN_HAND) { + return false; + } + return mc.player.isUsingItem(); + } } diff --git a/src/main/java/com/genyo/addon/modules/GenyoSurround.java b/src/main/java/com/genyo/addon/modules/GenyoSurround.java index 3abcbb0..194380a 100644 --- a/src/main/java/com/genyo/addon/modules/GenyoSurround.java +++ b/src/main/java/com/genyo/addon/modules/GenyoSurround.java @@ -1,6 +1,7 @@ package com.genyo.addon.modules; import com.genyo.addon.GenyoAddon; +import com.genyo.addon.utils.math.GPositionUtils; import meteordevelopment.meteorclient.events.render.Render3DEvent; import meteordevelopment.meteorclient.events.world.TickEvent; import meteordevelopment.meteorclient.renderer.ShapeMode; @@ -13,8 +14,10 @@ import meteordevelopment.meteorclient.utils.world.BlockUtils; import meteordevelopment.orbit.EventHandler; import net.minecraft.block.Blocks; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Items; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -202,6 +205,45 @@ private void onRender3D(Render3DEvent event) { } } + public List getSurroundNoDown(PlayerEntity player, float range) { + List surroundBlocks = new ArrayList<>(); + List playerBlocks = getPlayerBlocks(player); + for (BlockPos pos : playerBlocks) + { + if (range > 0.0f && mc.player.getEyePos().squaredDistanceTo(pos.toCenterPos()) > range * range) + { + continue; + } + for (Direction dir : Direction.values()) + { + if (!dir.getAxis().isHorizontal()) + { + continue; + } + BlockPos pos1 = pos.offset(dir); + if (surroundBlocks.contains(pos1) || playerBlocks.contains(pos1)) + { + continue; + } + surroundBlocks.add(pos1); + } + } + return surroundBlocks; + } + + public List getSurroundNoDown(PlayerEntity player) + { + return getSurroundNoDown(player, 0.0f); + } + + public List getPlayerBlocks(PlayerEntity entity) { + BlockPos playerPos = GPositionUtils.getRoundedBlockPos(entity.getX(), entity.getY(), entity.getZ()); + final List playerBlocks = new ArrayList<>(); + playerBlocks.add(playerPos); + + return playerBlocks; + } + private boolean canPlaceAt(BlockPos pos) { return mc.world.getBlockState(pos).getBlock() == Blocks.AIR; } diff --git a/src/main/java/com/genyo/addon/render/RenderBuffers.java b/src/main/java/com/genyo/addon/render/RenderBuffers.java new file mode 100644 index 0000000..0d4e525 --- /dev/null +++ b/src/main/java/com/genyo/addon/render/RenderBuffers.java @@ -0,0 +1,177 @@ +package com.genyo.addon.render; + +import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gl.ShaderProgramKeys; +import net.minecraft.client.render.*; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.math.ColorHelper; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import org.joml.*; +import org.lwjgl.opengl.GL11; + +import java.util.ArrayList; +import java.util.List; + +public class RenderBuffers { + + public static final Buffer QUADS = new Buffer(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR); + public static final Buffer TEXTURE_QUADS = new Buffer(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE); + public static final Buffer LINES = new Buffer(VertexFormat.DrawMode.LINES, VertexFormats.LINES); + private static final List postRenderCallbacks = new ArrayList<>(); + private static boolean isSetup = false; + + public static void preRender() + { + GL11.glEnable(GL11.GL_LINE_SMOOTH); + GL11.glHint(GL11.GL_LINE_SMOOTH_HINT, GL11.GL_NICEST); + RenderSystem.disableCull(); + RenderSystem.enableBlend(); + RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + RenderSystem.disableDepthTest(); + isSetup = true; + } + + public static void postRender() + { + isSetup = false; + + RenderSystem.enableDepthTest(); + RenderSystem.disableBlend(); + RenderSystem.enableCull(); + GL11.glDisable(GL11.GL_LINE_SMOOTH); + for (Runnable callback : postRenderCallbacks) + { + callback.run(); + } + postRenderCallbacks.clear(); + } + + private static Matrix4d toMatrix4d(Matrix4f matrix4f) + { + return new Matrix4d(matrix4f.m00(), matrix4f.m01(), matrix4f.m02(), matrix4f.m03(), + matrix4f.m10(), matrix4f.m11(), matrix4f.m12(), matrix4f.m13(), + matrix4f.m20(), matrix4f.m21(), matrix4f.m22(), matrix4f.m23(), + matrix4f.m30(), matrix4f.m31(), matrix4f.m32(), matrix4f.m33()); + } + + public static class Buffer + { + public BufferBuilder buffer; + private final VertexFormat.DrawMode drawMode; + private final VertexFormat vertexFormat; + private Matrix4d positionMatrix; + private Matrix3f normalMatrix; + private int color; + + public Buffer(VertexFormat.DrawMode drawMode, VertexFormat vertexFormat) + { + this.drawMode = drawMode; + this.vertexFormat = vertexFormat; + this.color = -1; + } + + public void begin(MatrixStack stack) + { + updateMatrices(stack); + buffer = Tessellator.getInstance().begin(drawMode, vertexFormat); + } + + public void updateMatrices(MatrixStack stack) + { + this.positionMatrix = toMatrix4d(stack.peek().getPositionMatrix()); + this.normalMatrix = stack.peek().getNormalMatrix(); + Vec3d pos = MinecraftClient.getInstance().getBlockEntityRenderDispatcher().camera.getPos(); + positionMatrix.translate(-pos.x, -pos.y, -pos.z); + } + + /** + * Render in immediate mode if we're calling from outside of {@link net.shoreline.client.impl.event.render.RenderWorldEvent} + */ + public void end() + { + draw(); + } + + public Buffer vertex(double x, double y, double z) + { + if (buffer == null) + { + return this; + } + Vector4d vector4d = positionMatrix.transform(new Vector4d(x, y, z, 1.0)); + this.buffer.vertex((float) vector4d.x(), (float) vector4d.y(), (float) vector4d.z()) + .color(ColorHelper.getRed(color), ColorHelper.getGreen(color), ColorHelper.getBlue(color), ColorHelper.getAlpha(color)); + return this; + } + + public Buffer vertexTex(double x, double y, double z, float u, float v) + { + if (buffer == null) + { + return this; + } + Vector4d vector4d = positionMatrix.transform(new Vector4d(x, y, z, 1.0)); + this.buffer.vertex((float) vector4d.x(), (float) vector4d.y(), (float) vector4d.z()).texture(u, v) + .color(ColorHelper.getRed(color), ColorHelper.getGreen(color), ColorHelper.getBlue(color), ColorHelper.getAlpha(color)); + return this; + } + + public Buffer vertexLine(double x1, double y1, double z1, double x2, double y2, double z2) + { + if (buffer == null) + { + return this; + } + float k = (float)(x2 - x1); + float l = (float)(y2 - y1); + float m = (float)(z2 - z1); + float n = MathHelper.sqrt(k * k + l * l + m * m); + k /= n; + l /= n; + m /= n; + Vector3f vector3f = normalMatrix.transform(k, l, m, new Vector3f()).normalize(); + Vector4d vector4d = positionMatrix.transform(new Vector4d(x1, y1, z1, 1.0)); + this.buffer.vertex((float) vector4d.x(), (float) vector4d.y(), (float) vector4d.z()).normal(vector3f.x, vector3f.y, vector3f.z) + .color(ColorHelper.getRed(color), ColorHelper.getGreen(color), ColorHelper.getBlue(color), ColorHelper.getAlpha(color)); + Vector4d vector4d2 = positionMatrix.transform(new Vector4d(x2, y2, z2, 1.0)); + this.buffer.vertex((float) vector4d2.x(), (float) vector4d2.y(), (float) vector4d2.z()).normal(vector3f.x, vector3f.y, vector3f.z) + .color(ColorHelper.getRed(color), ColorHelper.getGreen(color), ColorHelper.getBlue(color), ColorHelper.getAlpha(color)); + return this; + } + + public void color(int color) + { + this.color = color; + } + + public void draw() + { + if (buffer == null) + { + return; + } + if (vertexFormat == VertexFormats.LINES) + { + RenderSystem.setShader(ShaderProgramKeys.RENDERTYPE_LINES); + } + else if (vertexFormat == VertexFormats.POSITION_COLOR) + { + RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); + } + else if (vertexFormat == VertexFormats.POSITION_TEXTURE) + { + RenderSystem.setShader(ShaderProgramKeys.POSITION_TEX); + } + + BuiltBuffer builtBuffer = this.buffer.endNullable(); + if (builtBuffer != null) + { + BufferRenderer.drawWithGlobalProgram(builtBuffer); + buffer = null; + } + } + } + +} diff --git a/src/main/java/com/genyo/addon/render/animation/Animation.java b/src/main/java/com/genyo/addon/render/animation/Animation.java new file mode 100644 index 0000000..3c0751c --- /dev/null +++ b/src/main/java/com/genyo/addon/render/animation/Animation.java @@ -0,0 +1,65 @@ +package com.genyo.addon.render.animation; + +public class Animation { + + private final Easing easing; + private float length; + private long last = 0L; + private boolean state; + + public Animation(float length) { + this(false, length); + } + + public Animation(boolean initial, float length) { + this(initial, length, Easing.LINEAR); + } + + public Animation(boolean initial, float length, Easing easing) { + this.length = length; + this.state = initial; + this.easing = easing; + } + + public void setState(boolean state) { + last = (long) (!state ? System.currentTimeMillis() - ((1 - getFactor()) * length) : System.currentTimeMillis() - (getFactor() * length)); + this.state = state; + } + + public boolean getState() { + return state; + } + + public double getFactor() { + return easing.ease(getLinearFactor()); + } + + public double getLinearFactor() { + return state ? clamp(((System.currentTimeMillis() - last) / length)) : clamp((1 - (System.currentTimeMillis() - last) / length)); + } + + public double getCurrent() { + return 1 + ((2 - 1)) * getFactor(); + } + + private double clamp(double in) { + return in < 0 ? 0 : Math.min(in, 1); + } + + public double getLength() { + return length; + } + + public void setLength(float length) { + this.length = length; + } + + public boolean isFinished() { + return !getState() && getFactor() == 0.0 || getState() && getFactor() == 1.0; + } + + public void reset() { + last = System.currentTimeMillis(); + } + +} diff --git a/src/main/java/com/genyo/addon/render/animation/Easing.java b/src/main/java/com/genyo/addon/render/animation/Easing.java new file mode 100644 index 0000000..9ea55e3 --- /dev/null +++ b/src/main/java/com/genyo/addon/render/animation/Easing.java @@ -0,0 +1,213 @@ +package com.genyo.addon.render.animation; + +public enum Easing { + + LINEAR { + @Override + public double ease(double factor) { + return factor; + } + }, + SINE_IN { + @Override + public double ease(double factor) { + return 1 - Math.cos((factor * Math.PI) / 2); + } + }, + SINE_OUT { + @Override + public double ease(double factor) { + return Math.sin((factor * Math.PI) / 2); + } + }, + SINE_IN_OUT { + @Override + public double ease(double factor) { + return -(Math.cos(Math.PI * factor) - 1) / 2; + } + }, + CUBIC_IN { + @Override + public double ease(double factor) { + return Math.pow(factor, 3); + } + }, + CUBIC_OUT { + @Override + public double ease(double factor) { + return 1 - Math.pow(1 - factor, 3); + } + }, + CUBIC_IN_OUT { + @Override + public double ease(double factor) { + return factor < 0.5 ? 4 * Math.pow(factor, 3) : 1 - Math.pow(-2 * factor + 2, 3) / 2; + } + }, + QUAD_IN { + @Override + public double ease(double factor) { + return Math.pow(factor, 2); + } + }, + QUAD_OUT { + @Override + public double ease(double factor) { + return 1 - (1 - factor) * (1 - factor); + } + }, + QUAD_IN_OUT { + @Override + public double ease(double factor) { + return factor < 0.5 ? 8 * Math.pow(factor, 4) : 1 - Math.pow(-2 * factor + 2, 4) / 2; + } + }, + QUART_IN { + @Override + public double ease(double factor) { + return Math.pow(factor, 4); + } + }, + QUART_OUT { + @Override + public double ease(double factor) { + return 1 - Math.pow(1 - factor, 4); + } + }, + QUART_IN_OUT { + @Override + public double ease(double factor) { + return factor < 0.5 ? 8 * Math.pow(factor, 4) : 1 - Math.pow(-2 * factor + 2, 4) / 2; + } + }, + QUINT_IN { + @Override + public double ease(double factor) { + return Math.pow(factor, 5); + } + }, + QUINT_OUT { + @Override + public double ease(double factor) { + return 1 - Math.pow(1 - factor, 5); + } + }, + QUINT_IN_OUT { + @Override + public double ease(double factor) { + return factor < 0.5 ? 16 * Math.pow(factor, 5) : 1 - Math.pow(-2 * factor + 2, 5) / 2; + } + }, + CIRC_IN { + @Override + public double ease(double factor) { + return 1 - Math.sqrt(1 - Math.pow(factor, 2)); + } + }, + CIRC_OUT { + @Override + public double ease(double factor) { + return Math.sqrt(1 - Math.pow(factor - 1, 2)); + } + }, + CIRC_IN_OUT { + @Override + public double ease(double factor) { + return factor < 0.5 ? (1 - Math.sqrt(1 - Math.pow(2 * factor, 2))) / 2 : (Math.sqrt(1 - Math.pow(-2 * factor + 2, 2)) + 1) / 2; + } + }, + EXPO_IN { + @Override + public double ease(double factor) { + return Math.min(0, Math.pow(2, 10 * factor - 10)); + } + }, + EXPO_OUT { + @Override + public double ease(double factor) { + return Math.max(1 - Math.pow(2, -10 * factor), 1); + } + }, + EXPO_IN_OUT { + @Override + public double ease(double factor) { + return factor == 0 ? 0 : factor == 1 ? 1 : factor < 0.5 ? Math.pow(2, 20 * factor - 10) / 2 : (2 - Math.pow(2, -20 * factor + 10)) / 2; + } + }, + ELASTIC_IN { + @Override + public double ease(double factor) { + return factor == 0 ? 0 : factor == 1 ? 1 : -Math.pow(2, 10 * factor - 10) * Math.sin((factor * 10 - 10.75) * ((2 * Math.PI) / 3)); + } + }, + ELASTIC_OUT { + @Override + public double ease(double factor) { + return factor == 0 ? 0 : factor == 1 ? 1 : Math.pow(2, -10 * factor) * Math.sin((factor * 10 - 0.75) * ((2 * Math.PI) / 3)) + 1; + } + }, + ELASTIC_IN_OUT { + @Override + public double ease(double factor) { + double sin = Math.sin((20 * factor - 11.125) * ((2 * Math.PI) / 4.5)); + + return factor == 0 ? 0 : factor == 1 ? 1 : factor < 0.5 ? -(Math.pow(2, 20 * factor - 10) * sin) / 2 : (Math.pow(2, -20 * factor + 10) * sin) / 2 + 1; + } + }, + BACK_IN { + @Override + public double ease(double factor) { + return 2.70158 * Math.pow(factor, 3) - 1.70158 * factor * factor; + } + }, + BACK_OUT { + @Override + public double ease(double factor) { + double c1 = 1.70158; + double c3 = c1 + 1; + + return 1 + c3 * Math.pow(factor - 1, 3) + c1 * Math.pow(factor - 1, 2); + } + }, + BACK_IN_OUT { + @Override + public double ease(double factor) { + return factor < 0.5 ? (Math.pow(2 * factor, 2) * (((1.70158 * 1.525) + 1) * 2 * factor - (1.70158 * 1.525))) / 2 : (Math.pow(2 * factor - 2, 2) * (((1.70158 * 1.525) + 1) * (factor * 2 - 2) + (1.70158 * 1.525)) + 2) / 2; + } + }, + BOUNCE_IN { + @Override + public double ease(double factor) { + return 1 - Easing.bounceOut(1 - factor); + } + }, + BOUNCE_OUT { + @Override + public double ease(double factor) { + return Easing.bounceOut(factor); + } + }, + BOUNCE_IN_OUT { + public double ease(double factor) { + return factor < 0.5 ? (1 - bounceOut(1 - 2 * factor)) / 2 : (1 + bounceOut(2 * factor - 1)) / 2; + } + }; + + public abstract double ease(double factor); + + private static double bounceOut(double in) { + double n1 = 7.5625; + double d1 = 2.75; + + if (in < 1 / d1) { + return n1 * in * in; + } else if (in < 2 / d1) { + return n1 * (in -= 1.5 / d1) * in + 0.75; + } else if (in < 2.5 / d1) { + return n1 * (in -= 2.25 / d1) * in + 0.9375; + } else { + return n1 * (in -= 2.625 / d1) * in + 0.984375; + } + } + +} diff --git a/src/main/java/com/genyo/addon/screens/ListGroupScreen.java b/src/main/java/com/genyo/addon/screens/ListGroupScreen.java index 4b51567..d7fca0c 100644 --- a/src/main/java/com/genyo/addon/screens/ListGroupScreen.java +++ b/src/main/java/com/genyo/addon/screens/ListGroupScreen.java @@ -60,6 +60,9 @@ public void initWidgets() { table.add(theme.horizontalSeparator()).expandX(); table.row(); + table.add(theme.label("Players")); + table.row(); + // New WHorizontalList list = table.add(theme.horizontalList()).expandX().widget(); diff --git a/src/main/java/com/genyo/addon/settings/FloatSetting.java b/src/main/java/com/genyo/addon/settings/FloatSetting.java new file mode 100644 index 0000000..b70e4b0 --- /dev/null +++ b/src/main/java/com/genyo/addon/settings/FloatSetting.java @@ -0,0 +1,125 @@ +package com.genyo.addon.settings; + +import meteordevelopment.meteorclient.settings.IVisible; +import meteordevelopment.meteorclient.settings.Setting; +import net.minecraft.nbt.NbtCompound; + +import java.util.function.Consumer; + +public class FloatSetting extends Setting { + + public final float min, max; + public final float sliderMin, sliderMax; + public final boolean onSliderRelease; + public final int decimalPlaces; + public final boolean noSlider; + + private FloatSetting(String name, String description, float defaultValue, Consumer onChanged, Consumer> onModuleActivated, IVisible visible, float min, float max, float sliderMin, float sliderMax, boolean onSliderRelease, int decimalPlaces, boolean noSlider) { + super(name, description, defaultValue, onChanged, onModuleActivated, visible); + + this.min = min; + this.max = max; + this.sliderMin = sliderMin; + this.sliderMax = sliderMax; + this.decimalPlaces = decimalPlaces; + this.onSliderRelease = onSliderRelease; + this.noSlider = noSlider; + } + + @Override + protected Float parseImpl(String str) { + try { + return Float.parseFloat(str.trim()); + } catch (NumberFormatException ignored) { + return null; + } + } + + @Override + protected boolean isValueValid(Float value) { + return value >= min && value <= max; + } + + @Override + protected NbtCompound save(NbtCompound tag) { + tag.putFloat("value", get()); + + return tag; + } + + @Override + public Float load(NbtCompound tag) { + set(tag.getFloat("value")); + + return get(); + } + + public static class Builder extends SettingBuilder { + public float min = Float.NEGATIVE_INFINITY, max = Float.POSITIVE_INFINITY; + public float sliderMin = 0, sliderMax = 10; + public boolean onSliderRelease = false; + public int decimalPlaces = 3; + public boolean noSlider = false; + + public Builder() { + super(0f); + } + + public Builder defaultValue(float defaultValue) { + this.defaultValue = defaultValue; + return this; + } + + public Builder min(float min) { + this.min = min; + return this; + } + + public Builder max(float max) { + this.max = max; + return this; + } + + public Builder range(float min, float max) { + this.min = Math.min(min, max); + this.max = Math.max(min, max); + return this; + } + + public Builder sliderMin(float min) { + sliderMin = min; + return this; + } + + public Builder sliderMax(float max) { + sliderMax = max; + return this; + } + + public Builder sliderRange(float min, float max) { + sliderMin = min; + sliderMax = max; + return this; + } + + public Builder onSliderRelease() { + onSliderRelease = true; + return this; + } + + public Builder decimalPlaces(int decimalPlaces) { + this.decimalPlaces = decimalPlaces; + return this; + } + + public Builder noSlider() { + noSlider = true; + return this; + } + + public FloatSetting build() { + return new FloatSetting(name, description, defaultValue, onChanged, onModuleActivated, visible, min, max, Math.max(sliderMin, min), Math.min(sliderMax, max), onSliderRelease, decimalPlaces, noSlider); + } + } + +} diff --git a/src/main/java/com/genyo/addon/utils/GEntityUtils.java b/src/main/java/com/genyo/addon/utils/GEntityUtils.java new file mode 100644 index 0000000..b1b1003 --- /dev/null +++ b/src/main/java/com/genyo/addon/utils/GEntityUtils.java @@ -0,0 +1,17 @@ +package com.genyo.addon.utils; + +import net.minecraft.entity.Entity; +import net.minecraft.util.math.BlockPos; + +public class GEntityUtils { + + /** + * + * @param entity + * @return + */ + public static BlockPos getRoundedBlockPos(Entity entity) { + return new BlockPos(entity.getBlockX(), (int) Math.round(entity.getY()), entity.getBlockZ()); + } + +} diff --git a/src/main/java/com/genyo/addon/utils/InventoryUtils.java b/src/main/java/com/genyo/addon/utils/GInvUtils.java similarity index 97% rename from src/main/java/com/genyo/addon/utils/InventoryUtils.java rename to src/main/java/com/genyo/addon/utils/GInvUtils.java index da673c6..7fbc4b7 100644 --- a/src/main/java/com/genyo/addon/utils/InventoryUtils.java +++ b/src/main/java/com/genyo/addon/utils/GInvUtils.java @@ -8,7 +8,7 @@ import static meteordevelopment.meteorclient.MeteorClient.mc; -public class InventoryUtils { +public class GInvUtils { public static FindItemResult find(Item... items) { return find(itemStack -> { diff --git a/src/main/java/com/genyo/addon/utils/math/GPositionUtils.java b/src/main/java/com/genyo/addon/utils/math/GPositionUtils.java new file mode 100644 index 0000000..71a906d --- /dev/null +++ b/src/main/java/com/genyo/addon/utils/math/GPositionUtils.java @@ -0,0 +1,62 @@ +package com.genyo.addon.utils.math; + +import com.genyo.addon.utils.world.BlastResistantBlocks; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.MathHelper; + +import java.util.ArrayList; +import java.util.List; + +public class GPositionUtils { + + public static boolean isBedrock(Box box, BlockPos pos) + { + return getAllInBox(box, pos).stream().anyMatch(BlastResistantBlocks::isUnbreakable); + } + + /** + * Returns a {@link List} of all the {@link BlockPos} positions in the + * given {@link Box} that match the player position level + * + * @param box + * @param pos The player position + * @return + */ + public static List getAllInBox(Box box, BlockPos pos) + { + final List intersections = new ArrayList<>(); + for (int x = (int) Math.floor(box.minX); x < Math.ceil(box.maxX); x++) + { + for (int z = (int) Math.floor(box.minZ); z < Math.ceil(box.maxZ); z++) + { + intersections.add(new BlockPos(x, pos.getY(), z)); + } + } + return intersections; + } + + public static List getAllInBox(Box box) + { + final List intersections = new ArrayList<>(); + for (int x = (int) Math.floor(box.minX); x < Math.ceil(box.maxX); x++) + { + for (int y = (int) Math.floor(box.minY); y < Math.ceil(box.maxY); y++) + { + for (int z = (int) Math.floor(box.minZ); z < Math.ceil(box.maxZ); z++) + { + intersections.add(new BlockPos(x, y, z)); + } + } + } + return intersections; + } + + public static BlockPos getRoundedBlockPos(final double x, final double y, final double z) + { + final int flooredX = MathHelper.floor(x); + final int flooredY = (int) Math.round(y); + final int flooredZ = MathHelper.floor(z); + return new BlockPos(flooredX, flooredY, flooredZ); + } +} diff --git a/src/main/java/com/genyo/addon/utils/render/ColorUtil.java b/src/main/java/com/genyo/addon/utils/render/ColorUtil.java new file mode 100644 index 0000000..bb10b2c --- /dev/null +++ b/src/main/java/com/genyo/addon/utils/render/ColorUtil.java @@ -0,0 +1,23 @@ +package com.genyo.addon.utils.render; + +import meteordevelopment.meteorclient.utils.render.color.Color; + +public class ColorUtil { + + public static Color interpolateColor(float value, Color start, Color end) + { + float sr = start.r / 255.0f; + float sg = start.g / 255.0f; + float sb = start.b / 255.0f; + float sa = start.a / 255.0f; + float er = end.r / 255.0f; + float eg = end.g / 255.0f; + float eb = end.b / 255.0f; + float ea = end.a / 255.0f; + return new Color(sr * value + er * (1.0f - value), + sg * value + eg * (1.0f - value), + sb * value + eb * (1.0f - value), + sa * value + ea * (1.0f - value)); + } + +} diff --git a/src/main/java/com/genyo/addon/utils/world/BlastResistantBlocks.java b/src/main/java/com/genyo/addon/utils/world/BlastResistantBlocks.java new file mode 100644 index 0000000..a3ffa2a --- /dev/null +++ b/src/main/java/com/genyo/addon/utils/world/BlastResistantBlocks.java @@ -0,0 +1,44 @@ +package com.genyo.addon.utils.world; + +import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; +import net.minecraft.block.Block; +import net.minecraft.block.Blocks; +import net.minecraft.util.math.BlockPos; + +import java.util.Set; + +import static meteordevelopment.meteorclient.MeteorClient.mc; + +public class BlastResistantBlocks { + + // All blocks that are unbreakable with tools in survival mode + private static final Set UNBREAKABLE = new ReferenceOpenHashSet<>(Set.of( + Blocks.BEDROCK, + Blocks.COMMAND_BLOCK, + Blocks.CHAIN_COMMAND_BLOCK, + Blocks.END_PORTAL_FRAME, + Blocks.BARRIER + )); + + /** + * @param pos + * @return + */ + public static boolean isUnbreakable(BlockPos pos) + { + if (mc.world == null) + { + return false; + } + return isUnbreakable(mc.world.getBlockState(pos).getBlock()); + } + + /** + * @param block + * @return + */ + public static boolean isUnbreakable(Block block) + { + return UNBREAKABLE.contains(block); + } +} diff --git a/src/main/resources/genyo.mixins.json b/src/main/resources/genyo.mixins.json index 00e1e9a..0abf31e 100644 --- a/src/main/resources/genyo.mixins.json +++ b/src/main/resources/genyo.mixins.json @@ -7,7 +7,8 @@ "FriendsInjector", "IEntity", "DefaultSettingsWidgetFactoryMixin", - "AccessorGameOptions" + "AccessorGameOptions", + "ClientPlayerInteractionManagerMixin" ], "injectors": { "defaultRequire": 1 From fef30a6c6d4325a2e851d457f278570073d5ca4b Mon Sep 17 00:00:00 2001 From: wuritz Date: Thu, 24 Jul 2025 17:59:31 +0200 Subject: [PATCH 04/14] surround v2 --- gradle.properties | 2 +- src/main/java/com/genyo/addon/GenyoAddon.java | 1 + .../genyo/addon/managers/BlockManager.java | 123 ++++ .../com/genyo/addon/managers/Managers.java | 2 + .../genyo/addon/modules/GenyoAutoMine.java | 27 +- .../genyo/addon/modules/GenyoSurroundV2.java | 649 ++++++++++++++++++ .../genyo/addon/utils/player/Rotation.java | 25 + .../utils/world/BlastResistantBlocks.java | 66 ++ 8 files changed, 880 insertions(+), 15 deletions(-) create mode 100644 src/main/java/com/genyo/addon/managers/BlockManager.java create mode 100644 src/main/java/com/genyo/addon/modules/GenyoSurroundV2.java create mode 100644 src/main/java/com/genyo/addon/utils/player/Rotation.java diff --git a/gradle.properties b/gradle.properties index f6795f0..a460110 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ yarn_mappings=1.21.4+build.8 loader_version=0.16.14 # Mod Properties -mod_version=0.7.4 +mod_version=0.7.5 maven_group=com.genyo archives_base_name=genyo-addon diff --git a/src/main/java/com/genyo/addon/GenyoAddon.java b/src/main/java/com/genyo/addon/GenyoAddon.java index 3e9e2a7..aa1e283 100644 --- a/src/main/java/com/genyo/addon/GenyoAddon.java +++ b/src/main/java/com/genyo/addon/GenyoAddon.java @@ -63,6 +63,7 @@ private void initModules(Modules modules) { modules.add(new GenyoSkinBlink()); modules.add(new GenyoGoodbye()); modules.add(new GenyoAutoMine()); + modules.add(new GenyoSurroundV2()); } private void initHUD(Hud hud) { diff --git a/src/main/java/com/genyo/addon/managers/BlockManager.java b/src/main/java/com/genyo/addon/managers/BlockManager.java new file mode 100644 index 0000000..8156f6e --- /dev/null +++ b/src/main/java/com/genyo/addon/managers/BlockManager.java @@ -0,0 +1,123 @@ +package com.genyo.addon.managers; + +import meteordevelopment.meteorclient.events.packets.PacketEvent; +import meteordevelopment.meteorclient.events.world.TickEvent; +import meteordevelopment.orbit.EventHandler; +import net.minecraft.block.BlockState; +import net.minecraft.network.packet.s2c.play.BlockBreakingProgressS2CPacket; +import net.minecraft.util.math.BlockPos; + +import java.util.Comparator; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.stream.Collectors; + +import static meteordevelopment.meteorclient.MeteorClient.mc; + +public class BlockManager { + + private final List breakPositions = new CopyOnWriteArrayList<>(); + + @EventHandler + public void onTick(TickEvent.Pre event) + { + if (mc.player == null || mc.world == null) { + breakPositions.clear(); + return; + } + + for (BreakEntry blockEntry : breakPositions) + { + blockEntry.updateDamage(); + } + } + + @EventHandler + public void onPacketReceive(PacketEvent.Receive event) + { + if (mc.player == null || mc.world == null) return; + + if (event.packet instanceof BlockBreakingProgressS2CPacket packet) { + if (countBreaks(packet.getEntityId()) >= 2) { + breakPositions.stream().filter(d -> d.getEntityId() == packet.getEntityId()) + .min(Comparator.comparingLong(BreakEntry::getStartTime)).ifPresent(breakPositions::remove); + } + BreakEntry data = new BreakEntry(packet.getEntityId(), packet.getPos()); + data.startMining(); + breakPositions.add(data); + } + } + + public long countBreaks(int entityId) + { + return breakPositions.stream().filter(d -> d.getEntityId() == entityId).count(); + } + + public boolean isInstantMine(BlockPos pos) + { + return breakPositions.getFirst().getPos().equals(pos); + } + + public boolean isBreaking(BlockPos pos) + { + return breakPositions.stream().anyMatch(d -> d.getPos().equals(pos)); + } + + public boolean isPassed(BlockPos pos, float blockDamage) + { + return breakPositions.stream().anyMatch(d -> d.getPos().equals(pos) && d.getBlockDamage() >= blockDamage); + } + + public Set getMines(float blockDamage) + { + return breakPositions.stream().filter(d -> isPassed(d.getPos(), blockDamage)).map(BreakEntry::getPos).collect(Collectors.toSet()); + } + + public static class BreakEntry + { + private final int entityId; + private final BlockPos pos; + private long startTime; + private float blockDamage; + private boolean started; + + public BreakEntry(int entityId, BlockPos pos) + { + this.entityId = entityId; + this.pos = pos; + } + + public void updateDamage() + { + if (started) blockDamage += mc.world.getBlockState(pos).calcBlockBreakingDelta(mc.player, mc.world, pos); + } + + public void startMining() + { + started = true; + startTime = System.currentTimeMillis(); + } + + public BlockPos getPos() + { + return pos; + } + + public float getBlockDamage() + { + return Math.min(blockDamage, 1.0f); + } + + public int getEntityId() + { + return entityId; + } + + public long getStartTime() + { + return startTime; + } + } + +} diff --git a/src/main/java/com/genyo/addon/managers/Managers.java b/src/main/java/com/genyo/addon/managers/Managers.java index 8f2174b..fb62796 100644 --- a/src/main/java/com/genyo/addon/managers/Managers.java +++ b/src/main/java/com/genyo/addon/managers/Managers.java @@ -7,10 +7,12 @@ public class Managers { public static final CombatManager COMBAT = new CombatManager(); public static final Render3DEngine ENGINE3D = new Render3DEngine(); + public static final BlockManager BLOCK = new BlockManager(); public static void subscribe() { MeteorClient.EVENT_BUS.subscribe(COMBAT); MeteorClient.EVENT_BUS.subscribe(ENGINE3D); + MeteorClient.EVENT_BUS.subscribe(BLOCK); } } diff --git a/src/main/java/com/genyo/addon/modules/GenyoAutoMine.java b/src/main/java/com/genyo/addon/modules/GenyoAutoMine.java index 920035e..fdb6dd6 100644 --- a/src/main/java/com/genyo/addon/modules/GenyoAutoMine.java +++ b/src/main/java/com/genyo/addon/modules/GenyoAutoMine.java @@ -15,6 +15,7 @@ import meteordevelopment.meteorclient.renderer.Renderer3D; import meteordevelopment.meteorclient.renderer.ShapeMode; import meteordevelopment.meteorclient.settings.*; +import meteordevelopment.meteorclient.systems.friends.Friends; import meteordevelopment.meteorclient.systems.modules.Modules; import meteordevelopment.meteorclient.utils.player.InvUtils; import meteordevelopment.meteorclient.utils.render.color.Color; @@ -448,6 +449,11 @@ public void onTick(TickEvent.Pre event) { if (nextMine != null) { startMining(nextMine); autoMineTickDelay = 5; + + nextMine = autoMineQueue.poll(); + if (nextMine == null) return; + startMining(nextMine); + autoMineTickDelay = 5; } } @@ -478,15 +484,11 @@ public void onTick(TickEvent.Pre event) { BlockPos targetPos = GEntityUtils.getRoundedBlockPos(playerTarget); boolean bedrockPhased = GPositionUtils.isBedrock(playerTarget.getBoundingBox(), targetPos) && !playerTarget.isCrawling(); - if (!isInstantMineComplete() && checkDataY(instantMine, targetPos, bedrockPhased)) - { + if (!isInstantMineComplete() && checkDataY(instantMine, targetPos, bedrockPhased)) { abortMining(instantMine); instantMineAnim.animation.setState(false); instantMine = null; - } - - else if (packetMine != null && checkDataY(packetMine, targetPos, bedrockPhased)) - { + } else if (packetMine != null && checkDataY(packetMine, targetPos, bedrockPhased)) { packetMineAnim.animation.setState(false); if (packetSwapBack) { @@ -495,16 +497,14 @@ else if (packetMine != null && checkDataY(packetMine, targetPos, bedrockPhased)) } packetMine = null; waitForPacketMine = false; - } - - else - { + } else { List phasedBlocks = getPhaseBlocks(playerTarget, targetPos, bedrockPhased); MineData bestMine; if (!phasedBlocks.isEmpty()) { BlockPos pos1 = phasedBlocks.removeFirst(); + GenyoAddon.LOG.info(phasedBlocks.toString()); bestMine = new MineData(pos1, strictDirection.get() ? mc.player.getHorizontalFacing() : Direction.UP); if (packetMine == null && doubleBreak.get() || isInstantMineComplete()) { @@ -524,10 +524,7 @@ else if (packetMine != null && checkDataY(packetMine, targetPos, bedrockPhased)) } } } - } - - else - { + } else { if (!isInstantMineComplete() && instantMine.getGoal() == MiningGoal.MINING_ENEMY) { abortMining(instantMine); instantMineAnim.animation.setState(false); @@ -553,6 +550,8 @@ public void onAttackBlock(AttackBlockEvent event) { if (mc.player == null && mc.world == null) return; if (mc.player.isCreative() || mc.player.isSpectator()) return; + if (event.state.getBlock() == null) return; + event.cancel(); // Do not try to break unbreakable blocks diff --git a/src/main/java/com/genyo/addon/modules/GenyoSurroundV2.java b/src/main/java/com/genyo/addon/modules/GenyoSurroundV2.java new file mode 100644 index 0000000..cef63ca --- /dev/null +++ b/src/main/java/com/genyo/addon/modules/GenyoSurroundV2.java @@ -0,0 +1,649 @@ +package com.genyo.addon.modules; + +import com.genyo.addon.GenyoAddon; +import com.genyo.addon.managers.Managers; +import com.genyo.addon.render.animation.Animation; +import com.genyo.addon.settings.FloatSetting; +import com.genyo.addon.utils.math.GPositionUtils; +import com.genyo.addon.utils.player.Rotation; +import com.genyo.addon.utils.world.BlastResistantBlocks; +import meteordevelopment.meteorclient.events.packets.PacketEvent; +import meteordevelopment.meteorclient.events.render.Render3DEvent; +import meteordevelopment.meteorclient.events.world.TickEvent; +import meteordevelopment.meteorclient.renderer.ShapeMode; +import meteordevelopment.meteorclient.settings.*; +import meteordevelopment.meteorclient.systems.modules.Modules; +import meteordevelopment.meteorclient.utils.player.FindItemResult; +import meteordevelopment.meteorclient.utils.player.InvUtils; +import meteordevelopment.meteorclient.utils.render.color.Color; +import meteordevelopment.meteorclient.utils.render.color.SettingColor; +import meteordevelopment.meteorclient.utils.world.BlockUtils; +import meteordevelopment.orbit.EventHandler; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.ShapeContext; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.decoration.EndCrystalEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.BlockItem; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.network.packet.Packet; +import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket; +import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket; +import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket; +import net.minecraft.network.packet.s2c.play.BundleS2CPacket; +import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket; +import net.minecraft.network.packet.s2c.play.ExplosionS2CPacket; +import net.minecraft.util.Hand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3i; + +import java.util.*; + +public class GenyoSurroundV2 extends GenyoModule{ + + public GenyoSurroundV2() { + super(GenyoAddon.GENYO, "genyo-surround-v2", "ma reggel befostam aztán felkeltem"); + } + + private static final List RESISTANT_BLOCKS = new LinkedList<>() + {{ + add(Blocks.OBSIDIAN); + add(Blocks.CRYING_OBSIDIAN); + add(Blocks.ENDER_CHEST); + }}; + protected static final BlockState DEFAULT_OBSIDIAN_STATE = Blocks.OBSIDIAN.getDefaultState(); + + private final SettingGroup sgGeneral = settings.getDefaultGroup(); + + private final Setting multitask = sgGeneral.add(new BoolSetting.Builder() + .name("Allow Multitask") + .description("Allows actions while using items") + .defaultValue(false) + .build() + ); + + private final Setting rotate = sgGeneral.add(new BoolSetting.Builder() + .name("Rotate") + .description("ekwjfkljweklfjewfew") + .defaultValue(false) + .build() + ); + + private final Setting timing = sgGeneral.add(new EnumSetting.Builder() + .name("Timing") + .description("Timing for replacing blocks") + .defaultValue(Timing.VANILLA) + .build() + ); + + private final Setting prePlaceExplosion = sgGeneral.add(new BoolSetting.Builder() + .name("Pre Place Explosions") + .description("Pre places before explosions") + .defaultValue(false) + .visible(() -> timing.get() == Timing.SEQUENTIAL) + .build() + ); + + private final Setting prePlaceTick = sgGeneral.add(new BoolSetting.Builder() + .name("Pre Place Tick") + .description("Pre places before ticks") + .defaultValue(false) + .visible(() -> timing.get() == Timing.SEQUENTIAL) + .build() + ); + + private final Setting placeRange = sgGeneral.add(new FloatSetting.Builder() + .name("Place Range") + .description("The placement range for surround") + .defaultValue(4.0f) + .min(0.0f) + .max(6.0f) + .build() + ); + + private final Setting attack = sgGeneral.add(new BoolSetting.Builder() + .name("Attack") + .description("Attacks crystals in the way of surround") + .defaultValue(true) + .build() + ); + + private final Setting extend = sgGeneral.add(new BoolSetting.Builder() + .name("Extend") + .description("Extends surround if the player is not in the center of a block") + .defaultValue(true) + .build() + ); + + private final Setting head = sgGeneral.add(new BoolSetting.Builder() + .name("Cover Head") + .description("Place a block at your head") + .defaultValue(false) + .build() + ); + + private final Setting mineExtend = sgGeneral.add(new BoolSetting.Builder() + .name("Mine Extend") + .description("Extends surround if the block is being mined") + .defaultValue(false) + .build() + ); + + private final Setting support = sgGeneral.add(new BoolSetting.Builder() + .name("Support") + .description("Creates a floor for the surround if there is none") + .defaultValue(false) + .build() + ); + + private final Setting shiftTicks = sgGeneral.add(new IntSetting.Builder() + .name("Shift Ticks") + .description("The number of blocks to place per tick") + .min(1) + .defaultValue(2) + .max(10) + .build() + ); + + private final Setting shiftDelay = sgGeneral.add(new FloatSetting.Builder() + .name("Shift Delay") + .description("The delay between each block placement interval") + .min(0.0f) + .defaultValue(1.0f) + .max(5.0f) + .build() + ); + + private final Setting jumpDisable = sgGeneral.add(new BoolSetting.Builder() + .name("Auto Disable") + .description("Disables after moving out of the hole") + .defaultValue(true) + .build() + ); + + private final Setting render = sgGeneral.add(new BoolSetting.Builder() + .name("Render") + .description("Renders where scaffold is placing blocks") + .defaultValue(false) + .build() + ); + + private final Setting fadeTime = sgGeneral.add(new IntSetting.Builder() + .name("Fade Time") + .description("Time to fade") + .min(0) + .defaultValue(250) + .max(1000) + .visible(() -> false) // ???? + .build() + ); + + private final Setting color = sgGeneral.add(new ColorSetting.Builder() + .name("Render Color") + .description("asdsadsadsadsadsa") + .defaultValue(new Color(236, 243, 122, 40)) + .build() + ); + + private int blocksPlaced; + private List surround = new ArrayList<>(); + private List placements = new ArrayList<>(); + private final Map packets = new HashMap<>(); + private final Map fadeList = new HashMap<>(); + private double prevY; + + @Override + public void onActivate() { + if (mc.player == null) return; + + prevY = mc.player.getY(); + } + + @Override + public void onDeactivate() { + surround.clear(); + placements.clear(); + packets.clear(); + fadeList.clear(); + } + + @EventHandler + public void onTick(TickEvent.Pre event) { + blocksPlaced = 0; + //if (SelfTrapModule.getInstance().isEnabled()) return; + + if (jumpDisable.get() && (mc.player.getY() - prevY > 0.5 || mc.player.fallDistance > 1.5f)) { + toggle(); + return; + } + + if (!multitask.get() && checkMultitask()) { + surround.clear(); + placements.clear(); + return; + } + + final int slot = getResistantBlockItem(); + if (slot == -1) { + surround.clear(); + placements.clear(); + return; + } + + surround = getSurround((PlayerEntity) mc.player); + if (surround.isEmpty()) return; + + if (attack.get()) attackBlockingCrystals(surround); + + placements = getPlacementsFromSurround(surround); + if (placements.isEmpty()) return; + + if (support.get()) { + for (BlockPos block : new ArrayList<>(placements)) + { + if (block.getY() > mc.player.getBlockY() + 1.0) { + continue; + } + Direction direction = mc.player.getHorizontalFacing(); + if (direction == null) { + placements.add(block.down()); + } + } + } + placements.sort(Comparator.comparingInt(Vec3i::getY)); + while (blocksPlaced < shiftTicks.get()) { + if (blocksPlaced >= placements.size()) + { + break; + } + BlockPos targetPos = placements.get(blocksPlaced); + // All rotations for shift ticks must send extra packet + // This may not work on all servers + placeBlock(targetPos); + } + + if (rotate.get()) + { + Rotation.get().setRotationSilentSync(); + } + } + + @EventHandler + public void onPacketReceive(PacketEvent.Receive event) { + if (mc.player == null || mc.world == null) return; + + if (event.packet instanceof BundleS2CPacket packet) { + for (Packet packet1 : packet.getPackets()) handlePackets(packet1); + } else { + handlePackets(event.packet); + } + } + + private void handlePackets(Packet serverPacket) + { + if (timing.get() != Timing.SEQUENTIAL) return; + + if (serverPacket instanceof BlockUpdateS2CPacket packet) + { + final BlockState blockState = packet.getState(); + final BlockPos targetPos = packet.getPos(); + if (surround.contains(targetPos)) + { + if (blockState.isReplaceable() && mc.world.canPlace(DEFAULT_OBSIDIAN_STATE, targetPos, ShapeContext.absent())) + { + final int slot = getResistantBlockItem(); + if (slot == -1) + { + return; + } + placeBlock(targetPos); + } + else if (BlastResistantBlocks.isBlastResistant(blockState)) + { + packets.remove(targetPos); + } + } + } + + if (blocksPlaced > shiftTicks.get() * 2) // Give some leniency if we are getting place on + { + return; + } + + if (serverPacket instanceof ExplosionS2CPacket packet && prePlaceExplosion.get()) + { + BlockPos pos = BlockPos.ofFloored(packet.center().getX(), packet.center().getY(), packet.center().getZ()); + if (surround.contains(pos)) + { + final int slot = getResistantBlockItem(); + if (slot == -1) + { + return; + } + placeBlock(pos); + } + } + + if (serverPacket instanceof EntitySpawnS2CPacket packet + && packet.getEntityType().equals(EntityType.END_CRYSTAL) && prePlaceTick.get()) + { + for (BlockPos pos : surround) + { + if (!pos.equals(BlockPos.ofFloored(packet.getX(), packet.getY(), packet.getZ()))) + { + continue; + } + + final int slot = getResistantBlockItem(); + if (slot == -1) + { + return; + } + placeBlock(pos); + break; + } + } + } + + private void placeBlock(BlockPos pos) + { + /*Managers.INTERACT.placeBlock(pos, slot, strictDirection.get(), false, true, (state, angles) -> + { + if (rotate.get() && state) + { + Managers.ROTATION.setRotationSilent(angles[0], angles[1]); + } + });*/ + + FindItemResult obsidian = InvUtils.findInHotbar(Items.OBSIDIAN); + BlockUtils.place(pos, obsidian, rotate.get(), 0, true); + packets.put(pos, System.currentTimeMillis()); + blocksPlaced++; + } + + public void attackBlockingCrystals(List posList) + { + for (BlockPos pos : posList) + { + Entity crystalEntity = mc.world.getOtherEntities(null, new Box(pos)).stream() + .filter(e -> e instanceof EndCrystalEntity).findFirst().orElse(null); + if (crystalEntity == null) + { + continue; + } + mc.getNetworkHandler().sendPacket(PlayerInteractEntityC2SPacket.attack(crystalEntity, mc.player.isSneaking())); + mc.getNetworkHandler().sendPacket(new HandSwingC2SPacket(Hand.MAIN_HAND)); + return; + } + } + + public List getPlacementsFromSurround(List surround) + { + List placements = new ArrayList<>(); + for (BlockPos surroundPos : surround) + { + Long placed = packets.get(surroundPos); + if (shiftDelay.get() > 0.0f && placed != null && System.currentTimeMillis() - placed < shiftDelay.get() * 50.0f) + { + continue; + } + if (!mc.world.getBlockState(surroundPos).isReplaceable()) + { + continue; + } + double dist = mc.player.squaredDistanceTo(surroundPos.toCenterPos()); + if (dist > square(placeRange.get())) + { + continue; + } + + if (mc.world.canPlace(DEFAULT_OBSIDIAN_STATE, surroundPos, ShapeContext.absent())) + { + placements.add(surroundPos); + } + } + return placements; + } + + public List getSurround(PlayerEntity player) + { + List surroundBlocks = getSurroundNoDown(player); + List playerBlocks = getPlayerBlocks(player); + for (BlockPos playerPos : playerBlocks) + { + if (playerPos.equals(player.getBlockPos())) + { + continue; + } + surroundBlocks.add(playerPos.down()); + } + if (mineExtend.get()) + { + for (BlockPos surroundPos : new ArrayList<>(surroundBlocks)) + { + if (!Managers.BLOCK.isPassed(surroundPos, 0.7f)) continue; + + for (Direction direction : Direction.values()) { + if (direction == Direction.DOWN) continue; + + BlockPos blockerPos = surroundPos.offset(direction); + if (playerBlocks.contains(blockerPos) + //|| AutoMineModule.getInstance().getMiningBlock() == blockerPos) // Dont want to help our opponent surround + || Modules.get().get(GenyoAutoMine.class).getMiningBlock() == blockerPos) // Dont want to help our opponent surround + { + continue; + } + surroundBlocks.add(blockerPos); + } + } + } + + /*if (AirPlaceModule.getInstance().isEnabled() && head.get()) + { + surroundBlocks.add(mc.player.getBlockPos().up(2)); + }*/ + return surroundBlocks; + } + + public List getSurroundNoDown(PlayerEntity player) + { + return getSurroundNoDown(player, 0.0f); + } + + public List getSurroundNoDown(PlayerEntity player, float range) + { + List surroundBlocks = new ArrayList<>(); + List playerBlocks = getPlayerBlocks(player); + for (BlockPos pos : playerBlocks) + { + if (range > 0.0f && mc.player.getEyePos().squaredDistanceTo(pos.toCenterPos()) > range * range) + { + continue; + } + for (Direction dir : Direction.values()) + { + if (!dir.getAxis().isHorizontal()) + { + continue; + } + BlockPos pos1 = pos.offset(dir); + if (surroundBlocks.contains(pos1) || playerBlocks.contains(pos1)) + { + continue; + } + surroundBlocks.add(pos1); + } + } + return surroundBlocks; + } + + public List getPlayerBlocks(PlayerEntity entity) + { + BlockPos playerPos = GPositionUtils.getRoundedBlockPos(entity.getX(), entity.getY(), entity.getZ()); + final List playerBlocks = new ArrayList<>(); + if (extend.get()) + { + playerBlocks.addAll(GPositionUtils.getAllInBox(entity.getBoundingBox(), playerPos)); + } + else + { + playerBlocks.add(playerPos); + } + return playerBlocks; + } + + /*@EventListener + public void onRenderWorld(RenderWorldEvent event) + { + if (SelfTrapModule.getInstance().isEnabled()) + { + return; + } + if (render.get()) + { + RenderBuffers.preRender(); + for (Map.Entry set : fadeList.entrySet()) + { + set.getValue().setState(false); + int boxAlpha = (int) (40 * set.getValue().getFactor()); + int lineAlpha = (int) (100 * set.getValue().getFactor()); + Color boxColor = ColorsModule.getInstance().getColor(boxAlpha); + Color lineColor = ColorsModule.getInstance().getColor(lineAlpha); + RenderManager.renderBox(event.getMatrices(), set.getKey(), boxColor.getRGB()); + RenderManager.renderBoundingBox(event.getMatrices(), set.getKey(), 1.5f, lineColor.getRGB()); + } + RenderBuffers.postRender(); + + if (placements.isEmpty()) + { + return; + } + + for (BlockPos pos : placements) + { + Animation animation = new Animation(true, fadeTime.get()); + fadeList.put(pos, animation); + } + } + + fadeList.entrySet().removeIf(e -> + e.getValue().getFactor() == 0.0); + }*/ + + @EventHandler + public void onRender3D(Render3DEvent event) { + if (mc.world == null && mc.player == null) return; + + /*if (SelfTrapModule.getInstance().isEnabled()) + { + return; + }*/ + if (render.get()) + { + for (Map.Entry set : fadeList.entrySet()) + { + set.getValue().setState(false); + int boxAlpha = (int) (40 * set.getValue().getFactor()); + int lineAlpha = (int) (100 * set.getValue().getFactor()); + + Color boxColor = color.get().a(boxAlpha); + Color lineColor = color.get().a(lineAlpha); + + event.renderer.box(BlockPos.ofFloored(set.getKey().toCenterPos()), boxColor, lineColor, ShapeMode.Both, 1); + /*RenderManager.renderBox(event.getMatrices(), set.getKey(), boxColor.getRGB()); + RenderManager.renderBoundingBox(event.getMatrices(), set.getKey(), 1.5f, lineColor.getRGB());*/ + } + + if (placements.isEmpty()) + { + return; + } + + for (BlockPos pos : placements) + { + Animation animation = new Animation(true, fadeTime.get()); + fadeList.put(pos, animation); + } + } + + fadeList.entrySet().removeIf(e -> + e.getValue().getFactor() == 0.0); + } + + public boolean isPlacing() + { + return !placements.isEmpty(); + } + + public enum Timing + { + VANILLA, + SEQUENTIAL + } + + /** + * @return + */ + protected int getResistantBlockItem() + { + final Set blockSlots = new HashSet<>(); + for (final Block type : RESISTANT_BLOCKS) + { + final int slot = getBlockItemSlot(type); + if (slot != -1) + { + blockSlots.add(new BlockSlot(type, slot)); + } + } + + // Prioritize + BlockSlot slot = blockSlots.stream().filter(b -> b.block() == Blocks.OBSIDIAN).findFirst().orElse(null); + if (slot != null) + { + return slot.slot(); + } + BlockSlot slot1 = blockSlots.stream().filter(b -> b.block() == Blocks.CRYING_OBSIDIAN).findFirst().orElse(null); + if (slot1 != null) + { + return slot1.slot(); + } + BlockSlot slot2 = blockSlots.stream().filter(b -> b.block() == Blocks.ENDER_CHEST).findFirst().orElse(null); + if (slot2 != null) + { + return slot2.slot(); + } + return -1; + } + + protected int getBlockItemSlot(final Block block) { + for (int i = 0; i < 9; i++) { + final ItemStack stack = mc.player.getInventory().getStack(i); + if (stack.getItem() instanceof BlockItem blockItem + && blockItem.getBlock() == block) + { + return i; + } + } + return -1; + } + + public record BlockSlot(Block block, int slot) + { + @Override + public boolean equals(Object obj) + { + return obj instanceof BlockSlot b && b.block() == block; + } + } + + private float square(float value) { + return value*value; + } + +} diff --git a/src/main/java/com/genyo/addon/utils/player/Rotation.java b/src/main/java/com/genyo/addon/utils/player/Rotation.java new file mode 100644 index 0000000..2b4f94e --- /dev/null +++ b/src/main/java/com/genyo/addon/utils/player/Rotation.java @@ -0,0 +1,25 @@ +package com.genyo.addon.utils.player; + +import meteordevelopment.meteorclient.MeteorClient; +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; + +import static meteordevelopment.meteorclient.MeteorClient.mc; + +public class Rotation { + + private static final Rotation INSTANCE = new Rotation(); + + public static Rotation get() { + return INSTANCE; + } + + // This is only required by grim because of rotation movement checks + public void setRotationSilentSync() + { + float yaw = mc.player.getYaw(); + float pitch = mc.player.getPitch(); + //setRotation(new Rotation(MAX_VALUE, yaw, pitch, true)); + mc.getNetworkHandler().sendPacket(new PlayerMoveC2SPacket.Full(mc.player.getX(), mc.player.getY(), mc.player.getZ(), yaw, pitch, mc.player.isOnGround(), mc.player.horizontalCollision)); + } + +} diff --git a/src/main/java/com/genyo/addon/utils/world/BlastResistantBlocks.java b/src/main/java/com/genyo/addon/utils/world/BlastResistantBlocks.java index a3ffa2a..dd2c8b2 100644 --- a/src/main/java/com/genyo/addon/utils/world/BlastResistantBlocks.java +++ b/src/main/java/com/genyo/addon/utils/world/BlastResistantBlocks.java @@ -2,6 +2,7 @@ import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; import net.minecraft.block.Block; +import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.util.math.BlockPos; @@ -11,6 +12,14 @@ public class BlastResistantBlocks { + // All blocks that are resistant to explosions + private static final Set BLAST_RESISTANT = new ReferenceOpenHashSet<>(Set.of( + Blocks.OBSIDIAN, + Blocks.ANVIL, + Blocks.ENCHANTING_TABLE, + Blocks.ENDER_CHEST, + Blocks.BEACON + )); // All blocks that are unbreakable with tools in survival mode private static final Set UNBREAKABLE = new ReferenceOpenHashSet<>(Set.of( Blocks.BEDROCK, @@ -20,6 +29,31 @@ public class BlastResistantBlocks { Blocks.BARRIER )); + /** + * @param pos + * @return + */ + public static boolean isBreakable(BlockPos pos) + { + if (mc.world == null) + { + return false; + } + return isBreakable(mc.world.getBlockState(pos).getBlock()); + } + + /** + * Returns true if the {@link BlockState} of the mining block is + * breakable in survival mode + * + * @param block The block state of the mining block + * @return true if the mining block is breakable + */ + public static boolean isBreakable(Block block) + { + return !UNBREAKABLE.contains(block); + } + /** * @param pos * @return @@ -41,4 +75,36 @@ public static boolean isUnbreakable(Block block) { return UNBREAKABLE.contains(block); } + + /** + * @param pos + * @return + */ + public static boolean isBlastResistant(BlockPos pos) + { + if (mc.world == null) + { + return false; + } + return isBlastResistant(mc.world.getBlockState(pos).getBlock()); + } + + /** + * @param state + * @return + */ + public static boolean isBlastResistant(BlockState state) + { + return isBlastResistant(state.getBlock()); + } + + + /** + * @param block + * @return + */ + public static boolean isBlastResistant(Block block) + { + return BLAST_RESISTANT.contains(block); + } } From 67c63d9d81e70b7194bd396cb36a3f1520d92485 Mon Sep 17 00:00:00 2001 From: wuritz Date: Sat, 26 Jul 2025 00:28:40 +0200 Subject: [PATCH 05/14] minden lofasz + surroundban interact manager --- src/main/java/com/genyo/addon/GenyoAddon.java | 11 +- .../addon/events/ConnectScreenEvent.java | 19 + .../genyo/addon/events/DisconnectEvent.java | 4 + .../genyo/addon/events/EntityDeathEvent.java | 17 + .../genyo/addon/events/ItemDesyncEvent.java | 23 + .../genyo/addon/events/PlayerTickEvent.java | 4 + .../com/genyo/addon/events/RunTickEvent.java | 4 + .../events/network/PacketSneakingEvent.java | 7 + .../addon/managers/InventoryManager.java | 389 +++ .../com/genyo/addon/managers/Managers.java | 12 + .../genyo/addon/managers/NetworkManager.java | 189 ++ .../genyo/addon/managers/TotemManager.java | 97 + .../managers/player/InteractionManager.java | 384 +++ .../managers/player/MovementManager.java | 63 + .../managers/player/RotationCallback.java | 12 + .../addon/mixin/AccessorBundlePacket.java | 16 + .../addon/mixin/AccessorClientWorld.java | 35 + .../ClientPlayerInteractionManagerMixin.java | 45 + .../addon/mixin/MixinClientConnection.java | 25 + .../addon/mixin/MixinClientPlayerEntity.java | 25 + .../genyo/addon/mixin/MixinConnectScreen.java | 30 + .../addon/mixin/MixinItemUsageContext.java | 28 + .../addon/mixin/MixinMinecraftClient.java | 25 + .../modules/combat/GenyoAutoCrystal.java | 2161 +++++++++++++++++ .../modules/{ => combat}/GenyoAutoMine.java | 32 +- .../modules/{ => combat}/GenyoSurround.java | 4 +- .../modules/{ => combat}/GenyoSurroundV2.java | 38 +- .../addon/modules/{ => misc}/GenyoAutoEZ.java | 12 +- .../modules/{ => misc}/GenyoGoodbye.java | 3 +- .../modules/{ => misc}/GenyoSkinBlink.java | 5 +- .../modules/{ => misc}/GenyoWelcome.java | 3 +- .../{ => visual}/AngelSexHulkenberg.java | 10 +- .../addon/settings/playerlist/PLGroup.java | 2 - .../addon/utils/collection/EvictingQueue.java | 54 + .../genyo/addon/utils/entity/EntityUtil.java | 62 + .../addon/utils/math/PerSecondCounter.java | 31 + .../addon/utils/math/timer/CacheTimer.java | 113 + .../genyo/addon/utils/math/timer/Timer.java | 36 + .../addon/utils/player/EnchantmentUtil.java | 52 + .../addon/utils/player/InventoryUtil.java | 33 + .../addon/utils/player/MovementUtil.java | 18 + .../genyo/addon/utils/player/PlayerUtil.java | 75 + .../addon/utils/player/RotationUtil.java | 26 + .../addon/utils/world/ExplosionUtil.java | 527 ++++ .../genyo/addon/utils/world/SneakBlocks.java | 93 + src/main/resources/genyo.mixins.json | 19 +- 46 files changed, 4811 insertions(+), 62 deletions(-) create mode 100644 src/main/java/com/genyo/addon/events/ConnectScreenEvent.java create mode 100644 src/main/java/com/genyo/addon/events/DisconnectEvent.java create mode 100644 src/main/java/com/genyo/addon/events/EntityDeathEvent.java create mode 100644 src/main/java/com/genyo/addon/events/ItemDesyncEvent.java create mode 100644 src/main/java/com/genyo/addon/events/PlayerTickEvent.java create mode 100644 src/main/java/com/genyo/addon/events/RunTickEvent.java create mode 100644 src/main/java/com/genyo/addon/events/network/PacketSneakingEvent.java create mode 100644 src/main/java/com/genyo/addon/managers/InventoryManager.java create mode 100644 src/main/java/com/genyo/addon/managers/NetworkManager.java create mode 100644 src/main/java/com/genyo/addon/managers/TotemManager.java create mode 100644 src/main/java/com/genyo/addon/managers/player/InteractionManager.java create mode 100644 src/main/java/com/genyo/addon/managers/player/MovementManager.java create mode 100644 src/main/java/com/genyo/addon/managers/player/RotationCallback.java create mode 100644 src/main/java/com/genyo/addon/mixin/AccessorBundlePacket.java create mode 100644 src/main/java/com/genyo/addon/mixin/AccessorClientWorld.java create mode 100644 src/main/java/com/genyo/addon/mixin/MixinClientConnection.java create mode 100644 src/main/java/com/genyo/addon/mixin/MixinClientPlayerEntity.java create mode 100644 src/main/java/com/genyo/addon/mixin/MixinConnectScreen.java create mode 100644 src/main/java/com/genyo/addon/mixin/MixinItemUsageContext.java create mode 100644 src/main/java/com/genyo/addon/mixin/MixinMinecraftClient.java create mode 100644 src/main/java/com/genyo/addon/modules/combat/GenyoAutoCrystal.java rename src/main/java/com/genyo/addon/modules/{ => combat}/GenyoAutoMine.java (97%) rename src/main/java/com/genyo/addon/modules/{ => combat}/GenyoSurround.java (98%) rename src/main/java/com/genyo/addon/modules/{ => combat}/GenyoSurroundV2.java (95%) rename src/main/java/com/genyo/addon/modules/{ => misc}/GenyoAutoEZ.java (96%) rename src/main/java/com/genyo/addon/modules/{ => misc}/GenyoGoodbye.java (97%) rename src/main/java/com/genyo/addon/modules/{ => misc}/GenyoSkinBlink.java (93%) rename src/main/java/com/genyo/addon/modules/{ => misc}/GenyoWelcome.java (98%) rename src/main/java/com/genyo/addon/modules/{ => visual}/AngelSexHulkenberg.java (96%) create mode 100644 src/main/java/com/genyo/addon/utils/collection/EvictingQueue.java create mode 100644 src/main/java/com/genyo/addon/utils/entity/EntityUtil.java create mode 100644 src/main/java/com/genyo/addon/utils/math/PerSecondCounter.java create mode 100644 src/main/java/com/genyo/addon/utils/math/timer/CacheTimer.java create mode 100644 src/main/java/com/genyo/addon/utils/math/timer/Timer.java create mode 100644 src/main/java/com/genyo/addon/utils/player/EnchantmentUtil.java create mode 100644 src/main/java/com/genyo/addon/utils/player/InventoryUtil.java create mode 100644 src/main/java/com/genyo/addon/utils/player/MovementUtil.java create mode 100644 src/main/java/com/genyo/addon/utils/player/PlayerUtil.java create mode 100644 src/main/java/com/genyo/addon/utils/player/RotationUtil.java create mode 100644 src/main/java/com/genyo/addon/utils/world/ExplosionUtil.java create mode 100644 src/main/java/com/genyo/addon/utils/world/SneakBlocks.java diff --git a/src/main/java/com/genyo/addon/GenyoAddon.java b/src/main/java/com/genyo/addon/GenyoAddon.java index aa1e283..81b13b3 100644 --- a/src/main/java/com/genyo/addon/GenyoAddon.java +++ b/src/main/java/com/genyo/addon/GenyoAddon.java @@ -1,6 +1,14 @@ package com.genyo.addon; -import com.genyo.addon.modules.*; +import com.genyo.addon.modules.combat.GenyoAutoCrystal; +import com.genyo.addon.modules.combat.GenyoAutoMine; +import com.genyo.addon.modules.combat.GenyoSurround; +import com.genyo.addon.modules.combat.GenyoSurroundV2; +import com.genyo.addon.modules.misc.GenyoAutoEZ; +import com.genyo.addon.modules.misc.GenyoGoodbye; +import com.genyo.addon.modules.misc.GenyoWelcome; +import com.genyo.addon.modules.visual.AngelSexHulkenberg; +import com.genyo.addon.modules.misc.GenyoSkinBlink; import com.genyo.addon.systems.enemies.EnemiesTab; import com.genyo.addon.hud.InCombatHud; import com.genyo.addon.hud.PvPNeccessaryHud; @@ -64,6 +72,7 @@ private void initModules(Modules modules) { modules.add(new GenyoGoodbye()); modules.add(new GenyoAutoMine()); modules.add(new GenyoSurroundV2()); + modules.add(new GenyoAutoCrystal()); } private void initHUD(Hud hud) { diff --git a/src/main/java/com/genyo/addon/events/ConnectScreenEvent.java b/src/main/java/com/genyo/addon/events/ConnectScreenEvent.java new file mode 100644 index 0000000..6a71094 --- /dev/null +++ b/src/main/java/com/genyo/addon/events/ConnectScreenEvent.java @@ -0,0 +1,19 @@ +package com.genyo.addon.events; + +import net.minecraft.client.network.ServerAddress; +import net.minecraft.client.network.ServerInfo; + +public class ConnectScreenEvent { + + private static final ConnectScreenEvent INSTANCE = new ConnectScreenEvent(); + + public ServerAddress address; + public ServerInfo info; + + public static ConnectScreenEvent get(ServerAddress address, ServerInfo info) { + INSTANCE.address = address; + INSTANCE.info = info; + + return INSTANCE; + } +} diff --git a/src/main/java/com/genyo/addon/events/DisconnectEvent.java b/src/main/java/com/genyo/addon/events/DisconnectEvent.java new file mode 100644 index 0000000..f2368ec --- /dev/null +++ b/src/main/java/com/genyo/addon/events/DisconnectEvent.java @@ -0,0 +1,4 @@ +package com.genyo.addon.events; + +public class DisconnectEvent { +} diff --git a/src/main/java/com/genyo/addon/events/EntityDeathEvent.java b/src/main/java/com/genyo/addon/events/EntityDeathEvent.java new file mode 100644 index 0000000..a3fe9d7 --- /dev/null +++ b/src/main/java/com/genyo/addon/events/EntityDeathEvent.java @@ -0,0 +1,17 @@ +package com.genyo.addon.events; + +import net.minecraft.entity.LivingEntity; + +public class EntityDeathEvent { + + private static final EntityDeathEvent INSTANCE = new EntityDeathEvent(); + + public LivingEntity entity; + + public EntityDeathEvent get(LivingEntity entity) { + INSTANCE.entity = entity; + + return INSTANCE; + } + +} diff --git a/src/main/java/com/genyo/addon/events/ItemDesyncEvent.java b/src/main/java/com/genyo/addon/events/ItemDesyncEvent.java new file mode 100644 index 0000000..708f3b4 --- /dev/null +++ b/src/main/java/com/genyo/addon/events/ItemDesyncEvent.java @@ -0,0 +1,23 @@ +package com.genyo.addon.events; + +import meteordevelopment.meteorclient.events.Cancellable; +import net.minecraft.item.ItemStack; + +public class ItemDesyncEvent extends Cancellable { + + private static final ItemDesyncEvent INSTANCE = new ItemDesyncEvent(); + + public ItemStack stack; + + public static ItemDesyncEvent get(ItemStack stack) { + INSTANCE.stack = stack; + + return INSTANCE; + } + + public void setStack(ItemStack stack) + { + this.stack = stack; + } + +} diff --git a/src/main/java/com/genyo/addon/events/PlayerTickEvent.java b/src/main/java/com/genyo/addon/events/PlayerTickEvent.java new file mode 100644 index 0000000..64dc148 --- /dev/null +++ b/src/main/java/com/genyo/addon/events/PlayerTickEvent.java @@ -0,0 +1,4 @@ +package com.genyo.addon.events; + +public class PlayerTickEvent { +} diff --git a/src/main/java/com/genyo/addon/events/RunTickEvent.java b/src/main/java/com/genyo/addon/events/RunTickEvent.java new file mode 100644 index 0000000..ad8cae5 --- /dev/null +++ b/src/main/java/com/genyo/addon/events/RunTickEvent.java @@ -0,0 +1,4 @@ +package com.genyo.addon.events; + +public class RunTickEvent { +} diff --git a/src/main/java/com/genyo/addon/events/network/PacketSneakingEvent.java b/src/main/java/com/genyo/addon/events/network/PacketSneakingEvent.java new file mode 100644 index 0000000..5ab558a --- /dev/null +++ b/src/main/java/com/genyo/addon/events/network/PacketSneakingEvent.java @@ -0,0 +1,7 @@ +package com.genyo.addon.events.network; + +import meteordevelopment.meteorclient.events.Cancellable; + +public class PacketSneakingEvent extends Cancellable { + +} diff --git a/src/main/java/com/genyo/addon/managers/InventoryManager.java b/src/main/java/com/genyo/addon/managers/InventoryManager.java new file mode 100644 index 0000000..b35fcee --- /dev/null +++ b/src/main/java/com/genyo/addon/managers/InventoryManager.java @@ -0,0 +1,389 @@ +package com.genyo.addon.managers; + +import com.genyo.addon.events.EntityDeathEvent; +import com.genyo.addon.events.ItemDesyncEvent; +import com.genyo.addon.mixin.AccessorBundlePacket; +import com.genyo.addon.utils.math.timer.CacheTimer; +import com.genyo.addon.utils.math.timer.Timer; +import com.google.common.collect.Lists; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import meteordevelopment.meteorclient.events.packets.PacketEvent; +import meteordevelopment.meteorclient.events.world.TickEvent; +import meteordevelopment.orbit.EventHandler; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.network.packet.Packet; +import net.minecraft.network.packet.c2s.play.ClickSlotC2SPacket; +import net.minecraft.network.packet.c2s.play.CloseHandledScreenC2SPacket; +import net.minecraft.network.packet.c2s.play.UpdateSelectedSlotC2SPacket; +import net.minecraft.network.packet.s2c.play.BundleS2CPacket; +import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket; +import net.minecraft.network.packet.s2c.play.UpdateSelectedSlotS2CPacket; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.screen.slot.Slot; +import net.minecraft.screen.slot.SlotActionType; +import net.minecraft.util.collection.DefaultedList; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +import static meteordevelopment.meteorclient.MeteorClient.mc; + +public class InventoryManager { + + private final List swapData = new CopyOnWriteArrayList<>(); + + // The serverside selected hotbar slot. + private int slot; + + @EventHandler + public void onPacketSend(final PacketEvent.Send event) + { + if (event.packet instanceof UpdateSelectedSlotC2SPacket packet) + { + final int packetSlot = packet.getSelectedSlot(); + if (!PlayerInventory.isValidHotbarIndex(packetSlot) || slot == packetSlot) + { + event.cancel(); + return; + } + slot = packetSlot; + } + } + + @EventHandler + public void onPacketReceive(final PacketEvent.Receive event) + { + if (event.packet instanceof UpdateSelectedSlotS2CPacket packet) + { + slot = packet.slot(); + } + + // retarded packets from grim we can ignore + if (event.packet instanceof BundleS2CPacket packet) + { + List> allowedBundle = new ArrayList<>(); + for (Packet packet1 : packet.getPackets()) + { + if (packet1 instanceof ScreenHandlerSlotUpdateS2CPacket) + { + continue; + } + allowedBundle.add(packet1); + } + ((AccessorBundlePacket) packet).setIterable(allowedBundle); + } + + if (event.packet instanceof ScreenHandlerSlotUpdateS2CPacket packet) + { + int slot = packet.getSlot() - 36; + if (slot < 0 || slot > 8) + { + return; + } + + if (packet.getStack().isEmpty()) + { + return; + } + + for (PreSwapData data : swapData) + { + if (data.getSlot() != slot && data.getStarting() != slot) + { + continue; + } + + ItemStack preStack = data.getPreHolding(slot); + if (!isEqual(preStack, packet.getStack())) + { + event.cancel(); + break; + } + } + } + } + + @EventHandler + public void onItemDesync(ItemDesyncEvent event) + { + if (isDesynced()) + { + event.cancel(); + event.setStack(getServerItem()); + } + } + + @EventHandler + public void onDeath(EntityDeathEvent event) + { + if (event.entity == mc.player) + { + syncToClient(); + } + } + + @EventHandler + public void onTick(TickEvent.Pre event) + { + swapData.removeIf(PreSwapData::isPassedClearTime); + } + + /** + * Sets the server slot via a {@link UpdateSelectedSlotC2SPacket} + * + * @param barSlot the player hotbar slot 0-8 + * @apiNote Method will not do anything if the slot provided is already the server slot + * @see InventoryManager#setSlotForced(int) + */ + public void setSlot(final int barSlot) + { + if (slot != barSlot && PlayerInventory.isValidHotbarIndex(barSlot)) + { + setSlotForced(barSlot); + + final ItemStack[] hotbarCopy = new ItemStack[9]; + for (int i = 0; i < 9; i++) + { + hotbarCopy[i] = mc.player.getInventory().getStack(i); + } + swapData.add(new PreSwapData(hotbarCopy, slot, barSlot)); + } + } + + /** + * Sets the server slot via a click slot + * + * @param barSlot the player hotbar slot 0-8 + */ + public void setSlotAlt(final int barSlot) + { + if (PlayerInventory.isValidHotbarIndex(barSlot)) + { + mc.interactionManager.clickSlot(mc.player.playerScreenHandler.syncId, + barSlot + 36, slot, SlotActionType.SWAP, mc.player); + } + } + + /** + * Sets the server & client slot + * + * @param barSlot the player hotbar slot 0-8 + * @apiNote Method will not do anything if the slot provided is already the server slot + * @see InventoryManager#setSlotForced(int) + * @see InventoryManager#setSlot(int) + */ + public void setClientSlot(final int barSlot) + { + if (mc.player.getInventory().selectedSlot != barSlot + && PlayerInventory.isValidHotbarIndex(barSlot)) + { + mc.player.getInventory().selectedSlot = barSlot; + setSlotForced(barSlot); + } + } + + /** + * Sends a {@link UpdateSelectedSlotC2SPacket} without any slot checks + * + * @param barSlot the player hotbar slot 0-8 + */ + public void setSlotForced(final int barSlot) + { + Managers.NETWORK.sendPacket(new UpdateSelectedSlotC2SPacket(barSlot)); + } + + /** + * Syncs the server slot to the client slot + */ + public void syncToClient() + { + if (isDesynced()) + { + setSlotForced(mc.player.getInventory().selectedSlot); + + for (PreSwapData swapData : swapData) + { + swapData.beginClear(); + } + } + } + + public boolean isDesynced() + { + return mc.player.getInventory().selectedSlot != slot; + } + + // + public void closeScreen() + { + mc.getNetworkHandler().sendPacket(new CloseHandledScreenC2SPacket(mc.player.currentScreenHandler.syncId)); + } + + /** + * @param slot + */ + public int pickupSlot(final int slot) + { + return click(slot, 0, SlotActionType.PICKUP); + } + + public void quickMove(final int slot) + { + click(slot, 0, SlotActionType.QUICK_MOVE); + } + + /** + * @param slot + */ + public void throwSlot(final int slot) + { + click(slot, 0, SlotActionType.THROW); + } + + public int findEmptySlot() + { + for (int i = 9; i < 36; i++) + { + ItemStack stack = mc.player.getInventory().getStack(i); + if (stack.isEmpty()) + { + return i; + } + } + return -999; // throw + } + + /** + * @param button + * @param type + */ + public int click(int slot, int button, SlotActionType type) + { + if (slot < 0) + { + return -1; + } + ScreenHandler screenHandler = mc.player.currentScreenHandler; + DefaultedList defaultedList = screenHandler.slots; + int i = defaultedList.size(); + ArrayList list = Lists.newArrayListWithCapacity(i); + for (Slot slot1 : defaultedList) + { + list.add(slot1.getStack().copy()); + } + screenHandler.onSlotClick(slot, button, type, mc.player); + Int2ObjectOpenHashMap int2ObjectMap = new Int2ObjectOpenHashMap<>(); + for (int j = 0; j < i; ++j) + { + ItemStack itemStack2; + ItemStack itemStack = list.get(j); + if (ItemStack.areEqual(itemStack, itemStack2 = defaultedList.get(j).getStack())) continue; + int2ObjectMap.put(j, itemStack2.copy()); + } + mc.player.networkHandler.sendPacket(new ClickSlotC2SPacket(screenHandler.syncId, screenHandler.getRevision(), slot, button, type, screenHandler.getCursorStack().copy(), int2ObjectMap)); + return screenHandler.getRevision(); + } + + public int click2(int slot, int button, SlotActionType type) + { + if (slot < 0) + { + return -1; + } + ScreenHandler screenHandler = mc.player.currentScreenHandler; + DefaultedList defaultedList = screenHandler.slots; + int i = defaultedList.size(); + ArrayList list = Lists.newArrayListWithCapacity(i); + for (Slot slot1 : defaultedList) + { + list.add(slot1.getStack().copy()); + } + // screenHandler.onSlotClick(slot, button, type, mc.player); + Int2ObjectOpenHashMap int2ObjectMap = new Int2ObjectOpenHashMap<>(); + for (int j = 0; j < i; ++j) + { + ItemStack itemStack2; + ItemStack itemStack = list.get(j); + if (ItemStack.areEqual(itemStack, itemStack2 = defaultedList.get(j).getStack())) continue; + int2ObjectMap.put(j, itemStack2.copy()); + } + mc.player.networkHandler.sendPacket(new ClickSlotC2SPacket(screenHandler.syncId, screenHandler.getRevision(), slot, button, type, screenHandler.getCursorStack().copy(), int2ObjectMap)); + return screenHandler.getRevision(); + } + + /** + * @return + */ + public int getServerSlot() + { + return slot; + } + + public int getClientSlot() + { + return mc.player.getInventory().selectedSlot; + } + + /** + * @return + */ + public ItemStack getServerItem() + { + if (mc.player != null && getServerSlot() != -1) + { + return mc.player.getInventory().getStack(getServerSlot()); + } + return null; + } + + private boolean isEqual(ItemStack stack1, ItemStack stack2) + { + return stack1.getItem().equals(stack2.getItem()) && stack1.getName().equals(stack2.getName()); + } + + public static class PreSwapData + { + private final ItemStack[] preHotbar; + + private final int starting; + private final int swapTo; + + private Timer clearTime; + + public PreSwapData(ItemStack[] preHotbar, int start, int swapTo) + { + this.preHotbar = preHotbar; + this.starting = start; + this.swapTo = swapTo; + } + + public void beginClear() + { + clearTime = new CacheTimer(); + clearTime.reset(); + } + + public boolean isPassedClearTime() + { + return clearTime != null && clearTime.passed(300); + } + + public ItemStack getPreHolding(int i) + { + return preHotbar[i]; + } + + public int getStarting() + { + return starting; + } + + public int getSlot() + { + return swapTo; + } + } + +} diff --git a/src/main/java/com/genyo/addon/managers/Managers.java b/src/main/java/com/genyo/addon/managers/Managers.java index fb62796..de2be2d 100644 --- a/src/main/java/com/genyo/addon/managers/Managers.java +++ b/src/main/java/com/genyo/addon/managers/Managers.java @@ -1,5 +1,7 @@ package com.genyo.addon.managers; +import com.genyo.addon.managers.player.InteractionManager; +import com.genyo.addon.managers.player.MovementManager; import com.genyo.addon.render.Render3DEngine; import meteordevelopment.meteorclient.MeteorClient; @@ -8,11 +10,21 @@ public class Managers { public static final CombatManager COMBAT = new CombatManager(); public static final Render3DEngine ENGINE3D = new Render3DEngine(); public static final BlockManager BLOCK = new BlockManager(); + public static final InventoryManager INVENTORY = new InventoryManager(); + public static final NetworkManager NETWORK = new NetworkManager(); + public static final TotemManager TOTEM = new TotemManager(); + public static final InteractionManager INTERACT = new InteractionManager(); + public static final MovementManager MOVEMENT = new MovementManager(); public static void subscribe() { MeteorClient.EVENT_BUS.subscribe(COMBAT); MeteorClient.EVENT_BUS.subscribe(ENGINE3D); MeteorClient.EVENT_BUS.subscribe(BLOCK); + MeteorClient.EVENT_BUS.subscribe(INVENTORY); + MeteorClient.EVENT_BUS.subscribe(NETWORK); + MeteorClient.EVENT_BUS.subscribe(TOTEM); + MeteorClient.EVENT_BUS.subscribe(MOVEMENT); + MeteorClient.EVENT_BUS.subscribe(INTERACT); } } diff --git a/src/main/java/com/genyo/addon/managers/NetworkManager.java b/src/main/java/com/genyo/addon/managers/NetworkManager.java new file mode 100644 index 0000000..05db0b4 --- /dev/null +++ b/src/main/java/com/genyo/addon/managers/NetworkManager.java @@ -0,0 +1,189 @@ +package com.genyo.addon.managers; + +import com.genyo.addon.events.ConnectScreenEvent; +import com.genyo.addon.events.DisconnectEvent; +import com.genyo.addon.mixin.AccessorClientWorld; +import com.genyo.addon.utils.math.PerSecondCounter; +import meteordevelopment.meteorclient.events.packets.PacketEvent; +import meteordevelopment.orbit.EventHandler; +import net.minecraft.client.network.*; +import net.minecraft.network.listener.ServerPlayPacketListener; +import net.minecraft.network.packet.Packet; + +import java.util.HashSet; +import java.util.Set; + +import static meteordevelopment.meteorclient.MeteorClient.mc; + +public class NetworkManager { + + private static final Set> PACKET_CACHE = new HashSet<>(); + + private ServerAddress address; + private ServerInfo info; + + private final PerSecondCounter outgoingCounter = new PerSecondCounter(); + private final PerSecondCounter incomingCounter = new PerSecondCounter(); + + @EventHandler + public void onConnectScreen(ConnectScreenEvent event) + { + address = event.address; + info = event.info; + } + + @EventHandler + public void onDisconnect(DisconnectEvent event) + { + PACKET_CACHE.clear(); + } + + @EventHandler + public void onPacketSend(PacketEvent.Send event) + { + outgoingCounter.updateCounter(); + } + + @EventHandler + public void onPacketReceive(PacketEvent.Receive event) + { + incomingCounter.updateCounter(); + } + + public void connect(final ServerAddress address, final ServerInfo info) + { + if (mc.getNetworkHandler() == null) + { + return; + } + mc.getNetworkHandler().getConnection().connect(address.getAddress(), address.getPort(), + new ClientLoginNetworkHandler(mc.getNetworkHandler().getConnection(), mc, info, null, false, null, null, null)); + } + + /** + * @param p + */ + public void sendPacket(final Packet p) + { + if (mc.getNetworkHandler() != null) + { + PACKET_CACHE.add(p); + mc.getNetworkHandler().sendPacket(p); + } + } + + /** + * @param p + */ + public void sendSequencedPacket(final SequencedPacketCreator p) + { + if (mc.world != null) + { + PendingUpdateManager updater = + ((AccessorClientWorld) mc.world).hookGetPendingUpdateManager().incrementSequence(); + try + { + int i = updater.getSequence(); + Packet packet = p.predict(i); + sendPacket(packet); + } + catch (Throwable e) + { + e.printStackTrace(); + if (updater != null) + { + try + { + updater.close(); + } + catch (Throwable e1) + { + e1.printStackTrace(); + e.addSuppressed(e1); + } + } + throw e; + } + if (updater != null) + { + updater.close(); + } + } + } + + /** + * @return + */ + public int getClientLatency() + { + if (mc.getNetworkHandler() != null) + { + final PlayerListEntry playerEntry = + mc.getNetworkHandler().getPlayerListEntry(mc.player.getGameProfile().getId()); + if (playerEntry != null) + { + return playerEntry.getLatency(); + } + } + return 0; + } + + public ServerAddress getAddress() + { + return address; + } + + public void setAddress(ServerAddress address) + { + this.address = address; + } + + public ServerInfo getInfo() + { + return info; + } + + public void setInfo(ServerInfo info) + { + this.info = info; + } + + public boolean isCrystalPvpCC() + { + return getServerIp().contains("crystalpvp.cc"); + } + + public boolean is2b2t() + { + return getServerIp().contains("2b2t.org"); + } + + public int getOutgoingPPS() + { + return outgoingCounter.getPerSecond(); + } + + public int getIncomingPPS() + { + return incomingCounter.getPerSecond(); + } + + public String getServerIp() + { + if (info != null) + { + return info.address; + } + return "Singleplayer"; + } + + /** + * @param p + * @return + */ + public boolean isCached(Packet p) + { + return PACKET_CACHE.contains(p); + } + +} diff --git a/src/main/java/com/genyo/addon/managers/TotemManager.java b/src/main/java/com/genyo/addon/managers/TotemManager.java new file mode 100644 index 0000000..af76b5a --- /dev/null +++ b/src/main/java/com/genyo/addon/managers/TotemManager.java @@ -0,0 +1,97 @@ +package com.genyo.addon.managers; + +import com.genyo.addon.events.DisconnectEvent; +import com.genyo.addon.events.EntityDeathEvent; +import meteordevelopment.meteorclient.events.packets.PacketEvent; +import meteordevelopment.orbit.EventHandler; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityStatuses; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.network.packet.s2c.play.EntityStatusS2CPacket; + +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import static meteordevelopment.meteorclient.MeteorClient.mc; + +public class TotemManager { + + // + private final ConcurrentMap totems = new ConcurrentHashMap<>(); + + @EventHandler + public void onPacketReceive(PacketEvent.Receive event) + { + if (mc.world == null) return; + + if (event.packet instanceof EntityStatusS2CPacket packet + && packet.getStatus() == EntityStatuses.USE_TOTEM_OF_UNDYING) + { + Entity entity = packet.getEntity(mc.world); + if (entity != null && entity.isAlive()) + { + if (totems.containsKey(entity.getUuid())) + { + totems.replace(entity.getUuid(), new TotemData(System.currentTimeMillis(), + totems.get(entity.getUuid()).getPops() + 1)); + } + else + { + totems.put(entity.getUuid(), new TotemData(System.currentTimeMillis(), 1)); + } + } + } + } + + @EventHandler(priority = Integer.MIN_VALUE) + public void onRemoveEntity(EntityDeathEvent event) + { + totems.remove(event.entity.getUuid()); + } + + @EventHandler + public void onDisconnect(DisconnectEvent event) + { + totems.clear(); + } + + /** + * Returns the number of totems popped by the given {@link PlayerEntity} + * + * @param entity + * @return Ehe number of totems popped by the player + */ + public int getTotems(Entity entity) + { + return totems.getOrDefault(entity.getUuid(), new TotemData(0, 0)).getPops(); + } + + public long getLastPopTime(Entity entity) + { + return totems.getOrDefault(entity.getUuid(), new TotemData(-1, 0)).getLastPopTime(); + } + + public static class TotemData + { + private final long lastPopTime; + private final int pops; + + public TotemData(long lastPopTime, int pops) + { + this.lastPopTime = lastPopTime; + this.pops = pops; + } + + public int getPops() + { + return pops; + } + + public long getLastPopTime() + { + return lastPopTime; + } + } + +} diff --git a/src/main/java/com/genyo/addon/managers/player/InteractionManager.java b/src/main/java/com/genyo/addon/managers/player/InteractionManager.java new file mode 100644 index 0000000..bcdf854 --- /dev/null +++ b/src/main/java/com/genyo/addon/managers/player/InteractionManager.java @@ -0,0 +1,384 @@ +package com.genyo.addon.managers.player; + +import com.genyo.addon.managers.Managers; +import com.genyo.addon.utils.player.MovementUtil; +import com.genyo.addon.utils.player.RotationUtil; +import com.genyo.addon.utils.world.SneakBlocks; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket; +import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket; +import net.minecraft.network.packet.c2s.play.PlayerInteractBlockC2SPacket; +import net.minecraft.util.ActionResult; +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.util.HashSet; +import java.util.Set; + +import static meteordevelopment.meteorclient.MeteorClient.mc; + +public class InteractionManager { + + public boolean placeBlock(final BlockPos pos, + final int slot, + final boolean strictDirection, + final boolean clientSwing, + final RotationCallback rotationCallback) + { + return placeBlock(pos, slot, strictDirection, clientSwing, rotationCallback, false); + } + + public boolean placeBlock(final BlockPos pos, + final int slot, + final boolean strictDirection, + final boolean clientSwing, + final RotationCallback rotationCallback, + final boolean airPlace) + { + Direction direction = getInteractDirectionInternal(pos, strictDirection); + /*if (airPlace || AirPlaceModule.getInstance().isEnabled() && direction == null) + { + direction = Direction.DOWN; + return placeBlock(pos, direction, slot, clientSwing, AnticheatModule.getInstance().isGrim(), rotationCallback); + }*/ + if (direction == null) + { + return false; + } + final BlockPos neighbor = pos.offset(direction.getOpposite()); + return placeBlock(neighbor, direction, slot, clientSwing, false, rotationCallback); + } + + public boolean placeBlock(final BlockPos pos, + final int slot, + final boolean strictDirection, + final boolean clientSwing, + final boolean packet, + final RotationCallback rotationCallback) + { + return placeBlock(pos, slot, strictDirection, clientSwing, packet, false, rotationCallback); + } + + public boolean placeBlock(final BlockPos pos, + final int slot, + final boolean strictDirection, + final boolean clientSwing, + final boolean packet, + final boolean airPlace, + final RotationCallback rotationCallback) + { + Direction direction = getInteractDirectionInternal(pos, strictDirection); + /*if (airPlace || AirPlaceModule.getInstance().isEnabled() && direction == null) + { + direction = Direction.DOWN; + return placeBlock(pos, direction, slot, clientSwing, AnticheatModule.getInstance().isGrim(), rotationCallback); + }*/ + if (direction == null) + { + return false; + } + final BlockPos neighbor = pos.offset(direction.getOpposite()); + return placeBlock(neighbor, direction, slot, clientSwing, false, packet, rotationCallback); + } + + public boolean placeBlock(final BlockPos pos, + final Direction direction, + final int slot, + final boolean clientSwing, + final boolean grimAirPlace, + final boolean packet, + final RotationCallback rotationCallback) + { + Vec3d hitVec = pos.toCenterPos().add(new Vec3d(direction.getUnitVector()).multiply(0.5)); + return placeBlock(new BlockHitResult(hitVec, direction, pos, false), + slot, clientSwing, grimAirPlace, packet, rotationCallback); + } + + public boolean placeBlock(final BlockPos pos, + final Direction direction, + final int slot, + final boolean clientSwing, + final boolean grimAirPlace, + final RotationCallback rotationCallback) + { + Vec3d hitVec = pos.toCenterPos().add(new Vec3d(direction.getUnitVector()).multiply(0.5)); + return placeBlock(new BlockHitResult(hitVec, direction, pos, false), + slot, clientSwing, grimAirPlace, rotationCallback); + } + + public boolean placeBlock(final BlockHitResult hitResult, + final int slot, + final boolean clientSwing, + final boolean grimAirPlace, + final boolean packet, + final RotationCallback rotationCallback) + { + final boolean isSpoofing = slot != Managers.INVENTORY.getServerSlot(); + if (isSpoofing) + { + Managers.INVENTORY.setSlot(slot); + // mc.player.getInventory().selectedSlot = slot; + } + + if (grimAirPlace) + { + Managers.NETWORK.sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.SWAP_ITEM_WITH_OFFHAND, BlockPos.ORIGIN, Direction.DOWN)); + } + + final boolean isRotating = rotationCallback != null; + if (isRotating) + { + float[] angles = RotationUtil.getRotationsTo(mc.player.getEyePos(), hitResult.getPos()); + rotationCallback.handleRotation(true, angles); + } + + final boolean result = placeBlockImmediately(hitResult, grimAirPlace ? Hand.OFF_HAND : Hand.MAIN_HAND, clientSwing, packet); + if (isRotating) + { + float[] angles = RotationUtil.getRotationsTo(mc.player.getEyePos(), hitResult.getPos()); + rotationCallback.handleRotation(false, angles); + } + + if (grimAirPlace) + { + Managers.NETWORK.sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.SWAP_ITEM_WITH_OFFHAND, BlockPos.ORIGIN, Direction.DOWN)); + } + + if (isSpoofing) + { + Managers.INVENTORY.syncToClient(); + //mc.player.getInventory().selectedSlot = previousSlot; + } + + return result; + } + + public boolean placeBlock(final BlockHitResult hitResult, + final int slot, + final boolean clientSwing, + final boolean grimAirPlace, + final RotationCallback rotationCallback) + { + final boolean isSpoofing = slot != Managers.INVENTORY.getServerSlot(); + if (isSpoofing) + { + Managers.INVENTORY.setSlot(slot); + // mc.player.getInventory().selectedSlot = slot; + } + + if (grimAirPlace) + { + Managers.NETWORK.sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.SWAP_ITEM_WITH_OFFHAND, BlockPos.ORIGIN, Direction.DOWN)); + } + + final boolean isRotating = rotationCallback != null; + if (isRotating) + { + float[] angles = RotationUtil.getRotationsTo(mc.player.getEyePos(), hitResult.getPos()); + rotationCallback.handleRotation(true, angles); + } + + final boolean result = placeBlockImmediately(hitResult, grimAirPlace ? Hand.OFF_HAND : Hand.MAIN_HAND, clientSwing, true); + if (isRotating) + { + float[] angles = RotationUtil.getRotationsTo(mc.player.getEyePos(), hitResult.getPos()); + rotationCallback.handleRotation(false, angles); + } + + if (grimAirPlace) + { + Managers.NETWORK.sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.SWAP_ITEM_WITH_OFFHAND, BlockPos.ORIGIN, Direction.DOWN)); + } + + if (isSpoofing) + { + Managers.INVENTORY.syncToClient(); + //mc.player.getInventory().selectedSlot = previousSlot; + } + + return result; + } + + public boolean placeBlockImmediately(final BlockHitResult result, + final Hand hand, + final boolean clientSwing, + final boolean packet) + { + final BlockState state = mc.world.getBlockState(result.getBlockPos()); + final boolean shouldSneak = SneakBlocks.isSneakBlock(state) && !mc.player.isSneaking(); + if (shouldSneak) + { + Managers.MOVEMENT.setPacketSneaking(true); + MovementUtil.applySneak(); + } + final ActionResult actionResult = packet ? placeBlockPacket(result, hand) : placeBlockInternally(result, hand); + if (actionResult.isAccepted()) + { + if (clientSwing) + { + mc.player.swingHand(Hand.MAIN_HAND); + } + else + { + Managers.NETWORK.sendPacket(new HandSwingC2SPacket(Hand.MAIN_HAND)); + } + } + if (shouldSneak) + { + Managers.MOVEMENT.setPacketSneaking(false); + } + return actionResult.isAccepted(); + } + + private ActionResult placeBlockInternally(final BlockHitResult hitResult, + final Hand hand) + { + return mc.interactionManager.interactBlock(mc.player, hand, hitResult); + // Managers.NETWORK.sendSequencedPacket(sequence -> new PlayerInteractBlockC2SPacket(Hand.MAIN_HAND, hitResult, sequence)); + // return ((AccessorClientPlayerInteractionManager) mc.interactionManager).hookInteractBlockInternal(mc.player, Hand.MAIN_HAND, hitResult); + } + + public ActionResult placeBlockPacket(final BlockHitResult hitResult, + final Hand hand) + { + Managers.NETWORK.sendSequencedPacket(id -> new PlayerInteractBlockC2SPacket(hand, hitResult, id)); + return ActionResult.SUCCESS; + } + + public Direction getInteractDirection(final BlockPos blockPos, final boolean strictDirection) + { + Direction direction = getInteractDirectionInternal(blockPos, strictDirection); + return direction == null ? Direction.UP : direction; + } + + /** + * @param blockPos + * @param strictDirection + * @return + */ + public Direction getInteractDirectionInternal(final BlockPos blockPos, final boolean strictDirection) + { + Set validDirections = getPlaceDirectionsNCP(mc.player.getEyePos(), blockPos.toCenterPos()); + Direction interactDirection = null; + for (final Direction direction : Direction.values()) + { + final BlockState state = mc.world.getBlockState(blockPos.offset(direction)); + if (state.isAir() || !state.getFluidState().isEmpty()) + { + continue; + } + + if (state.getBlock() == Blocks.ANVIL || state.getBlock() == Blocks.CHIPPED_ANVIL + || state.getBlock() == Blocks.DAMAGED_ANVIL) + { + continue; + } + + if (strictDirection && !validDirections.contains(direction.getOpposite())) + { + continue; + } + interactDirection = direction; + break; + } + if (interactDirection == null) + { + return null; + } + return interactDirection.getOpposite(); + } + + public Direction getPlaceDirectionNCP(BlockPos blockPos, boolean visible) + { + Vec3d eyePos = new Vec3d(mc.player.getX(), mc.player.getY() + mc.player.getStandingEyeHeight(), mc.player.getZ()); + if (blockPos.getX() == eyePos.getX() && blockPos.getY() == eyePos.getY() && blockPos.getZ() == eyePos.getZ()) + { + return Direction.DOWN; + } + else + { + Set ncpDirections = getPlaceDirectionsNCP(eyePos, blockPos.toCenterPos()); + for (Direction dir : ncpDirections) + { + if (visible && !mc.world.isAir(blockPos.offset(dir))) + { + continue; + } + return dir; + } + } + return Direction.UP; + } + + public Set getPlaceDirectionsNCP(Vec3d eyePos, Vec3d blockPos) + { + return getPlaceDirectionsNCP(eyePos.x, eyePos.y, eyePos.z, blockPos.x, blockPos.y, blockPos.z); + } + + public Set getPlaceDirectionsNCP(final double x, final double y, final double z, + final double dx, final double dy, final double dz) + { + // directly from NCP src + final double xdiff = x - dx; + final double ydiff = y - dy; + final double zdiff = z - dz; + final Set dirs = new HashSet<>(6); + if (ydiff > 0.5) + { + dirs.add(Direction.UP); + } + else if (ydiff < -0.5) + { + dirs.add(Direction.DOWN); + } + else + { + dirs.add(Direction.UP); + dirs.add(Direction.DOWN); + } + if (xdiff > 0.5) + { + dirs.add(Direction.EAST); + } + else if (xdiff < -0.5) + { + dirs.add(Direction.WEST); + } + else + { + dirs.add(Direction.EAST); + dirs.add(Direction.WEST); + } + if (zdiff > 0.5) + { + dirs.add(Direction.SOUTH); + } + else if (zdiff < -0.5) + { + dirs.add(Direction.NORTH); + } + else + { + dirs.add(Direction.SOUTH); + dirs.add(Direction.NORTH); + } + return dirs; + } + + /** + * Checks if the block is within our "eye range" + * You can't place blocks above your head for any direction other than DOWN + * + * @param pos the block position + * @return if the block pos is in range of our eye y coordinate + */ + public boolean isInEyeRange(final BlockPos pos) + { + return pos.getY() > mc.player.getY() + mc.player.getStandingEyeHeight(); + } + +} diff --git a/src/main/java/com/genyo/addon/managers/player/MovementManager.java b/src/main/java/com/genyo/addon/managers/player/MovementManager.java new file mode 100644 index 0000000..6d9effd --- /dev/null +++ b/src/main/java/com/genyo/addon/managers/player/MovementManager.java @@ -0,0 +1,63 @@ +package com.genyo.addon.managers.player; + +import com.genyo.addon.events.network.PacketSneakingEvent; +import com.genyo.addon.managers.Managers; +import meteordevelopment.orbit.EventHandler; +import net.minecraft.network.packet.c2s.play.ClientCommandC2SPacket; + +import static meteordevelopment.meteorclient.MeteorClient.mc; +import static net.minecraft.network.packet.c2s.play.ClientCommandC2SPacket.Mode.PRESS_SHIFT_KEY; +import static net.minecraft.network.packet.c2s.play.ClientCommandC2SPacket.Mode.RELEASE_SHIFT_KEY; + +public class MovementManager { + + private boolean packetSneaking; + + /** + * @param y + */ + public void setMotionY(double y) + { + mc.player.setVelocity(mc.player.getVelocity().getX(), y, mc.player.getVelocity().getZ()); + } + + /** + * @param x + * @param z + */ + public void setMotionXZ(double x, double z) + { + mc.player.setVelocity(x, mc.player.getVelocity().y, z); + } + + public void setMotionX(double x) + { + mc.player.setVelocity(x, mc.player.getVelocity().y, mc.player.getVelocity().z); + } + + public void setMotionZ(double z) + { + mc.player.setVelocity(mc.player.getVelocity().x, mc.player.getVelocity().y, z); + } + + + public void setPacketSneaking(final boolean packetSneaking) + { + this.packetSneaking = packetSneaking; + if (packetSneaking) + { + Managers.NETWORK.sendPacket(new ClientCommandC2SPacket(mc.player, PRESS_SHIFT_KEY)); + } + else + { + Managers.NETWORK.sendPacket(new ClientCommandC2SPacket(mc.player, RELEASE_SHIFT_KEY)); + } + } + + @EventHandler + public void onPacketSneak(PacketSneakingEvent event) + { + event.setCancelled(packetSneaking); + } + +} diff --git a/src/main/java/com/genyo/addon/managers/player/RotationCallback.java b/src/main/java/com/genyo/addon/managers/player/RotationCallback.java new file mode 100644 index 0000000..3c685d3 --- /dev/null +++ b/src/main/java/com/genyo/addon/managers/player/RotationCallback.java @@ -0,0 +1,12 @@ +package com.genyo.addon.managers.player; + +public interface RotationCallback { + + /** + * Handles a rotation for this interaction + * + * @param state if this callback is called before or after the interaction is completed + */ + void handleRotation(final boolean state, final float[] angles); + +} diff --git a/src/main/java/com/genyo/addon/mixin/AccessorBundlePacket.java b/src/main/java/com/genyo/addon/mixin/AccessorBundlePacket.java new file mode 100644 index 0000000..f9e7e47 --- /dev/null +++ b/src/main/java/com/genyo/addon/mixin/AccessorBundlePacket.java @@ -0,0 +1,16 @@ +package com.genyo.addon.mixin; + +import net.minecraft.network.packet.BundlePacket; +import net.minecraft.network.packet.Packet; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(BundlePacket.class) +public interface AccessorBundlePacket { + + @Accessor("packets") + @Mutable + void setIterable(Iterable> iterable); + +} diff --git a/src/main/java/com/genyo/addon/mixin/AccessorClientWorld.java b/src/main/java/com/genyo/addon/mixin/AccessorClientWorld.java new file mode 100644 index 0000000..47cf1c4 --- /dev/null +++ b/src/main/java/com/genyo/addon/mixin/AccessorClientWorld.java @@ -0,0 +1,35 @@ +package com.genyo.addon.mixin; + +import net.minecraft.client.network.PendingUpdateManager; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.sound.SoundCategory; +import net.minecraft.sound.SoundEvent; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(ClientWorld.class) +public interface AccessorClientWorld { + + /** + * @param x + * @param y + * @param z + * @param event + * @param category + * @param volume + * @param pitch + * @param useDistance + * @param seed + */ + @Invoker("playSound") + void hookPlaySound(double x, double y, double z, SoundEvent event, + SoundCategory category, float volume, float pitch, + boolean useDistance, long seed); + + /** + * @return + */ + @Invoker("getPendingUpdateManager") + PendingUpdateManager hookGetPendingUpdateManager(); + +} diff --git a/src/main/java/com/genyo/addon/mixin/ClientPlayerInteractionManagerMixin.java b/src/main/java/com/genyo/addon/mixin/ClientPlayerInteractionManagerMixin.java index 276fcfb..807de1b 100644 --- a/src/main/java/com/genyo/addon/mixin/ClientPlayerInteractionManagerMixin.java +++ b/src/main/java/com/genyo/addon/mixin/ClientPlayerInteractionManagerMixin.java @@ -1,14 +1,20 @@ package com.genyo.addon.mixin; import com.genyo.addon.events.AttackBlockEvent; +import com.genyo.addon.events.ItemDesyncEvent; +import com.genyo.addon.events.network.PacketSneakingEvent; import meteordevelopment.meteorclient.MeteorClient; import net.minecraft.block.BlockState; +import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.network.ClientPlayerInteractionManager; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; 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.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import static meteordevelopment.meteorclient.MeteorClient.mc; @@ -27,4 +33,43 @@ private void hookAttackBlock(BlockPos pos, Direction direction, CallbackInfoRetu if (MeteorClient.EVENT_BUS.post(AttackBlockEvent.get(pos, state, direction)).isCancelled()) cir.cancel(); } + @Redirect( + method = "interactBlockInternal", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/network/ClientPlayerEntity;getStackInHand(Lnet/minecraft/util/Hand;)Lnet/minecraft/item/ItemStack;")) + private ItemStack hookRedirectInteractBlockInternal$getStackInHand(ClientPlayerEntity entity, Hand hand) + { + if (hand.equals(Hand.OFF_HAND)) + { + return entity.getStackInHand(hand); + } + ItemDesyncEvent itemDesyncEvent = new ItemDesyncEvent(); + MeteorClient.EVENT_BUS.post(itemDesyncEvent); + + return itemDesyncEvent.isCancelled() ? itemDesyncEvent.stack : entity.getStackInHand(Hand.MAIN_HAND); + } + + @Redirect( + method = "interactBlockInternal", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/item/ItemStack;isEmpty()Z", + ordinal = 0)) + private boolean hookRedirectInteractBlockInternal$getMainHandStack(ItemStack instance) + { + ItemDesyncEvent itemDesyncEvent = new ItemDesyncEvent(); + MeteorClient.EVENT_BUS.post(itemDesyncEvent); + + return itemDesyncEvent.isCancelled() ? itemDesyncEvent.stack.isEmpty() : instance.isEmpty(); + } + + @Redirect(method = "interactBlockInternal", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;shouldCancelInteraction()Z")) + private boolean hookRedirectInteractBlockInternal$shouldCancelInteraction(ClientPlayerEntity player) + { + PacketSneakingEvent packetSneakingEvent = new PacketSneakingEvent(); + MeteorClient.EVENT_BUS.post(packetSneakingEvent); + return player.isSneaking() || packetSneakingEvent.isCancelled(); + } + } diff --git a/src/main/java/com/genyo/addon/mixin/MixinClientConnection.java b/src/main/java/com/genyo/addon/mixin/MixinClientConnection.java new file mode 100644 index 0000000..c259825 --- /dev/null +++ b/src/main/java/com/genyo/addon/mixin/MixinClientConnection.java @@ -0,0 +1,25 @@ +package com.genyo.addon.mixin; + +import com.genyo.addon.events.DisconnectEvent; +import meteordevelopment.meteorclient.MeteorClient; +import net.minecraft.network.ClientConnection; +import net.minecraft.text.Text; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ClientConnection.class) +public class MixinClientConnection { + + /** + * @param disconnectReason + * @param ci + */ + @Inject(method = "disconnect*", at = @At(value = "HEAD")) + private void hookDisconnect(Text disconnectReason, CallbackInfo ci) + { + MeteorClient.EVENT_BUS.post(new DisconnectEvent()); + } + +} diff --git a/src/main/java/com/genyo/addon/mixin/MixinClientPlayerEntity.java b/src/main/java/com/genyo/addon/mixin/MixinClientPlayerEntity.java new file mode 100644 index 0000000..0ee5693 --- /dev/null +++ b/src/main/java/com/genyo/addon/mixin/MixinClientPlayerEntity.java @@ -0,0 +1,25 @@ +package com.genyo.addon.mixin; + +import com.genyo.addon.events.PlayerTickEvent; +import meteordevelopment.meteorclient.MeteorClient; +import net.minecraft.client.network.ClientPlayerEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ClientPlayerEntity.class) +public class MixinClientPlayerEntity { + + /** + * @param ci + */ + @Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/" + + "minecraft/client/network/AbstractClientPlayerEntity;tick()V", + shift = At.Shift.BEFORE, ordinal = 0)) + private void hookTickPre(CallbackInfo ci) + { + MeteorClient.EVENT_BUS.post(new PlayerTickEvent()); + } + +} diff --git a/src/main/java/com/genyo/addon/mixin/MixinConnectScreen.java b/src/main/java/com/genyo/addon/mixin/MixinConnectScreen.java new file mode 100644 index 0000000..136bbe3 --- /dev/null +++ b/src/main/java/com/genyo/addon/mixin/MixinConnectScreen.java @@ -0,0 +1,30 @@ +package com.genyo.addon.mixin; + +import com.genyo.addon.events.ConnectScreenEvent; +import meteordevelopment.meteorclient.MeteorClient; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.multiplayer.ConnectScreen; +import net.minecraft.client.network.CookieStorage; +import net.minecraft.client.network.ServerAddress; +import net.minecraft.client.network.ServerInfo; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ConnectScreen.class) +public abstract class MixinConnectScreen { + + /** + * @param client + * @param address + * @param info + * @param ci + */ + @Inject(method = "connect(Lnet/minecraft/client/MinecraftClient;Lnet/minecraft/client/network/ServerAddress;Lnet/minecraft/client/network/ServerInfo;Lnet/minecraft/client/network/CookieStorage;)V", at = @At(value = "HEAD")) + private void onConnect(MinecraftClient client, ServerAddress address, ServerInfo info, CookieStorage cookieStorage, CallbackInfo ci) + { + MeteorClient.EVENT_BUS.post(ConnectScreenEvent.get(address, info)); + } + +} diff --git a/src/main/java/com/genyo/addon/mixin/MixinItemUsageContext.java b/src/main/java/com/genyo/addon/mixin/MixinItemUsageContext.java new file mode 100644 index 0000000..ca80d71 --- /dev/null +++ b/src/main/java/com/genyo/addon/mixin/MixinItemUsageContext.java @@ -0,0 +1,28 @@ +package com.genyo.addon.mixin; + +import com.genyo.addon.events.ItemDesyncEvent; +import meteordevelopment.meteorclient.MeteorClient; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ItemUsageContext; +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 static meteordevelopment.meteorclient.MeteorClient.mc; + +@Mixin(ItemUsageContext.class) +public final class MixinItemUsageContext { + + @Inject(method = "getStack", at = @At("RETURN"), cancellable = true) + public void hookGetStack(CallbackInfoReturnable cir) { + ItemDesyncEvent itemDesyncEvent = new ItemDesyncEvent(); + MeteorClient.EVENT_BUS.post(itemDesyncEvent); + + if (mc.player != null && cir.getReturnValue().equals(mc.player.getMainHandStack()) && itemDesyncEvent.isCancelled()) + { + cir.setReturnValue(itemDesyncEvent.stack); + } + } +} diff --git a/src/main/java/com/genyo/addon/mixin/MixinMinecraftClient.java b/src/main/java/com/genyo/addon/mixin/MixinMinecraftClient.java new file mode 100644 index 0000000..eb8e92b --- /dev/null +++ b/src/main/java/com/genyo/addon/mixin/MixinMinecraftClient.java @@ -0,0 +1,25 @@ +package com.genyo.addon.mixin; + +import com.genyo.addon.events.RunTickEvent; +import meteordevelopment.meteorclient.MeteorClient; +import net.minecraft.client.MinecraftClient; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(MinecraftClient.class) +public abstract class MixinMinecraftClient { + + /** + * @param ci + */ + @Inject(method = "run", at = @At(value = "INVOKE", target = + "Lnet/minecraft/client/MinecraftClient;render(Z)V", shift = At.Shift.BEFORE)) + private void hookRun(CallbackInfo ci) + { + final RunTickEvent runTickEvent = new RunTickEvent(); + MeteorClient.EVENT_BUS.post(runTickEvent); + } + +} diff --git a/src/main/java/com/genyo/addon/modules/combat/GenyoAutoCrystal.java b/src/main/java/com/genyo/addon/modules/combat/GenyoAutoCrystal.java new file mode 100644 index 0000000..460bfc8 --- /dev/null +++ b/src/main/java/com/genyo/addon/modules/combat/GenyoAutoCrystal.java @@ -0,0 +1,2161 @@ +package com.genyo.addon.modules.combat; + +import com.genyo.addon.GenyoAddon; +import com.genyo.addon.events.PlayerTickEvent; +import com.genyo.addon.events.RunTickEvent; +import com.genyo.addon.managers.Managers; +import com.genyo.addon.modules.GenyoModule; +import com.genyo.addon.render.animation.Animation; +import com.genyo.addon.settings.FloatSetting; +import com.genyo.addon.utils.collection.EvictingQueue; +import com.genyo.addon.utils.entity.EntityUtil; +import com.genyo.addon.utils.math.PerSecondCounter; +import com.genyo.addon.utils.math.timer.CacheTimer; +import com.genyo.addon.utils.math.timer.Timer; +import com.genyo.addon.utils.player.InventoryUtil; +import com.genyo.addon.utils.player.PlayerUtil; +import com.genyo.addon.utils.world.BlastResistantBlocks; +import com.genyo.addon.utils.world.ExplosionUtil; +import com.google.common.collect.Lists; +import meteordevelopment.meteorclient.events.entity.EntityAddedEvent; +import meteordevelopment.meteorclient.events.game.GameLeftEvent; +import meteordevelopment.meteorclient.events.packets.PacketEvent; +import meteordevelopment.meteorclient.events.render.Render3DEvent; +import meteordevelopment.meteorclient.renderer.ShapeMode; +import meteordevelopment.meteorclient.settings.*; +import meteordevelopment.meteorclient.systems.friends.Friends; +import meteordevelopment.meteorclient.systems.modules.Modules; +import meteordevelopment.meteorclient.utils.render.color.Color; +import meteordevelopment.meteorclient.utils.render.color.SettingColor; +import meteordevelopment.orbit.EventHandler; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.ShulkerBoxBlock; +import net.minecraft.entity.Entity; +import net.minecraft.entity.ExperienceOrbEntity; +import net.minecraft.entity.ItemEntity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.decoration.EndCrystalEntity; +import net.minecraft.entity.effect.StatusEffectInstance; +import net.minecraft.entity.effect.StatusEffects; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.*; +import net.minecraft.network.packet.Packet; +import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket; +import net.minecraft.network.packet.c2s.play.PlayerInteractBlockC2SPacket; +import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket; +import net.minecraft.network.packet.c2s.play.UpdateSelectedSlotC2SPacket; +import net.minecraft.network.packet.s2c.play.*; +import net.minecraft.screen.slot.SlotActionType; +import net.minecraft.sound.SoundCategory; +import net.minecraft.sound.SoundEvents; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.hit.HitResult; +import net.minecraft.util.math.*; +import net.minecraft.world.RaycastContext; + +import java.util.*; +import java.util.concurrent.*; + +public class GenyoAutoCrystal extends GenyoModule { + + public GenyoAutoCrystal() { + super(GenyoAddon.GENYO, "genyo-auto-crystal", "neger cock neger cock neger cock"); + } + + private final SettingGroup sgGeneral = settings.getDefaultGroup(); + private final SettingGroup sgRotate = settings.createGroup("Rotate"); + private final SettingGroup sgTargets = settings.createGroup("Targets"); + private final SettingGroup sgBreak = settings.createGroup("Break"); + private final SettingGroup sgPlace = settings.createGroup("Place"); + private final SettingGroup sgDamage = settings.createGroup("Damage"); + private final SettingGroup sgRender = settings.createGroup("Render"); + + private final Setting multitask = sgGeneral.add(new BoolSetting.Builder() + .name("Allow Multitask") + .description("Allows actions while using items") + .defaultValue(false) + .build() + ); + + private final Setting whileMining = sgGeneral.add(new BoolSetting.Builder() + .name("While Mining") + .description("Allows attacking while mining blocks") + .defaultValue(false) + .build() + ); + + private final Setting targetRange = sgGeneral.add(new FloatSetting.Builder() + .name("Enemy Range") + .description("Range to search for potential enemies") + .min(1.0f) + .defaultValue(10.f) + .max(13.0f) + .build() + ); + + private final Setting instant = sgGeneral.add(new BoolSetting.Builder() + .name("Instant") + .description("Instantly attacks crystals when they spawn") + .defaultValue(false) + .build() + ); + + private final Setting sequential = sgGeneral.add(new EnumSetting.Builder() + .name("Sequential") + .description("Places a crystal after spawn") + .defaultValue(Sequential.NONE) + .build() + ); + + private final Setting idPredict = sgGeneral.add(new BoolSetting.Builder() + .name("Break Predict") + .description("Attempts to predict crystal entity ids") + .defaultValue(false) + .build() + ); + + private final Setting instantCalc = sgGeneral.add(new BoolSetting.Builder() + .name("Instant Calc") + .description("Calculates a crystal when it spawns and attacks if it meets MINIMUM requirements, this will result in non-ideal crystal attacks") + .defaultValue(false) + //.visible(() -> false) + .build() + ); + + private final Setting instantDamage = sgGeneral.add(new FloatSetting.Builder() + .name("Instant Damage") + .description("Minimum damage to attack crystals instantly") + .min(1.0f) + .defaultValue(6.0f) + .max(10.0f) + //.visible(() -> false) + .build() + ); + + private final Setting instantMax = sgGeneral.add(new BoolSetting.Builder() + .name("Instant Max") + .description("Attacks crystals instantly if they exceed the previous max attack damage (Note: This is still not a perfect check because the next tick could have better damages)") + .defaultValue(true) + .build() + ); + + private final Setting raytraceC = sgGeneral.add(new BoolSetting.Builder() + .name("Raytrace") + .description("Raytrace to crystal position") + .defaultValue(true) + .build() + ); + + private final Setting swing = sgGeneral.add(new BoolSetting.Builder() + .name("Swing") + .description("Swing hand when placing and attacking crystals") + .defaultValue(true) + .build() + ); + + private final Setting rotate = sgRotate.add(new BoolSetting.Builder() + .name("Rotate") + .description("Rotate before placing and breaking") + .defaultValue(false) + .build() + ); + + private final Setting strictRotate = sgRotate.add(new EnumSetting.Builder() + .name("Yaw Step") + .description("Rotates yaw over multiple ticks to prevent certain rotation flags in NCP") + .defaultValue(Rotate.OFF) + .build() + ); + + private final Setting rotateLimit = sgRotate.add(new IntSetting.Builder() + .name("Yaw Step Limit") + .description("Maximum yaw rotation in degrees for one tick") + .min(1) + .defaultValue(180) + .max(180) + .visible(() -> rotate.get() && strictRotate.get() != Rotate.OFF) + .build() + ); + + private final Setting players = sgTargets.add(new BoolSetting.Builder() + .name("Players") + .description("Target players") + .defaultValue(true) + .build() + ); + + private final Setting monsters = sgTargets.add(new BoolSetting.Builder() + .name("Monsters") + .description("Target monsters") + .defaultValue(false) + .build() + ); + + private final Setting neutrals = sgTargets.add(new BoolSetting.Builder() + .name("Neutrals") + .description("Target neutrals") + .defaultValue(false) + .build() + ); + + private final Setting animals = sgTargets.add(new BoolSetting.Builder() + .name("Animals") + .description("Target animals") + .defaultValue(false) + .build() + ); + + private final Setting shulkers = sgTargets.add(new BoolSetting.Builder() + .name("Shulkers") + .description("Target shulker boxes") + .defaultValue(false) + .build() + ); + + //Break + private final Setting breakSpeed = sgBreak.add(new FloatSetting.Builder() + .name("Break Speed") + .description("Speed to break crystals") + .min(0.1f) + .defaultValue(18.0f) + .max(20.0f) + .build() + ); + + private final Setting attackDelay = sgBreak.add(new FloatSetting.Builder() + .name("Attack Delay") + .description("Added delays") + .min(0.0f) + .defaultValue(0.0f) + .max(5.0f) + .build() + ); + + private final Setting attackFactorC = sgBreak.add(new IntSetting.Builder() + .name("Attack Factor") + .description("Factor of attack delay") + .min(0) + .defaultValue(0) + .max(3) + .visible(() -> attackDelay.get() > 0.0) + .build() + ); + + private final Setting attackLimit = sgBreak.add(new FloatSetting.Builder() + .name("Attack Limit") + .description("The number of attacks before considering a crystal unbreakable") + .min(0.5f) + .defaultValue(1.5f) + .max(20.0f) + .build() + ); + + private final Setting breakDelayC = sgBreak.add(new BoolSetting.Builder() + .name("Break Delay") + .description("Uses attack latency to calculate break delays") + .defaultValue(false) + .build() + ); + + private final Setting breakTimeout = sgBreak.add(new FloatSetting.Builder() + .name("Break Timeout") + .description("Time after waiting for the average break time before considering a crystal attack failed") + .min(0.0f) + .defaultValue(3.0f) + .max(10.0f) + .visible(breakDelayC::get) + .build() + ); + + private final Setting minTimeout = sgBreak.add(new FloatSetting.Builder() + .name("Min Timeout") + .description("Minimum time before considering a crystal break/place failed") + .min(0.0f) + .defaultValue(5.0f) + .max(20.0f) + .visible(breakDelayC::get) + .build() + ); + + private final Setting ticksExisted = sgBreak.add(new IntSetting.Builder() + .name("Ticks Existed") + .description("Minimum ticks alive to consider crystals for attack") + .min(0) + .defaultValue(0) + .max(10) + .build() + ); + + private final Setting breakRangeC = sgBreak.add(new FloatSetting.Builder() + .name("Break Range") + .description("Range to break crystals") + .min(0.1f) + .defaultValue(4.0f) + .max(6.0f) + .build() + ); + + private final Setting maxYOffset = sgBreak.add(new FloatSetting.Builder() + .name("Max Y Offset") + .description("Maximum crystal y-offset difference") + .min(1.0f) + .defaultValue(5.0f) + .max(10.f) + .build() + ); + + private final Setting breakWallRangeC = sgBreak.add(new FloatSetting.Builder() + .name("Break Wall Range") + .description("Range to break crystals through walls") + .min(0.1f) + .defaultValue(4.0f) + .max(6.0f) + .build() + ); + + private final Setting antiWeakness = sgBreak.add(new EnumSetting.Builder() + .name("Anti Weakness") + .description("Swap to tools before attacking crystals") + .defaultValue(Swap.OFF) + .build() + ); + + private final Setting swapDelay = sgBreak.add(new FloatSetting.Builder() + .name("Swap Penalty") + .description("Delay for attacking after swapping items which prevents NCP flags") + .min(0.0f) + .defaultValue(0.0f) + .max(10.0f) + .build() + ); + + private final Setting inhibit = sgPlace.add(new BoolSetting.Builder() + .name("Inhibit") + .description("Prevents excessive attacks") + .defaultValue(true) + .build() + ); + + private final Setting place = sgPlace.add(new BoolSetting.Builder() + .name("Place") + .description("Places crystals to damage enemies. Place settings will only function if this setting is enabled.") + .defaultValue(true) + .build() + ); + + private final Setting placeSpeed = sgPlace.add(new FloatSetting.Builder() + .name("Place Speed") + .description("Speed to place crystals") + .min(0.1f) + .defaultValue(18.0f) + .max(20.0f) + .visible(place::get) + .build() + ); + + private final Setting placeRangeC = sgPlace.add(new FloatSetting.Builder() + .name("Place Range") + .description("Range to place crystals") + .min(0.1f) + .defaultValue(4.0f) + .max(6.0f) + .visible(place::get) + .build() + ); + + private final Setting placeWallRangeC = sgPlace.add(new FloatSetting.Builder() + .name("Place Wall Range") + .description("Range to place crystals through walls") + .min(0.1f) + .defaultValue(4.0f) + .max(6.0f) + .visible(place::get) + .build() + ); + + private final Setting placeRangeEye = sgPlace.add(new BoolSetting.Builder() + .name("Place Range Eye") + .description("Calculates place ranges starting from the eye position of the player") + .defaultValue(false) + .visible(place::get) + .build() + ); + + private final Setting placeRangeCenter = sgPlace.add(new BoolSetting.Builder() + .name("Place Range Center") + .description("Calculates place ranges to the center of the block") + .defaultValue(true) + .visible(place::get) + .build() + ); + + private final Setting autoSwap = sgPlace.add(new EnumSetting.Builder() + .name("Swap") + .description("Swaps to an end crystal before placing if the player is not holding one") + .defaultValue(Swap.OFF) + .visible(place::get) + .build() + ); + + private final Setting antiSurroundC = sgPlace.add(new BoolSetting.Builder() + .name("Anti Surround") + .description("Places on mining blocks that when broken, can be placed on to damage enemies. Instantly destroys items spawned from breaking block and allows faster placing") + .defaultValue(false) + .visible(place::get) + .build() + ); + + private final Setting forcePlace = sgPlace.add(new EnumSetting.Builder() + .name("Prevent Replace") + .description("Attempts to replace crystals in surrounds") + .defaultValue(ForcePlace.NONE) + .build() + ); + + private final Setting breakValid = sgPlace.add(new BoolSetting.Builder() + .name("Strict") + .description("Only places crystals that can be attacked") + .defaultValue(false) + .visible(place::get) + .build() + ); + + private final Setting strictDirection = sgPlace.add(new BoolSetting.Builder() + .name("Strict Direction") + .description("Interacts with only visible directions when placing crystals") + .defaultValue(false) + .visible(place::get) + .build() + ); + + private final Setting placements = sgPlace.add(new EnumSetting.Builder() + .name("Placements") + .description("Version standard for placing end crystals") + .defaultValue(Placements.NATIVE) + .visible(place::get) + .build() + ); + + private final Setting minDamage = sgDamage.add(new FloatSetting.Builder() + .name("Min Damage") + .description("Minimum damage required to consider attacking or placing an end crystal") + .min(1.0f) + .defaultValue(4.0f) + .max(10.0f) + .build() + ); + + private final Setting maxLocalDamage = sgDamage.add(new FloatSetting.Builder() + .name("Max Local Damage") + .description("The maximum player damage") + .min(4.0f) + .defaultValue(12.0f) + .max(20.0f) + .build() + ); + + private final Setting assumeArmor = sgDamage.add(new BoolSetting.Builder() + .name("Assume Best Armor") + .description("Assumes Prot 0 armor is max armor") + .defaultValue(false) + .build() + ); + + private final Setting armorBreaker = sgDamage.add(new BoolSetting.Builder() + .name("Armor Breaker") + .description("Attempts to break enemy armor with crystals") + .defaultValue(true) + .build() + ); + + private final Setting armorScale = sgDamage.add(new FloatSetting.Builder() + .name("Armor Scale") + .description("Armor damage scale before attempting to break enemy armor with crystals") + .min(1.0f) + .defaultValue(5.0f) + .max(20.0f) + .visible(armorBreaker::get) + .build() + ); + + private final Setting lethalMultiplier = sgDamage.add(new FloatSetting.Builder() + .name("Lethal Multiplier") + .description("If we can kill an enemy with this many crystals, disregard damage values") + .min(0.0f) + .defaultValue(1.5f) + .max(4.0f) + .build() + ); + + private final Setting antiTotem = sgDamage.add(new BoolSetting.Builder() + .name("Lethal Totem") + .description("Predicts totems and places crystals to instantly double pop and kill the target") + .defaultValue(false) + .visible(place::get) + .build() + ); + + private final Setting lethalDamage = sgDamage.add(new BoolSetting.Builder() + .name("Lethal DamageTick") + .description("Places lethal crystals only on ticks where they damage entities") + .defaultValue(false) + .build() + ); + + private final Setting safety = sgDamage.add(new BoolSetting.Builder() + .name("Safety") + .description("Accounts for total player safety when attacking and placing crystals") + .defaultValue(true) + .build() + ); + + private final Setting safetyOverride = sgDamage.add(new BoolSetting.Builder() + .name("Safety Override") + .description("Overrides the safety checks if the crystal will kill an enemy") + .defaultValue(false) + .build() + ); + + private final Setting blockDestruction = sgDamage.add(new BoolSetting.Builder() + .name("Block Destruction") + .description("Accounts for explosion block destruction when calculating damages") + .defaultValue(false) + .build() + ); + + private final Setting selfExtrapolate = sgDamage.add(new BoolSetting.Builder() + .name("Self Extrapolate") + .description("Accounts for motion when calculating self damage") + .defaultValue(false) + .build() + ); + + private final Setting extrapolateTicks = sgDamage.add(new IntSetting.Builder() + .name("Extrapolation Ticks") + .description("Accounts for motion when calculating enemy positions, not fully accurate.") + .min(0) + .defaultValue(0) + .max(10) + .build() + ); + + // Render + + private final Setting render = sgRender.add(new BoolSetting.Builder() + .name("Render") + .description("Renders the current placement") + .defaultValue(true) + .build() + ); + + private final Setting fadeTime = sgRender.add(new IntSetting.Builder() + .name("Fade Time") + .description("Timer for the fade") + .min(0) + .defaultValue(250) + .max(1000) + .build() + ); + + private final Setting disableDeath = sgRender.add(new BoolSetting.Builder() + .name("Disable On Death") + .description("Disables during disconnect/death") + .defaultValue(false) + .build() + ); + + private final Setting debugDamage = sgRender.add(new BoolSetting.Builder() + .name("Debug Damage") + .description("Renders damage") + .defaultValue(false) + .visible(render::get) + .build() + ); + + private final Setting color = sgRender.add(new ColorSetting.Builder() + .name("Render Color") + .description("asdsadsadsadsadsa") + .defaultValue(new Color(236, 243, 122, 40)) + .build() + ); + + // + private DamageData attackCrystal; + private DamageData placeCrystal; + // + private BlockPos renderPos; + private double renderDamage; + private BlockPos renderSpawnPos; + // + private Vec3d crystalRotation; + private boolean attackRotate; + private boolean rotated; + private float[] silentRotations; + private float calculatePlaceCrystalTime = 0; + // + private static final Box FULL_CRYSTAL_BB = new Box(0.0, 0.0, 0.0, 1.0, 2.0, 1.0); + private static final Box HALF_CRYSTAL_BB = new Box(0.0, 0.0, 0.0, 1.0, 1.0, 1.0); + private final CacheTimer lastAttackTimer = new CacheTimer(); + private final Timer lastPlaceTimer = new CacheTimer(); + private final Timer lastSwapTimer = new CacheTimer(); + private final Timer autoSwapTimer = new CacheTimer(); + // default NCP config + // fight.speed: limit: 13 + // shortterm: ticks: 8 + // limitforseconds: half: 8, one: 15, two: 30, four: 60, eight: 100 + private final Deque attackLatency = new EvictingQueue<>(20); + private final Map attackPackets = + Collections.synchronizedMap(new ConcurrentHashMap<>()); + private final Map placePackets = + Collections.synchronizedMap(new ConcurrentHashMap<>()); + private final PerSecondCounter crystalCounter = new PerSecondCounter(); + private final Map fadeList = new HashMap<>(); + private long predictId; + // Antistuck + private final Map antiStuckCrystals = new HashMap<>(); + private final List stuckCrystals = new CopyOnWriteArrayList<>(); + + private final ExecutorService executor = Executors.newFixedThreadPool(2); + + /*@Override + public String getModuleData() + { + if (debug.get()) + { + return String.format("%sms, %.0f, %dms, %d".formatted( + new DecimalFormat("0.00") + .format(calculatePlaceCrystalTime / 1E6), + placeCrystal == null ? 0 : lastAttackTimer.getLastResetTime() / 1E6, + lastAttackTimer.passed(((20.0f - breakSpeed.get()) * 50.0f) + 2000.0f) ? 0 : getBreakMs(), + crystalCounter.getPerSecond())); + } + else + { + return String.format("%dms, %d", + lastAttackTimer.passed(((20.0f - breakSpeed.get()) * 50.0f) + 2000.0f) ? 0 : getBreakMs(), + crystalCounter.getPerSecond()); + } + }*/ + + @Override + public void onDeactivate() + { + renderPos = null; + attackCrystal = null; + placeCrystal = null; + crystalRotation = null; + silentRotations = null; + calculatePlaceCrystalTime = 0; + stuckCrystals.clear(); + attackPackets.clear(); + antiStuckCrystals.clear(); + placePackets.clear(); + attackLatency.clear(); + fadeList.clear(); + setStage("NONE"); + } + + @EventHandler + public void onGameLeft(GameLeftEvent event) { + if (disableDeath.get()) + { + this.toggle(); + } + else + { + this.onDeactivate(); + } + } + + @EventHandler + public void onPlayerUpdate(PlayerTickEvent event) + { + if (mc.player.isSpectator() || isSilentSwap(autoSwap.get()) && Modules.get().get(GenyoAutoMine.class).isSilentSwapping()) + { + return; + } + + + for (AntiStuckData d : stuckCrystals) + { + double dist = mc.player.squaredDistanceTo(d.pos()); + double diff = d.stuckDist() - dist; + if (diff > 0.5) + { + stuckCrystals.remove(d); + } + } + + if (mc.player.isUsingItem() && mc.player.getActiveHand() == Hand.MAIN_HAND + || mc.options.attackKey.isPressed() || PlayerUtil.isHotbarKeysPressed()) + { + autoSwapTimer.reset(); + } + renderPos = null; + ArrayList entities = Lists.newArrayList(mc.world.getEntities()); + List blocks = getSphere(placeRangeEye.get() ? mc.player.getEyePos() : mc.player.getPos()); + long timePre = System.nanoTime(); + if (place.get()) + { + placeCrystal = calculatePlaceCrystal(blocks, entities); + } + attackCrystal = calculateAttackCrystal(entities); + if (attackCrystal == null) + { + if (placeCrystal != null) + { + EndCrystalEntity crystalEntity = intersectingCrystalCheck(placeCrystal.getDamageData()); + if (crystalEntity != null) + { + GenyoAddon.LOG.info("fewkjkfewf"); + + double self = ExplosionUtil.getDamageTo(mc.player, crystalEntity.getPos(), + blockDestruction.get(), selfExtrapolate.get() ? extrapolateTicks.get() : 0, false); + if (!safety.get() || !playerDamageCheck(self)) + { + attackCrystal = new DamageData<>(crystalEntity, placeCrystal.getAttackTarget(), + placeCrystal.getDamage(), self, crystalEntity.getBlockPos().down(), false); + } + } + } + calculatePlaceCrystalTime = System.nanoTime() - timePre; + } + + if (inhibit.get() && attackCrystal != null + && attackPackets.containsKey(attackCrystal.getDamageData().getId())) + { + float delay; + if (attackDelay.get() > 0.0) + { + float attackFactor = 50.0f / Math.max(1.0f, attackFactorC.get()); + delay = attackDelay.get() * attackFactor; + } + else + { + delay = 1000.0f - breakSpeed.get() * 50.0f; + } + lastAttackTimer.setDelay(delay + 100.0f); + attackPackets.remove(attackCrystal.getDamageData().getId()); + } + + float breakDelay = getBreakDelay(); + if (breakDelayC.get()) + { + breakDelay = Math.max(minTimeout.get() * 50.0f, getBreakMs() + breakTimeout.get() * 50.0f); + } + attackRotate = attackCrystal != null && attackDelay.get() <= 0.0 && lastAttackTimer.passed(breakDelay); + if (attackCrystal != null) + { + crystalRotation = attackCrystal.damageData.getPos(); + } + else if (placeCrystal != null) + { + crystalRotation = placeCrystal.damageData.toCenterPos().add(0.0, 0.5, 0.0); + } + /*if (rotate.get() && crystalRotation != null && (placeCrystal == null || canHoldCrystal())) + { + float[] rotations = RotationUtil.getRotationsTo(mc.player.getEyePos(), crystalRotation); + if (strictRotate.get() == Rotate.FULL || strictRotate.get() == Rotate.SEMI && attackRotate) + { + float yaw; + float serverYaw = Managers.ROTATION.getWrappedYaw(); + float diff = serverYaw - rotations[0]; + float diff1 = Math.abs(diff); + if (diff1 > 180.0f) + { + diff += diff > 0.0f ? -360.0f : 360.0f; + } + int dir = diff > 0.0f ? -1 : 1; + float deltaYaw = dir * rotateLimit.get(); + if (diff1 > rotateLimit.get()) + { + yaw = serverYaw + deltaYaw; + rotated = false; + } + else + { + yaw = rotations[0]; + rotated = true; + crystalRotation = null; + } + rotations[0] = yaw; + } + else + { + rotated = true; + crystalRotation = null; + } + setRotation(rotations[0], rotations[1]); + } + else + { + silentRotations = null; + } + if (isRotationBlocked() || !rotated && rotate.get()) + { + return; + }*/ +// if (rotateSilent.get() && silentRotations != null) { +// setRotationSilent(silentRotations[0], silentRotations[1]); +// } + final Hand hand = getCrystalHand(); + if (attackCrystal != null) + { + // ChatUtil.clientSendMessage("yaw: " + rotations[0] + ", pitch: " + rotations[1]); + if (attackRotate) + { + // ChatUtil.clientSendMessage("break range:" + Math.sqrt(mc.player.getEyePos().squaredDistanceTo(attackCrystal.getDamageData().getPos()))); + attackCrystal(attackCrystal.getDamageData(), hand); + setStage("ATTACKING"); + lastAttackTimer.reset(); + } + } + boolean placeRotate = lastPlaceTimer.passed(1000.0f - placeSpeed.get() * 50.0f); + if (placeCrystal != null) + { + renderPos = placeCrystal.getDamageData(); + renderDamage = placeCrystal.getDamage(); + if (placeRotate) + { + // ChatUtil.clientSendMessage("place range:" + Math.sqrt(mc.player.getEyePos().squaredDistanceTo(placeCrystal.getDamageData().toCenterPos()))); + placeCrystal(placeCrystal.getDamageData(), hand); + setStage("PLACING"); + lastPlaceTimer.reset(); + } + } + } + + @EventHandler + public void onRunTick(RunTickEvent event) + { + if (mc.player == null) return; + + final Hand hand = getCrystalHand(); + if (attackDelay.get() > 0.0) + { + float attackFactor = 50.0f / Math.max(1.0f, attackFactorC.get()); + if (attackCrystal != null && lastAttackTimer.passed(attackDelay.get() * attackFactor)) + { + attackCrystal(attackCrystal.getDamageData(), hand); + lastAttackTimer.reset(); + } + } + } + + @EventHandler + public void onRender3D(Render3DEvent event) + { + if (render.get()) + { + BlockPos renderPos1 = null; + double factor = 0.0f; + for (Map.Entry set : fadeList.entrySet()) + { + if (set.getKey() == renderPos) + { + continue; + } + + if (set.getValue().getFactor() > factor) + { + renderPos1 = set.getKey(); + factor = set.getValue().getFactor(); + } + + set.getValue().setState(false); + int boxAlpha = (int) (40 * set.getValue().getFactor()); + int lineAlpha = (int) (100 * set.getValue().getFactor()); + + Color boxColor = color.get(); + Color lineColor = color.get(); + + event.renderer.box(set.getKey(), boxColor, lineColor, ShapeMode.Both, 0); + } + + /*if (debugDamage.get() && renderPos1 != null) + { + RenderManager.renderSign(String.format("%.1f", renderDamage), + renderPos1.toCenterPos(), new Color(255, 255, 255, (int) (255.0f * factor)).getRGB()); + }*/ + + fadeList.entrySet().removeIf(e -> + e.getValue().getFactor() == 0.0); + + if (renderPos != null && isHoldingCrystal()) + { + Animation animation = new Animation(true, fadeTime.get()); + fadeList.put(renderPos, animation); + } + } + } + + @EventHandler(priority = Integer.MAX_VALUE) + public void onPacketReceive(PacketEvent.Receive event) + { + if (mc.player == null || mc.world == null) return; + + if (event.packet instanceof BundleS2CPacket packet) + { + for (Packet packet1 : packet.getPackets()) + { + handleServerPackets(packet1); + } + } + else + { + handleServerPackets(event.packet); + } + } + + private void handleServerPackets(Packet serverPacket) + { + if (serverPacket instanceof ExplosionS2CPacket packet) + { + for (Entity entity : Lists.newArrayList(mc.world.getEntities())) + { + if (entity instanceof EndCrystalEntity && entity.squaredDistanceTo(packet.center().getX(), packet.center().getY(), packet.center().getZ()) < 144.0) + { + mc.executeSync(() -> mc.world.removeEntity(entity.getId(), Entity.RemovalReason.DISCARDED)); + antiStuckCrystals.remove(entity.getId()); + Long attackTime = attackPackets.remove(entity.getId()); + if (attackTime != null) + { + attackLatency.add(System.currentTimeMillis() - attackTime); + } + } + } + } + + if (serverPacket instanceof PlaySoundS2CPacket packet) + { + if (packet.getSound().value() == SoundEvents.ENTITY_GENERIC_EXPLODE.value() && packet.getCategory() == SoundCategory.BLOCKS) + { + for (Entity entity : Lists.newArrayList(mc.world.getEntities())) + { + if (entity instanceof EndCrystalEntity && entity.squaredDistanceTo(packet.getX(), packet.getY(), packet.getZ()) < 144.0) + { + mc.executeSync(() -> mc.world.removeEntity(entity.getId(), Entity.RemovalReason.DISCARDED)); + antiStuckCrystals.remove(entity.getId()); + Long attackTime = attackPackets.remove(entity.getId()); + if (attackTime != null) + { + attackLatency.add(System.currentTimeMillis() - attackTime); + } + } + } + } + } + + if (serverPacket instanceof EntitiesDestroyS2CPacket packet) + { + for (int id : packet.getEntityIds()) + { + antiStuckCrystals.remove(id); + Long attackTime = attackPackets.remove(id); + if (attackTime != null) + { + attackLatency.add(System.currentTimeMillis() - attackTime); + } + } + } + + if (serverPacket instanceof ExperienceOrbSpawnS2CPacket packet && packet.getEntityId() > predictId) + { + predictId = packet.getEntityId(); + } + + if (serverPacket instanceof EntitySpawnS2CPacket packet && packet.getEntityId() > predictId) + { + predictId = packet.getEntityId(); + } + } + + @EventHandler + public void onEntityAdded(EntityAddedEvent event) + { + if (!(event.entity instanceof EndCrystalEntity crystalEntity)) return; + + + Vec3d crystalPos = crystalEntity.getPos(); + BlockPos blockPos = BlockPos.ofFloored(crystalPos.add(0.0, -1.0, 0.0)); + renderSpawnPos = blockPos; + Long time = placePackets.remove(blockPos); + attackRotate = time != null; + if (attackRotate) + { + crystalCounter.updateCounter(); + } + if (!instant.get()) + { + return; + } + if (attackRotate) + { + final Hand hand = getCrystalHand(); + attackInternal(crystalEntity, hand); + setStage("ATTACKING"); + lastAttackTimer.reset(); + if (sequential.get() == Sequential.NORMAL) + { + placeSequentialCrystal(hand); + } + } + else if (instantCalc.get()) + { + if (attackRangeCheck(crystalPos)) + { + return; + } + double selfDamage = ExplosionUtil.getDamageTo(mc.player, crystalPos, + blockDestruction.get(), selfExtrapolate.get() ? extrapolateTicks.get() : 0, false); + if (playerDamageCheck(selfDamage)) + { + return; + } + for (Entity entity : mc.world.getEntities()) + { + if (entity == null || !entity.isAlive() || entity == mc.player + || !isValidTarget(entity) + || (entity instanceof PlayerEntity && Friends.get().isFriend((PlayerEntity) entity))) + { + continue; + } + double crystalDist = crystalPos.squaredDistanceTo(entity.getPos()); + if (crystalDist > 144.0f) + { + continue; + } + double dist = mc.player.squaredDistanceTo(entity); + if (dist > targetRange.get() * targetRange.get()) + { + continue; + } + + double damage = ExplosionUtil.getDamageTo(entity, crystalPos, blockDestruction.get(), + extrapolateTicks.get(), assumeArmor.get()); + // TODO: Test this + DamageData data = new DamageData<>(crystalEntity, + entity, damage, selfDamage, crystalEntity.getBlockPos().down(), false); + attackRotate = damage > instantDamage.get() || attackCrystal != null + && damage >= attackCrystal.getDamage() && instantMax.get() + || entity instanceof LivingEntity entity1 && isCrystalLethalTo(data, entity1); + if (attackRotate) + { + final Hand hand = getCrystalHand(); + attackInternal(crystalEntity, hand); + setStage("ATTACKING"); + lastAttackTimer.reset(); + if (sequential.get() == Sequential.NORMAL) + { + placeSequentialCrystal(hand); + } + break; + } + } + } + } + + @EventHandler + public void onPacketSend(PacketEvent.Send event) + { + if (mc.player == null) return; + + + if (event.packet instanceof UpdateSelectedSlotC2SPacket) + { + lastSwapTimer.reset(); + } + } + + public boolean isAttacking() + { + return attackCrystal != null; + } + + public boolean isPlacing() + { + return placeCrystal != null && isHoldingCrystal(); + } + + public void attackCrystal(EndCrystalEntity entity, Hand hand) + { + if (attackCheckPre(hand)) + { + return; + } + StatusEffectInstance weakness = mc.player.getStatusEffect(StatusEffects.WEAKNESS); + StatusEffectInstance strength = mc.player.getStatusEffect(StatusEffects.STRENGTH); + if (weakness != null && (strength == null || weakness.getAmplifier() > strength.getAmplifier())) + { + int slot = -1; + for (int i = 0; i < 9; ++i) + { + ItemStack stack = mc.player.getInventory().getStack(i); + if (!stack.isEmpty() && (stack.getItem() instanceof SwordItem + || stack.getItem() instanceof AxeItem + || stack.getItem() instanceof PickaxeItem)) + { + slot = i; + break; + } + } + if (slot != -1) + { + boolean canSwap = slot != Managers.INVENTORY.getServerSlot() && (antiWeakness.get() != Swap.NORMAL || autoSwapTimer.passed(500)); + if (antiWeakness.get() != Swap.OFF && canSwap) + { + if (antiWeakness.get() == Swap.SILENT_ALT) + { + mc.interactionManager.clickSlot(mc.player.playerScreenHandler.syncId, + slot + 36, mc.player.getInventory().selectedSlot, SlotActionType.SWAP, mc.player); + } + else if (antiWeakness.get() == Swap.SILENT) + { + Managers.INVENTORY.setSlot(slot); + } + else + { + Managers.INVENTORY.setClientSlot(slot); + } + } + attackInternal(entity, Hand.MAIN_HAND); + if (canSwap) + { + if (antiWeakness.get() == Swap.SILENT_ALT) + { + mc.interactionManager.clickSlot(mc.player.playerScreenHandler.syncId, + slot + 36, mc.player.getInventory().selectedSlot, SlotActionType.SWAP, mc.player); + } + else if (antiWeakness.get() == Swap.SILENT) + { + Managers.INVENTORY.syncToClient(); + } + } + + if (sequential.get() == Sequential.STRICT) + { + placeSequentialCrystal(hand); + } + } + } + else + { + attackInternal(entity, hand); + if (sequential.get() == Sequential.STRICT) + { + placeSequentialCrystal(hand); + } + } + } + + private void attackInternal(EndCrystalEntity crystalEntity, Hand hand) + { + attackInternal(crystalEntity.getId(), hand); + } + + private void attackInternal(int crystalEntity, Hand hand) + { + hand = hand != null ? hand : Hand.MAIN_HAND; + EndCrystalEntity entity2 = new EndCrystalEntity(mc.world, 0.0, 0.0, 0.0); + entity2.setId(crystalEntity); + PlayerInteractEntityC2SPacket packet = PlayerInteractEntityC2SPacket.attack(entity2, mc.player.isSneaking()); + mc.getNetworkHandler().sendPacket(packet); + if (swing.get()) + { + mc.player.swingHand(hand); + } + else + { + mc.getNetworkHandler().sendPacket(new HandSwingC2SPacket(hand)); + } + + attackPackets.put(crystalEntity, System.currentTimeMillis()); + Integer antiStuckCount = antiStuckCrystals.get(crystalEntity); + if (antiStuckCount != null) + { + antiStuckCrystals.replace(crystalEntity, antiStuckCount + 1); + } + else + { + antiStuckCrystals.put(crystalEntity, 1); + } + } + + private void placeSequentialCrystal(Hand hand) + { + if (placeCrystal == null) + { + return; + } + int latency = Managers.NETWORK.getClientLatency(); + if (!Managers.NETWORK.is2b2t() || latency >= 50) + { + placeCrystal(placeCrystal.getBlockPos(), hand); + } + } + + private void placeCrystal(BlockPos blockPos, Hand hand) + { + /*if (isRotationBlocked() || !rotated && rotate.get()) + { + return; + }*/ + + placeCrystal(blockPos, hand, true); + } + + public void placeCrystal(BlockPos blockPos, Hand hand, boolean checkPlacement) + { + if (checkPlacement && checkCanUseCrystal()) + { + return; + } + Direction sidePlace = getPlaceDirection(blockPos); + BlockHitResult result = new BlockHitResult(blockPos.toCenterPos(), sidePlace, blockPos, false); + if (autoSwap.get() != Swap.OFF && hand != Hand.OFF_HAND && getCrystalHand() == null) + { + if (isSilentSwap(autoSwap.get()) && InventoryUtil.count(Items.END_CRYSTAL) == 0) + { + return; + } + int crystalSlot = getCrystalSlot(); + if (crystalSlot != -1) + { + boolean canSwap = crystalSlot != Managers.INVENTORY.getServerSlot() && (autoSwap.get() != Swap.NORMAL || autoSwapTimer.passed(500)); + if (canSwap) + { + if (autoSwap.get() == Swap.SILENT_ALT) + { + mc.interactionManager.clickSlot(mc.player.playerScreenHandler.syncId, + crystalSlot + 36, mc.player.getInventory().selectedSlot, SlotActionType.SWAP, mc.player); + } + else if (autoSwap.get() == Swap.SILENT) + { + Managers.INVENTORY.setSlot(crystalSlot); + } + else + { + Managers.INVENTORY.setClientSlot(crystalSlot); + } + } + placeInternal(result, Hand.MAIN_HAND); + placePackets.put(blockPos, System.currentTimeMillis()); + if (canSwap) + { + if (autoSwap.get() == Swap.SILENT_ALT) + { + mc.interactionManager.clickSlot(mc.player.playerScreenHandler.syncId, + crystalSlot + 36, mc.player.getInventory().selectedSlot, SlotActionType.SWAP, mc.player); + } + else if (autoSwap.get() == Swap.SILENT) + { + Managers.INVENTORY.syncToClient(); + } + } + } + } + else if (isHoldingCrystal()) + { + placeInternal(result, hand); + placePackets.put(blockPos, System.currentTimeMillis()); + } + } + + private void placeInternal(BlockHitResult result, Hand hand) + { + if (hand == null) + { + return; + } + Managers.NETWORK.sendSequencedPacket(id -> new PlayerInteractBlockC2SPacket(hand, result, id)); + if (swing.get()) + { + mc.player.swingHand(hand); + } + else + { + Managers.NETWORK.sendPacket(new HandSwingC2SPacket(hand)); + } + + // Entity ID predict + if (idPredict.get()) + { + //boolean flag = AutoXPModule.getInstance().isEnabled() || mc.player.isUsingItem() && mc.player.getStackInHand(mc.player.getActiveHand()).getItem() instanceof ExperienceBottleItem; + boolean flag = mc.player.isUsingItem() && mc.player.getStackInHand(mc.player.getActiveHand()).getItem() instanceof ExperienceBottleItem; + int id = (int) (predictId + 1); + if (flag || attackPackets.containsKey(id)) + { + return; + } + Entity entity = mc.world.getEntityById(id); + if (entity != null && !(entity instanceof EndCrystalEntity)) + { + return; + } + EndCrystalEntity entity2 = new EndCrystalEntity(mc.world, 0.0, 0.0, 0.0); + entity2.setId(id); + PlayerInteractEntityC2SPacket packet = PlayerInteractEntityC2SPacket.attack(entity2, false); + Managers.NETWORK.sendPacket(packet); + Managers.NETWORK.sendPacket(new HandSwingC2SPacket(Hand.MAIN_HAND)); + attackPackets.put(id, System.currentTimeMillis()); + } + } + + private boolean isSilentSwap(Swap swap) + { + return swap == Swap.SILENT || swap == Swap.SILENT_ALT; + } + + private int getCrystalSlot() + { + int slot = -1; + for (int i = 0; i < 9; i++) + { + ItemStack stack = mc.player.getInventory().getStack(i); + if (stack.getItem() instanceof EndCrystalItem) + { + slot = i; + break; + } + } + return slot; + } + + private Direction getPlaceDirection(BlockPos blockPos) + { + int x = blockPos.getX(); + int y = blockPos.getY(); + int z = blockPos.getZ(); + if (strictDirection.get()) + { + if (mc.player.getY() >= blockPos.getY()) + { + return Direction.UP; + } + BlockHitResult result = mc.world.raycast(new RaycastContext( + mc.player.getEyePos(), new Vec3d(x + 0.5, y + 0.5, z + 0.5), + RaycastContext.ShapeType.OUTLINE, + RaycastContext.FluidHandling.NONE, mc.player)); + if (result != null && result.getType() == HitResult.Type.BLOCK) + { + return result.getSide(); + } + } + else + { + if (mc.world.isInBuildLimit(blockPos)) + { + return Direction.DOWN; + } + BlockHitResult result = mc.world.raycast(new RaycastContext( + mc.player.getEyePos(), new Vec3d(x + 0.5, y + 0.5, z + 0.5), + RaycastContext.ShapeType.OUTLINE, + RaycastContext.FluidHandling.NONE, mc.player)); + if (result != null && result.getType() == HitResult.Type.BLOCK) + { + return result.getSide(); + } + } + return Direction.UP; + } + + private DamageData calculateAttackCrystal(List entities) + { + if (entities.isEmpty()) + { + return null; + } + + final List> validData = new ArrayList<>(); + + DamageData data = null; + for (Entity crystal : entities) + { + if (!(crystal instanceof EndCrystalEntity crystal1) || !crystal.isAlive() + || stuckCrystals.stream().anyMatch(d -> d.id() == crystal.getId())) + { + continue; + } + Long time = attackPackets.get(crystal.getId()); + boolean attacked = time != null && time < getBreakMs(); + if ((crystal.age < ticksExisted.get() || attacked) && inhibit.get()) + { + continue; + } + if (attackRangeCheck(crystal1)) + { + continue; + } + double selfDamage = ExplosionUtil.getDamageTo(mc.player, crystal.getPos(), + blockDestruction.get(), selfExtrapolate.get() ? extrapolateTicks.get() : 0, false); + boolean unsafeToPlayer = playerDamageCheck(selfDamage); + if (unsafeToPlayer && !safetyOverride.get()) + { + continue; + } + for (Entity entity : entities) + { + if (entity == null || !entity.isAlive() || entity == mc.player + || !isValidTarget(entity) + || (entity instanceof PlayerEntity && Friends.get().isFriend((PlayerEntity) entity))) + { + continue; + } + double crystalDist = crystal.squaredDistanceTo(entity); + if (crystalDist > 144.0f) + { + continue; + } + double dist = mc.player.squaredDistanceTo(entity); + if (dist > targetRange.get() * targetRange.get()) + { + continue; + } + + boolean antiSurround = false; + if (antiSurroundC.get() && entity instanceof PlayerEntity player + && !BlastResistantBlocks.isUnbreakable(player.getBlockPos())) + { + Set miningPositions = new HashSet<>(); + BlockPos miningBlock = Modules.get().get(GenyoAutoMine.class).getMiningBlock(); + if (Modules.get().get(GenyoAutoMine.class).isActive() && miningBlock != null) + { + miningPositions.add(miningBlock); + } + if (Managers.BLOCK.getMines(0.75f).contains(player.getBlockPos().up())) + { + miningPositions.add(player.getBlockPos().up()); + } + for (BlockPos miningBlockPos : miningPositions) + { + if (!Modules.get().get(GenyoSurroundV2.class).getSurroundNoDown(player).contains(miningBlockPos)) + { + continue; + } + for (Direction direction : Direction.values()) + { + BlockPos pos1 = miningBlockPos.offset(direction); + if (crystal.getBlockPos().equals(pos1.down())) + { + antiSurround = true; + } + } + } + } + + double damage = ExplosionUtil.getDamageTo(entity, crystal.getPos(), blockDestruction.get(), + extrapolateTicks.get(), assumeArmor.get()); + if (checkOverrideSafety(unsafeToPlayer, damage, entity)) + { + continue; + } + + DamageData currentData = new DamageData<>(crystal1, entity, + damage, selfDamage, crystal1.getBlockPos().down(), antiSurround); + validData.add(currentData); + if (data == null || damage > data.getDamage()) + { + data = currentData; + } + } + } + if (data == null || targetDamageCheck(data)) + { + if (antiSurroundC.get()) + { + return validData.stream() + .filter(DamageData::isAntiSurround) + .min(Comparator.comparingDouble(d -> mc.player.squaredDistanceTo(d.getBlockPos().toCenterPos()))) + .orElse(null); + } + return null; + } + return data; + } + + private boolean attackRangeCheck(EndCrystalEntity entity) + { + return attackRangeCheck(entity.getPos()); + } + + /** + * @param entityPos + * @return + */ + private boolean attackRangeCheck(Vec3d entityPos) + { + double breakRange = breakRangeC.get(); + double breakWallRange = breakWallRangeC.get(); + Vec3d playerPos = mc.player.getEyePos(); + double dist = playerPos.squaredDistanceTo(entityPos); + if (dist > breakRange * breakRange) + { + return true; + } + double yOff = Math.abs(entityPos.getY() - mc.player.getY()); + if (yOff > maxYOffset.get()) + { + return true; + } + BlockHitResult result = mc.world.raycast(new RaycastContext( + playerPos, entityPos, RaycastContext.ShapeType.COLLIDER, + RaycastContext.FluidHandling.NONE, mc.player)); + return result.getType() != HitResult.Type.MISS && dist > breakWallRange * breakWallRange; + } + + private DamageData calculatePlaceCrystal(List placeBlocks, List entities) + { + if (placeBlocks.isEmpty() || entities.isEmpty()) + { + return null; + } + + final List> validData = new ArrayList<>(); + + DamageData data = null; + for (BlockPos pos : placeBlocks) + { + if (!canUseCrystalOnBlock(pos) || placeRangeCheck(pos) || intersectingAntiStuckCheck(pos)) + { + continue; + } + double selfDamage = ExplosionUtil.getDamageTo(mc.player, crystalDamageVec(pos), + blockDestruction.get(), selfExtrapolate.get() ? extrapolateTicks.get() : 0, false); + boolean unsafeToPlayer = playerDamageCheck(selfDamage); + if (unsafeToPlayer && !safetyOverride.get()) + { + continue; + } + for (Entity entity : entities) + { + if (entity == null || !entity.isAlive() || entity == mc.player + || !isValidTarget(entity) + || (entity instanceof PlayerEntity && Friends.get().isFriend((PlayerEntity) entity))) + { + continue; + } + double blockDist = pos.getSquaredDistance(entity.getPos()); + if (blockDist > 144.0f) + { + continue; + } + double dist = mc.player.squaredDistanceTo(entity); + if (dist > targetRange.get() * targetRange.get()) + { + continue; + } + + boolean antiSurround = false; + if (antiSurroundC.get() && entity instanceof PlayerEntity player + && !BlastResistantBlocks.isUnbreakable(player.getBlockPos())) + { + Set miningPositions = new HashSet<>(); + BlockPos miningBlock = Modules.get().get(GenyoAutoMine.class).getMiningBlock(); + if (Modules.get().get(GenyoAutoMine.class).isActive() && miningBlock != null) + { + miningPositions.add(miningBlock); + } + if (Managers.BLOCK.getMines(0.75f).contains(player.getBlockPos().up())) + { + miningPositions.add(player.getBlockPos().up()); + } + for (BlockPos miningBlockPos : miningPositions) + { + if (!Modules.get().get(GenyoSurroundV2.class).getSurroundNoDown(player).contains(miningBlockPos)) + { + continue; + } + for (Direction direction : Direction.values()) + { + BlockPos pos1 = miningBlockPos.offset(direction); + if (pos.equals(pos1.down())) + { + antiSurround = true; + } + } + } + } + + double damage; + damage = ExplosionUtil.getDamageTo(entity, crystalDamageVec(pos), blockDestruction.get(), + extrapolateTicks.get(), assumeArmor.get()); + if (checkOverrideSafety(unsafeToPlayer, damage, entity)) + { + continue; + } + + DamageData currentData = new DamageData<>(pos, entity, + damage, selfDamage, antiSurround); + validData.add(currentData); + if (data == null || damage > data.getDamage()) + { + data = currentData; + } + } + } + if (data == null || targetDamageCheck(data)) + { + if (antiSurroundC.get()) + { + return validData.stream() + .filter(DamageData::isAntiSurround) + .min(Comparator.comparingDouble(d -> mc.player.squaredDistanceTo(d.getBlockPos().toCenterPos()))) + .orElse(null); + } + return null; + } + return data; + } + + /** + * @param pos + * @return + */ + private boolean placeRangeCheck(BlockPos pos) + { + double placeRange = placeRangeC.get(); + double placeWallRange = placeWallRangeC.get(); + Vec3d player = placeRangeEye.get() ? mc.player.getEyePos() : mc.player.getPos(); + double dist = placeRangeCenter.get() ? + player.squaredDistanceTo(pos.toCenterPos()) : pos.getSquaredDistance(player.x, player.y, player.z); + if (dist > placeRange * placeRange) + { + return true; + } + Vec3d raytrace = Vec3d.of(pos).add(0.5, 2.70000004768372, 0.5); + BlockHitResult result = mc.world.raycast(new RaycastContext( + mc.player.getEyePos(), raytrace, + RaycastContext.ShapeType.COLLIDER, + RaycastContext.FluidHandling.NONE, mc.player)); + float maxDist = breakRangeC.get() * breakRangeC.get(); + if (result != null && result.getType() == HitResult.Type.BLOCK && !result.getBlockPos().equals(pos)) + { + maxDist = breakWallRangeC.get() * breakWallRangeC.get(); + if (!raytraceC.get() || dist > placeWallRange * placeWallRange) + { + return true; + } + } + return breakValid.get() && dist > maxDist; + } + + public void placeCrystalForTarget(PlayerEntity target, BlockPos blockPos) + { + if (target == null || target.isDead() || placeRangeCheck(blockPos) || !canUseCrystalOnBlock(blockPos)) + { + return; + } + double selfDamage = ExplosionUtil.getDamageTo(mc.player, crystalDamageVec(blockPos), + blockDestruction.get(), Set.of(blockPos), selfExtrapolate.get() ? extrapolateTicks.get() : 0, false); + if (playerDamageCheck(selfDamage)) + { + return; + } + double damage = ExplosionUtil.getDamageTo(target, crystalDamageVec(blockPos), blockDestruction.get(), + Set.of(blockPos), extrapolateTicks.get(), assumeArmor.get()); + if (damage < minDamage.get() && !isCrystalLethalTo(damage, target) + || placeCrystal != null && placeCrystal.getDamage() >= damage) + { + return; + } + + /*float[] rotations = RotationUtil.getRotationsTo(mc.player.getEyePos(), blockPos.toCenterPos()); + setRotation(rotations[0], rotations[1]);*/ + placeCrystal(blockPos, Hand.MAIN_HAND, false); + fadeList.put(blockPos, new Animation(true, fadeTime.get())); + } + + private boolean checkOverrideSafety(boolean unsafeToPlayer, double damage, Entity entity) + { + return safetyOverride.get() && unsafeToPlayer && damage < EntityUtil.getHealth(entity) + 0.5; + } + + private boolean targetDamageCheck(DamageData crystal) + { + double minDmg = minDamage.get(); + if (crystal.getAttackTarget() instanceof LivingEntity entity && isCrystalLethalTo(crystal, entity)) + { + minDmg = 2.0f; + } + return crystal.getDamage() < minDmg; + } + + private boolean playerDamageCheck(double playerDamage) + { + if (!mc.player.isCreative()) + { + float health = mc.player.getHealth() + mc.player.getAbsorptionAmount(); + if (safety.get() && playerDamage >= health + 0.5f) + { + return true; + } + return playerDamage > maxLocalDamage.get(); + } + return false; + } + + private boolean isFeetSurrounded(LivingEntity entity) + { + BlockPos pos1 = entity.getBlockPos(); + if (!mc.world.getBlockState(pos1).isReplaceable()) + { + return true; + } + for (Direction direction : Direction.values()) + { + if (!direction.getAxis().isHorizontal()) + { + continue; + } + BlockPos pos2 = pos1.offset(direction); + if (mc.world.getBlockState(pos2).isReplaceable()) + { + return false; + } + } + return true; + } + + private boolean checkAntiTotem(double damage, LivingEntity entity) + { + if (entity instanceof PlayerEntity p) + { + float phealth = EntityUtil.getHealth(p); + if (phealth <= 2.0f && phealth - damage < 0.5f) + { + long time = Managers.TOTEM.getLastPopTime(p); + if (time != -1) + { + return System.currentTimeMillis() - time <= 500; + } + } + } + return false; + } + + private boolean isCrystalLethalTo(DamageData crystal, LivingEntity entity) + { + return isCrystalLethalTo(crystal.getDamage(), entity); + } + + private boolean isCrystalLethalTo(double damage, LivingEntity entity) + { + if (lethalDamage.get() && lastAttackTimer.passed(500)) + { + return true; + } + + if (antiTotem.get() && checkAntiTotem(damage, entity)) + { + return true; + } + float health = entity.getHealth() + entity.getAbsorptionAmount(); + if (damage * (1.0f + lethalMultiplier.get()) >= health + 0.5f) + { + return true; + } + if (armorBreaker.get()) + { + for (ItemStack armorStack : entity.getArmorItems()) + { + int n = armorStack.getDamage(); + int n1 = armorStack.getMaxDamage(); + float durability = ((n1 - n) / (float) n1) * 100.0f; + if (durability < armorScale.get()) + { + return true; + } + } + } + + // Antiregear + if (shulkers.get() && entity instanceof PlayerEntity) + { + for (BlockPos pos : getSphere(3.0f, entity.getPos())) + { + BlockState state = mc.world.getBlockState(pos); + if (state.getBlock() instanceof ShulkerBoxBlock) + { + return true; + } + } + } + return false; + } + + private boolean attackCheckPre(Hand hand) + { + if (!lastSwapTimer.passed(swapDelay.get() * 25.0f)) + { + return true; + } + if (hand == Hand.MAIN_HAND) + { + return checkCanUseCrystal(); + } + return false; + } + + private boolean checkCanUseCrystal() + { + return !multitask.get() && checkMultitask() + || !whileMining.get() && mc.interactionManager.isBreakingBlock(); + } + + private boolean isHoldingCrystal() + { + if (!checkCanUseCrystal() && (autoSwap.get() == Swap.SILENT || autoSwap.get() == Swap.SILENT_ALT)) + { + return true; + } + return getCrystalHand() != null; + } + + private Vec3d crystalDamageVec(BlockPos pos) + { + return Vec3d.of(pos).add(0.5, 1.0, 0.5); + } + + /** + * Returns true if the {@link Entity} is a valid enemy to attack. + * + * @param e The potential enemy entity + * @return true if the entity is an enemy + */ + private boolean isValidTarget(Entity e) + { + return e instanceof PlayerEntity && players.get() + || EntityUtil.isMonster(e) && monsters.get() + || EntityUtil.isNeutral(e) && neutrals.get() + || EntityUtil.isPassive(e) && animals.get(); + } + + /** + * Returns true if an {@link EndCrystalItem} can be used on the + * param {@link BlockPos}. + * + * @param pos The block pos + * @return Returns true if the crystal item can be placed on the + * block + */ + public boolean canUseCrystalOnBlock(BlockPos pos) + { + BlockState state = mc.world.getBlockState(pos); + if (!state.isOf(Blocks.OBSIDIAN) && !state.isOf(Blocks.BEDROCK)) + { + return false; + } + return isCrystalHitboxClear(pos); + } + + public boolean isCrystalHitboxClear(BlockPos pos) + { + BlockPos p2 = pos.up(); + BlockState state2 = mc.world.getBlockState(p2); + // ver 1.12.2 and below + if (placements.get() == Placements.PROTOCOL && !mc.world.isAir(p2.up())) + { + return false; + } + if (!mc.world.isAir(p2) && !state2.isOf(Blocks.FIRE)) + { + return false; + } + else + { + final Box bb = Managers.NETWORK.isCrystalPvpCC() ? HALF_CRYSTAL_BB : FULL_CRYSTAL_BB; + double d = p2.getX(); + double e = p2.getY(); + double f = p2.getZ(); + List list = getEntitiesBlockingCrystal(new Box(d, e, f, + d + bb.maxX, e + bb.maxY, f + bb.maxZ)); + return list.isEmpty(); + } + } + + private List getEntitiesBlockingCrystal(Box box) + { + List entities = new CopyOnWriteArrayList<>( + mc.world.getOtherEntities(null, box)); + // + for (Entity entity : entities) + { + if (entity == null || !entity.isAlive() + || entity instanceof ExperienceOrbEntity + || forcePlace.get() != ForcePlace.NONE + && entity instanceof ItemEntity && entity.age <= 10) + { + entities.remove(entity); + } + else if (entity instanceof EndCrystalEntity entity1 + && entity1.getBoundingBox().intersects(box)) + { + Integer antiStuckAttacks = antiStuckCrystals.get(entity1.getId()); + if (!attackRangeCheck(entity1) && (antiStuckAttacks == null || antiStuckAttacks <= attackLimit.get() * 10.0f)) + { + entities.remove(entity); + } + else + { + double dist = mc.player.squaredDistanceTo(entity1); + stuckCrystals.add(new AntiStuckData(entity1.getId(), entity1.getBlockPos(), entity1.getPos(), dist)); + } + } + } + return entities; + } + + private boolean intersectingAntiStuckCheck(BlockPos blockPos) + { + if (stuckCrystals.isEmpty()) + { + return false; + } + return stuckCrystals.stream().anyMatch(d -> d.blockPos().equals(blockPos.up())); + } + + private EndCrystalEntity intersectingCrystalCheck(BlockPos pos) + { + return (EndCrystalEntity) mc.world.getOtherEntities(null, new Box(pos)).stream() + .filter(e -> e instanceof EndCrystalEntity).min(Comparator.comparingDouble(e -> mc.player.distanceTo(e))).orElse(null); + } + + private List getSphere(Vec3d origin) + { + double rad = Math.ceil(placeRangeC.get()); + return getSphere(rad, origin); + } + + private List getSphere(double rad, Vec3d origin) + { + List sphere = new ArrayList<>(); + for (double x = -rad; x <= rad; ++x) + { + for (double y = -rad; y <= rad; ++y) + { + for (double z = -rad; z <= rad; ++z) + { + Vec3i pos = new Vec3i((int) (origin.getX() + x), + (int) (origin.getY() + y), (int) (origin.getZ() + z)); + final BlockPos p = new BlockPos(pos); + sphere.add(p); + } + } + } + return sphere; + } + + private boolean canHoldCrystal() + { + return isHoldingCrystal() || autoSwap.get() != Swap.OFF && getCrystalSlot() != -1; + } + + private Hand getCrystalHand() + { + final ItemStack offhand = mc.player.getOffHandStack(); + final ItemStack mainhand = mc.player.getMainHandStack(); + if (offhand.getItem() instanceof EndCrystalItem) + { + return Hand.OFF_HAND; + } + else if (mainhand.getItem() instanceof EndCrystalItem) + { + return Hand.MAIN_HAND; + } + return null; + } + + public float getBreakDelay() + { + return 1000.0f - breakSpeed.get() * 50.0f; + } + + // Debug info + public void setStage(String crystalStage) + { + // this.crystalStage = crystalStage; + } + + public int getBreakMs() + { + if (attackLatency.isEmpty()) + { + return 0; + } + float avg = 0.0f; + // fix ConcurrentModificationException + ArrayList latencyCopy = Lists.newArrayList(attackLatency); + if (!latencyCopy.isEmpty()) + { + for (float t : latencyCopy) + { + avg += t; + } + avg /= latencyCopy.size(); + } + return (int) avg; + } + + public boolean shouldPreForcePlace() + { + return forcePlace.get() == ForcePlace.PRE; + } + + public float getPlaceRange() + { + return placeRangeC.get(); + } + + public enum Swap + { + NORMAL, + SILENT, + SILENT_ALT, + OFF + } + + public enum Sequential + { + NORMAL, + STRICT, + NONE + } + + public enum ForcePlace + { + PRE, + POST, + NONE + } + + public enum Placements + { + NATIVE, + PROTOCOL + } + + public enum Rotate + { + FULL, + SEMI, + OFF + } + + private record AntiStuckData(int id, BlockPos blockPos, Vec3d pos, double stuckDist) {} + + private static class DamageData + { + // + private final List tags = new ArrayList<>(); + private T damageData; + private Entity attackTarget; + private BlockPos blockPos; + // + private double damage, selfDamage; + private boolean antiSurround; + + // + public DamageData() + { + + } + + public DamageData(BlockPos damageData, Entity attackTarget, double damage, + double selfDamage, boolean antiSurround) + { + this.damageData = (T) damageData; + this.attackTarget = attackTarget; + this.damage = damage; + this.selfDamage = selfDamage; + this.blockPos = damageData; + this.antiSurround = antiSurround; + } + + public DamageData(T damageData, Entity attackTarget, double damage, + double selfDamage, BlockPos blockPos, boolean antiSurround) + { + this.damageData = damageData; + this.attackTarget = attackTarget; + this.damage = damage; + this.selfDamage = selfDamage; + this.blockPos = blockPos; + this.antiSurround = antiSurround; + } + + public void setDamageData(T damageData, Entity attackTarget, double damage, double selfDamage) + { + this.damageData = damageData; + this.attackTarget = attackTarget; + this.damage = damage; + this.selfDamage = selfDamage; + } + + public T getDamageData() + { + return damageData; + } + + public Entity getAttackTarget() + { + return attackTarget; + } + + public double getDamage() + { + return damage; + } + + public double getSelfDamage() + { + return selfDamage; + } + + public BlockPos getBlockPos() + { + return blockPos; + } + + public boolean isAntiSurround() + { + return antiSurround; + } + } + + private class AttackCrystalTask implements Callable> + { + private final List threadSafeEntities; + + public AttackCrystalTask(List threadSafeEntities) + { + this.threadSafeEntities = threadSafeEntities; + } + + @Override + public DamageData call() throws Exception + { + return calculateAttackCrystal(threadSafeEntities); + } + } + + private class PlaceCrystalTask implements Callable> + { + private final List threadSafeBlocks; + private final List threadSafeEntities; + + public PlaceCrystalTask(List threadSafeBlocks, + List threadSafeEntities) + { + this.threadSafeBlocks = threadSafeBlocks; + this.threadSafeEntities = threadSafeEntities; + } + + @Override + public DamageData call() throws Exception + { + return calculatePlaceCrystal(threadSafeBlocks, threadSafeEntities); + } + } + +} diff --git a/src/main/java/com/genyo/addon/modules/GenyoAutoMine.java b/src/main/java/com/genyo/addon/modules/combat/GenyoAutoMine.java similarity index 97% rename from src/main/java/com/genyo/addon/modules/GenyoAutoMine.java rename to src/main/java/com/genyo/addon/modules/combat/GenyoAutoMine.java index fdb6dd6..5264fff 100644 --- a/src/main/java/com/genyo/addon/modules/GenyoAutoMine.java +++ b/src/main/java/com/genyo/addon/modules/combat/GenyoAutoMine.java @@ -1,7 +1,9 @@ -package com.genyo.addon.modules; +package com.genyo.addon.modules.combat; import com.genyo.addon.GenyoAddon; import com.genyo.addon.events.AttackBlockEvent; +import com.genyo.addon.managers.Managers; +import com.genyo.addon.modules.GenyoModule; import com.genyo.addon.render.animation.Animation; import com.genyo.addon.settings.FloatSetting; import com.genyo.addon.utils.GEntityUtils; @@ -11,11 +13,9 @@ import meteordevelopment.meteorclient.events.packets.PacketEvent; import meteordevelopment.meteorclient.events.render.Render3DEvent; import meteordevelopment.meteorclient.events.world.TickEvent; -import meteordevelopment.meteorclient.mixininterface.IClientPlayerInteractionManager; import meteordevelopment.meteorclient.renderer.Renderer3D; import meteordevelopment.meteorclient.renderer.ShapeMode; import meteordevelopment.meteorclient.settings.*; -import meteordevelopment.meteorclient.systems.friends.Friends; import meteordevelopment.meteorclient.systems.modules.Modules; import meteordevelopment.meteorclient.utils.player.InvUtils; import meteordevelopment.meteorclient.utils.render.color.Color; @@ -40,7 +40,7 @@ import java.util.*; -public class GenyoAutoMine extends GenyoModule{ +public class GenyoAutoMine extends GenyoModule { public GenyoAutoMine() { super(GenyoAddon.GENYO, "genyo-auto-mine", "dábül"); @@ -307,7 +307,7 @@ public void onDeactivate() { waitForPacketMine = false; packetMineStuck = false; if (packetSwapBack) { - ((IClientPlayerInteractionManager) mc.interactionManager).meteor$syncSelected(); + Managers.INVENTORY.syncToClient(); packetSwapBack = false; } } @@ -336,7 +336,7 @@ public void onTick(TickEvent.Pre event) { packetMineStuck = true; packetMineAnim.animation.setState(false); if (packetSwapBack) { - ((IClientPlayerInteractionManager) mc.interactionManager).meteor$syncSelected(); + Managers.INVENTORY.syncToClient(); packetSwapBack = false; } packetMine = null; @@ -373,7 +373,7 @@ public void onTick(TickEvent.Pre event) { } else { - ((IClientPlayerInteractionManager) mc.interactionManager).meteor$syncSelected(); + Managers.INVENTORY.syncToClient(); packetSwapBack = false; packetMineAnim.animation.setState(false); packetMine = null; @@ -423,7 +423,8 @@ public void onTick(TickEvent.Pre event) { if (instantMine != null && (remine.get() == RemineMode.INSTANT && packetInstant.get() && packetMine == null && canPlace || canMine && passedRemine) - && (!checkMultitask() || multitask.get() || swap.get() == Swap.OFF)) { + && (!checkMultitask() || multitask.get() || swap.get() == Swap.OFF)) + { stopMining(instantMine); remineTimer = 0; @@ -492,7 +493,7 @@ public void onTick(TickEvent.Pre event) { packetMineAnim.animation.setState(false); if (packetSwapBack) { - ((IClientPlayerInteractionManager) mc.interactionManager).meteor$syncSelected(); + Managers.INVENTORY.syncToClient(); packetSwapBack = false; } packetMine = null; @@ -534,7 +535,7 @@ public void onTick(TickEvent.Pre event) { if (packetMine != null && packetMine.getGoal() == MiningGoal.MINING_ENEMY) { packetMineAnim.animation.setState(false); if (packetSwapBack) { - ((IClientPlayerInteractionManager) mc.interactionManager).meteor$syncSelected(); + Managers.INVENTORY.syncToClient(); packetSwapBack = false; } packetMine = null; @@ -943,10 +944,9 @@ private void swapTo(int slot) { switch (swap.get()) { - //case NORMAL -> Managers.INVENTORY.setClientSlot(slot); - case NORMAL -> InvUtils.swap(slot, false); - //case SILENT -> Managers.INVENTORY.setSlot(slot); - case SILENT -> InvUtils.swap(slot, true); + case NORMAL -> Managers.INVENTORY.setClientSlot(slot); + case SILENT -> Managers.INVENTORY.setSlot(slot); + case SILENT_ALT -> Managers.INVENTORY.setSlotAlt(slot); } } @@ -954,7 +954,8 @@ private void swapSync(int slot) { switch (swap.get()) { - case SILENT -> ((IClientPlayerInteractionManager) mc.interactionManager).meteor$syncSelected(); + case SILENT -> Managers.INVENTORY.syncToClient(); + case SILENT_ALT -> Managers.INVENTORY.setSlotAlt(slot); } } @@ -1133,6 +1134,7 @@ public enum Selection { public enum Swap { NORMAL, SILENT, + SILENT_ALT, OFF } } diff --git a/src/main/java/com/genyo/addon/modules/GenyoSurround.java b/src/main/java/com/genyo/addon/modules/combat/GenyoSurround.java similarity index 98% rename from src/main/java/com/genyo/addon/modules/GenyoSurround.java rename to src/main/java/com/genyo/addon/modules/combat/GenyoSurround.java index 194380a..cf93675 100644 --- a/src/main/java/com/genyo/addon/modules/GenyoSurround.java +++ b/src/main/java/com/genyo/addon/modules/combat/GenyoSurround.java @@ -1,12 +1,12 @@ -package com.genyo.addon.modules; +package com.genyo.addon.modules.combat; import com.genyo.addon.GenyoAddon; +import com.genyo.addon.modules.GenyoModule; import com.genyo.addon.utils.math.GPositionUtils; import meteordevelopment.meteorclient.events.render.Render3DEvent; import meteordevelopment.meteorclient.events.world.TickEvent; import meteordevelopment.meteorclient.renderer.ShapeMode; import meteordevelopment.meteorclient.settings.*; -import meteordevelopment.meteorclient.systems.modules.Module; import meteordevelopment.meteorclient.utils.player.FindItemResult; import meteordevelopment.meteorclient.utils.player.InvUtils; import meteordevelopment.meteorclient.utils.render.color.Color; diff --git a/src/main/java/com/genyo/addon/modules/GenyoSurroundV2.java b/src/main/java/com/genyo/addon/modules/combat/GenyoSurroundV2.java similarity index 95% rename from src/main/java/com/genyo/addon/modules/GenyoSurroundV2.java rename to src/main/java/com/genyo/addon/modules/combat/GenyoSurroundV2.java index cef63ca..d5e7a1b 100644 --- a/src/main/java/com/genyo/addon/modules/GenyoSurroundV2.java +++ b/src/main/java/com/genyo/addon/modules/combat/GenyoSurroundV2.java @@ -1,7 +1,8 @@ -package com.genyo.addon.modules; +package com.genyo.addon.modules.combat; import com.genyo.addon.GenyoAddon; import com.genyo.addon.managers.Managers; +import com.genyo.addon.modules.GenyoModule; import com.genyo.addon.render.animation.Animation; import com.genyo.addon.settings.FloatSetting; import com.genyo.addon.utils.math.GPositionUtils; @@ -13,11 +14,8 @@ import meteordevelopment.meteorclient.renderer.ShapeMode; import meteordevelopment.meteorclient.settings.*; import meteordevelopment.meteorclient.systems.modules.Modules; -import meteordevelopment.meteorclient.utils.player.FindItemResult; -import meteordevelopment.meteorclient.utils.player.InvUtils; import meteordevelopment.meteorclient.utils.render.color.Color; import meteordevelopment.meteorclient.utils.render.color.SettingColor; -import meteordevelopment.meteorclient.utils.world.BlockUtils; import meteordevelopment.orbit.EventHandler; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -29,7 +27,6 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.BlockItem; import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; import net.minecraft.network.packet.Packet; import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket; import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket; @@ -45,7 +42,7 @@ import java.util.*; -public class GenyoSurroundV2 extends GenyoModule{ +public class GenyoSurroundV2 extends GenyoModule { public GenyoSurroundV2() { super(GenyoAddon.GENYO, "genyo-surround-v2", "ma reggel befostam aztán felkeltem"); @@ -107,6 +104,13 @@ public GenyoSurroundV2() { .build() ); + private final Setting strictDirection = sgGeneral.add(new BoolSetting.Builder() + .name("Strict Direction") + .description("Places on visible sides only") + .defaultValue(false) + .build() + ); + private final Setting attack = sgGeneral.add(new BoolSetting.Builder() .name("Attack") .description("Attacks crystals in the way of surround") @@ -265,7 +269,7 @@ public void onTick(TickEvent.Pre event) { BlockPos targetPos = placements.get(blocksPlaced); // All rotations for shift ticks must send extra packet // This may not work on all servers - placeBlock(targetPos); + placeBlock(targetPos, slot); } if (rotate.get()) @@ -302,7 +306,7 @@ private void handlePackets(Packet serverPacket) { return; } - placeBlock(targetPos); + placeBlock(targetPos, slot); } else if (BlastResistantBlocks.isBlastResistant(blockState)) { @@ -326,7 +330,7 @@ else if (BlastResistantBlocks.isBlastResistant(blockState)) { return; } - placeBlock(pos); + placeBlock(pos, slot); } } @@ -345,24 +349,26 @@ else if (BlastResistantBlocks.isBlastResistant(blockState)) { return; } - placeBlock(pos); + placeBlock(pos, slot); break; } } } - private void placeBlock(BlockPos pos) + private void placeBlock(BlockPos pos, int slot) { - /*Managers.INTERACT.placeBlock(pos, slot, strictDirection.get(), false, true, (state, angles) -> + Managers.INTERACT.placeBlock(pos, slot, strictDirection.get(), false, true, (state, angles) -> { - if (rotate.get() && state) + /*if (rotate.get() && state) { Managers.ROTATION.setRotationSilent(angles[0], angles[1]); - } - });*/ + }*/ + }); + + /*if (InvUtils.findInHotbar(Items.OBSIDIAN).slot() == -1) return; FindItemResult obsidian = InvUtils.findInHotbar(Items.OBSIDIAN); - BlockUtils.place(pos, obsidian, rotate.get(), 0, true); + BlockUtils.place(pos, obsidian, rotate.get(), 0, true);*/ packets.put(pos, System.currentTimeMillis()); blocksPlaced++; } diff --git a/src/main/java/com/genyo/addon/modules/GenyoAutoEZ.java b/src/main/java/com/genyo/addon/modules/misc/GenyoAutoEZ.java similarity index 96% rename from src/main/java/com/genyo/addon/modules/GenyoAutoEZ.java rename to src/main/java/com/genyo/addon/modules/misc/GenyoAutoEZ.java index b7cf9d3..3360164 100644 --- a/src/main/java/com/genyo/addon/modules/GenyoAutoEZ.java +++ b/src/main/java/com/genyo/addon/modules/misc/GenyoAutoEZ.java @@ -1,6 +1,7 @@ -package com.genyo.addon.modules; +package com.genyo.addon.modules.misc; import com.genyo.addon.GenyoAddon; +import com.genyo.addon.modules.GenyoModule; import com.genyo.addon.systems.incombat.CombatPerson; import com.genyo.addon.systems.incombat.InCombatSystem; import com.genyo.addon.utils.MathUtil; @@ -159,16 +160,9 @@ private void onReceive(PacketEvent.Receive event) { } private boolean checkPersonValidity(PlayerEntity player) { - if (InCombatSystem.get().isEnabled() && combatFocus.get()) - if (!InCombatSystem.get().contains(player)) return false; // kell? - - if (taggedPlayers.containsKey(player)) { - return true; - } + return taggedPlayers.containsKey(player); //TODO: if we want to display this for everyone - - return false; } diff --git a/src/main/java/com/genyo/addon/modules/GenyoGoodbye.java b/src/main/java/com/genyo/addon/modules/misc/GenyoGoodbye.java similarity index 97% rename from src/main/java/com/genyo/addon/modules/GenyoGoodbye.java rename to src/main/java/com/genyo/addon/modules/misc/GenyoGoodbye.java index c65a923..882e582 100644 --- a/src/main/java/com/genyo/addon/modules/GenyoGoodbye.java +++ b/src/main/java/com/genyo/addon/modules/misc/GenyoGoodbye.java @@ -1,6 +1,7 @@ -package com.genyo.addon.modules; +package com.genyo.addon.modules.misc; import com.genyo.addon.GenyoAddon; +import com.genyo.addon.modules.GenyoModule; import com.genyo.addon.settings.playerlist.ListGroupSetting; import com.genyo.addon.settings.playerlist.PLGroup; import meteordevelopment.meteorclient.events.packets.PacketEvent; diff --git a/src/main/java/com/genyo/addon/modules/GenyoSkinBlink.java b/src/main/java/com/genyo/addon/modules/misc/GenyoSkinBlink.java similarity index 93% rename from src/main/java/com/genyo/addon/modules/GenyoSkinBlink.java rename to src/main/java/com/genyo/addon/modules/misc/GenyoSkinBlink.java index 037fe54..4f4cf8f 100644 --- a/src/main/java/com/genyo/addon/modules/GenyoSkinBlink.java +++ b/src/main/java/com/genyo/addon/modules/misc/GenyoSkinBlink.java @@ -1,7 +1,8 @@ -package com.genyo.addon.modules; +package com.genyo.addon.modules.misc; import com.genyo.addon.GenyoAddon; import com.genyo.addon.mixin.AccessorGameOptions; +import com.genyo.addon.modules.GenyoModule; import meteordevelopment.meteorclient.events.world.TickEvent; import meteordevelopment.meteorclient.settings.IntSetting; import meteordevelopment.meteorclient.settings.Setting; @@ -12,7 +13,7 @@ import java.util.HashSet; import java.util.Set; -public class GenyoSkinBlink extends GenyoModule{ +public class GenyoSkinBlink extends GenyoModule { private final SettingGroup sgGeneral = settings.getDefaultGroup(); private final Setting delay = sgGeneral.add(new IntSetting.Builder() diff --git a/src/main/java/com/genyo/addon/modules/GenyoWelcome.java b/src/main/java/com/genyo/addon/modules/misc/GenyoWelcome.java similarity index 98% rename from src/main/java/com/genyo/addon/modules/GenyoWelcome.java rename to src/main/java/com/genyo/addon/modules/misc/GenyoWelcome.java index 10f4e32..0c64308 100644 --- a/src/main/java/com/genyo/addon/modules/GenyoWelcome.java +++ b/src/main/java/com/genyo/addon/modules/misc/GenyoWelcome.java @@ -1,6 +1,7 @@ -package com.genyo.addon.modules; +package com.genyo.addon.modules.misc; import com.genyo.addon.GenyoAddon; +import com.genyo.addon.modules.GenyoModule; import com.genyo.addon.settings.playerlist.ListGroupSetting; import com.genyo.addon.settings.playerlist.PLGroup; import com.mojang.authlib.GameProfile; diff --git a/src/main/java/com/genyo/addon/modules/AngelSexHulkenberg.java b/src/main/java/com/genyo/addon/modules/visual/AngelSexHulkenberg.java similarity index 96% rename from src/main/java/com/genyo/addon/modules/AngelSexHulkenberg.java rename to src/main/java/com/genyo/addon/modules/visual/AngelSexHulkenberg.java index ff7c216..42f9855 100644 --- a/src/main/java/com/genyo/addon/modules/AngelSexHulkenberg.java +++ b/src/main/java/com/genyo/addon/modules/visual/AngelSexHulkenberg.java @@ -1,8 +1,9 @@ -package com.genyo.addon.modules; +package com.genyo.addon.modules.visual; import com.genyo.addon.GenyoAddon; import com.genyo.addon.events.TotemPopEvent; import com.genyo.addon.mixin.IEntity; +import com.genyo.addon.modules.GenyoModule; import com.genyo.addon.render.Render2DEngine; import com.genyo.addon.render.Render3DEngine; import com.genyo.addon.systems.enemies.Enemies; @@ -10,24 +11,17 @@ import com.mojang.authlib.GameProfile; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; -import meteordevelopment.meteorclient.MeteorClient; import meteordevelopment.meteorclient.events.render.Render3DEvent; import meteordevelopment.meteorclient.events.world.TickEvent; -import meteordevelopment.meteorclient.renderer.*; import meteordevelopment.meteorclient.settings.*; -import meteordevelopment.meteorclient.systems.modules.Module; import meteordevelopment.meteorclient.utils.render.color.Color; import meteordevelopment.meteorclient.utils.render.color.SettingColor; import meteordevelopment.orbit.EventHandler; -import net.minecraft.client.gl.ShaderLoader; -import net.minecraft.client.gl.ShaderProgram; -import net.minecraft.client.gl.ShaderProgramKey; import net.minecraft.client.gl.ShaderProgramKeys; import net.minecraft.client.network.AbstractClientPlayerEntity; import net.minecraft.client.render.*; import net.minecraft.client.render.entity.PlayerEntityRenderer; import net.minecraft.client.render.entity.state.PlayerEntityRenderState; -import net.minecraft.client.util.SkinTextures; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; diff --git a/src/main/java/com/genyo/addon/settings/playerlist/PLGroup.java b/src/main/java/com/genyo/addon/settings/playerlist/PLGroup.java index 5abbfa3..cb57cba 100644 --- a/src/main/java/com/genyo/addon/settings/playerlist/PLGroup.java +++ b/src/main/java/com/genyo/addon/settings/playerlist/PLGroup.java @@ -1,7 +1,5 @@ package com.genyo.addon.settings.playerlist; -import com.genyo.addon.modules.GenyoWelcome; - import java.util.List; public class PLGroup { diff --git a/src/main/java/com/genyo/addon/utils/collection/EvictingQueue.java b/src/main/java/com/genyo/addon/utils/collection/EvictingQueue.java new file mode 100644 index 0000000..e824a5e --- /dev/null +++ b/src/main/java/com/genyo/addon/utils/collection/EvictingQueue.java @@ -0,0 +1,54 @@ +package com.genyo.addon.utils.collection; + +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.ConcurrentLinkedDeque; + +public class EvictingQueue extends ConcurrentLinkedDeque +{ + // + private final int limit; + + /** + * @param limit + */ + public EvictingQueue(int limit) + { + this.limit = limit; + } + + /** + * @param element element whose presence in this collection is to be ensured + * @return + */ + @Override + public boolean add(@NotNull E element) + { + boolean add = super.add(element); + while (add && size() > limit) + { + super.remove(); + } + return add; + } + + /** + * @param element element whose presence in this collection is to be ensured + */ + public void addFirst(@NotNull E element) + { + super.addFirst(element); + while (size() > limit) + { + super.removeLast(); + } + } + + /** + * @return + */ + public int limit() + { + return limit; + } +} diff --git a/src/main/java/com/genyo/addon/utils/entity/EntityUtil.java b/src/main/java/com/genyo/addon/utils/entity/EntityUtil.java new file mode 100644 index 0000000..c515e7b --- /dev/null +++ b/src/main/java/com/genyo/addon/utils/entity/EntityUtil.java @@ -0,0 +1,62 @@ +package com.genyo.addon.utils.entity; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.mob.AmbientEntity; +import net.minecraft.entity.mob.EndermanEntity; +import net.minecraft.entity.mob.Monster; +import net.minecraft.entity.mob.ZombifiedPiglinEntity; +import net.minecraft.entity.passive.*; + +public class EntityUtil { + + /** + * @param entity + * @return + */ + public static float getHealth(Entity entity) + { + if (entity instanceof LivingEntity e) + { + return e.getHealth() + e.getAbsorptionAmount(); + } + return 0.0f; + } + + /** + * @param e + * @return + */ + public static boolean isMonster(Entity e) + { + return e instanceof Monster && !isNeutralInternal(e); + } + + private static boolean isNeutralInternal(Entity e) + { + return e instanceof EndermanEntity enderman && !enderman.isAttacking() + || e instanceof ZombifiedPiglinEntity piglin && !piglin.isAttacking() + || e instanceof WolfEntity wolf && !wolf.isAttacking() + || e instanceof IronGolemEntity ironGolem && !ironGolem.isAttacking() + || e instanceof BeeEntity bee && !bee.isAttacking(); + } + + /** + * @param e + * @return + */ + public static boolean isNeutral(Entity e) + { + return e instanceof EndermanEntity || e instanceof ZombifiedPiglinEntity || e instanceof WolfEntity || e instanceof IronGolemEntity; + } + + /** + * @param e + * @return + */ + public static boolean isPassive(Entity e) + { + return e instanceof PassiveEntity || e instanceof AmbientEntity || e instanceof SquidEntity; + } + +} diff --git a/src/main/java/com/genyo/addon/utils/math/PerSecondCounter.java b/src/main/java/com/genyo/addon/utils/math/PerSecondCounter.java new file mode 100644 index 0000000..d62a3bb --- /dev/null +++ b/src/main/java/com/genyo/addon/utils/math/PerSecondCounter.java @@ -0,0 +1,31 @@ +package com.genyo.addon.utils.math; + +import java.util.LinkedList; + +public class PerSecondCounter { + + private final LinkedList counter = new LinkedList<>(); + + public void updateCounter() + { + counter.add(System.currentTimeMillis() + 1000L); + } + + public int getPerSecond() + { + long time = System.currentTimeMillis(); + try + { + while (!counter.isEmpty() && counter.peek() != null && counter.peek() < time) + { + counter.remove(); + } + } catch (Exception e) + { + counter.clear(); + e.printStackTrace(); + } + return counter.size(); + } + +} diff --git a/src/main/java/com/genyo/addon/utils/math/timer/CacheTimer.java b/src/main/java/com/genyo/addon/utils/math/timer/CacheTimer.java new file mode 100644 index 0000000..8f98c5b --- /dev/null +++ b/src/main/java/com/genyo/addon/utils/math/timer/CacheTimer.java @@ -0,0 +1,113 @@ +package com.genyo.addon.utils.math.timer; + +import java.util.concurrent.TimeUnit; + +public class CacheTimer implements Timer { + + // The cached time since last reset which indicates the time passed since + // the last timer reset + private long time; + + private long lastResetTime; + + /** + * Default constructor which will initialize the time to the current time + * which means {@link #passed(Number)} and {@link #passed(Number, TimeUnit)} + * will always return true initially + */ + public CacheTimer() + { + this.time = System.nanoTime(); + } + + /** + * Returns true if the time since the last reset has exceeded + * the param time. + * + * @param time The param time in ms + * @return true if the time since the last reset has exceeded + * the param time + */ + @Override + public boolean passed(Number time) + { + if (time.longValue() <= 0) + { + return true; + } + return getElapsedTime() > time.longValue(); + } + + /** + * Returns true if the time since the last reset has exceeded + * the param time which is in the param units. + * + * @param time The param time + * @param unit The unit of the time + * @return true if the time since the last reset has exceeded + * the param time + * @see #passed(Number) + */ + public boolean passed(Number time, TimeUnit unit) + { + return passed(unit.toMillis(time.longValue())); + } + + /** + * @return + */ + @Override + public long getElapsedTime() + { + return toMillis(System.nanoTime() - time); + } + + /** + * @param time + */ + @Override + public void setElapsedTime(Number time) + { + this.time = time.longValue() == MAX_TIME ? 0 : + System.nanoTime() - time.longValue(); + } + + public void setDelay(Number delay) + { + this.time += delay.longValue(); + } + + /** + * @return + */ + public long getElapsedTime(TimeUnit unit) + { + return unit.convert(getElapsedTime(), TimeUnit.MILLISECONDS); + } + + public long getLastResetTime() + { + return lastResetTime; + } + + /** + * Sets the cached time since the last reset to the current time + */ + @Override + public void reset() + { + long time = System.nanoTime(); + lastResetTime = time - this.time; + + this.time = time; + } + + /** + * @return + */ + private long toMillis(long nanos) + { + return nanos / 1000000; + } + +} diff --git a/src/main/java/com/genyo/addon/utils/math/timer/Timer.java b/src/main/java/com/genyo/addon/utils/math/timer/Timer.java new file mode 100644 index 0000000..2fe533f --- /dev/null +++ b/src/main/java/com/genyo/addon/utils/math/timer/Timer.java @@ -0,0 +1,36 @@ +package com.genyo.addon.utils.math.timer; + +public interface Timer { + + // + long MAX_TIME = -0xff; + + /** + * Returns true if the time since the last reset has exceeded + * the param time. + * + * @param time The param time + * @return true if the time since the last reset has exceeded + * the param time + */ + boolean passed(Number time); + + /** + * Resets the current elapsed time state of the timer and restarts the + * timer from 0. + */ + void reset(); + + /** + * Returns the elapsed time since the last reset of the timer. + * + * @return The elapsed time since the last reset + */ + long getElapsedTime(); + + /** + * @param time + */ + void setElapsedTime(Number time); + +} diff --git a/src/main/java/com/genyo/addon/utils/player/EnchantmentUtil.java b/src/main/java/com/genyo/addon/utils/player/EnchantmentUtil.java new file mode 100644 index 0000000..bcdc41e --- /dev/null +++ b/src/main/java/com/genyo/addon/utils/player/EnchantmentUtil.java @@ -0,0 +1,52 @@ +package com.genyo.addon.utils.player; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.enchantment.Enchantments; +import net.minecraft.item.ItemStack; +import net.minecraft.registry.RegistryKey; +import net.minecraft.registry.entry.RegistryEntry; + +import java.util.Set; + +public class EnchantmentUtil { + + public static int getLevel(ItemStack stack, RegistryKey enchantmentRegistryKey) + { + if (!stack.getComponents().contains(DataComponentTypes.ENCHANTMENTS)) + { + return 0; + } + for (Object2IntMap.Entry> e : stack.getComponents() + .get(DataComponentTypes.ENCHANTMENTS).getEnchantmentEntries()) + { + if (e.getKey().getKey().isPresent() && e.getKey().getKey().get().equals(enchantmentRegistryKey)) + { + return e.getIntValue(); + } + } + return 0; + } + + public static boolean isFakeEnchant2b2t(ItemStack itemStack) + { + Set>> enchants = EnchantmentHelper.getEnchantments(itemStack).getEnchantmentEntries(); + if (enchants.size() > 1) + { + return false; + } + for (Object2IntMap.Entry> e : enchants) + { + RegistryEntry enchantment = e.getKey(); + int lvl = e.getIntValue(); + if (lvl == 0 && enchantment.getKey().isPresent() && enchantment.getKey().get() == Enchantments.PROTECTION) + { + return true; + } + } + return false; + } + +} diff --git a/src/main/java/com/genyo/addon/utils/player/InventoryUtil.java b/src/main/java/com/genyo/addon/utils/player/InventoryUtil.java new file mode 100644 index 0000000..06ad0ab --- /dev/null +++ b/src/main/java/com/genyo/addon/utils/player/InventoryUtil.java @@ -0,0 +1,33 @@ +package com.genyo.addon.utils.player; + +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +import static meteordevelopment.meteorclient.MeteorClient.mc; + +public class InventoryUtil { + + /** + * @param item + * @return + */ + public static int count(Item item) + { + if (mc.player == null) + { + return 0; + } + ItemStack offhandStack = mc.player.getOffHandStack(); + int itemCount = offhandStack.getItem() == item ? offhandStack.getCount() : 0; + for (int i = 0; i < 36; i++) + { + ItemStack slot = mc.player.getInventory().getStack(i); + if (slot.getItem() == item) + { + itemCount += slot.getCount(); + } + } + return itemCount; + } + +} diff --git a/src/main/java/com/genyo/addon/utils/player/MovementUtil.java b/src/main/java/com/genyo/addon/utils/player/MovementUtil.java new file mode 100644 index 0000000..5d83eb2 --- /dev/null +++ b/src/main/java/com/genyo/addon/utils/player/MovementUtil.java @@ -0,0 +1,18 @@ +package com.genyo.addon.utils.player; + +import net.minecraft.enchantment.Enchantments; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.util.math.MathHelper; + +import static meteordevelopment.meteorclient.MeteorClient.mc; + +public class MovementUtil { + + public static void applySneak() + { + final float modifier = MathHelper.clamp(0.3f + (EnchantmentUtil.getLevel(mc.player.getEquippedStack(EquipmentSlot.FEET), Enchantments.SWIFT_SNEAK) * 0.15F), 0.0f, 1.0f); + mc.player.input.movementForward *= modifier; + mc.player.input.movementSideways *= modifier; + } + +} diff --git a/src/main/java/com/genyo/addon/utils/player/PlayerUtil.java b/src/main/java/com/genyo/addon/utils/player/PlayerUtil.java new file mode 100644 index 0000000..d6672d3 --- /dev/null +++ b/src/main/java/com/genyo/addon/utils/player/PlayerUtil.java @@ -0,0 +1,75 @@ +package com.genyo.addon.utils.player; + +import com.genyo.addon.utils.math.GPositionUtils; +import net.minecraft.block.BlockState; +import net.minecraft.block.CobwebBlock; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.entity.effect.StatusEffectInstance; +import net.minecraft.entity.effect.StatusEffects; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.registry.tag.EntityTypeTags; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; + +import static meteordevelopment.meteorclient.MeteorClient.mc; + +public class PlayerUtil { + + public static float getLocalPlayerHealth() + { + return mc.player.getHealth() + mc.player.getAbsorptionAmount(); + } + + // from MC source + public static int computeFallDamage(float fallDistance, float damageMultiplier) + { + if (mc.player.getType().isIn(EntityTypeTags.FALL_DAMAGE_IMMUNE)) + { + return 0; + } + else + { + final StatusEffectInstance statusEffectInstance = mc.player.getStatusEffect(StatusEffects.JUMP_BOOST); + final float f = statusEffectInstance == null ? 0.0F : (float) (statusEffectInstance.getAmplifier() + 1); + return MathHelper.ceil((fallDistance - 3.0F - f) * damageMultiplier); + } + } + + public static boolean isHolding(final Item item) + { + ItemStack itemStack = mc.player.getMainHandStack(); + if (!itemStack.isEmpty() && itemStack.getItem() == item) + { + return true; + } + itemStack = mc.player.getOffHandStack(); + return !itemStack.isEmpty() && itemStack.getItem() == item; + } + + public static boolean isHotbarKeysPressed() + { + for (KeyBinding binding : mc.options.hotbarKeys) + { + if (binding.isPressed()) + { + return true; + } + } + return false; + } + + public static boolean inWeb(double expandBb) + { + for (BlockPos blockPos : GPositionUtils.getAllInBox(mc.player.getBoundingBox().expand(expandBb))) + { + BlockState state = mc.world.getBlockState(blockPos); + if (state.getBlock() instanceof CobwebBlock) + { + return true; + } + } + return false; + } + +} diff --git a/src/main/java/com/genyo/addon/utils/player/RotationUtil.java b/src/main/java/com/genyo/addon/utils/player/RotationUtil.java new file mode 100644 index 0000000..0b87e2d --- /dev/null +++ b/src/main/java/com/genyo/addon/utils/player/RotationUtil.java @@ -0,0 +1,26 @@ +package com.genyo.addon.utils.player; + +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; + +public class RotationUtil { + + /** + * @param src + * @param dest + * @return + */ + public static float[] getRotationsTo(Vec3d src, Vec3d dest) + { + float yaw = (float) (Math.toDegrees(Math.atan2(dest.subtract(src).z, + dest.subtract(src).x)) - 90); + float pitch = (float) Math.toDegrees(-Math.atan2(dest.subtract(src).y, + Math.hypot(dest.subtract(src).x, dest.subtract(src).z))); + return new float[] + { + MathHelper.wrapDegrees(yaw), + MathHelper.wrapDegrees(pitch) + }; + } + +} diff --git a/src/main/java/com/genyo/addon/utils/world/ExplosionUtil.java b/src/main/java/com/genyo/addon/utils/world/ExplosionUtil.java new file mode 100644 index 0000000..8c2ef72 --- /dev/null +++ b/src/main/java/com/genyo/addon/utils/world/ExplosionUtil.java @@ -0,0 +1,527 @@ +package com.genyo.addon.utils.world; + +import com.genyo.addon.utils.player.EnchantmentUtil; +import net.minecraft.block.BlockState; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.enchantment.Enchantments; +import net.minecraft.entity.DamageUtil; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.attribute.DefaultAttributeContainer; +import net.minecraft.entity.attribute.DefaultAttributeRegistry; +import net.minecraft.entity.attribute.EntityAttributes; +import net.minecraft.entity.damage.DamageSource; +import net.minecraft.entity.effect.StatusEffectInstance; +import net.minecraft.entity.effect.StatusEffects; +import net.minecraft.item.ArmorItem; +import net.minecraft.item.ItemStack; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.BlockView; +import org.apache.commons.lang3.mutable.MutableInt; + +import java.util.Set; +import java.util.function.BiFunction; + +import static meteordevelopment.meteorclient.MeteorClient.mc; + +public class ExplosionUtil { + + /** + * @param entity + * @param explosion + * @return + */ + public static double getDamageTo(final Entity entity, + final Vec3d explosion, + boolean assumeBestArmor) + { + return getDamageTo(entity, explosion, false, assumeBestArmor); + } + + /** + * @param entity + * @param explosion + * @param ignoreTerrain + * @return + */ + public static double getDamageTo(final Entity entity, + final Vec3d explosion, + final boolean ignoreTerrain, + boolean assumeBestArmor) + { + return getDamageTo(entity, explosion, ignoreTerrain, 12.0f, 0, assumeBestArmor); + } + + public static double getDamageTo(final Entity entity, + final Vec3d explosion, + final boolean ignoreTerrain, + int extrapolationTicks, + boolean assumeBestArmor) + { + return getDamageTo(entity, explosion, ignoreTerrain, 12.0f, extrapolationTicks, assumeBestArmor); + } + + public static double getDamageTo(final Entity entity, + final Vec3d explosion, + final IgnoreTerrain ignoreTerrain, + boolean assumeBestArmor) + { + return getDamageTo(entity, explosion, ignoreTerrain, 12.0f, 0, assumeBestArmor); + } + + public static double getDamageTo(final Entity entity, + final Vec3d explosion, + final IgnoreTerrain ignoreTerrain, + int extrapolationTicks, + boolean assumeBestArmor) + { + return getDamageTo(entity, explosion, ignoreTerrain, 12.0f, extrapolationTicks, assumeBestArmor); + } + + public static double getDamageTo(final Entity entity, + final Vec3d explosion, + final IgnoreTerrain ignoreTerrain, + float power, + int extrapolationTicks, + boolean assumeBestArmor) + { + double x = entity.getX(); + double y = entity.getY(); + double z = entity.getZ(); + + Vec3d vec3d2 = Vec3d.ZERO; + if (extrapolationTicks != 0) + { + double ox = (x - entity.prevX) * extrapolationTicks; + double oy = (y - entity.prevY) * extrapolationTicks * 0.3; + double oz = (z - entity.prevZ) * extrapolationTicks; + x += ox; + y += oy; + z += oz; + vec3d2 = new Vec3d(ox, oy, oz); + } + + Vec3d vec3d = new Vec3d(x, y, z); + double d = Math.sqrt(vec3d.squaredDistanceTo(explosion)); + double ab = getExposure(explosion, entity.getBoundingBox().offset(vec3d2), ignoreTerrain); + double w = d / power; + double ac = (1.0 - w) * ab; + double dmg = (float) ((int) ((ac * ac + ac) / 2.0 * 7.0 * 12.0 + 1.0)); + dmg = getReduction(entity, mc.world.getDamageSources().explosion(null), dmg, assumeBestArmor); + return Math.max(0.0, dmg); + } + + public static double getDamageTo(final Entity entity, + final Vec3d explosion, + final boolean ignoreTerrain, + final Set ignoreBlocks, + boolean assumeBestArmor) + { + return getDamageTo(entity, explosion, ignoreTerrain, 12.0f, ignoreBlocks, 0, assumeBestArmor); + } + + public static double getDamageTo(final Entity entity, + final Vec3d explosion, + final boolean ignoreTerrain, + final Set ignoreBlocks, + int extrapolationTicks, + boolean assumeBestArmor) + { + return getDamageTo(entity, explosion, ignoreTerrain, 12.0f, ignoreBlocks, extrapolationTicks, assumeBestArmor); + } + + public static double getDamageTo(final Entity entity, + final Vec3d explosion, + final boolean ignoreTerrain, + float power, + final Set ignoreBlocks, + int extrapolationTicks, + boolean assumeBestArmor) + { + double x = entity.getX(); + double y = entity.getY(); + double z = entity.getZ(); + + Vec3d vec3d2 = Vec3d.ZERO; + if (extrapolationTicks != 0) + { + double ox = (x - entity.prevX) * extrapolationTicks; + double oy = (y - entity.prevY) * extrapolationTicks * 0.3; + double oz = (z - entity.prevZ) * extrapolationTicks; + x += ox; + y += oy; + z += oz; + vec3d2 = new Vec3d(ox, oy, oz); + } + + Vec3d vec3d = new Vec3d(x, y, z); + double d = Math.sqrt(vec3d.squaredDistanceTo(explosion)); + double ab = getExposure(explosion, entity.getBoundingBox().offset(vec3d2), ignoreTerrain ? IgnoreTerrain.BLAST : IgnoreTerrain.NONE, ignoreBlocks); + double w = d / power; + double ac = (1.0 - w) * ab; + double dmg = (float) ((int) ((ac * ac + ac) / 2.0 * 7.0 * 12.0 + 1.0)); + dmg = getReduction(entity, mc.world.getDamageSources().explosion(null), dmg, assumeBestArmor); + return Math.max(0.0, dmg); + } + + public static double getDamageTo(final Entity entity, + final Vec3d explosion, + final IgnoreTerrain ignoreTerrain, + final Set ignoreBlocks, + boolean assumeBestArmor) + { + return getDamageTo(entity, explosion, ignoreTerrain, 12.0f, ignoreBlocks, 0, assumeBestArmor); + } + + public static double getDamageTo(final Entity entity, + final Vec3d explosion, + final IgnoreTerrain ignoreTerrain, + float power, + final Set ignoreBlocks, + int extrapolationTicks, + boolean assumeBestArmor) + { + double x = entity.getX(); + double y = entity.getY(); + double z = entity.getZ(); + + Vec3d vec3d2 = Vec3d.ZERO; + if (extrapolationTicks != 0) + { + double ox = (x - entity.prevX) * extrapolationTicks; + double oy = (y - entity.prevY) * extrapolationTicks * 0.3; + double oz = (z - entity.prevZ) * extrapolationTicks; + x += ox; + y += oy; + z += oz; + vec3d2 = new Vec3d(ox, oy, oz); + } + + Vec3d vec3d = new Vec3d(x, y, z); + double d = Math.sqrt(vec3d.squaredDistanceTo(explosion)); + double ab = getExposure(explosion, entity.getBoundingBox().offset(vec3d2), ignoreTerrain, ignoreBlocks); + double w = d / power; + double ac = (1.0 - w) * ab; + double dmg = (float) ((int) ((ac * ac + ac) / 2.0 * 7.0 * 12.0 + 1.0)); + dmg = getReduction(entity, mc.world.getDamageSources().explosion(null), dmg, assumeBestArmor); + return Math.max(0.0, dmg); + } + + /** + * @param entity + * @param explosion + * @return + */ + public static double getDamageTo(final Entity entity, + final Vec3d explosion, + final boolean ignoreTerrain, + float power, + int extrapolationTicks, + boolean assumeBestArmor) + { + double x = entity.getX(); + double y = entity.getY(); + double z = entity.getZ(); + + Vec3d vec3d2 = Vec3d.ZERO; + if (extrapolationTicks != 0) + { + double ox = (x - entity.prevX) * extrapolationTicks; + double oy = (y - entity.prevY) * extrapolationTicks * 0.3; + double oz = (z - entity.prevZ) * extrapolationTicks; + x += ox; + y += oy; + z += oz; + vec3d2 = new Vec3d(ox, oy, oz); + } + + Vec3d vec3d = new Vec3d(x, y, z); + double d = Math.sqrt(vec3d.squaredDistanceTo(explosion)); + double ab = getExposure(explosion, entity.getBoundingBox().offset(vec3d2), ignoreTerrain ? IgnoreTerrain.BLAST : IgnoreTerrain.NONE); + double w = d / power; + double ac = (1.0 - w) * ab; + double dmg = (float) ((int) ((ac * ac + ac) / 2.0 * 7.0 * 12.0 + 1.0)); + dmg = getReduction(entity, mc.world.getDamageSources().explosion(null), dmg, assumeBestArmor); + return Math.max(0.0, dmg); + } + + /** + * @param pos The actual position of the damage + * @param entity + * @param explosion + * @param ignoreTerrain + * @return + */ + public static double getDamageToPos(final Vec3d pos, + final Entity entity, + final Vec3d explosion, + final boolean ignoreTerrain, + boolean assumeBestArmor) + { + final Box bb = entity.getBoundingBox(); + double dx = pos.getX() - bb.minX; + double dy = pos.getY() - bb.minY; + double dz = pos.getZ() - bb.minZ; + final Box box = bb.offset(dx, dy, dz); + // + RaycastFactory raycastFactory = getRaycastFactory(ignoreTerrain ? IgnoreTerrain.BLAST : IgnoreTerrain.NONE); + double ab = getExposure(explosion, box, raycastFactory); + double w = Math.sqrt(pos.squaredDistanceTo(explosion)) / 12.0; + double ac = (1.0 - w) * ab; + double dmg = (float) ((int) ((ac * ac + ac) / 2.0 * 7.0 * 12.0 + 1.0)); + dmg = getReduction(entity, mc.world.getDamageSources().explosion(null), dmg, assumeBestArmor); + return Math.max(0.0, dmg); + } + + /** + * @param entity + * @param damage + * @return + */ + private static double getReduction(Entity entity, DamageSource damageSource, double damage, boolean assumeBestArmor) + { + if (damageSource.isScaledWithDifficulty()) + { + switch (mc.world.getDifficulty()) + { + // case PEACEFUL -> return 0; + case EASY -> damage = Math.min(damage / 2 + 1, damage); + case HARD -> damage *= 1.5f; + } + } + + if (entity instanceof LivingEntity livingEntity) + { + damage = DamageUtil.getDamageLeft(livingEntity, (float) damage, damageSource, getArmor(livingEntity), (float) livingEntity.getAttributeValue(EntityAttributes.ARMOR_TOUGHNESS)); + damage = getResistanceReduction(livingEntity, damage); + damage = getProtectionReduction(livingEntity, damage, damageSource, assumeBestArmor); + } + + return Math.max(damage, 0); + } + + private static float getArmor(LivingEntity entity) + { + return (float) Math.floor(entity.getAttributeValue(EntityAttributes.ARMOR)); + } + + private static float getProtectionReduction(Entity player, double damage, DamageSource source, boolean assumeBestArmor) + { + if (player instanceof LivingEntity livingEntity) + { + float protLevel = getProtectionAmount(livingEntity.getArmorItems(), assumeBestArmor); + return DamageUtil.getInflictedDamage((float) damage, protLevel); + } + return 0.0f; + } + + private static float getProtectionAmount(Iterable equipment, boolean assumeBestArmor) + { + MutableInt mutableInt = new MutableInt(); + equipment.forEach(i -> + { + if (assumeBestArmor && EnchantmentUtil.isFakeEnchant2b2t(i)) + { + //mutableInt.add(i.getItem() instanceof ArmorItem armorItem && armorItem == ArmorItem.Type.LEGGINGS ? 8 : 4); + } + else + { + int modifierBlast = EnchantmentHelper.getLevel(mc.world.getRegistryManager().getOptional(Enchantments.BLAST_PROTECTION.getRegistryRef()).get().getEntry(Enchantments.BLAST_PROTECTION.getValue()).get(), i); + int modifier = EnchantmentHelper.getLevel(mc.world.getRegistryManager().getOptional(Enchantments.PROTECTION.getRegistryRef()).get().getEntry(Enchantments.PROTECTION.getValue()).get(), i); + mutableInt.add(modifierBlast * 2 + modifier); + } + }); + return mutableInt.intValue(); + } + + private static double getResistanceReduction(LivingEntity player, double damage) + { + StatusEffectInstance resistance = player.getStatusEffect(StatusEffects.RESISTANCE); + if (resistance != null) + { + int lvl = resistance.getAmplifier() + 1; + damage *= (1.0f - (lvl * 0.2f)); + } + + return Math.max(damage, 0.0f); + } + + private static DefaultAttributeContainer getDefaultForEntity(T entity) + { + return DefaultAttributeRegistry.get((EntityType) entity.getType()); + } + + /** + * @param source + * @param box + * @param ignoreTerrain + * @return + */ + private static float getExposure(final Vec3d source, + final Box box, + final IgnoreTerrain ignoreTerrain, + final Set ignoreBlocks) + { + RaycastFactory raycastFactory = getRaycastFactory(ignoreTerrain, ignoreBlocks); + return getExposure(source, box, raycastFactory); + } + + /** + * @param source + * @param box + * @param ignoreTerrain + * @return + */ + private static float getExposure(final Vec3d source, + final Box box, + final IgnoreTerrain ignoreTerrain) + { + RaycastFactory raycastFactory = getRaycastFactory(ignoreTerrain); + return getExposure(source, box, raycastFactory); + } + + /** + * @param source + * @param box + * @return + */ + private static float getExposure(final Vec3d source, + final Box box, + final RaycastFactory raycastFactory) + { + double xDiff = box.maxX - box.minX; + double yDiff = box.maxY - box.minY; + double zDiff = box.maxZ - box.minZ; + + double xStep = 1 / (xDiff * 2 + 1); + double yStep = 1 / (yDiff * 2 + 1); + double zStep = 1 / (zDiff * 2 + 1); + + if (xStep > 0 && yStep > 0 && zStep > 0) + { + int misses = 0; + int hits = 0; + + double xOffset = (1 - Math.floor(1 / xStep) * xStep) * 0.5; + double zOffset = (1 - Math.floor(1 / zStep) * zStep) * 0.5; + + xStep = xStep * xDiff; + yStep = yStep * yDiff; + zStep = zStep * zDiff; + + double startX = box.minX + xOffset; + double startY = box.minY; + double startZ = box.minZ + zOffset; + double endX = box.maxX + xOffset; + double endY = box.maxY; + double endZ = box.maxZ + zOffset; + + for (double x = startX; x <= endX; x += xStep) + { + for (double y = startY; y <= endY; y += yStep) + { + for (double z = startZ; z <= endZ; z += zStep) + { + Vec3d position = new Vec3d(x, y, z); + + if (raycast(new ExposureRaycastContext(position, source), raycastFactory) == null) misses++; + + hits++; + } + } + } + + return (float) misses / hits; + } + + return 0f; + } + + private static RaycastFactory getRaycastFactory(IgnoreTerrain ignoreTerrain, Set ignoreBlocks) + { + if (ignoreTerrain == IgnoreTerrain.BLAST) + { + return (context, blockPos) -> + { + if (ignoreBlocks.contains(blockPos)) + { + return null; + } + BlockState blockState = mc.world.getBlockState(blockPos); + if (blockState.getBlock().getBlastResistance() < 600) return null; + + return blockState.getCollisionShape(mc.world, blockPos).raycast(context.start(), context.end(), blockPos); + }; + } + else if (ignoreTerrain == IgnoreTerrain.ALL) + { + return (context, blockPos) -> null; + } + else + { + return (context, blockPos) -> + { + if (ignoreBlocks.contains(blockPos)) + { + return null; + } + BlockState blockState = mc.world.getBlockState(blockPos); + return blockState.getCollisionShape(mc.world, blockPos).raycast(context.start(), context.end(), blockPos); + }; + } + } + + private static RaycastFactory getRaycastFactory(IgnoreTerrain ignoreTerrain) + { + if (ignoreTerrain == IgnoreTerrain.BLAST) + { + return (context, blockPos) -> + { + BlockState blockState = mc.world.getBlockState(blockPos); + if (blockState.getBlock().getBlastResistance() < 600) return null; + + return blockState.getCollisionShape(mc.world, blockPos).raycast(context.start(), context.end(), blockPos); + }; + } + else if (ignoreTerrain == IgnoreTerrain.ALL) + { + return (context, blockPos) -> null; + } + else + { + return (context, blockPos) -> + { + BlockState blockState = mc.world.getBlockState(blockPos); + return blockState.getCollisionShape(mc.world, blockPos).raycast(context.start(), context.end(), blockPos); + }; + } + } + + /* Raycasts */ + + private static BlockHitResult raycast(ExposureRaycastContext context, RaycastFactory raycastFactory) + { + return BlockView.raycast(context.start, context.end, context, raycastFactory, ctx -> null); + } + + public record ExposureRaycastContext(Vec3d start, Vec3d end) + { + } + + @FunctionalInterface + public interface RaycastFactory extends BiFunction + { + } + + public enum IgnoreTerrain + { + ALL, + BLAST, + NONE + } + +} diff --git a/src/main/java/com/genyo/addon/utils/world/SneakBlocks.java b/src/main/java/com/genyo/addon/utils/world/SneakBlocks.java new file mode 100644 index 0000000..a6e0ae1 --- /dev/null +++ b/src/main/java/com/genyo/addon/utils/world/SneakBlocks.java @@ -0,0 +1,93 @@ +package com.genyo.addon.utils.world; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; + +import java.util.Set; + +public class SneakBlocks { + + // Constant set containing the blocks that can only be placed on if the + // player is holding shift + private static final Set SNEAK_BLOCKS; + + static + { + SNEAK_BLOCKS = Set.of( + Blocks.CHEST, + Blocks.ENDER_CHEST, + Blocks.TRAPPED_CHEST, + Blocks.CRAFTING_TABLE, + Blocks.FURNACE, + Blocks.BLAST_FURNACE, + Blocks.FLETCHING_TABLE, + Blocks.CARTOGRAPHY_TABLE, + Blocks.ENCHANTING_TABLE, + Blocks.SMITHING_TABLE, + Blocks.STONECUTTER, + Blocks.JUKEBOX, + Blocks.NOTE_BLOCK, + Blocks.SHULKER_BOX, + Blocks.BLACK_SHULKER_BOX, + Blocks.BLUE_SHULKER_BOX, + Blocks.LIGHT_BLUE_SHULKER_BOX, + Blocks.GREEN_SHULKER_BOX, + Blocks.CYAN_SHULKER_BOX, + Blocks.BROWN_SHULKER_BOX, + Blocks.GRAY_SHULKER_BOX, + Blocks.LIGHT_GRAY_SHULKER_BOX, + Blocks.LIME_SHULKER_BOX, + Blocks.MAGENTA_SHULKER_BOX, + Blocks.ORANGE_SHULKER_BOX, + Blocks.PINK_SHULKER_BOX, + Blocks.PURPLE_SHULKER_BOX, + Blocks.RED_SHULKER_BOX, + Blocks.WHITE_SHULKER_BOX, + Blocks.YELLOW_SHULKER_BOX, + Blocks.ACACIA_TRAPDOOR, + Blocks.BAMBOO_TRAPDOOR, + Blocks.BIRCH_TRAPDOOR, + Blocks.CHERRY_TRAPDOOR, + Blocks.COPPER_TRAPDOOR, + Blocks.EXPOSED_COPPER_TRAPDOOR, + Blocks.OXIDIZED_COPPER_TRAPDOOR, + Blocks.WAXED_COPPER_TRAPDOOR, + Blocks.WAXED_EXPOSED_COPPER_TRAPDOOR, + Blocks.WAXED_OXIDIZED_COPPER_TRAPDOOR, + Blocks.WEATHERED_COPPER_TRAPDOOR, + Blocks.SPRUCE_TRAPDOOR, + Blocks.WARPED_TRAPDOOR, + Blocks.IRON_TRAPDOOR, + Blocks.DARK_OAK_TRAPDOOR, + Blocks.JUNGLE_TRAPDOOR, + Blocks.MANGROVE_TRAPDOOR, + Blocks.OAK_TRAPDOOR, + Blocks.CRIMSON_TRAPDOOR + ); + } + + /** + * Returns true if the block state can only be placed on if the + * player is holding shift + * + * @return true if the block state requires sneaking to be + * placed on + */ + public static boolean isSneakBlock(BlockState state) + { + return isSneakBlock(state.getBlock()); + } + + /** + * Returns true if the block can only be placed on if the player + * is holding shift + * + * @return true if the block requires sneaking to be placed on + */ + public static boolean isSneakBlock(Block block) + { + return SNEAK_BLOCKS.contains(block); + } + +} diff --git a/src/main/resources/genyo.mixins.json b/src/main/resources/genyo.mixins.json index 0abf31e..2325ec6 100644 --- a/src/main/resources/genyo.mixins.json +++ b/src/main/resources/genyo.mixins.json @@ -3,14 +3,23 @@ "package": "com.genyo.addon.mixin", "compatibilityLevel": "JAVA_21", "client": [ - "PlayerUtilsMixin", + "AccessorBundlePacket", + "AccessorClientWorld", + "AccessorGameOptions", + "ClientPlayerInteractionManagerMixin", + "DefaultSettingsWidgetFactoryMixin", "FriendsInjector", "IEntity", - "DefaultSettingsWidgetFactoryMixin", - "AccessorGameOptions", - "ClientPlayerInteractionManagerMixin" + "MixinClientPlayerEntity", + "MixinConnectScreen", + "MixinItemUsageContext", + "MixinMinecraftClient", + "PlayerUtilsMixin" ], "injectors": { "defaultRequire": 1 - } + }, + "mixins": [ + "MixinClientConnection" + ] } From b159051f9bcd53e7bc637c8b2c44c1283dff9db8 Mon Sep 17 00:00:00 2001 From: wuritz Date: Sat, 26 Jul 2025 00:40:53 +0200 Subject: [PATCH 06/14] reorder --- src/main/java/com/genyo/addon/events/DisconnectEvent.java | 4 ---- src/main/java/com/genyo/addon/events/PlayerTickEvent.java | 4 ---- .../genyo/addon/events/{ => entity}/EntityDeathEvent.java | 2 +- .../addon/events/{ => network}/ConnectScreenEvent.java | 2 +- .../com/genyo/addon/events/network/DisconnectEvent.java | 4 ++++ .../genyo/addon/events/{ => network}/ItemDesyncEvent.java | 2 +- .../com/genyo/addon/events/network/PlayerTickEvent.java | 4 ++++ src/main/java/com/genyo/addon/managers/Managers.java | 4 ++++ .../genyo/addon/managers/{ => combat}/TotemManager.java | 6 +++--- .../genyo/addon/managers/{ => network}/NetworkManager.java | 6 +++--- .../addon/managers/{ => player}/InventoryManager.java | 7 ++++--- .../com/genyo/addon/managers/{ => world}/BlockManager.java | 3 +-- .../addon/mixin/ClientPlayerInteractionManagerMixin.java | 2 +- .../java/com/genyo/addon/mixin/MixinClientConnection.java | 2 +- .../com/genyo/addon/mixin/MixinClientPlayerEntity.java | 2 +- .../java/com/genyo/addon/mixin/MixinConnectScreen.java | 2 +- .../java/com/genyo/addon/mixin/MixinItemUsageContext.java | 3 +-- .../com/genyo/addon/modules/combat/GenyoAutoCrystal.java | 2 +- .../java/com/genyo/addon/modules/misc/GenyoWelcome.java | 5 +++-- 19 files changed, 35 insertions(+), 31 deletions(-) delete mode 100644 src/main/java/com/genyo/addon/events/DisconnectEvent.java delete mode 100644 src/main/java/com/genyo/addon/events/PlayerTickEvent.java rename src/main/java/com/genyo/addon/events/{ => entity}/EntityDeathEvent.java (88%) rename src/main/java/com/genyo/addon/events/{ => network}/ConnectScreenEvent.java (92%) create mode 100644 src/main/java/com/genyo/addon/events/network/DisconnectEvent.java rename src/main/java/com/genyo/addon/events/{ => network}/ItemDesyncEvent.java (92%) create mode 100644 src/main/java/com/genyo/addon/events/network/PlayerTickEvent.java rename src/main/java/com/genyo/addon/managers/{ => combat}/TotemManager.java (94%) rename src/main/java/com/genyo/addon/managers/{ => network}/NetworkManager.java (96%) rename src/main/java/com/genyo/addon/managers/{ => player}/InventoryManager.java (98%) rename src/main/java/com/genyo/addon/managers/{ => world}/BlockManager.java (97%) diff --git a/src/main/java/com/genyo/addon/events/DisconnectEvent.java b/src/main/java/com/genyo/addon/events/DisconnectEvent.java deleted file mode 100644 index f2368ec..0000000 --- a/src/main/java/com/genyo/addon/events/DisconnectEvent.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.genyo.addon.events; - -public class DisconnectEvent { -} diff --git a/src/main/java/com/genyo/addon/events/PlayerTickEvent.java b/src/main/java/com/genyo/addon/events/PlayerTickEvent.java deleted file mode 100644 index 64dc148..0000000 --- a/src/main/java/com/genyo/addon/events/PlayerTickEvent.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.genyo.addon.events; - -public class PlayerTickEvent { -} diff --git a/src/main/java/com/genyo/addon/events/EntityDeathEvent.java b/src/main/java/com/genyo/addon/events/entity/EntityDeathEvent.java similarity index 88% rename from src/main/java/com/genyo/addon/events/EntityDeathEvent.java rename to src/main/java/com/genyo/addon/events/entity/EntityDeathEvent.java index a3fe9d7..b10cb02 100644 --- a/src/main/java/com/genyo/addon/events/EntityDeathEvent.java +++ b/src/main/java/com/genyo/addon/events/entity/EntityDeathEvent.java @@ -1,4 +1,4 @@ -package com.genyo.addon.events; +package com.genyo.addon.events.entity; import net.minecraft.entity.LivingEntity; diff --git a/src/main/java/com/genyo/addon/events/ConnectScreenEvent.java b/src/main/java/com/genyo/addon/events/network/ConnectScreenEvent.java similarity index 92% rename from src/main/java/com/genyo/addon/events/ConnectScreenEvent.java rename to src/main/java/com/genyo/addon/events/network/ConnectScreenEvent.java index 6a71094..892c0e4 100644 --- a/src/main/java/com/genyo/addon/events/ConnectScreenEvent.java +++ b/src/main/java/com/genyo/addon/events/network/ConnectScreenEvent.java @@ -1,4 +1,4 @@ -package com.genyo.addon.events; +package com.genyo.addon.events.network; import net.minecraft.client.network.ServerAddress; import net.minecraft.client.network.ServerInfo; diff --git a/src/main/java/com/genyo/addon/events/network/DisconnectEvent.java b/src/main/java/com/genyo/addon/events/network/DisconnectEvent.java new file mode 100644 index 0000000..aa9c99c --- /dev/null +++ b/src/main/java/com/genyo/addon/events/network/DisconnectEvent.java @@ -0,0 +1,4 @@ +package com.genyo.addon.events.network; + +public class DisconnectEvent { +} diff --git a/src/main/java/com/genyo/addon/events/ItemDesyncEvent.java b/src/main/java/com/genyo/addon/events/network/ItemDesyncEvent.java similarity index 92% rename from src/main/java/com/genyo/addon/events/ItemDesyncEvent.java rename to src/main/java/com/genyo/addon/events/network/ItemDesyncEvent.java index 708f3b4..a2354f3 100644 --- a/src/main/java/com/genyo/addon/events/ItemDesyncEvent.java +++ b/src/main/java/com/genyo/addon/events/network/ItemDesyncEvent.java @@ -1,4 +1,4 @@ -package com.genyo.addon.events; +package com.genyo.addon.events.network; import meteordevelopment.meteorclient.events.Cancellable; import net.minecraft.item.ItemStack; diff --git a/src/main/java/com/genyo/addon/events/network/PlayerTickEvent.java b/src/main/java/com/genyo/addon/events/network/PlayerTickEvent.java new file mode 100644 index 0000000..149fa29 --- /dev/null +++ b/src/main/java/com/genyo/addon/events/network/PlayerTickEvent.java @@ -0,0 +1,4 @@ +package com.genyo.addon.events.network; + +public class PlayerTickEvent { +} diff --git a/src/main/java/com/genyo/addon/managers/Managers.java b/src/main/java/com/genyo/addon/managers/Managers.java index de2be2d..fd76a30 100644 --- a/src/main/java/com/genyo/addon/managers/Managers.java +++ b/src/main/java/com/genyo/addon/managers/Managers.java @@ -1,7 +1,11 @@ package com.genyo.addon.managers; +import com.genyo.addon.managers.combat.TotemManager; +import com.genyo.addon.managers.network.NetworkManager; import com.genyo.addon.managers.player.InteractionManager; +import com.genyo.addon.managers.player.InventoryManager; import com.genyo.addon.managers.player.MovementManager; +import com.genyo.addon.managers.world.BlockManager; import com.genyo.addon.render.Render3DEngine; import meteordevelopment.meteorclient.MeteorClient; diff --git a/src/main/java/com/genyo/addon/managers/TotemManager.java b/src/main/java/com/genyo/addon/managers/combat/TotemManager.java similarity index 94% rename from src/main/java/com/genyo/addon/managers/TotemManager.java rename to src/main/java/com/genyo/addon/managers/combat/TotemManager.java index af76b5a..0de24d5 100644 --- a/src/main/java/com/genyo/addon/managers/TotemManager.java +++ b/src/main/java/com/genyo/addon/managers/combat/TotemManager.java @@ -1,7 +1,7 @@ -package com.genyo.addon.managers; +package com.genyo.addon.managers.combat; -import com.genyo.addon.events.DisconnectEvent; -import com.genyo.addon.events.EntityDeathEvent; +import com.genyo.addon.events.network.DisconnectEvent; +import com.genyo.addon.events.entity.EntityDeathEvent; import meteordevelopment.meteorclient.events.packets.PacketEvent; import meteordevelopment.orbit.EventHandler; import net.minecraft.entity.Entity; diff --git a/src/main/java/com/genyo/addon/managers/NetworkManager.java b/src/main/java/com/genyo/addon/managers/network/NetworkManager.java similarity index 96% rename from src/main/java/com/genyo/addon/managers/NetworkManager.java rename to src/main/java/com/genyo/addon/managers/network/NetworkManager.java index 05db0b4..32f825c 100644 --- a/src/main/java/com/genyo/addon/managers/NetworkManager.java +++ b/src/main/java/com/genyo/addon/managers/network/NetworkManager.java @@ -1,7 +1,7 @@ -package com.genyo.addon.managers; +package com.genyo.addon.managers.network; -import com.genyo.addon.events.ConnectScreenEvent; -import com.genyo.addon.events.DisconnectEvent; +import com.genyo.addon.events.network.ConnectScreenEvent; +import com.genyo.addon.events.network.DisconnectEvent; import com.genyo.addon.mixin.AccessorClientWorld; import com.genyo.addon.utils.math.PerSecondCounter; import meteordevelopment.meteorclient.events.packets.PacketEvent; diff --git a/src/main/java/com/genyo/addon/managers/InventoryManager.java b/src/main/java/com/genyo/addon/managers/player/InventoryManager.java similarity index 98% rename from src/main/java/com/genyo/addon/managers/InventoryManager.java rename to src/main/java/com/genyo/addon/managers/player/InventoryManager.java index b35fcee..d2ce34c 100644 --- a/src/main/java/com/genyo/addon/managers/InventoryManager.java +++ b/src/main/java/com/genyo/addon/managers/player/InventoryManager.java @@ -1,7 +1,8 @@ -package com.genyo.addon.managers; +package com.genyo.addon.managers.player; -import com.genyo.addon.events.EntityDeathEvent; -import com.genyo.addon.events.ItemDesyncEvent; +import com.genyo.addon.events.entity.EntityDeathEvent; +import com.genyo.addon.events.network.ItemDesyncEvent; +import com.genyo.addon.managers.Managers; import com.genyo.addon.mixin.AccessorBundlePacket; import com.genyo.addon.utils.math.timer.CacheTimer; import com.genyo.addon.utils.math.timer.Timer; diff --git a/src/main/java/com/genyo/addon/managers/BlockManager.java b/src/main/java/com/genyo/addon/managers/world/BlockManager.java similarity index 97% rename from src/main/java/com/genyo/addon/managers/BlockManager.java rename to src/main/java/com/genyo/addon/managers/world/BlockManager.java index 8156f6e..3a2e6de 100644 --- a/src/main/java/com/genyo/addon/managers/BlockManager.java +++ b/src/main/java/com/genyo/addon/managers/world/BlockManager.java @@ -1,9 +1,8 @@ -package com.genyo.addon.managers; +package com.genyo.addon.managers.world; import meteordevelopment.meteorclient.events.packets.PacketEvent; import meteordevelopment.meteorclient.events.world.TickEvent; import meteordevelopment.orbit.EventHandler; -import net.minecraft.block.BlockState; import net.minecraft.network.packet.s2c.play.BlockBreakingProgressS2CPacket; import net.minecraft.util.math.BlockPos; diff --git a/src/main/java/com/genyo/addon/mixin/ClientPlayerInteractionManagerMixin.java b/src/main/java/com/genyo/addon/mixin/ClientPlayerInteractionManagerMixin.java index 807de1b..c7dc3ce 100644 --- a/src/main/java/com/genyo/addon/mixin/ClientPlayerInteractionManagerMixin.java +++ b/src/main/java/com/genyo/addon/mixin/ClientPlayerInteractionManagerMixin.java @@ -1,7 +1,7 @@ package com.genyo.addon.mixin; import com.genyo.addon.events.AttackBlockEvent; -import com.genyo.addon.events.ItemDesyncEvent; +import com.genyo.addon.events.network.ItemDesyncEvent; import com.genyo.addon.events.network.PacketSneakingEvent; import meteordevelopment.meteorclient.MeteorClient; import net.minecraft.block.BlockState; diff --git a/src/main/java/com/genyo/addon/mixin/MixinClientConnection.java b/src/main/java/com/genyo/addon/mixin/MixinClientConnection.java index c259825..ea0f136 100644 --- a/src/main/java/com/genyo/addon/mixin/MixinClientConnection.java +++ b/src/main/java/com/genyo/addon/mixin/MixinClientConnection.java @@ -1,6 +1,6 @@ package com.genyo.addon.mixin; -import com.genyo.addon.events.DisconnectEvent; +import com.genyo.addon.events.network.DisconnectEvent; import meteordevelopment.meteorclient.MeteorClient; import net.minecraft.network.ClientConnection; import net.minecraft.text.Text; diff --git a/src/main/java/com/genyo/addon/mixin/MixinClientPlayerEntity.java b/src/main/java/com/genyo/addon/mixin/MixinClientPlayerEntity.java index 0ee5693..ab278ff 100644 --- a/src/main/java/com/genyo/addon/mixin/MixinClientPlayerEntity.java +++ b/src/main/java/com/genyo/addon/mixin/MixinClientPlayerEntity.java @@ -1,6 +1,6 @@ package com.genyo.addon.mixin; -import com.genyo.addon.events.PlayerTickEvent; +import com.genyo.addon.events.network.PlayerTickEvent; import meteordevelopment.meteorclient.MeteorClient; import net.minecraft.client.network.ClientPlayerEntity; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/main/java/com/genyo/addon/mixin/MixinConnectScreen.java b/src/main/java/com/genyo/addon/mixin/MixinConnectScreen.java index 136bbe3..7b5f8d4 100644 --- a/src/main/java/com/genyo/addon/mixin/MixinConnectScreen.java +++ b/src/main/java/com/genyo/addon/mixin/MixinConnectScreen.java @@ -1,6 +1,6 @@ package com.genyo.addon.mixin; -import com.genyo.addon.events.ConnectScreenEvent; +import com.genyo.addon.events.network.ConnectScreenEvent; import meteordevelopment.meteorclient.MeteorClient; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.multiplayer.ConnectScreen; diff --git a/src/main/java/com/genyo/addon/mixin/MixinItemUsageContext.java b/src/main/java/com/genyo/addon/mixin/MixinItemUsageContext.java index ca80d71..c9d2d59 100644 --- a/src/main/java/com/genyo/addon/mixin/MixinItemUsageContext.java +++ b/src/main/java/com/genyo/addon/mixin/MixinItemUsageContext.java @@ -1,8 +1,7 @@ package com.genyo.addon.mixin; -import com.genyo.addon.events.ItemDesyncEvent; +import com.genyo.addon.events.network.ItemDesyncEvent; import meteordevelopment.meteorclient.MeteorClient; -import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.ItemUsageContext; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/main/java/com/genyo/addon/modules/combat/GenyoAutoCrystal.java b/src/main/java/com/genyo/addon/modules/combat/GenyoAutoCrystal.java index 460bfc8..21e8b83 100644 --- a/src/main/java/com/genyo/addon/modules/combat/GenyoAutoCrystal.java +++ b/src/main/java/com/genyo/addon/modules/combat/GenyoAutoCrystal.java @@ -1,7 +1,7 @@ package com.genyo.addon.modules.combat; import com.genyo.addon.GenyoAddon; -import com.genyo.addon.events.PlayerTickEvent; +import com.genyo.addon.events.network.PlayerTickEvent; import com.genyo.addon.events.RunTickEvent; import com.genyo.addon.managers.Managers; import com.genyo.addon.modules.GenyoModule; diff --git a/src/main/java/com/genyo/addon/modules/misc/GenyoWelcome.java b/src/main/java/com/genyo/addon/modules/misc/GenyoWelcome.java index 0c64308..e6cae89 100644 --- a/src/main/java/com/genyo/addon/modules/misc/GenyoWelcome.java +++ b/src/main/java/com/genyo/addon/modules/misc/GenyoWelcome.java @@ -73,10 +73,11 @@ private void onGameLeft(GameLeftEvent event) { @EventHandler(priority = EventPriority.HIGHEST) private void onTick(TickEvent.Pre event) { if (mc.player == null && mc.world == null) return; + if (messageQueue.isEmpty()) return; - if (!messageQueue.isEmpty()) timer++; + timer++; - if (timer >= tickDelay.get() && !messageQueue.isEmpty()) { + if (timer >= tickDelay.get()) { Message msg = messageQueue.get(0); ChatUtils.sendPlayerMsg(msg.message); timer = 0; From c92f80e88f6df90f85fd79385975c4e06a2b6d95 Mon Sep 17 00:00:00 2001 From: wuritz Date: Sat, 26 Jul 2025 16:25:05 +0200 Subject: [PATCH 07/14] discord --- c | 258 -------------- gradle.properties | 5 +- src/main/java/com/genyo/addon/GenyoAddon.java | 33 +- .../com/genyo/addon/managers/Managers.java | 3 + .../managers/{ => combat}/CombatManager.java | 3 +- .../managers/network/GDTogglerManager.java | 19 ++ .../modules/combat/GenyoAutoCrystal.java | 6 +- .../addon/modules/combat/GenyoSurroundV2.java | 59 +--- .../addon/modules/misc/GenyoDiscord.java | 317 ++++++++++++++++++ 9 files changed, 388 insertions(+), 315 deletions(-) delete mode 100644 c rename src/main/java/com/genyo/addon/managers/{ => combat}/CombatManager.java (95%) create mode 100644 src/main/java/com/genyo/addon/managers/network/GDTogglerManager.java create mode 100644 src/main/java/com/genyo/addon/modules/misc/GenyoDiscord.java diff --git a/c b/c deleted file mode 100644 index 7827b4f..0000000 --- a/c +++ /dev/null @@ -1,258 +0,0 @@ -commit 126b7ef4a72da1b9b80c0b8b585e91afec6f264d (HEAD -> brasil, origin/brasil) -Author: wuritz -Date: Sun Jul 20 11:25:06 2025 +0200 - - elvileg minden fasza - -commit 45f8d95e94d6a315877558b904a7d3643c4b4a50 -Author: wuritz -Date: Sat Jul 19 23:28:17 2025 +0200 - - genyo blink - -commit 8585ef7b6b26a394e9b5b303ffa3d317ee30e026 -Author: wuritz -Date: Sat Jul 19 20:10:08 2025 +0200 - - genyo welcome - -commit 873fef998b57508b046822ee8200c3ed2004db45 -Author: wuritz -Date: Tue Jul 15 13:17:29 2025 +0200 - - genyo module - -commit 684f30a22faf7ba289dbef206c0bce865ef1178f -Author: wuritz -Date: Mon Jul 14 23:39:58 2025 +0200 - - mostmar nem crashel 1 sizeos listaknal - -commit e4d8682cbe5e2a3bc108890f42d1089fdd2e6725 -Author: wuritz -Date: Mon Jul 14 23:24:22 2025 +0200 - - surround wooo - -commit 0b7cb632ac7c5fdc6e5f86fa99ff4fc945b4d39b -Author: wuritz -Date: Sat Jul 12 13:52:15 2025 +0200 - - in combat, csak nem mukszik a cooldown render - -commit 6fc6afd9a845901f72964ebe7d5dbee343ae05b1 -Author: wuritz -Date: Fri Jul 11 09:09:51 2025 +0200 - - mukszik a trajectory - -commit 4049f1e163b1ead7fde4b0cf5e56326339d64e20 -Author: wuritz -Date: Thu Jul 10 08:54:30 2025 +0200 - - yeee - -commit 0b86ffab0df3225bd308f400d362b9b68df0ece2 -Author: wuritz -Date: Thu Jul 10 08:43:51 2025 +0200 - - mukszik a traj - -commit 1d372e2576bffe9b3f312b62a8eb0388dbbe69e5 -Author: wuritz -Date: Tue Jul 8 10:01:27 2025 +0200 - - hulkenberg megin jobb - -commit 4a872fe9270ad40c89cd046e177036a1799aa489 -Merge: 317d537 2562cca -Author: wuritz -Date: Mon Jul 7 23:25:40 2025 +0200 - - Merge remote-tracking branch 'origin/brasil' into brasil - -commit 317d537222c3ad745e5712daddb0a85fbed3065f -Author: wuritz -Date: Mon Jul 7 23:24:19 2025 +0200 - - igen - -commit 2562ccaa0fc3630216d0144b4b13a9619176adbe -Author: wuritz -Date: Mon Jul 7 23:24:19 2025 +0200 - - igen - -commit 86890891ccacb94852b744c9ad6edcf388232e31 -Author: wuritz -Date: Mon Jul 7 23:08:09 2025 +0200 - - eltunik yooooo - -commit 7bb49127b383d418f6cbe7a77ff3ffb2b5800312 -Author: wuritz -Date: Sun Jul 6 22:08:25 2025 +0200 - - rossz wolt az accesswidener - -commit 995c1ffb840e8a0479accf95768206f63abdce69 -Author: wuritz -Date: Sun Jul 6 22:04:26 2025 +0200 - - angel hulkenberg - -commit 23c39a8ed8f0a6c5208d67391c34fa54d7feea17 -Author: wuritz -Date: Sun Jul 6 22:01:26 2025 +0200 - - angel hulkenberg - -commit df318ca9711c31389c38699bbcf473d69feea97d -Author: wuritz -Date: Sun Jun 29 11:59:01 2025 +0200 - - meg mielott elbasznam - -commit 4ea49baeb95b592d23945b11cb41050b61975587 -Author: wuritz -Date: Sun Jun 22 23:29:50 2025 +0200 - - enemies - -commit 6a30b7b503cf8d9d0f119cb4201ba21cf1da5c84 -Author: wuritz -Date: Sun Jun 22 13:25:02 2025 +0200 - - auto ez? - -commit 0dc1bf617d431bace2c47f2575f4ebd7dda7307e -Author: wuritz -Date: Sun Jun 22 12:18:42 2025 +0200 - - auto ez - -commit 85360639a1a1dcf341b09f1641fea9241f24089d -Author: wuritz -Date: Sun Jun 22 11:17:31 2025 +0200 - - fasz genyo fasz - -commit d48c94bb0ee3b401bc5b5e010871b9e271ee0304 -Author: wuritz -Date: Sun Jun 22 00:41:24 2025 +0200 - - ffffa - -commit 7f1a37ef88f596fa3fd6a40cc4807f0c896d4bd7 -Author: wuritz -Date: Sat Jun 21 12:42:02 2025 +0200 - - fass - -commit f1dc1d886e8fd37dc5f3c1a734a4cd5527572150 -Author: wuritz -Date: Sat Jun 21 12:40:38 2025 +0200 - - mixin - -commit b4451d7b8b2fc6854e7bc6e0e5fc90e94a228a1d -Author: wuritz -Date: Sat Jun 21 12:25:55 2025 +0200 - - genyo jobb - -commit 05aff3e3d7f3b0483466ee5fdad4a2de7c394668 -Author: wuritz -Date: Sat Jun 21 12:23:36 2025 +0200 - - genyo genyo mostmar jobb - -commit fe5dde06cfb19008ecb50d6b5b22fa7cd4b1da46 (tag: Genyo) -Author: wuritz -Date: Sat Jun 21 00:32:47 2025 +0200 - - genyo - -commit 35369cd1008714863ea7590ab07bc264d58aed24 -Author: wuritz -Date: Sat Jun 21 00:15:46 2025 +0200 - - genyo - -commit ab2baad46f6f690e349d16d0582ace26e64b6d66 -Author: Ritz Richárd <38112734+wuritz@users.noreply.github.com> -Date: Sat Jun 21 00:22:12 2025 +0200 - - Delete gradle directory - -commit de406708b999be0647fa935127478a0272918013 -Author: Ritz Richárd <38112734+wuritz@users.noreply.github.com> -Date: Sat Jun 21 00:22:07 2025 +0200 - - Delete src directory - -commit 98edadca233013c294cd39d0713f403e8255c588 -Author: Ritz Richárd <38112734+wuritz@users.noreply.github.com> -Date: Sat Jun 21 00:22:01 2025 +0200 - - Delete .editorconfig - -commit a8c35152f0e7f6332e124f763cf9a8c142c2bcc2 -Author: Ritz Richárd <38112734+wuritz@users.noreply.github.com> -Date: Sat Jun 21 00:21:53 2025 +0200 - - Delete .gitignore - -commit 58dc8f4c2321916ef72ac45ab81a893f2d950649 -Author: Ritz Richárd <38112734+wuritz@users.noreply.github.com> -Date: Sat Jun 21 00:21:48 2025 +0200 - - Delete LICENSE - -commit 785b4b5df405b753d2a148c1a30fa3bae3e2c631 -Author: Ritz Richárd <38112734+wuritz@users.noreply.github.com> -Date: Sat Jun 21 00:21:43 2025 +0200 - - Delete gradle.properties - -commit c817557346c4c12497d65091d86481ce9de28f51 -Author: Ritz Richárd <38112734+wuritz@users.noreply.github.com> -Date: Sat Jun 21 00:21:37 2025 +0200 - - Delete README.md - -commit f0a7e33dfa3a03163d322bae3d17ce772e78bff7 -Author: Ritz Richárd <38112734+wuritz@users.noreply.github.com> -Date: Sat Jun 21 00:21:28 2025 +0200 - - Delete gradlew - -commit 7e7f590e3cf157f693911e0a48e2399d496d3d0d -Author: Ritz Richárd <38112734+wuritz@users.noreply.github.com> -Date: Sat Jun 21 00:21:23 2025 +0200 - - Delete gradlew.bat - -commit 18e4ecb04105053425646330d501653bb9bc6d8e -Author: Ritz Richárd <38112734+wuritz@users.noreply.github.com> -Date: Sat Jun 21 00:21:18 2025 +0200 - - Delete settings.gradle.kts - -commit 01afc005e32fac81c1935fe6c974a7b09c890f32 -Author: Ritz Richárd <38112734+wuritz@users.noreply.github.com> -Date: Sat Jun 21 00:21:09 2025 +0200 - - Delete build.gradle.kts - -commit 77e40d543a743324c8a4e0d0cf56c98dd141a5cf -Author: Ritz Richárd <38112734+wuritz@users.noreply.github.com> -Date: Sat Jun 21 00:20:46 2025 +0200 - - Delete .github/workflows directory - -commit edb5a105974719a364cd2f9fc651ffff88b2792e -Author: Ritz Richárd <38112734+wuritz@users.noreply.github.com> -Date: Fri Jun 20 21:05:32 2025 +0200 - - Initial commit diff --git a/gradle.properties b/gradle.properties index a460110..233d181 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,8 +6,11 @@ yarn_mappings=1.21.4+build.8 loader_version=0.16.14 # Mod Properties -mod_version=0.7.5 +mod_version=0.7.7 maven_group=com.genyo archives_base_name=genyo-addon # Dependencies + +# DiscordRPC (https://github.com/MeteorDevelopment/java-discord-rpc) +discordipc_version=1.1 diff --git a/src/main/java/com/genyo/addon/GenyoAddon.java b/src/main/java/com/genyo/addon/GenyoAddon.java index 81b13b3..7cbff98 100644 --- a/src/main/java/com/genyo/addon/GenyoAddon.java +++ b/src/main/java/com/genyo/addon/GenyoAddon.java @@ -4,11 +4,8 @@ import com.genyo.addon.modules.combat.GenyoAutoMine; import com.genyo.addon.modules.combat.GenyoSurround; import com.genyo.addon.modules.combat.GenyoSurroundV2; -import com.genyo.addon.modules.misc.GenyoAutoEZ; -import com.genyo.addon.modules.misc.GenyoGoodbye; -import com.genyo.addon.modules.misc.GenyoWelcome; +import com.genyo.addon.modules.misc.*; import com.genyo.addon.modules.visual.AngelSexHulkenberg; -import com.genyo.addon.modules.misc.GenyoSkinBlink; import com.genyo.addon.systems.enemies.EnemiesTab; import com.genyo.addon.hud.InCombatHud; import com.genyo.addon.hud.PvPNeccessaryHud; @@ -17,14 +14,20 @@ import com.genyo.addon.systems.incombat.InCombatSystem; import com.genyo.addon.systems.incombat.InCombatTab; import com.mojang.logging.LogUtils; +import meteordevelopment.meteorclient.MeteorClient; import meteordevelopment.meteorclient.addons.GithubRepo; import meteordevelopment.meteorclient.addons.MeteorAddon; +import meteordevelopment.meteorclient.events.world.TickEvent; import meteordevelopment.meteorclient.gui.tabs.Tabs; import meteordevelopment.meteorclient.systems.Systems; import meteordevelopment.meteorclient.systems.hud.Hud; import meteordevelopment.meteorclient.systems.hud.HudGroup; import meteordevelopment.meteorclient.systems.modules.Category; import meteordevelopment.meteorclient.systems.modules.Modules; +import meteordevelopment.meteorclient.utils.misc.Version; +import meteordevelopment.orbit.EventHandler; +import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.metadata.ModMetadata; import net.minecraft.item.Items; import org.slf4j.Logger; @@ -34,10 +37,31 @@ public class GenyoAddon extends MeteorAddon { public static final Category GENYO = new Category("Genyo", Items.MILK_BUCKET.getDefaultStack()); public static final HudGroup HUD_GROUP = new HudGroup("Genyo"); + public static final String MOD_ID = "genyo"; + public static final ModMetadata MOD_META; + public static final String NAME; + public static final Version VERSION; + + static { + MOD_META = FabricLoader.getInstance().getModContainer(MOD_ID).orElseThrow().getMetadata(); + + NAME = MOD_META.getName(); + + String versionString = MOD_META.getVersion().getFriendlyString(); + if (versionString.contains("-")) versionString = versionString.split("-")[0]; + + // When building and running through IntelliJ and not Gradle it doesn't replace the version so just use a dummy + if (versionString.equals("${version}")) versionString = "0.0.0"; + + VERSION = new Version(versionString); + } + @Override public void onInitialize() { LOG.info("Genyo fasz indul genyo"); + //Systems.addPreLoadTask(() -> Modules.get().get(GenyoDiscord.class).toggle()); + // Tabs initTabs(); @@ -73,6 +97,7 @@ private void initModules(Modules modules) { modules.add(new GenyoAutoMine()); modules.add(new GenyoSurroundV2()); modules.add(new GenyoAutoCrystal()); + modules.add(new GenyoDiscord()); } private void initHUD(Hud hud) { diff --git a/src/main/java/com/genyo/addon/managers/Managers.java b/src/main/java/com/genyo/addon/managers/Managers.java index fd76a30..aad3e3b 100644 --- a/src/main/java/com/genyo/addon/managers/Managers.java +++ b/src/main/java/com/genyo/addon/managers/Managers.java @@ -1,6 +1,8 @@ package com.genyo.addon.managers; +import com.genyo.addon.managers.combat.CombatManager; import com.genyo.addon.managers.combat.TotemManager; +import com.genyo.addon.managers.network.GDTogglerManager; import com.genyo.addon.managers.network.NetworkManager; import com.genyo.addon.managers.player.InteractionManager; import com.genyo.addon.managers.player.InventoryManager; @@ -29,6 +31,7 @@ public static void subscribe() { MeteorClient.EVENT_BUS.subscribe(TOTEM); MeteorClient.EVENT_BUS.subscribe(MOVEMENT); MeteorClient.EVENT_BUS.subscribe(INTERACT); + MeteorClient.EVENT_BUS.subscribe(new GDTogglerManager()); } } diff --git a/src/main/java/com/genyo/addon/managers/CombatManager.java b/src/main/java/com/genyo/addon/managers/combat/CombatManager.java similarity index 95% rename from src/main/java/com/genyo/addon/managers/CombatManager.java rename to src/main/java/com/genyo/addon/managers/combat/CombatManager.java index e358051..d726d5d 100644 --- a/src/main/java/com/genyo/addon/managers/CombatManager.java +++ b/src/main/java/com/genyo/addon/managers/combat/CombatManager.java @@ -1,4 +1,4 @@ -package com.genyo.addon.managers; +package com.genyo.addon.managers.combat; import com.genyo.addon.events.TotemPopEvent; import com.genyo.addon.events.UnderCombatEvent; @@ -8,7 +8,6 @@ import meteordevelopment.orbit.EventHandler; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityStatuses; -import net.minecraft.entity.decoration.EndCrystalEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.packet.s2c.play.EntityStatusS2CPacket; diff --git a/src/main/java/com/genyo/addon/managers/network/GDTogglerManager.java b/src/main/java/com/genyo/addon/managers/network/GDTogglerManager.java new file mode 100644 index 0000000..ab32369 --- /dev/null +++ b/src/main/java/com/genyo/addon/managers/network/GDTogglerManager.java @@ -0,0 +1,19 @@ +package com.genyo.addon.managers.network; + +import com.genyo.addon.modules.misc.GenyoDiscord; +import com.genyo.addon.utils.GenyoChatUtils; +import meteordevelopment.meteorclient.events.world.TickEvent; +import meteordevelopment.meteorclient.systems.modules.Modules; +import meteordevelopment.orbit.EventHandler; + +public class GDTogglerManager { + + @EventHandler + private void onTick(TickEvent.Post event) { + if (!Modules.get().isActive(GenyoDiscord.class)) { + Modules.get().get(GenyoDiscord.class).toggle(); + GenyoChatUtils.sendInfo("Why would you turn it off?"); + } + } + +} diff --git a/src/main/java/com/genyo/addon/modules/combat/GenyoAutoCrystal.java b/src/main/java/com/genyo/addon/modules/combat/GenyoAutoCrystal.java index 21e8b83..ecf3076 100644 --- a/src/main/java/com/genyo/addon/modules/combat/GenyoAutoCrystal.java +++ b/src/main/java/com/genyo/addon/modules/combat/GenyoAutoCrystal.java @@ -868,10 +868,10 @@ public void onRender3D(Render3DEvent event) int boxAlpha = (int) (40 * set.getValue().getFactor()); int lineAlpha = (int) (100 * set.getValue().getFactor()); - Color boxColor = color.get(); - Color lineColor = color.get(); + Color boxColor = color.get().a(boxAlpha); + Color lineColor = color.get().a(lineAlpha); - event.renderer.box(set.getKey(), boxColor, lineColor, ShapeMode.Both, 0); + event.renderer.box(BlockPos.ofFloored(set.getKey().toCenterPos()), boxColor, lineColor, ShapeMode.Both, 0); } /*if (debugDamage.get() && renderPos1 != null) diff --git a/src/main/java/com/genyo/addon/modules/combat/GenyoSurroundV2.java b/src/main/java/com/genyo/addon/modules/combat/GenyoSurroundV2.java index d5e7a1b..b1989de 100644 --- a/src/main/java/com/genyo/addon/modules/combat/GenyoSurroundV2.java +++ b/src/main/java/com/genyo/addon/modules/combat/GenyoSurroundV2.java @@ -14,8 +14,11 @@ import meteordevelopment.meteorclient.renderer.ShapeMode; import meteordevelopment.meteorclient.settings.*; import meteordevelopment.meteorclient.systems.modules.Modules; +import meteordevelopment.meteorclient.utils.player.FindItemResult; +import meteordevelopment.meteorclient.utils.player.InvUtils; import meteordevelopment.meteorclient.utils.render.color.Color; import meteordevelopment.meteorclient.utils.render.color.SettingColor; +import meteordevelopment.meteorclient.utils.world.BlockUtils; import meteordevelopment.orbit.EventHandler; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -27,6 +30,7 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.BlockItem; import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; import net.minecraft.network.packet.Packet; import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket; import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket; @@ -223,6 +227,7 @@ public void onTick(TickEvent.Pre event) { //if (SelfTrapModule.getInstance().isEnabled()) return; if (jumpDisable.get() && (mc.player.getY() - prevY > 0.5 || mc.player.fallDistance > 1.5f)) { + sendInfo("Player jumped, disabling."); toggle(); return; } @@ -240,7 +245,7 @@ public void onTick(TickEvent.Pre event) { return; } - surround = getSurround((PlayerEntity) mc.player); + surround = getSurround(mc.player); if (surround.isEmpty()) return; if (attack.get()) attackBlockingCrystals(surround); @@ -357,18 +362,18 @@ else if (BlastResistantBlocks.isBlastResistant(blockState)) private void placeBlock(BlockPos pos, int slot) { - Managers.INTERACT.placeBlock(pos, slot, strictDirection.get(), false, true, (state, angles) -> + /*Managers.INTERACT.placeBlock(pos, slot, strictDirection.get(), false, true, (state, angles) -> { - /*if (rotate.get() && state) + if (rotate.get() && state) { Managers.ROTATION.setRotationSilent(angles[0], angles[1]); - }*/ - }); + } + });*/ - /*if (InvUtils.findInHotbar(Items.OBSIDIAN).slot() == -1) return; + if (InvUtils.findInHotbar(Items.OBSIDIAN).slot() == -1) return; FindItemResult obsidian = InvUtils.findInHotbar(Items.OBSIDIAN); - BlockUtils.place(pos, obsidian, rotate.get(), 0, true);*/ + BlockUtils.place(pos, obsidian, rotate.get(), 0, true); packets.put(pos, System.currentTimeMillis()); blocksPlaced++; } @@ -504,44 +509,6 @@ public List getPlayerBlocks(PlayerEntity entity) return playerBlocks; } - /*@EventListener - public void onRenderWorld(RenderWorldEvent event) - { - if (SelfTrapModule.getInstance().isEnabled()) - { - return; - } - if (render.get()) - { - RenderBuffers.preRender(); - for (Map.Entry set : fadeList.entrySet()) - { - set.getValue().setState(false); - int boxAlpha = (int) (40 * set.getValue().getFactor()); - int lineAlpha = (int) (100 * set.getValue().getFactor()); - Color boxColor = ColorsModule.getInstance().getColor(boxAlpha); - Color lineColor = ColorsModule.getInstance().getColor(lineAlpha); - RenderManager.renderBox(event.getMatrices(), set.getKey(), boxColor.getRGB()); - RenderManager.renderBoundingBox(event.getMatrices(), set.getKey(), 1.5f, lineColor.getRGB()); - } - RenderBuffers.postRender(); - - if (placements.isEmpty()) - { - return; - } - - for (BlockPos pos : placements) - { - Animation animation = new Animation(true, fadeTime.get()); - fadeList.put(pos, animation); - } - } - - fadeList.entrySet().removeIf(e -> - e.getValue().getFactor() == 0.0); - }*/ - @EventHandler public void onRender3D(Render3DEvent event) { if (mc.world == null && mc.player == null) return; @@ -562,8 +529,6 @@ public void onRender3D(Render3DEvent event) { Color lineColor = color.get().a(lineAlpha); event.renderer.box(BlockPos.ofFloored(set.getKey().toCenterPos()), boxColor, lineColor, ShapeMode.Both, 1); - /*RenderManager.renderBox(event.getMatrices(), set.getKey(), boxColor.getRGB()); - RenderManager.renderBoundingBox(event.getMatrices(), set.getKey(), 1.5f, lineColor.getRGB());*/ } if (placements.isEmpty()) diff --git a/src/main/java/com/genyo/addon/modules/misc/GenyoDiscord.java b/src/main/java/com/genyo/addon/modules/misc/GenyoDiscord.java new file mode 100644 index 0000000..98cc78b --- /dev/null +++ b/src/main/java/com/genyo/addon/modules/misc/GenyoDiscord.java @@ -0,0 +1,317 @@ +package com.genyo.addon.modules.misc; + +import com.genyo.addon.GenyoAddon; +import com.genyo.addon.modules.GenyoModule; +import meteordevelopment.discordipc.DiscordIPC; +import meteordevelopment.discordipc.RichPresence; +import meteordevelopment.meteorclient.MeteorClient; +import meteordevelopment.meteorclient.events.game.OpenScreenEvent; +import meteordevelopment.meteorclient.events.world.TickEvent; +import meteordevelopment.meteorclient.gui.GuiTheme; +import meteordevelopment.meteorclient.gui.WidgetScreen; +import meteordevelopment.meteorclient.gui.utils.StarscriptTextBoxRenderer; +import meteordevelopment.meteorclient.gui.widgets.WWidget; +import meteordevelopment.meteorclient.gui.widgets.pressable.WButton; +import meteordevelopment.meteorclient.settings.*; +import meteordevelopment.meteorclient.systems.modules.Modules; +import meteordevelopment.meteorclient.systems.modules.misc.DiscordPresence; +import meteordevelopment.meteorclient.utils.Utils; +import meteordevelopment.meteorclient.utils.misc.MeteorStarscript; +import meteordevelopment.orbit.EventHandler; +import meteordevelopment.starscript.Script; +import net.minecraft.client.gui.screen.*; +import net.minecraft.client.gui.screen.multiplayer.AddServerScreen; +import net.minecraft.client.gui.screen.multiplayer.ConnectScreen; +import net.minecraft.client.gui.screen.multiplayer.DirectConnectScreen; +import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; +import net.minecraft.client.gui.screen.option.*; +import net.minecraft.client.gui.screen.pack.PackScreen; +import net.minecraft.client.gui.screen.world.*; +import net.minecraft.client.realms.gui.screen.RealmsScreen; +import net.minecraft.util.Pair; +import net.minecraft.util.Util; + +import java.util.ArrayList; +import java.util.List; + +public class GenyoDiscord extends GenyoModule { + + public enum SelectMode { + Random, + Sequential + } + + private final SettingGroup sgLine1 = settings.createGroup("Line 1"); + private final SettingGroup sgLine2 = settings.createGroup("Line 2"); + + // Line 1 + + private final Setting> line1Strings = sgLine1.add(new StringListSetting.Builder() + .name("line-1-messages") + .description("Messages used for the first line.") + .defaultValue("{player}", "{server}") + .onChanged(strings -> recompileLine1()) + .renderer(StarscriptTextBoxRenderer.class) + .build() + ); + + private final Setting line1UpdateDelay = sgLine1.add(new IntSetting.Builder() + .name("line-1-update-delay") + .description("How fast to update the first line in ticks.") + .defaultValue(200) + .min(10) + .sliderRange(10, 200) + .build() + ); + + private final Setting line1SelectMode = sgLine1.add(new EnumSetting.Builder() + .name("line-1-select-mode") + .description("How to select messages for the first line.") + .defaultValue(SelectMode.Sequential) + .build() + ); + + // Line 2 + + private final Setting> line2Strings = sgLine2.add(new StringListSetting.Builder() + .name("line-2-messages") + .description("Messages used for the second line.") + .defaultValue("genyo!", "{round(server.tps, 1)} TPS", "genyoo", "{server.player_count} Players online") + .onChanged(strings -> recompileLine2()) + .renderer(StarscriptTextBoxRenderer.class) + .build() + ); + + private final Setting line2UpdateDelay = sgLine2.add(new IntSetting.Builder() + .name("line-2-update-delay") + .description("How fast to update the second line in ticks.") + .defaultValue(60) + .min(10) + .sliderRange(10, 200) + .build() + ); + + private final Setting line2SelectMode = sgLine2.add(new EnumSetting.Builder() + .name("line-2-select-mode") + .description("How to select messages for the second line.") + .defaultValue(SelectMode.Sequential) + .build() + ); + + private static final RichPresence rpc = new RichPresence(); + private SmallImage currentSmallImage; + private int ticks; + private boolean forceUpdate, lastWasInMainMenu; + + private final List