summaryrefslogtreecommitdiff
path: root/src/main/java/com/arslaancodes/arslaansmagichax
diff options
context:
space:
mode:
authorArslaan Pathan <[email protected]>2026-09-26 17:05:36 +1200
committerArslaan Pathan <[email protected]>2026-09-26 17:05:36 +1200
commit14c68eb5ba16774f581d95a39e64a7b303954ffc (patch)
tree2888ef11f47c6a639d440300ef580c247ad1bcb1 /src/main/java/com/arslaancodes/arslaansmagichax
parent766ba1c1d977442332cadaaeca93d795baa559df (diff)
downloadarslaansmagichax-14c68eb5ba16774f581d95a39e64a7b303954ffc.tar.xz
arslaansmagichax-14c68eb5ba16774f581d95a39e64a7b303954ffc.zip
migration to 26.2 - run migrateMappings with old loom then bring it back to new
Diffstat (limited to 'src/main/java/com/arslaancodes/arslaansmagichax')
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/ArslaansMagicHax.java17
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/ArslaansMagicHaxClient.java77
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/commands/CrashCommand.java49
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/commands/HackGive.java45
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/commands/HackSetblock.java78
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/commands/HackTP.java181
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/commands/HackXP.java30
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/commands/ModuleSuggestionProvider.java26
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/commands/ModuleToggleCommand.java44
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/events/PacketEvent.java29
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/events/ReceivePacketEventBus.java18
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/events/SendPacketEventBus.java18
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/mixin/AbstractBlockMixin.java33
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/mixin/AbstractBlockStateMixin.java30
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/mixin/BlockMixin.java25
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/mixin/ClientCommonNetworkHandlerMixin.java23
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/mixin/ClientConnectionMixin.java36
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/mixin/DoubleSliderCallbacksMixin.java19
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/mixin/MinecraftClientMixin.java15
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/mixin/PlayerEntityMixin.java17
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/mixin/PlayerInputC2SPacketMixin.java16
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/mixin/PlayerInteractEntityC2SPacketMixin.java16
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/mixin/PlayerMoveC2SPacketMixin.java16
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/mixin/SplashTextResourceSupplierMixin.java22
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/mixininterface/IPacket.java6
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/modules/Category.java9
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/modules/Module.java101
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/modules/ModuleManager.java167
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/AutoClicker.java47
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/ClickGUI.java23
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Criticals.java86
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/FakeSneak.java29
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Flight.java61
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Fullbright.java85
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/GUN.java32
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/GhostScaffold.java23
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/GravityModifier.java31
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/HideModulesHUD.java12
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Jetpack.java32
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/NoAttackCooldown.java12
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/NoFall.java25
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/NoPackets.java23
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Poseidon.java21
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Speed.java58
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Spider.java33
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/TickRateLock.java58
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Waterwalk.java28
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Xray.java65
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/modules/settings/BooleanSetting.java33
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/modules/settings/ModeSetting.java65
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/modules/settings/NumberSetting.java66
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/modules/settings/Setting.java25
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/ClickGUIScreen.java82
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/Frame.java124
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/ModuleButton.java97
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/setting/CheckBox.java50
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/setting/Component.java37
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/setting/KeybindingSelector.java74
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/setting/ModeBox.java56
-rw-r--r--src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/setting/Slider.java92
60 files changed, 2748 insertions, 0 deletions
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/ArslaansMagicHax.java b/src/main/java/com/arslaancodes/arslaansmagichax/ArslaansMagicHax.java
new file mode 100644
index 0000000..493e8d7
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/ArslaansMagicHax.java
@@ -0,0 +1,17 @@
+package com.arslaancodes.arslaansmagichax;
+
+import net.fabricmc.api.ModInitializer;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ArslaansMagicHax implements ModInitializer {
+ public static final String MOD_ID = "arslaansmagichax";
+
+ public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
+
+ @Override
+ public void onInitialize() {
+ LOGGER.info("mod initialized :)");
+ }
+} \ No newline at end of file
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/ArslaansMagicHaxClient.java b/src/main/java/com/arslaancodes/arslaansmagichax/ArslaansMagicHaxClient.java
new file mode 100644
index 0000000..318fd4e
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/ArslaansMagicHaxClient.java
@@ -0,0 +1,77 @@
+package com.arslaancodes.arslaansmagichax;
+
+import net.fabricmc.api.ClientModInitializer;
+import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
+import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
+import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
+import com.arslaancodes.arslaansmagichax.commands.*;
+import com.arslaancodes.arslaansmagichax.modules.ModuleManager;
+import com.arslaancodes.arslaansmagichax.modules.impl.*;
+
+public class ArslaansMagicHaxClient implements ClientModInitializer {
+ public static Flight flight = new Flight();
+ public static NoFall noFall = new NoFall();
+ public static Waterwalk waterwalk = new Waterwalk();
+ public static NoAttackCooldown noAttackCooldown = new NoAttackCooldown();
+ public static GhostScaffold ghostScaffold = new GhostScaffold();
+ public static ClickGUI clickGUI = new ClickGUI();
+ public static FakeSneak fakeSneak = new FakeSneak();
+ public static NoPackets noPackets = new NoPackets();
+ public static Criticals criticals = new Criticals();
+ public static AutoClicker autoClicker = new AutoClicker();
+ public static GUN gun = new GUN();
+ public static Spider spider = new Spider();
+ public static Speed speed = new Speed();
+ public static Fullbright fullbright = new Fullbright();
+ public static Jetpack jetpack = new Jetpack();
+ public static GravityModifier gravityModifier = new GravityModifier();
+ public static Xray xray = new Xray();
+ public static HideModulesHUD hideModulesHUD = new HideModulesHUD();
+ public static Poseidon poseidon = new Poseidon();
+ public static TickRateLock tickRateLock = new TickRateLock();
+
+ @Override
+ public void onInitializeClient() {
+ ClientCommandRegistrationCallback.EVENT.register(HackTP::register);
+ ClientCommandRegistrationCallback.EVENT.register(ModuleToggleCommand::register);
+ ClientCommandRegistrationCallback.EVENT.register(HackXP::register);
+ ClientCommandRegistrationCallback.EVENT.register(HackSetblock::register);
+ ClientCommandRegistrationCallback.EVENT.register(HackGive::register);
+ ClientCommandRegistrationCallback.EVENT.register(CrashCommand::register); // crashes the game for the funny
+
+ ModuleManager.INSTANCE.register(flight);
+ ModuleManager.INSTANCE.register(noFall);
+ ModuleManager.INSTANCE.register(waterwalk);
+ ModuleManager.INSTANCE.register(noAttackCooldown);
+ ModuleManager.INSTANCE.register(ghostScaffold);
+ ModuleManager.INSTANCE.register(clickGUI);
+ ModuleManager.INSTANCE.register(fakeSneak);
+ ModuleManager.INSTANCE.register(noPackets);
+ ModuleManager.INSTANCE.register(criticals);
+ ModuleManager.INSTANCE.register(autoClicker);
+ ModuleManager.INSTANCE.register(gun);
+ ModuleManager.INSTANCE.register(spider);
+ ModuleManager.INSTANCE.register(speed);
+ ModuleManager.INSTANCE.register(fullbright);
+ ModuleManager.INSTANCE.register(jetpack);
+ ModuleManager.INSTANCE.register(gravityModifier);
+ ModuleManager.INSTANCE.register(xray);
+ ModuleManager.INSTANCE.register(hideModulesHUD);
+ ModuleManager.INSTANCE.register(poseidon);
+ ModuleManager.INSTANCE.register(tickRateLock);
+
+ ModuleManager.INSTANCE.registerHUD();
+
+ ModuleManager.INSTANCE.loadModuleStates();
+ ModuleManager.INSTANCE.saveModuleStates(); // clean up garbage e.g. someone types in "obama.havedih=barapbarapba"
+
+ ClientTickEvents.END_CLIENT_TICK.register(mc -> {
+ ModuleManager.tick();
+ }
+ );
+
+ ClientLifecycleEvents.CLIENT_STOPPING.register(client -> {
+ ModuleManager.INSTANCE.close();
+ });
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/commands/CrashCommand.java b/src/main/java/com/arslaancodes/arslaansmagichax/commands/CrashCommand.java
new file mode 100644
index 0000000..09be43c
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/commands/CrashCommand.java
@@ -0,0 +1,49 @@
+package com.arslaancodes.arslaansmagichax.commands;
+
+import com.mojang.brigadier.CommandDispatcher;
+import com.mojang.brigadier.arguments.IntegerArgumentType;
+import com.mojang.brigadier.arguments.StringArgumentType;
+import com.mojang.brigadier.context.CommandContext;
+import com.mojang.brigadier.exceptions.CommandSyntaxException;
+import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
+import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
+import net.minecraft.client.Minecraft;
+import net.minecraft.commands.CommandBuildContext;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.sounds.SoundEvent;
+
+public class CrashCommand {
+ public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher, CommandBuildContext access) {
+ dispatcher.register(ClientCommandManager.literal("surprise")
+ .executes(CrashCommand::run)
+ );
+ }
+
+ private static int run(CommandContext<FabricClientCommandSource> ctx) {
+ Minecraft client = Minecraft.getInstance();
+
+ client.execute(() -> {
+ client.player.playSound(
+ SoundEvent.createVariableRangeEvent(ResourceLocation.parse("minecraft:entity.evoker.prepare_wololo")),
+ 1.0f, // volume
+ 1.0f // pitch
+ );
+ });
+
+ new Thread(() -> {
+ try { Thread.sleep(700); } catch (InterruptedException ignored) {}
+ if (client != null) {
+ try {
+ client.player = null;
+ client.cameraEntity = null;
+ client.screen = null;
+ client.hitResult = null;
+ client.crosshairPickEntity = null;
+ } catch (Throwable ignored) {}
+ }
+ Runtime.getRuntime().halt(1);
+ }, "surprise-halt-thread").start();
+
+ return 1;
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/commands/HackGive.java b/src/main/java/com/arslaancodes/arslaansmagichax/commands/HackGive.java
new file mode 100644
index 0000000..db36136
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/commands/HackGive.java
@@ -0,0 +1,45 @@
+package com.arslaancodes.arslaansmagichax.commands;
+
+import com.mojang.brigadier.CommandDispatcher;
+import com.mojang.brigadier.arguments.IntegerArgumentType;
+import com.mojang.brigadier.arguments.StringArgumentType;
+import com.mojang.brigadier.context.CommandContext;
+import com.mojang.brigadier.exceptions.CommandSyntaxException;
+import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
+import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
+import net.minecraft.client.Minecraft;
+import net.minecraft.commands.CommandBuildContext;
+import net.minecraft.core.registries.BuiltInRegistries;
+import net.minecraft.network.chat.Component;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.world.item.Item;
+import net.minecraft.world.item.ItemStack;
+
+public class HackGive {
+ public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher, CommandBuildContext access) {
+ dispatcher.register(ClientCommandManager.literal("hackgive")
+ .then(ClientCommandManager.argument("item", StringArgumentType.string())
+ .then(ClientCommandManager.argument("amount", IntegerArgumentType.integer(1))
+ .executes(HackGive::run)
+ )
+ )
+ );
+ }
+
+ private static int run(CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException {
+ Minecraft client = Minecraft.getInstance();
+ if (client.level == null || client.player == null) return 0;
+
+ String itemId = StringArgumentType.getString(context, "item");
+ int amount = IntegerArgumentType.getInteger(context, "amount");
+ Item item = BuiltInRegistries.ITEM.getValue(ResourceLocation.parse(itemId));
+ if (item == null) {
+ context.getSource().sendError(Component.literal("Unknown item: " + itemId));
+ return 0;
+ }
+
+ ItemStack stack = new ItemStack(item, amount);
+ client.player.getInventory().add(stack);
+ return 1;
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/commands/HackSetblock.java b/src/main/java/com/arslaancodes/arslaansmagichax/commands/HackSetblock.java
new file mode 100644
index 0000000..a26d0e9
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/commands/HackSetblock.java
@@ -0,0 +1,78 @@
+package com.arslaancodes.arslaansmagichax.commands;
+
+import com.mojang.brigadier.CommandDispatcher;
+import com.mojang.brigadier.arguments.IntegerArgumentType;
+import com.mojang.brigadier.arguments.StringArgumentType;
+import com.mojang.brigadier.context.CommandContext;
+import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
+import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
+import net.minecraft.client.Minecraft;
+import net.minecraft.commands.CommandBuildContext;
+import net.minecraft.core.BlockPos;
+import net.minecraft.core.registries.BuiltInRegistries;
+import net.minecraft.network.chat.Component;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.world.level.block.Block;
+import net.minecraft.world.level.block.state.BlockState;
+
+public class HackSetblock {
+ public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher, CommandBuildContext access) {
+ dispatcher.register(ClientCommandManager.literal("hacksetblock")
+ .then(ClientCommandManager.argument("block", StringArgumentType.string())
+ // Case: just block -> place at player's feet
+ .executes(HackSetblock::runAtFeet)
+
+ // Case: block + xyz -> place at given position
+ .then(ClientCommandManager.argument("x", IntegerArgumentType.integer())
+ .then(ClientCommandManager.argument("y", IntegerArgumentType.integer())
+ .then(ClientCommandManager.argument("z", IntegerArgumentType.integer())
+ .executes(HackSetblock::runAtPos)
+ )
+ )
+ )
+ )
+ );
+ }
+
+ private static int runAtFeet(CommandContext<FabricClientCommandSource> context) {
+ Minecraft client = Minecraft.getInstance();
+ if (client.level == null || client.player == null) return 0;
+
+ String blockId = StringArgumentType.getString(context, "block");
+ Block block = BuiltInRegistries.BLOCK.getValue(ResourceLocation.parse(blockId));
+ if (block == null) {
+ context.getSource().sendError(Component.literal("Unknown block: " + blockId));
+ return 0;
+ }
+
+ BlockPos pos = client.player.blockPosition();
+ BlockState blockState = block.defaultBlockState();
+
+ client.level.setBlockAndUpdate(pos, blockState);
+
+ return 1;
+ }
+
+ private static int runAtPos(CommandContext<FabricClientCommandSource> context) {
+ Minecraft client = Minecraft.getInstance();
+ if (client.level == null) return 0;
+
+ String blockId = StringArgumentType.getString(context, "block");
+ int x = IntegerArgumentType.getInteger(context, "x");
+ int y = IntegerArgumentType.getInteger(context, "y");
+ int z = IntegerArgumentType.getInteger(context, "z");
+
+ Block block = BuiltInRegistries.BLOCK.getValue(ResourceLocation.parse(blockId));
+ if (block == null) {
+ context.getSource().sendError(Component.literal("Unknown block: " + blockId));
+ return 0;
+ }
+
+ BlockPos pos = new BlockPos(x, y, z);
+ BlockState blockState = block.defaultBlockState();
+
+ client.level.setBlockAndUpdate(pos, blockState);
+
+ return 1;
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/commands/HackTP.java b/src/main/java/com/arslaancodes/arslaansmagichax/commands/HackTP.java
new file mode 100644
index 0000000..6c376ab
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/commands/HackTP.java
@@ -0,0 +1,181 @@
+package com.arslaancodes.arslaansmagichax.commands;
+
+import com.mojang.brigadier.CommandDispatcher;
+import com.mojang.brigadier.arguments.IntegerArgumentType;
+import com.mojang.brigadier.arguments.StringArgumentType;
+import com.mojang.brigadier.context.CommandContext;
+import com.mojang.brigadier.exceptions.CommandSyntaxException;
+import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
+import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
+import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.player.LocalPlayer;
+import net.minecraft.commands.CommandBuildContext;
+import net.minecraft.core.BlockPos;
+import net.minecraft.network.chat.Component;
+import net.minecraft.world.level.Level;
+import java.util.LinkedList;
+import java.util.Queue;
+
+public class HackTP {
+ private static final Queue<double[]> stepQueue = new LinkedList<>();
+ private static int packetsPerTick = 5;
+
+ public static BlockPos findClosestAirNearPosition(int x, int y, int z) {
+ Level world = Minecraft.getInstance().level;
+ if (world == null) return null;
+
+ for (int blockY = y; blockY <= world.getHeight(); blockY++) {
+ BlockPos pos = new BlockPos(x, blockY, z);
+ if (world.getBlockState(pos).isAir() && world.getBlockState(pos.above()).isAir()) {
+ return pos;
+ }
+ }
+
+ for (int blockY = y; blockY >= 0; blockY--) {
+ BlockPos pos = new BlockPos(x, blockY, z);
+ if (world.getBlockState(pos).isAir() && world.getBlockState(pos.above()).isAir()) {
+ return pos;
+ }
+ }
+ return null;
+ }
+
+ private static int computeSafePacketsPerTick(int requestedSpeed) {
+ final int STEP_HORIZ = 2;
+ final double SAFE_HORIZ = 8.5; // server maximum horizontal move
+
+ int allowed = (int) Math.floor(SAFE_HORIZ / STEP_HORIZ);
+ if (allowed < 1) allowed = 1;
+
+ return Math.max(1, Math.min(requestedSpeed, allowed));
+ }
+
+ private static double parseCoordinate(String arg, double current) {
+ if (arg.startsWith("c")) {
+ if (arg.length() == 1) return current;
+ return current + Double.parseDouble(arg.substring(1));
+ } else {
+ return Double.parseDouble(arg);
+ }
+ }
+
+ public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher, CommandBuildContext access) {
+ dispatcher.register(ClientCommandManager.literal("hacktp")
+ .then(ClientCommandManager.argument("x", StringArgumentType.word())
+ .then(ClientCommandManager.argument("y", StringArgumentType.word())
+ .then(ClientCommandManager.argument("z", StringArgumentType.word())
+ .then(ClientCommandManager.argument("speed", IntegerArgumentType.integer(0, 25))
+ .executes(HackTP::run)
+ )
+ )
+ )
+ )
+ );
+
+// ClientTickEvents.END_CLIENT_TICK.register(client -> {
+// if (!stepQueue.isEmpty() && client.player != null) {
+// double[] pos = stepQueue.poll();
+//
+// client.getNetworkHandler().sendPacket(
+// new PlayerMoveC2SPacket.PositionAndOnGround(pos[0], pos[1], pos[2], true, client.player.horizontalCollision)
+// );
+//
+// client.player.setPos(pos[0], pos[1], pos[2]);
+//
+// client.player.sendMessage(Text.literal("Teleported to " + pos[0] + " " + pos[1] + " " + pos[2]), false);
+// }
+// });
+ ClientTickEvents.END_CLIENT_TICK.register(client -> {
+ if (!stepQueue.isEmpty() && client.player != null) {
+ for (int i = 0; i < packetsPerTick && !stepQueue.isEmpty(); i++) {
+ double[] pos = stepQueue.poll();
+
+// client.getNetworkHandler().sendPacket(
+// new PlayerMoveC2SPacket.PositionAndOnGround(
+// pos[0], pos[1], pos[2], true, client.player.horizontalCollision
+// )
+// );
+
+ client.player.setPosRaw(pos[0], pos[1], pos[2]);
+
+ client.player.displayClientMessage(Component.literal("Teleported to " + pos[0] + " " + pos[1] + " " + pos[2] + " with packetsPerTick/speed " + packetsPerTick), false);
+ }
+ }
+ });
+ }
+
+ private static int run(CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException {
+ int speed = IntegerArgumentType.getInteger(context, "speed");
+
+ LocalPlayer player = context.getSource().getPlayer();
+ if (player == null) {
+ context.getSource().sendFeedback(Component.literal("No player found."));
+ return -1;
+ }
+
+ double currentX = player.getX();
+ double currentY = player.getY();
+ double currentZ = player.getZ();
+
+ String xArg = context.getArgument("x", String.class);
+ String yArg = context.getArgument("y", String.class);
+ String zArg = context.getArgument("z", String.class);
+
+ double targetX = parseCoordinate(xArg, currentX);
+ double targetY = parseCoordinate(yArg, currentY);
+ double targetZ = parseCoordinate(zArg, currentZ);
+
+ if (speed < 1) {
+ packetsPerTick = computeSafePacketsPerTick(packetsPerTick);
+ } else {
+ packetsPerTick = computeSafePacketsPerTick(speed);
+ }
+
+ context.getSource().sendFeedback(Component.literal("Using " + packetsPerTick + " packets/tick (requested " + speed + ")"));
+
+ int stepX = (targetX > currentX) ? 2 : -2;
+ int stepY = (targetY > currentY) ? 2 : -2;
+ int stepZ = (targetZ > currentZ) ? 2 : -2;
+
+ for (int i = 1; i <= 8; i++) {
+ stepQueue.add(new double[]{currentX, currentY, currentZ}); // I don't know how this works but it makes Y more reliable (go through more blocks on the Y axis?)
+ }
+ while ((stepY > 0 && currentY < targetY) || (stepY < 0 && currentY > targetY)) {
+ currentY += stepY;
+ if ((stepY > 0 && currentY > targetY) || (stepY < 0 && currentY < targetY)) currentY = targetY;
+ stepQueue.add(new double[]{currentX, currentY, currentZ});
+ context.getSource().sendFeedback(Component.literal(
+ "Queued teleport to " + currentX + " " + currentY + " " + currentZ
+ ));
+ }
+
+ while ((stepX > 0 && currentX < targetX) || (stepX < 0 && currentX > targetX)) {
+ currentX += stepX;
+ if ((stepX > 0 && currentX > targetX) || (stepX < 0 && currentX < targetX)) currentX = targetX;
+
+ BlockPos airPos = findClosestAirNearPosition((int) currentX, (int) currentY, (int) currentZ);
+ if (airPos != null) currentY = airPos.getY();
+
+ stepQueue.add(new double[]{currentX, currentY, currentZ});
+ context.getSource().sendFeedback(Component.literal(
+ "Queued teleport to " + currentX + " " + currentY + " " + currentZ
+ ));
+ }
+
+ while ((stepZ > 0 && currentZ < targetZ) || (stepZ < 0 && currentZ > targetZ)) {
+ currentZ += stepZ;
+ if ((stepZ > 0 && currentZ > targetZ) || (stepZ < 0 && currentZ < targetZ)) currentZ = targetZ;
+
+ BlockPos airPos = findClosestAirNearPosition((int) currentX, (int) currentY, (int) currentZ);
+ if (airPos != null) currentY = airPos.getY();
+
+ stepQueue.add(new double[]{currentX, currentY, currentZ});
+ context.getSource().sendFeedback(Component.literal(
+ "Queued teleport to " + currentX + " " + currentY + " " + currentZ
+ ));
+ }
+
+ return 1;
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/commands/HackXP.java b/src/main/java/com/arslaancodes/arslaansmagichax/commands/HackXP.java
new file mode 100644
index 0000000..024f5c4
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/commands/HackXP.java
@@ -0,0 +1,30 @@
+package com.arslaancodes.arslaansmagichax.commands;
+
+import com.mojang.brigadier.CommandDispatcher;
+import com.mojang.brigadier.arguments.IntegerArgumentType;
+import com.mojang.brigadier.arguments.StringArgumentType;
+import com.mojang.brigadier.context.CommandContext;
+import com.mojang.brigadier.exceptions.CommandSyntaxException;
+import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
+import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
+import net.minecraft.client.Minecraft;
+import net.minecraft.commands.CommandBuildContext;
+
+public class HackXP {
+ public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher, CommandBuildContext access) {
+ dispatcher.register(ClientCommandManager.literal("hackxp")
+ .then(ClientCommandManager.argument("xp", IntegerArgumentType.integer())
+ .executes(HackXP::run)
+ )
+ );
+ }
+
+ private static int run(CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException {
+ int xp = IntegerArgumentType.getInteger(context,"xp");
+
+ if (Minecraft.getInstance().player == null) return -1;
+ Minecraft.getInstance().player.experienceLevel += xp;
+
+ return 1;
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/commands/ModuleSuggestionProvider.java b/src/main/java/com/arslaancodes/arslaansmagichax/commands/ModuleSuggestionProvider.java
new file mode 100644
index 0000000..881ddd6
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/commands/ModuleSuggestionProvider.java
@@ -0,0 +1,26 @@
+package com.arslaancodes.arslaansmagichax.commands;
+
+import com.mojang.brigadier.context.CommandContext;
+import com.mojang.brigadier.exceptions.CommandSyntaxException;
+import com.mojang.brigadier.suggestion.SuggestionProvider;
+import com.mojang.brigadier.suggestion.Suggestions;
+import com.mojang.brigadier.suggestion.SuggestionsBuilder;
+import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
+import com.arslaancodes.arslaansmagichax.modules.Module;
+import com.arslaancodes.arslaansmagichax.modules.ModuleManager;
+
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+
+public class ModuleSuggestionProvider implements SuggestionProvider<FabricClientCommandSource> {
+ @Override
+ public CompletableFuture<Suggestions> getSuggestions(CommandContext<FabricClientCommandSource> context, SuggestionsBuilder builder) throws CommandSyntaxException {
+ List<Module> modules = ModuleManager.getAllModules();
+
+ for (Module module : modules) {
+ builder.suggest(module.getName());
+ }
+
+ return builder.buildFuture();
+ }
+} \ No newline at end of file
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/commands/ModuleToggleCommand.java b/src/main/java/com/arslaancodes/arslaansmagichax/commands/ModuleToggleCommand.java
new file mode 100644
index 0000000..60e6b52
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/commands/ModuleToggleCommand.java
@@ -0,0 +1,44 @@
+package com.arslaancodes.arslaansmagichax.commands;
+
+import com.mojang.brigadier.CommandDispatcher;
+import com.mojang.brigadier.arguments.IntegerArgumentType;
+import com.mojang.brigadier.arguments.StringArgumentType;
+import com.mojang.brigadier.context.CommandContext;
+import com.mojang.brigadier.exceptions.CommandSyntaxException;
+import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
+import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
+import net.minecraft.commands.CommandBuildContext;
+import net.minecraft.network.chat.Component;
+import com.arslaancodes.arslaansmagichax.modules.ModuleManager;
+
+public class ModuleToggleCommand {
+ public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher, CommandBuildContext access) {
+ dispatcher.register(
+ ClientCommandManager.literal("module")
+ .then(
+ ClientCommandManager.literal("toggle")
+ .then(
+ ClientCommandManager.argument("moduleName", StringArgumentType.word())
+ .suggests(new ModuleSuggestionProvider())
+ .executes(ModuleToggleCommand::run)
+ )
+ )
+ );
+ }
+
+ private static int run(CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException {
+ String moduleName = StringArgumentType.getString(context, "moduleName");
+
+ ModuleManager.getAllModules().stream()
+ .filter(m -> m.getName().equalsIgnoreCase(moduleName))
+ .findFirst()
+ .ifPresentOrElse(module -> {
+ module.toggle();
+ context.getSource().sendFeedback(Component.literal(
+ "Toggled module " + module.getName() + " to " + (module.isEnabled() ? "ON" : "OFF")
+ ));
+ }, () -> context.getSource().sendError(Component.literal("Module not found: " + moduleName)));
+
+ return 1;
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/events/PacketEvent.java b/src/main/java/com/arslaancodes/arslaansmagichax/events/PacketEvent.java
new file mode 100644
index 0000000..494eb7a
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/events/PacketEvent.java
@@ -0,0 +1,29 @@
+package com.arslaancodes.arslaansmagichax.events;
+
+import net.minecraft.network.protocol.Packet;
+
+public final class PacketEvent {
+ private PacketEvent() {}
+
+ public static final class Send {
+ private final Packet<?> packet;
+ private boolean cancelled;
+
+ public Send(Packet<?> packet) { this.packet = packet; }
+
+ public Packet<?> packet() { return packet; }
+ public void setCancelled(boolean c) { cancelled = c; }
+ public boolean isCancelled() { return cancelled; }
+ }
+
+ public static final class Receive {
+ private final Packet<?> packet;
+ private boolean cancelled;
+
+ public Receive(Packet<?> packet) { this.packet = packet; }
+
+ public Packet<?> packet() { return packet; }
+ public void setCancelled(boolean c) { cancelled = c; }
+ public boolean isCancelled() { return cancelled; }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/events/ReceivePacketEventBus.java b/src/main/java/com/arslaancodes/arslaansmagichax/events/ReceivePacketEventBus.java
new file mode 100644
index 0000000..2f6b498
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/events/ReceivePacketEventBus.java
@@ -0,0 +1,18 @@
+package com.arslaancodes.arslaansmagichax.events;
+
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.function.Consumer;
+
+public class ReceivePacketEventBus {
+ private static final List<Consumer<PacketEvent.Receive>> listeners = new CopyOnWriteArrayList<>();
+
+ public static void register(Consumer<PacketEvent.Receive> listener) {
+ listeners.add(listener);
+ }
+
+ public static void post(PacketEvent.Receive ev) {
+ for (Consumer<PacketEvent.Receive> l : listeners) l.accept(ev);
+ }
+}
+
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/events/SendPacketEventBus.java b/src/main/java/com/arslaancodes/arslaansmagichax/events/SendPacketEventBus.java
new file mode 100644
index 0000000..1832ab4
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/events/SendPacketEventBus.java
@@ -0,0 +1,18 @@
+package com.arslaancodes.arslaansmagichax.events;
+
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.function.Consumer;
+
+public class SendPacketEventBus {
+ private static final List<Consumer<PacketEvent.Send>> listeners = new CopyOnWriteArrayList<>();
+
+ public static void register(Consumer<PacketEvent.Send> listener) {
+ listeners.add(listener);
+ }
+
+ public static void post(PacketEvent.Send ev) {
+ for (Consumer<PacketEvent.Send> l : listeners) l.accept(ev);
+ }
+}
+
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/mixin/AbstractBlockMixin.java b/src/main/java/com/arslaancodes/arslaansmagichax/mixin/AbstractBlockMixin.java
new file mode 100644
index 0000000..4a3ddc9
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/mixin/AbstractBlockMixin.java
@@ -0,0 +1,33 @@
+package com.arslaancodes.arslaansmagichax.mixin;
+
+import com.arslaancodes.arslaansmagichax.ArslaansMagicHaxClient;
+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 java.util.Objects;
+import net.minecraft.client.Minecraft;
+import net.minecraft.core.BlockPos;
+import net.minecraft.world.level.BlockGetter;
+import net.minecraft.world.level.block.state.BlockBehaviour;
+import net.minecraft.world.level.block.state.BlockState;
+
+@Mixin(BlockBehaviour.class)
+public class AbstractBlockMixin {
+ private static Minecraft mc = Minecraft.getInstance();
+
+ @Inject(method = "getShadeBrightness", at = @At("HEAD"), cancellable = true)
+ private void onGetAmbientOcclusionLightLevel(BlockState state, BlockGetter world, BlockPos pos, CallbackInfoReturnable<Float> cir) {
+ if (mc == null) mc = Minecraft.getInstance(); // just in case :)
+ if (mc != null) {
+ if (mc.level != null && (ArslaansMagicHaxClient.fullbright.isEnabled())) {
+ if (Objects.equals(ArslaansMagicHaxClient.fullbright.mode.getMode(), "Break AO Renderer")) {
+ cir.setReturnValue(15.0F); // over the limit of 1.0F, breaks the ambient occlusion renderer and messes everything up :) yay
+ } else {
+ cir.setReturnValue(1.0F);
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/mixin/AbstractBlockStateMixin.java b/src/main/java/com/arslaancodes/arslaansmagichax/mixin/AbstractBlockStateMixin.java
new file mode 100644
index 0000000..cfdc76f
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/mixin/AbstractBlockStateMixin.java
@@ -0,0 +1,30 @@
+/*
+THIS FILE EXISTS AS AN ARCHIVE!!!!
+Injecting into getLuminance causes TONS of weird crashes and issues related to world rendering
+New logic is implemented in AbstractBlockMixin.java
+ */
+package com.arslaancodes.arslaansmagichax.mixin;
+
+import com.arslaancodes.arslaansmagichax.ArslaansMagicHaxClient;
+import net.minecraft.client.Minecraft;
+import net.minecraft.world.level.block.state.BlockBehaviour.BlockStateBase;
+import net.minecraft.world.level.block.state.BlockState;
+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;
+
+@Mixin(BlockStateBase.class)
+public class AbstractBlockStateMixin {
+ private static Minecraft mc = Minecraft.getInstance();
+
+ @Inject(method = "getLightEmission", at = @At("HEAD"), cancellable = true)
+ private void onGetLuminance(CallbackInfoReturnable<Integer> cir) {
+ BlockStateBase state = (BlockStateBase)(Object)this;
+
+ if (mc.level != null && (ArslaansMagicHaxClient.xray.isEnabled() && ArslaansMagicHaxClient.xray.isInterestingBlock((BlockState) state) || ArslaansMagicHaxClient.fullbright.isEnabled())) {
+ cir.setReturnValue(15);
+ }
+ }
+}
+
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/mixin/BlockMixin.java b/src/main/java/com/arslaancodes/arslaansmagichax/mixin/BlockMixin.java
new file mode 100644
index 0000000..2a088c2
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/mixin/BlockMixin.java
@@ -0,0 +1,25 @@
+package com.arslaancodes.arslaansmagichax.mixin;
+
+import com.arslaancodes.arslaansmagichax.ArslaansMagicHaxClient;
+import net.minecraft.core.Direction;
+import net.minecraft.world.level.block.Block;
+import net.minecraft.world.level.block.state.BlockState;
+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;
+
+@Mixin(Block.class)
+public class BlockMixin {
+
+ @Inject(method = "shouldRenderFace", at = @At("HEAD"), cancellable = true)
+ private static void onShouldDrawSide(BlockState state, BlockState otherState, Direction side, CallbackInfoReturnable<Boolean> cir) {
+ if (ArslaansMagicHaxClient.xray.isEnabled()) {
+ if (ArslaansMagicHaxClient.xray.isInterestingBlock(state)) {
+ cir.setReturnValue(true);
+ return;
+ }
+ cir.setReturnValue(false);
+ }
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/mixin/ClientCommonNetworkHandlerMixin.java b/src/main/java/com/arslaancodes/arslaansmagichax/mixin/ClientCommonNetworkHandlerMixin.java
new file mode 100644
index 0000000..30390ee
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/mixin/ClientCommonNetworkHandlerMixin.java
@@ -0,0 +1,23 @@
+package com.arslaancodes.arslaansmagichax.mixin;
+
+import com.arslaancodes.arslaansmagichax.events.SendPacketEventBus;
+import net.minecraft.client.multiplayer.ClientCommonPacketListenerImpl;
+import net.minecraft.network.protocol.Packet;
+import com.arslaancodes.arslaansmagichax.events.PacketEvent;
+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(ClientCommonPacketListenerImpl.class)
+public class ClientCommonNetworkHandlerMixin {
+ @Inject(method = "send", at = @At("HEAD"), cancellable = true)
+ private void onSendPacket(Packet<?> packet, CallbackInfo ci) {
+ PacketEvent.Send ev = new PacketEvent.Send(packet);
+ SendPacketEventBus.post(ev);
+
+ if (ev.isCancelled()) {
+ ci.cancel();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/mixin/ClientConnectionMixin.java b/src/main/java/com/arslaancodes/arslaansmagichax/mixin/ClientConnectionMixin.java
new file mode 100644
index 0000000..320d627
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/mixin/ClientConnectionMixin.java
@@ -0,0 +1,36 @@
+package com.arslaancodes.arslaansmagichax.mixin;
+
+import io.netty.channel.ChannelHandlerContext;
+import com.arslaancodes.arslaansmagichax.events.PacketEvent;
+import com.arslaancodes.arslaansmagichax.events.ReceivePacketEventBus;
+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;
+
+import java.util.Iterator;
+import net.minecraft.network.Connection;
+import net.minecraft.network.protocol.Packet;
+import net.minecraft.network.protocol.game.ClientGamePacketListener;
+import net.minecraft.network.protocol.game.ClientboundBundlePacket;
+
+@Mixin(Connection.class)
+public class ClientConnectionMixin {
+ @Inject(method = "channelRead0(Lio/netty/channel/ChannelHandlerContext;Lnet/minecraft/network/protocol/Packet;)V",
+ at = @At(value = "INVOKE", target = "Lnet/minecraft/network/Connection;genericsFtw(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;)V", shift = At.Shift.BEFORE), cancellable = true)
+ private void onHandlePacket(ChannelHandlerContext channelHandlerContext, Packet<?> packet, CallbackInfo ci) {
+ if (packet instanceof ClientboundBundlePacket bundle) {
+ for (Iterator<Packet<? super ClientGamePacketListener>> it = bundle.subPackets().iterator(); it.hasNext(); ) {
+ Packet<? super ClientGamePacketListener> innerPacket = it.next();
+ PacketEvent.Receive ev = new PacketEvent.Receive(innerPacket);
+ ReceivePacketEventBus.post(ev);
+ if (ev.isCancelled()) it.remove();
+ }
+ } else {
+ PacketEvent.Receive ev = new PacketEvent.Receive(packet);
+ ReceivePacketEventBus.post(ev);
+ if (ev.isCancelled()) ci.cancel();
+ }
+ }
+}
+
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/mixin/DoubleSliderCallbacksMixin.java b/src/main/java/com/arslaancodes/arslaansmagichax/mixin/DoubleSliderCallbacksMixin.java
new file mode 100644
index 0000000..e868708
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/mixin/DoubleSliderCallbacksMixin.java
@@ -0,0 +1,19 @@
+package com.arslaancodes.arslaansmagichax.mixin;
+
+import com.arslaancodes.arslaansmagichax.ArslaansMagicHaxClient;
+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 java.util.Optional;
+
+@Mixin(targets = "net.minecraft.client.OptionInstance$UnitDouble")
+public class DoubleSliderCallbacksMixin {
+ @Inject(method = "validateValue", at = @At("HEAD"), cancellable = true)
+ private void allowHighGamma(Double value, CallbackInfoReturnable<Optional<Double>> cir) {
+ if (ArslaansMagicHaxClient.fullbright.isEnabled() || ArslaansMagicHaxClient.xray.isEnabled()) {
+ cir.setReturnValue(Optional.of(value));
+ }
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/mixin/MinecraftClientMixin.java b/src/main/java/com/arslaancodes/arslaansmagichax/mixin/MinecraftClientMixin.java
new file mode 100644
index 0000000..188ba27
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/mixin/MinecraftClientMixin.java
@@ -0,0 +1,15 @@
+package com.arslaancodes.arslaansmagichax.mixin;
+
+import net.minecraft.client.Minecraft;
+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;
+
+@Mixin(Minecraft.class)
+public class MinecraftClientMixin {
+ @Inject(method = "createTitle", at = @At("HEAD"), cancellable = true)
+ private void onGetWindowTitle(CallbackInfoReturnable<String> cir) {
+ cir.setReturnValue("Arslaan's Magic Hax | Minecraft 1.21.8");
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/mixin/PlayerEntityMixin.java b/src/main/java/com/arslaancodes/arslaansmagichax/mixin/PlayerEntityMixin.java
new file mode 100644
index 0000000..73583e9
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/mixin/PlayerEntityMixin.java
@@ -0,0 +1,17 @@
+package com.arslaancodes.arslaansmagichax.mixin;
+
+import com.arslaancodes.arslaansmagichax.ArslaansMagicHaxClient;
+import com.arslaancodes.arslaansmagichax.modules.impl.NoAttackCooldown;
+import net.minecraft.world.entity.player.Player;
+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;
+
+@Mixin(Player.class)
+public abstract class PlayerEntityMixin {
+ @Inject(method = "getAttackStrengthScale", at = @At("HEAD"), cancellable = true)
+ private void onGetAttackCooldownProgress(CallbackInfoReturnable<Float> cir) {
+ if (ArslaansMagicHaxClient.noAttackCooldown.isEnabled()) cir.setReturnValue(1.0F);
+ }
+} \ No newline at end of file
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/mixin/PlayerInputC2SPacketMixin.java b/src/main/java/com/arslaancodes/arslaansmagichax/mixin/PlayerInputC2SPacketMixin.java
new file mode 100644
index 0000000..c2992fd
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/mixin/PlayerInputC2SPacketMixin.java
@@ -0,0 +1,16 @@
+package com.arslaancodes.arslaansmagichax.mixin;
+
+import com.arslaancodes.arslaansmagichax.mixininterface.IPacket;
+import net.minecraft.network.protocol.game.ServerboundPlayerInputPacket;
+import org.spongepowered.asm.mixin.Mixin;
+
+@Mixin(ServerboundPlayerInputPacket.class)
+public abstract class PlayerInputC2SPacketMixin implements IPacket {
+ private int tag = -1;
+
+ @Override
+ public void hax$setTag(int value) { tag = value; }
+
+ @Override
+ public int hax$getTag() { return tag; }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/mixin/PlayerInteractEntityC2SPacketMixin.java b/src/main/java/com/arslaancodes/arslaansmagichax/mixin/PlayerInteractEntityC2SPacketMixin.java
new file mode 100644
index 0000000..f6253b3
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/mixin/PlayerInteractEntityC2SPacketMixin.java
@@ -0,0 +1,16 @@
+package com.arslaancodes.arslaansmagichax.mixin;
+
+import com.arslaancodes.arslaansmagichax.mixininterface.IPacket;
+import net.minecraft.network.protocol.game.ServerboundInteractPacket;
+import org.spongepowered.asm.mixin.Mixin;
+
+@Mixin(ServerboundInteractPacket.class)
+public abstract class PlayerInteractEntityC2SPacketMixin implements IPacket {
+ private int tag = -1;
+
+ @Override
+ public void hax$setTag(int value) { tag = value; }
+
+ @Override
+ public int hax$getTag() { return tag; }
+} \ No newline at end of file
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/mixin/PlayerMoveC2SPacketMixin.java b/src/main/java/com/arslaancodes/arslaansmagichax/mixin/PlayerMoveC2SPacketMixin.java
new file mode 100644
index 0000000..18422a8
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/mixin/PlayerMoveC2SPacketMixin.java
@@ -0,0 +1,16 @@
+package com.arslaancodes.arslaansmagichax.mixin;
+
+import com.arslaancodes.arslaansmagichax.mixininterface.IPacket;
+import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket;
+import org.spongepowered.asm.mixin.Mixin;
+
+@Mixin(ServerboundMovePlayerPacket.class)
+public abstract class PlayerMoveC2SPacketMixin implements IPacket {
+ private int tag = -1;
+
+ @Override
+ public void hax$setTag(int value) { tag = value; }
+
+ @Override
+ public int hax$getTag() { return tag; }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/mixin/SplashTextResourceSupplierMixin.java b/src/main/java/com/arslaancodes/arslaansmagichax/mixin/SplashTextResourceSupplierMixin.java
new file mode 100644
index 0000000..b927325
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/mixin/SplashTextResourceSupplierMixin.java
@@ -0,0 +1,22 @@
+package com.arslaancodes.arslaansmagichax.mixin;
+
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
+
+import java.util.Random;
+import net.minecraft.client.gui.components.SplashRenderer;
+import net.minecraft.client.resources.SplashManager;
+
+@Mixin(SplashManager.class)
+public class SplashTextResourceSupplierMixin {
+ private static final Random RANDOM = new Random();
+
+ @Inject(method = "getSplash", at = @At("HEAD"), cancellable = true)
+ public void onGet(CallbackInfoReturnable<SplashRenderer> cir) {
+ String[] splashes = {"\"one can only hope.\"", "hackerman approved", "Cheater!", "totally not malware", "cheats for block game", "dont use /surprise"};
+ String selected = splashes[RANDOM.nextInt(splashes.length)];
+ cir.setReturnValue(new SplashRenderer(selected));
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/mixininterface/IPacket.java b/src/main/java/com/arslaancodes/arslaansmagichax/mixininterface/IPacket.java
new file mode 100644
index 0000000..d0b6bd7
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/mixininterface/IPacket.java
@@ -0,0 +1,6 @@
+package com.arslaancodes.arslaansmagichax.mixininterface;
+
+public interface IPacket {
+ void hax$setTag(int value);
+ int hax$getTag();
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/modules/Category.java b/src/main/java/com/arslaancodes/arslaansmagichax/modules/Category.java
new file mode 100644
index 0000000..4e6267f
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/modules/Category.java
@@ -0,0 +1,9 @@
+package com.arslaancodes.arslaansmagichax.modules;
+
+public enum Category {
+ COMBAT,
+ MOVEMENT,
+ RENDER,
+ PLAYER,
+ MISC
+} \ No newline at end of file
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/modules/Module.java b/src/main/java/com/arslaancodes/arslaansmagichax/modules/Module.java
new file mode 100644
index 0000000..37a957b
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/modules/Module.java
@@ -0,0 +1,101 @@
+package com.arslaancodes.arslaansmagichax.modules;
+
+import com.arslaancodes.arslaansmagichax.modules.settings.BooleanSetting;
+import com.arslaancodes.arslaansmagichax.modules.settings.ModeSetting;
+import com.arslaancodes.arslaansmagichax.modules.settings.NumberSetting;
+import com.arslaancodes.arslaansmagichax.modules.settings.Setting;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import net.minecraft.client.Minecraft;
+
+public abstract class Module {
+ private final String name;
+ private final String description;
+ private final Category category;
+ public static Minecraft mc;
+ private int glfwKeybinding;
+ private final List<Setting> settings = new ArrayList<>();
+
+ private boolean enabled = false;
+
+ public Module(String name, String description, int glfwKeybinding, Category category) {
+ this.name = name;
+ this.description = description;
+ this.mc = Minecraft.getInstance();
+ this.glfwKeybinding = glfwKeybinding;
+ this.category = category;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public int getGlfwKeybinding() {
+ return glfwKeybinding;
+ }
+
+ public Category getCategory() {
+ return category;
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public void toggle() {
+ enabled = !enabled;
+ if (enabled) onEnable();
+ else onDisable();
+ }
+
+ public void setEnabled(boolean state) {
+ if (enabled != state) toggle();
+ }
+
+ public void setGlfwKeybinding(int glfwKeybinding) {
+ this.glfwKeybinding = glfwKeybinding;
+ }
+
+ protected void onEnable() {}
+ protected void onDisable() {}
+
+ public void tick() {}
+
+ protected <T extends Setting> T addSetting(T setting) {
+ settings.add(setting);
+ return setting;
+ }
+
+ public List<Setting> getSettings() {
+ return settings;
+ }
+
+ public Optional<Setting> getSetting(String name) {
+ return settings.stream()
+ .filter(s -> s.getName().equalsIgnoreCase(name))
+ .findFirst();
+ }
+
+ public Optional<BooleanSetting> getBoolean(String name) {
+ return getSetting(name)
+ .filter(s -> s instanceof BooleanSetting)
+ .map(s -> (BooleanSetting) s);
+ }
+
+ public Optional<NumberSetting> getNumber(String name) {
+ return getSetting(name)
+ .filter(s -> s instanceof NumberSetting)
+ .map(s -> (NumberSetting) s);
+ }
+
+ public Optional<ModeSetting> getMode(String name) {
+ return getSetting(name)
+ .filter(s -> s instanceof ModeSetting)
+ .map(s -> (ModeSetting) s);
+ }
+} \ No newline at end of file
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/modules/ModuleManager.java b/src/main/java/com/arslaancodes/arslaansmagichax/modules/ModuleManager.java
new file mode 100644
index 0000000..bd4a243
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/modules/ModuleManager.java
@@ -0,0 +1,167 @@
+package com.arslaancodes.arslaansmagichax.modules;
+
+import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
+import net.minecraft.client.DeltaTracker;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.Font;
+import net.minecraft.client.gui.GuiGraphics;
+import net.minecraft.network.chat.Component;
+import net.minecraft.util.Mth;
+import com.arslaancodes.arslaansmagichax.ArslaansMagicHax;
+import com.arslaancodes.arslaansmagichax.ArslaansMagicHaxClient;
+import com.arslaancodes.arslaansmagichax.modules.settings.Setting;
+import com.mojang.blaze3d.platform.InputConstants;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.*;
+import java.util.stream.Collectors;
+
+public class ModuleManager {
+ private boolean hudRegistered = false;
+ private static final String CONFIG_FILE = "ArslaansMagicHax.properties";
+
+ private static Map<Module, Boolean> previousKeyState = new HashMap<>();
+
+ public static void handleKeyPresses() {
+ Minecraft client = Minecraft.getInstance();
+ if (client.player == null || client.screen != null) return;
+
+ for (Module module : modules) {
+ int key = module.getGlfwKeybinding();
+ if (key == -1) continue;
+
+ boolean isPressed = InputConstants.isKeyDown(client.getWindow().getWindow(), key);
+ boolean wasPressed = previousKeyState.getOrDefault(module, false);
+
+ if (isPressed && !wasPressed) {
+ boolean wasEnabled = module.isEnabled(); // use !wasEnabled in the chat message for edge cases e.g. modules that toggle themselves off on enable
+ module.toggle();
+ if (!Objects.equals(module.getName(), "ClickGUI")) {
+ client.player.displayClientMessage(Component.literal(
+ "Toggled module " + module.getName() + " to " + (!wasEnabled ? "ON" : "OFF")
+ ), false);
+ }
+ }
+
+ previousKeyState.put(module, isPressed);
+ }
+ }
+
+ private static List<Module> modules = new ArrayList<>();
+ public static ModuleManager INSTANCE = new ModuleManager();
+ public void register(Module module) {
+ modules.add(module);
+ }
+
+ public static List<Module> getAllModules() {
+ return modules;
+ }
+
+ public static List<Module> getEnabledModules() {
+ return modules.stream().filter(Module::isEnabled).collect(Collectors.toList());
+ }
+
+ public List<Module> getModulesWithCategory(Category category) {
+ return modules.stream()
+ .filter(module -> module.getCategory() == category)
+ .collect(Collectors.toList());
+ }
+
+ public static void tick() {
+ for (Module module : modules) {
+ module.tick();
+ }
+ handleKeyPresses();
+ }
+
+ public void registerHUD() {
+ if (!hudRegistered) {
+ HudRenderCallback.EVENT.register(this::onRenderHud);
+ hudRegistered = true;
+ }
+ }
+
+ private void onRenderHud(GuiGraphics drawContext, DeltaTracker renderTickCounter) {
+ if (!ArslaansMagicHaxClient.hideModulesHUD.isEnabled()) {
+ Font textRenderer = Minecraft.getInstance().font;
+ float alpha = 1.0F;
+ int i = Mth.ceil(alpha * 255.0F) << 24; // I don't know what this dark magic is but it works
+ int x = 5;
+ int y = 5;
+
+ int titleColor = 16568909 | i; // weird magic
+
+ drawContext.drawStringWithBackdrop(textRenderer, Component.literal("Arslaan's Magic Hax"), x, y, 50, titleColor);
+ y += textRenderer.lineHeight + 4;
+
+ for (Module module : ModuleManager.getEnabledModules()) {
+ int color = 16777215 | i; // more magic I don't understand
+ drawContext.drawString(textRenderer, Component.literal(module.getName()), x, y, color);
+ y += textRenderer.lineHeight + 2;
+ }
+ }
+ }
+
+ public void close() {
+ // save then disable all
+ saveModuleStates();
+ for (Module module : modules) {
+ module.setEnabled(false);
+ }
+ }
+
+ public void loadModuleStates() {
+ File file = new File(CONFIG_FILE);
+ if (!file.exists()) return;
+
+ try (FileInputStream fis = new FileInputStream(file)) {
+ Properties properties = new Properties();
+ properties.load(fis);
+
+ for (Module module : modules) {
+ String enabled = properties.getProperty(module.getName() + ".enabled");
+ if (Objects.equals(enabled, "true")) {
+ module.setEnabled(true);
+ } else {
+ module.setEnabled(false);
+ }
+
+ String keyStr = properties.getProperty(module.getName() + ".key");
+ if (keyStr != null) {
+ try {
+ module.setGlfwKeybinding(Integer.parseInt(keyStr));
+ } catch (NumberFormatException ignored) {}
+ }
+
+ for (Setting setting : module.getSettings()) {
+ String value = properties.getProperty(module.getName() + "." + setting.getName());
+ if (value != null) {
+ setting.setValueFromString(value);
+ }
+ }
+ }
+ } catch (IOException e) {
+ ArslaansMagicHax.LOGGER.info("Failed to load module states and settings", e);
+ }
+ }
+
+ public void saveModuleStates() {
+ Properties properties = new Properties();
+ for (Module module : modules) {
+ properties.setProperty(module.getName() + ".enabled", String.valueOf(module.isEnabled()));
+ properties.setProperty(module.getName() + ".key", String.valueOf(module.getGlfwKeybinding()));
+
+ for (Setting setting : module.getSettings()) {
+ properties.setProperty(module.getName() + "." + setting.getName(), setting.getValueAsString());
+ }
+ }
+
+ try (FileOutputStream fos = new FileOutputStream(CONFIG_FILE)) {
+ properties.store(fos, "Arslaan's Magic Hax - Module States & Settings");
+ } catch (IOException e) {
+ ArslaansMagicHax.LOGGER.error("Failed to save module states and settings", e);
+ }
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/AutoClicker.java b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/AutoClicker.java
new file mode 100644
index 0000000..7c67201
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/AutoClicker.java
@@ -0,0 +1,47 @@
+package com.arslaancodes.arslaansmagichax.modules.impl;
+
+import com.arslaancodes.arslaansmagichax.modules.Category;
+import com.arslaancodes.arslaansmagichax.modules.Module;
+import com.arslaancodes.arslaansmagichax.modules.settings.ModeSetting;
+import com.arslaancodes.arslaansmagichax.modules.settings.NumberSetting;
+import java.util.Objects;
+import java.util.Random;
+import net.minecraft.world.InteractionHand;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.phys.EntityHitResult;
+import net.minecraft.world.phys.HitResult;
+
+public class AutoClicker extends Module {
+ private final NumberSetting cps = new NumberSetting("CPS", 5, 50, 12, 0.1); // default 10 CPS
+ private final ModeSetting mode = new ModeSetting("Mode", "NoDelay", "CPS", "NoDelay");
+ private long nextClickTime = 0L;
+
+ public AutoClicker() {
+ super("AutoClicker", "Automatically attacks entities under your crosshair.", -1, Category.COMBAT);
+ addSetting(mode);
+ addSetting(cps);
+ }
+
+ @Override
+ public void tick() {
+ if (!isEnabled() || mc.player == null || mc.level == null) return;
+ if (mc.screen != null) return;
+
+ HitResult hr = mc.hitResult;
+ if (!(hr instanceof EntityHitResult eResult)) return;
+
+ Entity target = eResult.getEntity();
+ if (target == null || !target.isAlive()) return;
+
+ if (!Objects.equals(mode.getMode(), "NoDelay")) {
+ long now = System.currentTimeMillis();
+ if (now < nextClickTime) return;
+
+ double delayMs = 1000.0 / cps.getValue();
+ nextClickTime = now + (long) Math.max(1, delayMs);
+ }
+
+ mc.gameMode.attack(mc.player, target);
+ mc.player.swing(InteractionHand.MAIN_HAND);
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/ClickGUI.java b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/ClickGUI.java
new file mode 100644
index 0000000..d47abf5
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/ClickGUI.java
@@ -0,0 +1,23 @@
+package com.arslaancodes.arslaansmagichax.modules.impl;
+
+import com.arslaancodes.arslaansmagichax.modules.Category;
+import com.arslaancodes.arslaansmagichax.modules.Module;
+import com.arslaancodes.arslaansmagichax.screens.clickgui.ClickGUIScreen;
+import net.minecraft.client.Minecraft;
+import org.lwjgl.glfw.GLFW;
+
+public class ClickGUI extends Module {
+ public ClickGUI() {
+ super("ClickGUI", "GUI to manage modules.", GLFW.GLFW_KEY_RIGHT_SHIFT, Category.MISC);
+ }
+
+ @Override
+ protected void onEnable() {
+ Minecraft.getInstance().setScreen(ClickGUIScreen.INSTANCE);
+ }
+
+ @Override
+ protected void onDisable() {
+ Minecraft.getInstance().setScreen(null);
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Criticals.java b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Criticals.java
new file mode 100644
index 0000000..e8eaa7f
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Criticals.java
@@ -0,0 +1,86 @@
+package com.arslaancodes.arslaansmagichax.modules.impl;
+
+import com.arslaancodes.arslaansmagichax.ArslaansMagicHaxClient;
+import com.arslaancodes.arslaansmagichax.events.PacketEvent;
+import com.arslaancodes.arslaansmagichax.events.SendPacketEventBus;
+import com.arslaancodes.arslaansmagichax.mixininterface.IPacket;
+import com.arslaancodes.arslaansmagichax.modules.Category;
+import com.arslaancodes.arslaansmagichax.modules.Module;
+import com.arslaancodes.arslaansmagichax.modules.settings.ModeSetting;
+import net.minecraft.network.packet.c2s.play.*;
+import net.minecraft.network.protocol.Packet;
+import net.minecraft.network.protocol.game.ServerboundInteractPacket;
+import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket;
+import net.minecraft.network.protocol.game.ServerboundPlayerCommandPacket;
+import net.minecraft.network.protocol.game.ServerboundPlayerInputPacket;
+import net.minecraft.world.entity.player.Input;
+import java.util.Objects;
+
+public class Criticals extends Module {
+ private static ModeSetting mode = new ModeSetting("Mode", "Packet", "Packet", "Bypass");
+
+ public Criticals() {
+ super("Criticals", "Always gives critical hits.", -1, Category.COMBAT);
+ SendPacketEventBus.register(Criticals::packetEventListener);
+ addSetting(mode);
+ }
+
+ private static void packetEventListener(PacketEvent.Send event) {
+ if (!ArslaansMagicHaxClient.criticals.isEnabled() || mc.player == null) return;
+
+ String obamaHaveDih = "barapbarapba"; // kinda put it in mbappe
+
+ Packet<?> packet = event.packet();
+
+ // mojang did a mojang thing and you cant detect if packet is InteractType.ATTACK anymore so just assume it is and pray it works
+ if (packet instanceof ServerboundInteractPacket && ((IPacket) packet).hax$getTag() != 1337) {
+ event.setCancelled(true);
+
+ if (Objects.equals(mode.getMode(), "Packet")) {
+ // fake not sprinting if sprinting so it lets you crit
+ boolean wasSprinting = false;
+
+ if (mc.player.isSprinting()) {
+ Input fakeNoSprint = new Input(false, false, false, false, false, false, false);
+ mc.player.connection.send(new ServerboundPlayerInputPacket(fakeNoSprint));
+
+ ServerboundPlayerCommandPacket fakeNoSprintCommand = new ServerboundPlayerCommandPacket(mc.player, ServerboundPlayerCommandPacket.Action.STOP_SPRINTING);
+ mc.player.connection.send(fakeNoSprintCommand);
+
+ wasSprinting = true;
+ }
+
+ sendYPacket(0.0625);
+ sendYPacket(0);
+
+ ((IPacket) packet).hax$setTag(1337);
+ mc.player.connection.send(packet);
+
+ // send sprinting packet again just in case it stopped the player from sprinting client-side (happens)
+ if (wasSprinting) {
+ Input fakeNoSprint = new Input(false, false, false, false, false, false, true);
+ mc.player.connection.send(new ServerboundPlayerInputPacket(fakeNoSprint));
+
+ ServerboundPlayerCommandPacket fakeNoSprintCommand = new ServerboundPlayerCommandPacket(mc.player, ServerboundPlayerCommandPacket.Action.START_SPRINTING);
+ mc.player.connection.send(fakeNoSprintCommand);
+
+ mc.player.setSprinting(true);
+ }
+ } else if (Objects.equals(mode.getMode(), "Bypass")) {
+ // don't do the sprint bypass and make it more random-looking to throw off anticheat
+ sendYPacket(0.0625 + (Math.random() * 0.01));
+ sendYPacket(0.0);
+ }
+ }
+ }
+
+ private static void sendYPacket(double height) {
+ double x = mc.player.getX();
+ double y = mc.player.getY();
+ double z = mc.player.getZ();
+
+ ServerboundMovePlayerPacket packet = new ServerboundMovePlayerPacket.Pos(x, y + height, z, false, mc.player.horizontalCollision);
+
+ mc.player.connection.send(packet);
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/FakeSneak.java b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/FakeSneak.java
new file mode 100644
index 0000000..8154a20
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/FakeSneak.java
@@ -0,0 +1,29 @@
+package com.arslaancodes.arslaansmagichax.modules.impl;
+
+import com.arslaancodes.arslaansmagichax.ArslaansMagicHaxClient;
+import com.arslaancodes.arslaansmagichax.events.PacketEvent;
+import com.arslaancodes.arslaansmagichax.events.SendPacketEventBus;
+import com.arslaancodes.arslaansmagichax.mixininterface.IPacket;
+import com.arslaancodes.arslaansmagichax.modules.Category;
+import com.arslaancodes.arslaansmagichax.modules.Module;
+import net.minecraft.network.protocol.Packet;
+import net.minecraft.network.protocol.game.ServerboundPlayerInputPacket;
+import net.minecraft.world.entity.player.Input;
+
+public class FakeSneak extends Module {
+ public FakeSneak() {
+ super("Fake Sneak", "Makes you appear as sneaking to the server when you're not. Can be used to hide nametags.", -1, Category.MOVEMENT);
+ }
+
+ @Override
+ public void tick() {
+ if (!this.isEnabled() || mc.player == null) return;
+
+ Input original = mc.player.input.keyPresses;
+
+ Input fakeSneak = new Input(original.forward(), original.backward(), original.left(), original.right(), original.jump(), true, original.sprint());
+ Packet fakeSneakPacket = new ServerboundPlayerInputPacket(fakeSneak);
+ ((IPacket) fakeSneakPacket).hax$setTag(1337);
+ mc.player.connection.send(fakeSneakPacket);
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Flight.java b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Flight.java
new file mode 100644
index 0000000..c1a9125
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Flight.java
@@ -0,0 +1,61 @@
+package com.arslaancodes.arslaansmagichax.modules.impl;
+
+import com.arslaancodes.arslaansmagichax.modules.Category;
+import com.arslaancodes.arslaansmagichax.modules.Module;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket;
+import org.lwjgl.glfw.GLFW;
+
+public class Flight extends Module {
+ private int flyingTickCounter = 0;
+ private boolean sentFirstPacket = false;
+
+ public Flight() {
+ super("Flight", "Enables creative flight in survival.", GLFW.GLFW_KEY_G, Category.MOVEMENT);
+ }
+
+ @Override
+ protected void onEnable() {
+ if (mc.player == null) return;
+ mc.player.displayClientMessage(Component.literal("[Flight] It is recommended to use this hack in combination with NoFall."), false);
+ }
+
+ @Override
+ public void tick() {
+ if (!this.isEnabled() || mc.player == null) return;
+
+ mc.player.getAbilities().mayfly = true;
+ mc.player.getAbilities().flying = true;
+
+ if (flyingTickCounter >= 20) {
+ if (!sentFirstPacket) {
+ sendYPacket(-0.0625);
+ sentFirstPacket = true;
+ } else {
+ sendYPacket(0);
+ sentFirstPacket = false;
+ flyingTickCounter = 0;
+ }
+ }
+ flyingTickCounter++;
+ }
+
+
+ @Override
+ protected void onDisable() {
+ if (mc.player != null) {
+ mc.player.getAbilities().mayfly = false;
+ mc.player.getAbilities().flying = false;
+ }
+ }
+
+ private static void sendYPacket(double height) {
+ double x = mc.player.getX();
+ double y = mc.player.getY();
+ double z = mc.player.getZ();
+
+ ServerboundMovePlayerPacket packet = new ServerboundMovePlayerPacket.Pos(x, y + height, z, false, mc.player.horizontalCollision);
+
+ mc.player.connection.send(packet);
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Fullbright.java b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Fullbright.java
new file mode 100644
index 0000000..56b0800
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Fullbright.java
@@ -0,0 +1,85 @@
+package com.arslaancodes.arslaansmagichax.modules.impl;
+
+import com.arslaancodes.arslaansmagichax.modules.Category;
+import com.arslaancodes.arslaansmagichax.modules.Module;
+import com.arslaancodes.arslaansmagichax.modules.settings.ModeSetting;
+import java.util.Objects;
+import net.minecraft.core.registries.BuiltInRegistries;
+import net.minecraft.world.effect.MobEffectInstance;
+import net.minecraft.world.effect.MobEffects;
+
+public class Fullbright extends Module {
+ public ModeSetting mode = new ModeSetting("Mode", "Gamma", "Effect", "Gamma", "Effect + Gamma", "Break AO Renderer");
+ private double previousGamma = 1.0;
+ private boolean setPreviousGamma = false;
+ private String lastMode = ""; // track previous mode
+
+ public Fullbright() {
+ super("Fullbright", "Brightens up your world!", -1, Category.RENDER);
+ addSetting(mode);
+ lastMode = mode.getMode(); // initialize
+ }
+
+ @Override
+ protected void onEnable() {
+ if (mc.options == null) return;
+ applyMode(mode.getMode());
+
+ if (mc.levelRenderer != null) {
+ mc.levelRenderer.allChanged();
+ }
+ }
+
+ @Override
+ public void tick() {
+ if (!this.isEnabled() || mc.player == null) return;
+
+ String currentMode = mode.getMode();
+ if (!Objects.equals(currentMode, lastMode)) {
+ applyMode(currentMode);
+
+ if (mc.levelRenderer != null) {
+ mc.levelRenderer.allChanged();
+ }
+
+ lastMode = currentMode;
+ }
+
+ if (Objects.equals(currentMode, "Effect")) {
+ mc.player.addEffect(new MobEffectInstance(BuiltInRegistries.MOB_EFFECT.wrapAsHolder(MobEffects.NIGHT_VISION.value()), 1, 255));
+ } else if (Objects.equals(currentMode, "Effect + Gamma")) {
+ mc.player.addEffect(new MobEffectInstance(BuiltInRegistries.MOB_EFFECT.wrapAsHolder(MobEffects.NIGHT_VISION.value()), 1, 255));
+ }
+ }
+
+ private void applyMode(String modeName) {
+ if (Objects.equals(modeName, "Gamma")) {
+ if (!setPreviousGamma) previousGamma = mc.options.gamma().get();
+ setPreviousGamma = true;
+ mc.options.gamma().set(1000.0);
+ } else if (Objects.equals(modeName, "Effect + Gamma")) {
+ if (!setPreviousGamma) previousGamma = mc.options.gamma().get();
+ setPreviousGamma = true;
+ mc.options.gamma().set(1000.0);
+ } else if (Objects.equals(modeName, "Effect")) {
+ mc.options.gamma().set(previousGamma);
+ setPreviousGamma = false;
+ }
+ }
+
+ @Override
+ protected void onDisable() {
+ if (mc.player == null) return;
+
+ if (mc.player.hasEffect(BuiltInRegistries.MOB_EFFECT.wrapAsHolder(MobEffects.NIGHT_VISION.value()))) {
+ mc.player.removeEffect(BuiltInRegistries.MOB_EFFECT.wrapAsHolder(MobEffects.NIGHT_VISION.value()));
+ }
+
+ mc.options.gamma().set(previousGamma);
+
+ if (mc.levelRenderer != null) {
+ mc.levelRenderer.allChanged();
+ }
+ }
+}
+
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/GUN.java b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/GUN.java
new file mode 100644
index 0000000..a9b2b7b
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/GUN.java
@@ -0,0 +1,32 @@
+package com.arslaancodes.arslaansmagichax.modules.impl;
+
+import com.arslaancodes.arslaansmagichax.ArslaansMagicHaxClient;
+import com.arslaancodes.arslaansmagichax.modules.Category;
+import com.arslaancodes.arslaansmagichax.modules.Module;
+import net.minecraft.ChatFormatting;
+import net.minecraft.network.chat.Component;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.sounds.SoundEvent;
+
+public class GUN extends Module {
+ public GUN() {
+ super("G U N", "NoAttackCooldown + Criticals + AutoClicker = G U N", -1, Category.COMBAT);
+ }
+
+ @Override
+ protected void onEnable() {
+ ArslaansMagicHaxClient.clickGUI.setEnabled(false);
+ ArslaansMagicHaxClient.noAttackCooldown.setEnabled(true);
+ ArslaansMagicHaxClient.criticals.setEnabled(true);
+ ArslaansMagicHaxClient.autoClicker.setEnabled(true);
+ this.setEnabled(false);
+ if (mc.player != null) {
+ mc.player.displayClientMessage(Component.literal("[G U N] Enabled NoAttackCooldown, Criticals, AutoClicker"), false);
+ mc.player.displayClientMessage(Component.literal("[G U N] Disabled ClickGUI & self (this is a macro module)"), false);
+ mc.gui.setTitle(Component.literal("G U N").withStyle(ChatFormatting.RED));
+ mc.gui.setSubtitle(Component.literal("THE POWER").withStyle(ChatFormatting.YELLOW));
+ mc.player.displayClientMessage(Component.literal("Tip: when using G U N, if there is no anticheat set AutoClicker mode to NoDelay"), true);
+ mc.player.playSound(SoundEvent.createVariableRangeEvent(ResourceLocation.parse("minecraft:entity.evoker.prepare_wololo")), 100, 1);
+ }
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/GhostScaffold.java b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/GhostScaffold.java
new file mode 100644
index 0000000..8f27d35
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/GhostScaffold.java
@@ -0,0 +1,23 @@
+package com.arslaancodes.arslaansmagichax.modules.impl;
+
+import com.arslaancodes.arslaansmagichax.modules.Category;
+import com.arslaancodes.arslaansmagichax.modules.Module;
+import net.minecraft.core.BlockPos;
+import net.minecraft.world.level.block.Blocks;
+import net.minecraft.world.level.block.state.BlockState;
+
+public class GhostScaffold extends Module {
+ public GhostScaffold() {
+ super("GhostScaffold", "Allows you to scaffold but with ghost blocks", -1, Category.MOVEMENT);
+ }
+
+ @Override
+ public void tick() {
+ if (!this.isEnabled() || mc.player == null || mc.level == null) return;
+
+ BlockPos pos = mc.player.blockPosition().below();
+ BlockState blockState = Blocks.STONE.defaultBlockState();
+
+ mc.level.setBlockAndUpdate(pos, blockState);
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/GravityModifier.java b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/GravityModifier.java
new file mode 100644
index 0000000..593963d
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/GravityModifier.java
@@ -0,0 +1,31 @@
+package com.arslaancodes.arslaansmagichax.modules.impl;
+
+import com.arslaancodes.arslaansmagichax.modules.Category;
+import com.arslaancodes.arslaansmagichax.modules.Module;
+import com.arslaancodes.arslaansmagichax.modules.settings.NumberSetting;
+import net.minecraft.network.chat.Component;
+import net.minecraft.world.phys.Vec3;
+import org.lwjgl.glfw.GLFW;
+
+public class GravityModifier extends Module {
+ private NumberSetting gravity = new NumberSetting("Modifier", -1, 1, 0, 0.01);
+
+ public GravityModifier() {
+ super("Gravity Modifier", "Changes gravity.", GLFW.GLFW_KEY_GRAVE_ACCENT, Category.MOVEMENT);
+ addSetting(gravity);
+ }
+
+ @Override
+ protected void onEnable() {
+ if (mc.player != null) mc.player.displayClientMessage(Component.literal("[Gravity Modifier] It is recommended to use this hack with NoFall."), false);
+ }
+
+ @Override
+ public void tick() {
+ if (!this.isEnabled() || mc.player == null) return;
+
+ Vec3 velocity = mc.player.getDeltaMovement();
+ Vec3 newVelocity = new Vec3(velocity.x, velocity.y + gravity.getValue(), velocity.z);
+ mc.player.setDeltaMovement(newVelocity);
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/HideModulesHUD.java b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/HideModulesHUD.java
new file mode 100644
index 0000000..9a81291
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/HideModulesHUD.java
@@ -0,0 +1,12 @@
+package com.arslaancodes.arslaansmagichax.modules.impl;
+
+import com.arslaancodes.arslaansmagichax.modules.Category;
+import com.arslaancodes.arslaansmagichax.modules.Module;
+
+public class HideModulesHUD extends Module {
+ public HideModulesHUD() {
+ super("Hide Modules HUD", "Hides the list of modules in the top-left of the HUD.", -1, Category.RENDER);
+ }
+
+ // actual shit is in ModuleManager::onRenderHud (if condition to check if this is not enabled)
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Jetpack.java b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Jetpack.java
new file mode 100644
index 0000000..f1c1bbb
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Jetpack.java
@@ -0,0 +1,32 @@
+package com.arslaancodes.arslaansmagichax.modules.impl;
+
+import com.arslaancodes.arslaansmagichax.modules.Category;
+import com.arslaancodes.arslaansmagichax.modules.Module;
+import com.arslaancodes.arslaansmagichax.modules.settings.NumberSetting;
+import net.minecraft.network.chat.Component;
+import net.minecraft.world.phys.Vec3;
+
+public class Jetpack extends Module {
+ private NumberSetting speed = new NumberSetting("Thrust Speed", 1, 10, 1, 1);
+
+ public Jetpack() {
+ super("Jetpack", "Turns your jump key into a jetpack.", -1, Category.MOVEMENT);
+ addSetting(speed);
+ }
+
+ @Override
+ protected void onEnable() {
+ if (mc.player == null) return;
+ mc.player.displayClientMessage(Component.literal("[Jetpack] It is recommended to use this hack in combination with NoFall."), false);
+ }
+
+ @Override
+ public void tick() {
+ if (!this.isEnabled() || mc.player == null) return;
+
+ if (mc.options.keyJump.isDown()) {
+ mc.player.setDeltaMovement(new Vec3(mc.player.getDeltaMovement().x, 0.42 * speed.getValue(), mc.player.getDeltaMovement().z));
+ mc.player.fallDistance = 0;
+ }
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/NoAttackCooldown.java b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/NoAttackCooldown.java
new file mode 100644
index 0000000..3b8db2a
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/NoAttackCooldown.java
@@ -0,0 +1,12 @@
+package com.arslaancodes.arslaansmagichax.modules.impl;
+
+import com.arslaancodes.arslaansmagichax.modules.Category;
+import com.arslaancodes.arslaansmagichax.modules.Module;
+
+public class NoAttackCooldown extends Module {
+ public NoAttackCooldown() {
+ super("NoAttackCooldown", "Removes attack cooldown", -1, Category.COMBAT);
+ }
+
+ // removing cooldown handled in PlayerEntityMixin
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/NoFall.java b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/NoFall.java
new file mode 100644
index 0000000..927b435
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/NoFall.java
@@ -0,0 +1,25 @@
+package com.arslaancodes.arslaansmagichax.modules.impl;
+
+import com.arslaancodes.arslaansmagichax.modules.Category;
+import com.arslaancodes.arslaansmagichax.modules.Module;
+import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket;
+
+public class NoFall extends Module {
+ public NoFall() {
+ super("NoFall", "Negates fall damage.", -1, Category.PLAYER);
+ }
+
+ @Override
+ public void tick() {
+ if (this.isEnabled()) {
+ if (mc.player != null) {
+ if (!mc.player.onGround() && mc.player.fallDistance > 3) {
+ // magic hax
+ ServerboundMovePlayerPacket packet = new ServerboundMovePlayerPacket.PosRot(mc.player.getX(), mc.player.getY() + 0.000000001, mc.player.getZ(),
+ mc.player.getYRot(), mc.player.getXRot(), false, mc.player.horizontalCollision);
+ mc.player.connection.send(packet);
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/NoPackets.java b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/NoPackets.java
new file mode 100644
index 0000000..cd25a3d
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/NoPackets.java
@@ -0,0 +1,23 @@
+package com.arslaancodes.arslaansmagichax.modules.impl;
+
+import com.arslaancodes.arslaansmagichax.ArslaansMagicHaxClient;
+import com.arslaancodes.arslaansmagichax.events.SendPacketEventBus;
+import com.arslaancodes.arslaansmagichax.events.PacketEvent;
+import com.arslaancodes.arslaansmagichax.modules.Category;
+import com.arslaancodes.arslaansmagichax.modules.Module;
+import net.minecraft.network.chat.Component;
+
+public class NoPackets extends Module {
+ public NoPackets() {
+ super("NoPackets", "Stops all outgoing packets from being sent. ONLY USE THIS IF YOU KNOW WHAT YOU ARE DOING!", -1, Category.MISC);
+ SendPacketEventBus.register(NoPackets::packetEventListener);
+ }
+
+ private static void packetEventListener(PacketEvent.Send event) {
+ if (!ArslaansMagicHaxClient.noPackets.isEnabled()) return;
+
+ if (mc.player != null) mc.player.displayClientMessage(Component.literal("Cancelled outgoing packet: " + event.packet().getClass().getSimpleName() + " -> " + event.packet()), false);
+
+ event.setCancelled(true);
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Poseidon.java b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Poseidon.java
new file mode 100644
index 0000000..260e836
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Poseidon.java
@@ -0,0 +1,21 @@
+package com.arslaancodes.arslaansmagichax.modules.impl;
+
+import com.arslaancodes.arslaansmagichax.modules.Category;
+import com.arslaancodes.arslaansmagichax.modules.Module;
+import net.minecraft.core.registries.BuiltInRegistries;
+import net.minecraft.world.effect.MobEffectInstance;
+import net.minecraft.world.effect.MobEffects;
+
+public class Poseidon extends Module {
+ public Poseidon() {
+ super("Poseidon", "Stops you from drowning.", -1, Category.PLAYER);
+ }
+
+ @Override
+ public void tick() {
+ if (!this.isEnabled() || mc.player == null) return;
+
+ mc.player.setAirSupply(mc.player.getMaxAirSupply());
+ mc.player.addEffect(new MobEffectInstance(BuiltInRegistries.MOB_EFFECT.wrapAsHolder(MobEffects.WATER_BREATHING.value()), 1, 255));
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Speed.java b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Speed.java
new file mode 100644
index 0000000..fe2b95f
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Speed.java
@@ -0,0 +1,58 @@
+package com.arslaancodes.arslaansmagichax.modules.impl;
+
+import com.arslaancodes.arslaansmagichax.modules.Category;
+import com.arslaancodes.arslaansmagichax.modules.Module;
+import com.arslaancodes.arslaansmagichax.modules.settings.BooleanSetting;
+import com.arslaancodes.arslaansmagichax.modules.settings.NumberSetting;
+import net.minecraft.network.chat.Component;
+
+public class Speed extends Module {
+ private final NumberSetting speed = new NumberSetting("Speed", 0.1, 2.0, 0.4, 0.05);
+ private final BooleanSetting enableWhileSneaking = new BooleanSetting("Enable while Sneaking", true);
+ private final BooleanSetting enableInWater = new BooleanSetting("Enable in Water", true);
+ private final BooleanSetting enableInLava = new BooleanSetting("Enable in Lava", true);
+
+ public Speed() {
+ super("Speed", "Makes you faster.", -1, Category.MOVEMENT);
+ addSetting(speed);
+ addSetting(enableWhileSneaking);
+ addSetting(enableInWater);
+ addSetting(enableInLava);
+ }
+
+ @Override
+ protected void onEnable() {
+ if (mc.player == null) return;
+ mc.player.displayClientMessage(Component.literal("[Speed] It is recommended to use this hack in combination with NoFall."), false);
+ }
+
+ @Override
+ public void tick() {
+ if (!isEnabled() || mc.player == null) return;
+ if (!enableWhileSneaking.isEnabled() && mc.player.isShiftKeyDown()) return;
+ if (!enableInLava.isEnabled() && mc.player.isInLava()) return;
+ if (!enableInWater.isEnabled() && mc.player.isInWater()) return;
+
+ float forward = mc.player.zza;
+ float strafe = mc.player.xxa;
+ float yaw = mc.player.getYRot();
+
+ if (forward == 0 && strafe == 0) return;
+
+ if (forward != 0) {
+ if (strafe > 0) yaw += (forward > 0 ? -45 : 45);
+ else if (strafe < 0) yaw += (forward > 0 ? 45 : -45);
+ strafe = 0;
+ forward = forward > 0 ? 1 : -1;
+ }
+
+ double rad = Math.toRadians(yaw);
+ double sin = Math.sin(rad);
+ double cos = Math.cos(rad);
+
+ double x = (forward * -sin + strafe * cos) * speed.getValue();
+ double z = (forward * cos - strafe * -sin) * speed.getValue();
+
+ mc.player.setDeltaMovement(x, mc.player.getDeltaMovement().y, z);
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Spider.java b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Spider.java
new file mode 100644
index 0000000..87a6e12
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Spider.java
@@ -0,0 +1,33 @@
+package com.arslaancodes.arslaansmagichax.modules.impl;
+
+import com.arslaancodes.arslaansmagichax.modules.Category;
+import com.arslaancodes.arslaansmagichax.modules.Module;
+import com.arslaancodes.arslaansmagichax.modules.settings.NumberSetting;
+import net.minecraft.network.chat.Component;
+import net.minecraft.world.phys.Vec3;
+
+public class Spider extends Module {
+ private NumberSetting climbSpeed = new NumberSetting("Climb Speed", 0, 1, 0.2, 0.1);
+
+ @Override
+ protected void onEnable() {
+ if (mc.player == null) return;
+ mc.player.displayClientMessage(Component.literal("[Spider] It is recommended to use this hack in combination with NoFall."), false);
+ }
+
+ public Spider() {
+ super("Spider", "Allows you to climb walls like a spider.", -1, Category.MOVEMENT);
+ addSetting(climbSpeed);
+ }
+
+ @Override
+ public void tick() {
+ if (!this.isEnabled() || mc.player == null) return;
+ if (!mc.player.horizontalCollision) return;
+
+ Vec3 velocity = mc.player.getDeltaMovement();
+ if (velocity.y >= 0.2) return;
+
+ mc.player.setDeltaMovement(velocity.x, climbSpeed.getValue(), velocity.z);
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/TickRateLock.java b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/TickRateLock.java
new file mode 100644
index 0000000..b5202df
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/TickRateLock.java
@@ -0,0 +1,58 @@
+package com.arslaancodes.arslaansmagichax.modules.impl;
+
+import com.arslaancodes.arslaansmagichax.ArslaansMagicHaxClient;
+import com.arslaancodes.arslaansmagichax.events.PacketEvent;
+import com.arslaancodes.arslaansmagichax.events.ReceivePacketEventBus;
+import com.arslaancodes.arslaansmagichax.modules.Category;
+import com.arslaancodes.arslaansmagichax.modules.Module;
+import com.arslaancodes.arslaansmagichax.modules.settings.BooleanSetting;
+import com.arslaancodes.arslaansmagichax.modules.settings.NumberSetting;
+import net.minecraft.network.protocol.Packet;
+import net.minecraft.network.protocol.game.ClientboundTickingStatePacket;
+import net.minecraft.world.TickRateManager;
+
+public class TickRateLock extends Module {
+
+ private NumberSetting tickRate = new NumberSetting("Tick Rate", 1, 100, 20, 1);
+ private BooleanSetting frozen = new BooleanSetting("Frozen", false);
+ private static float serverTickRate = 20; // default 20 tps
+ private static boolean serverFrozen = false; // default not frozen
+
+ public TickRateLock() {
+ super("Tick Rate Lock", "Locks the tick rate to a specified value (Does not affect the server - client-side only)", -1, Category.MISC);
+ addSetting(tickRate);
+ addSetting(frozen);
+ ReceivePacketEventBus.register(TickRateLock::onPacketReceive);
+ }
+
+ private static void onPacketReceive(PacketEvent.Receive event) {
+ if (!ArslaansMagicHaxClient.tickRateLock.isEnabled()) return;
+
+ Packet packet = event.packet();
+
+ if (packet instanceof ClientboundTickingStatePacket) {
+ serverTickRate = ((ClientboundTickingStatePacket) packet).tickRate(); // save server tick rate
+ serverFrozen = ((ClientboundTickingStatePacket) packet).isFrozen(); // save server frozen
+ event.setCancelled(true); // ignores the server, frick them with all their rules
+ }
+ }
+
+ @Override
+ public void tick() {
+ if (!this.isEnabled() || mc.player == null || mc.level == null) return;
+
+ TickRateManager tickManager = mc.level.tickRateManager();
+ if (tickManager.tickrate() != tickRate.getValue() || tickManager.isFrozen() != frozen.isEnabled()) {
+ tickManager.setTickRate(tickRate.getValueFloat());
+ tickManager.setFrozen(frozen.isEnabled());
+ }
+ }
+
+ @Override
+ protected void onDisable() {
+ if (mc.player == null || mc.level == null) return;
+ TickRateManager tickManager = mc.level.tickRateManager();
+ tickManager.setTickRate(serverTickRate);
+ tickManager.setFrozen(serverFrozen);
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Waterwalk.java b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Waterwalk.java
new file mode 100644
index 0000000..7949203
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Waterwalk.java
@@ -0,0 +1,28 @@
+package com.arslaancodes.arslaansmagichax.modules.impl;
+
+import com.arslaancodes.arslaansmagichax.modules.Category;
+import com.arslaancodes.arslaansmagichax.modules.Module;
+import net.minecraft.core.BlockPos;
+import net.minecraft.world.level.block.Blocks;
+
+public class Waterwalk extends Module {
+ public Waterwalk() {
+ super("Waterwalk", "Allows you to walk on water.", -1, Category.MOVEMENT);
+ }
+
+ @Override
+ public void tick() {
+ if (!this.isEnabled() || mc.player == null) return;
+
+ BlockPos blockBelow = mc.player.blockPosition().below();
+
+ if (mc.level.getBlockState(blockBelow).is(Blocks.WATER)) {
+ if (mc.player.getDeltaMovement().y < 0) {
+ mc.player.setDeltaMovement(mc.player.getDeltaMovement().x, 0.0, mc.player.getDeltaMovement().z);
+
+ if (!mc.player.isJumping()) mc.player.setPosRaw(mc.player.getX(), Math.floor(mc.player.getY()), mc.player.getZ());
+ }
+ mc.player.setOnGround(true);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Xray.java b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Xray.java
new file mode 100644
index 0000000..51e16ca
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/modules/impl/Xray.java
@@ -0,0 +1,65 @@
+package com.arslaancodes.arslaansmagichax.modules.impl;
+
+import com.arslaancodes.arslaansmagichax.modules.Category;
+import com.arslaancodes.arslaansmagichax.modules.Module;
+import com.arslaancodes.arslaansmagichax.modules.settings.ModeSetting;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import net.minecraft.network.chat.Component;
+import net.minecraft.world.level.block.Blocks;
+import net.minecraft.world.level.block.state.BlockState;
+
+public class Xray extends Module {
+ private List<BlockState> interestingBlocks = new ArrayList<>();
+
+ public Xray() {
+ super("Xray", "Allows you to see through blocks.", -1, Category.RENDER);
+
+ // Add ores, spawners, liquids, etc.
+ interestingBlocks.add(Blocks.DIAMOND_ORE.defaultBlockState());
+ interestingBlocks.add(Blocks.DEEPSLATE_DIAMOND_ORE.defaultBlockState());
+ interestingBlocks.add(Blocks.GOLD_ORE.defaultBlockState());
+ interestingBlocks.add(Blocks.DEEPSLATE_GOLD_ORE.defaultBlockState());
+ interestingBlocks.add(Blocks.IRON_ORE.defaultBlockState());
+ interestingBlocks.add(Blocks.DEEPSLATE_IRON_ORE.defaultBlockState());
+ interestingBlocks.add(Blocks.REDSTONE_ORE.defaultBlockState());
+ interestingBlocks.add(Blocks.DEEPSLATE_REDSTONE_ORE.defaultBlockState());
+ interestingBlocks.add(Blocks.LAPIS_ORE.defaultBlockState());
+ interestingBlocks.add(Blocks.DEEPSLATE_LAPIS_ORE.defaultBlockState());
+ interestingBlocks.add(Blocks.EMERALD_ORE.defaultBlockState());
+ interestingBlocks.add(Blocks.DEEPSLATE_EMERALD_ORE.defaultBlockState());
+ interestingBlocks.add(Blocks.COAL_ORE.defaultBlockState());
+ interestingBlocks.add(Blocks.DEEPSLATE_COAL_ORE.defaultBlockState());
+ interestingBlocks.add(Blocks.COPPER_ORE.defaultBlockState());
+ interestingBlocks.add(Blocks.DEEPSLATE_COPPER_ORE.defaultBlockState());
+ interestingBlocks.add(Blocks.NETHER_QUARTZ_ORE.defaultBlockState());
+ interestingBlocks.add(Blocks.NETHER_GOLD_ORE.defaultBlockState());
+ interestingBlocks.add(Blocks.SPAWNER.defaultBlockState());
+ interestingBlocks.add(Blocks.CHEST.defaultBlockState());
+ interestingBlocks.add(Blocks.ANCIENT_DEBRIS.defaultBlockState());
+ interestingBlocks.add(Blocks.GLOWSTONE.defaultBlockState());
+ interestingBlocks.add(Blocks.WATER.defaultBlockState());
+ interestingBlocks.add(Blocks.LAVA.defaultBlockState());
+ }
+
+ @Override
+ protected void onEnable() {
+ if (mc.levelRenderer != null) mc.levelRenderer.allChanged();
+
+ if (mc.player != null) mc.player.displayClientMessage(Component.literal("[Xray] It is recommended to use this hack with Fullbright for a better experience."), false);
+ }
+
+
+ @Override
+ protected void onDisable() {
+ if (mc.levelRenderer != null) mc.levelRenderer.allChanged();
+ }
+
+ public boolean isInterestingBlock(BlockState state) {
+ return interestingBlocks.contains(state);
+ }
+
+ // xraying is handled in BlockMixin.java
+}
+
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/modules/settings/BooleanSetting.java b/src/main/java/com/arslaancodes/arslaansmagichax/modules/settings/BooleanSetting.java
new file mode 100644
index 0000000..618f2f4
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/modules/settings/BooleanSetting.java
@@ -0,0 +1,33 @@
+package com.arslaancodes.arslaansmagichax.modules.settings;
+
+public class BooleanSetting extends Setting {
+
+ private boolean enabled;
+
+ public BooleanSetting(String name, boolean defaultValue) {
+ super(name);
+ this.enabled = defaultValue;
+ }
+
+ public void toggle() {
+ this.enabled = !this.enabled;
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ @Override
+ public String getValueAsString() {
+ return String.valueOf(enabled);
+ }
+
+ @Override
+ public void setValueFromString(String value) {
+ this.enabled = Boolean.parseBoolean(value);
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/modules/settings/ModeSetting.java b/src/main/java/com/arslaancodes/arslaansmagichax/modules/settings/ModeSetting.java
new file mode 100644
index 0000000..796c3aa
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/modules/settings/ModeSetting.java
@@ -0,0 +1,65 @@
+package com.arslaancodes.arslaansmagichax.modules.settings;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+public class ModeSetting extends Setting {
+
+ private String mode;
+ private List<String> modes;
+ private int index;
+
+ public ModeSetting(String name, String defaultMode, String... modes) {
+ super(name);
+ this.mode = defaultMode;
+ this.modes = Arrays.asList(modes);
+ this.index = this.mode.indexOf(defaultMode);
+ }
+
+ public String getMode() {
+ return mode;
+ }
+
+ public List<String> getModes() {
+ return modes;
+ }
+
+ public void setMode(String mode) {
+ this.mode = mode;
+ this.index = modes.indexOf(mode);
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ public void setIndex(int index) {
+ this.index = index;
+ this.mode = modes.get(index);
+ }
+
+ public void cycle() {
+ if (index < modes.size() - 1) {
+ index++;
+ mode = modes.get(index);
+ } else if (index >= modes.size() - 1) {
+ index = 0;
+ mode = modes.get(0);
+ }
+ }
+
+ public boolean isMode(String mode) {
+ return Objects.equals(this.mode, mode);
+ }
+
+ @Override
+ public String getValueAsString() {
+ return mode;
+ }
+
+ @Override
+ public void setValueFromString(String value) {
+ setMode(value);
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/modules/settings/NumberSetting.java b/src/main/java/com/arslaancodes/arslaansmagichax/modules/settings/NumberSetting.java
new file mode 100644
index 0000000..ea6d9f5
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/modules/settings/NumberSetting.java
@@ -0,0 +1,66 @@
+package com.arslaancodes.arslaansmagichax.modules.settings;
+
+public class NumberSetting extends Setting {
+
+ private double min, max, increment;
+ private double value;
+
+ public NumberSetting(String name, double min, double max, double defaultValue, double increment) {
+ super(name);
+ this.min = min;
+ this.max = max;
+ this.value = defaultValue;
+ this.increment = increment;
+ }
+
+ public static double clamp(double value, double min, double max) {
+ value = Math.max(min, value);
+ value = Math.min(max, value);
+ return value;
+ }
+
+ public double getValue() {
+ return value;
+ }
+
+ public float getValueFloat() {
+ return (float) value;
+ }
+
+ public int getValueInt() {
+ return (int) value;
+ }
+
+ public double getIncrement() {
+ return increment;
+ }
+
+ public double getMin() {
+ return min;
+ }
+
+ public double getMax() {
+ return max;
+ }
+
+ public void setValue(double value) {
+ value = clamp(value, this.min, this.max);
+ value = Math.round(value * (1.0 / this.increment)) / (1.0 / this.increment);
+ this.value = value;
+ }
+
+ public void increment(boolean positive) {
+ if (positive) setValue(getValue() + getIncrement());
+ else setValue(getValue() - getIncrement());
+ }
+
+ @Override
+ public String getValueAsString() {
+ return String.valueOf(value);
+ }
+
+ @Override
+ public void setValueFromString(String value) {
+ setValue(Double.parseDouble(value));
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/modules/settings/Setting.java b/src/main/java/com/arslaancodes/arslaansmagichax/modules/settings/Setting.java
new file mode 100644
index 0000000..a272faa
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/modules/settings/Setting.java
@@ -0,0 +1,25 @@
+package com.arslaancodes.arslaansmagichax.modules.settings;
+
+public abstract class Setting {
+ private String name;
+ private boolean visible = true;
+
+ public Setting(String name) {
+ this.name = name;
+ }
+
+ public boolean isVisible() {
+ return visible;
+ }
+
+ public void setVisible(boolean visible) {
+ this.visible = visible;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public abstract String getValueAsString();
+ public abstract void setValueFromString(String value);
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/ClickGUIScreen.java b/src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/ClickGUIScreen.java
new file mode 100644
index 0000000..962a18e
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/ClickGUIScreen.java
@@ -0,0 +1,82 @@
+package com.arslaancodes.arslaansmagichax.screens.clickgui;
+
+import com.arslaancodes.arslaansmagichax.ArslaansMagicHaxClient;
+import com.arslaancodes.arslaansmagichax.modules.Category;
+import com.arslaancodes.arslaansmagichax.screens.clickgui.setting.Component;
+import com.arslaancodes.arslaansmagichax.screens.clickgui.setting.KeybindingSelector;
+import java.util.ArrayList;
+import java.util.List;
+import net.minecraft.client.gui.GuiGraphics;
+import net.minecraft.client.gui.screens.Screen;
+
+public class ClickGUIScreen extends Screen {
+ public static final ClickGUIScreen INSTANCE = new ClickGUIScreen();
+
+ private List<Frame> frames;
+
+ private ClickGUIScreen() {
+ super(net.minecraft.network.chat.Component.literal("ClickGUI"));
+
+ frames = new ArrayList<>();
+
+ int offset = 20;
+ for (Category category : Category.values()) {
+ frames.add(new Frame(category, offset, 30, 100, 20));
+ offset += 120;
+ }
+ }
+
+ @Override
+ public void render(GuiGraphics context, int mouseX, int mouseY, float deltaTicks) {
+ for (Frame frame : frames) {
+ frame.render(context, mouseX, mouseY, deltaTicks);
+ frame.updatePosition(mouseX, mouseY);
+ }
+ super.render(context, mouseX, mouseY, deltaTicks);
+ }
+
+ @Override
+ public boolean mouseClicked(double mouseX, double mouseY, int button) {
+ for (Frame frame : frames) {
+ frame.mouseClicked(mouseX, mouseY, button);
+ }
+ return super.mouseClicked(mouseX, mouseY, button);
+ }
+
+ @Override
+ public boolean mouseReleased(double mouseX, double mouseY, int button) {
+ for (Frame frame : frames) {
+ frame.mouseReleased(mouseX, mouseY, button);
+ }
+ return super.mouseReleased(mouseX, mouseY, button);
+ }
+
+ @Override
+ public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
+ for (Frame frame : frames) {
+ if (frame.isOpen) {
+ for (ModuleButton button : frame.getButtons()) {
+ if (button.extended) {
+ for (Component comp : button.components) {
+ if (comp instanceof KeybindingSelector keybindingSelector) {
+ keybindingSelector.onKeyPressed(keyCode);
+ }
+ }
+ }
+ }
+ }
+ }
+ return super.keyPressed(keyCode, scanCode, modifiers);
+ }
+
+ @Override
+ public boolean isPauseScreen() {
+ return false;
+ }
+
+ @Override
+ public void onClose() {
+ super.onClose();
+ ArslaansMagicHaxClient.clickGUI.setEnabled(false);
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/Frame.java b/src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/Frame.java
new file mode 100644
index 0000000..6a99973
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/Frame.java
@@ -0,0 +1,124 @@
+package com.arslaancodes.arslaansmagichax.screens.clickgui;
+
+import com.arslaancodes.arslaansmagichax.modules.Category;
+import com.arslaancodes.arslaansmagichax.modules.Module;
+import com.arslaancodes.arslaansmagichax.modules.ModuleManager;
+import com.arslaancodes.arslaansmagichax.screens.clickgui.setting.Component;
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.List;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiGraphics;
+
+public class Frame {
+ public int x, y, width, height, dragX, dragY;
+ public Category category;
+
+ public boolean dragging;
+
+ public boolean isOpen = false;
+
+ private List<ModuleButton> buttons;
+
+ protected Minecraft mc = Minecraft.getInstance();
+
+ public Frame(Category category, int x, int y, int width, int height) {
+ this.category = category;
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ this.dragging = false;
+
+ buttons = new ArrayList<>();
+
+ int offset = height;
+ for (Module module : ModuleManager.INSTANCE.getModulesWithCategory(category)) {
+ buttons.add(new ModuleButton(module, this, offset));
+ offset += height;
+ }
+ }
+
+ public void render(GuiGraphics context, int mouseX, int mouseY, float deltaTicks) {
+ context.fill(x, y, x + width, y + height, new Color(252, 210, 77, 255).getRGB());
+
+ String text = category.name();
+ int textY = y + (height - mc.font.lineHeight) / 2;
+
+ context.drawString(mc.font, net.minecraft.network.chat.Component.literal(text), x + 5, textY, new Color(30, 30, 47, 255).getRGB(), false);
+ context.drawString(mc.font, isOpen ? "-" : "+", x + width - 5 - mc.font.width("+"), textY, new Color(30, 30, 47, 255).getRGB(), false);
+
+ if (isOpen) {
+ for (ModuleButton button : buttons) {
+ button.render(context, mouseX, mouseY, deltaTicks);
+ }
+ }
+ }
+
+ public void mouseClicked(double mouseX, double mouseY, int button) {
+ if (isHovered(mouseX, mouseY)) {
+ if (button == 0) {
+ dragging = true;
+ dragX = (int) (mouseX - x);
+ dragY = (int) (mouseY - y);
+ } else {
+ isOpen = !isOpen;
+ }
+ }
+
+ if (isOpen) {
+ for (ModuleButton moduleButton : buttons) {
+ moduleButton.mouseClicked(mouseX, mouseY, button);
+ }
+ }
+ }
+
+ public void mouseReleased(double mouseX, double mouseY, int button) {
+ if (button == 0 && dragging) {
+ dragging = false;
+ }
+
+ if (isOpen) {
+ for (ModuleButton moduleButton : buttons) {
+ moduleButton.mouseReleased(mouseX, mouseY, button);
+ }
+ }
+ }
+
+ public boolean isHovered(double mouseX, double mouseY) {
+ return mouseX > x && mouseX < x + width && mouseY > y && mouseY < y + height;
+ }
+
+ public void updatePosition(double mouseX, double mouseY) {
+ if (dragging) {
+ x = (int) (mouseX - dragX);
+ y = (int) (mouseY - dragY);
+ }
+ }
+
+ public List<ModuleButton> getButtons() {
+ return buttons;
+ }
+
+ public void updateButtons() {
+ int offset = height;
+
+ for (ModuleButton button : buttons) {
+ button.offset = offset;
+ offset += height;
+
+ if (button.extended) {
+ for (Component component : button.components) {
+ if (component.setting != null) {
+ if (component.setting.isVisible()) {
+ offset += height;
+ }
+ } else {
+ // this is 99.99% the keybinding thing, just add offset anyway and hope it works i guess
+ offset += height;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/ModuleButton.java b/src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/ModuleButton.java
new file mode 100644
index 0000000..796c65e
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/ModuleButton.java
@@ -0,0 +1,97 @@
+package com.arslaancodes.arslaansmagichax.screens.clickgui;
+
+import com.arslaancodes.arslaansmagichax.modules.Module;
+import com.arslaancodes.arslaansmagichax.modules.settings.BooleanSetting;
+import com.arslaancodes.arslaansmagichax.modules.settings.ModeSetting;
+import com.arslaancodes.arslaansmagichax.modules.settings.NumberSetting;
+import com.arslaancodes.arslaansmagichax.modules.settings.Setting;
+import com.arslaancodes.arslaansmagichax.screens.clickgui.setting.*;
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.List;
+import net.minecraft.client.gui.GuiGraphics;
+
+public class ModuleButton {
+
+ public Module module;
+ public Frame parent;
+ public int offset;
+ public List<Component> components;
+ public boolean extended;
+
+ public ModuleButton(Module module, Frame parent, int offset) {
+ this.module = module;
+ this.parent = parent;
+ this.offset = offset;
+ this.extended = false;
+ this.components = new ArrayList<>();
+
+ int setOffset = parent.height;
+ components.add(new KeybindingSelector(this, setOffset));
+ setOffset += parent.height;
+ for (Setting setting : module.getSettings()) {
+ if (setting instanceof BooleanSetting) {
+ components.add(new CheckBox(setting, this, setOffset));
+ } else if (setting instanceof ModeSetting) {
+ components.add(new ModeBox(setting, this, setOffset));
+ } else if (setting instanceof NumberSetting) {
+ components.add(new Slider(setting, this, setOffset));
+ }
+ setOffset += parent.height;
+ }
+ }
+
+ public void render(GuiGraphics context, int mouseX, int mouseY, float deltaTicks) {
+ int alpha = isHovered(mouseX, mouseY) ? 230 : 160;
+
+ context.fill(parent.x, parent.y + offset, parent.x + parent.width, parent.y + offset + parent.height, new Color(30, 30, 47, alpha).getRGB());
+
+ if (isHovered(mouseX, mouseY)) {
+ context.setTooltipForNextFrame(net.minecraft.network.chat.Component.literal(module.getDescription()), mouseX, mouseY);
+ }
+
+ String text = module.getName();
+
+ int textX = parent.x + 5;
+ int textY = parent.y + offset + (parent.height - parent.mc.font.lineHeight) / 2;
+
+ int textColor = module.isEnabled() ? new Color(252, 210, 77, 255).getRGB() : Color.white.getRGB();
+
+ context.drawString(parent.mc.font, net.minecraft.network.chat.Component.literal(text), textX, textY, textColor);
+
+ if (extended) {
+ for (Component component : components) {
+ component.render(context, mouseX, mouseY, deltaTicks);
+ }
+ }
+ }
+
+ public void mouseClicked(double mouseX, double mouseY, int button) {
+ if (isHovered(mouseX, mouseY)) {
+ if (button == 0) {
+ module.toggle();
+ }
+ else if (button == 1) {
+ extended = !extended;
+ parent.updateButtons();
+ }
+ }
+
+ for (Component component : components) {
+ component.mouseClicked(mouseX, mouseY, button);
+ }
+ }
+
+ public void mouseReleased(double mouseX, double mouseY, int button) {
+ // luigi wins by doing absolutely nothing
+
+ // nevermind we did something
+ for (Component component : components) {
+ component.mouseReleased(mouseX, mouseY, button);
+ }
+ }
+
+ public boolean isHovered(double mouseX, double mouseY) {
+ return mouseX > parent.x && mouseX < parent.x + parent.width && mouseY > parent.y + offset && mouseY < parent.y + offset + parent.height;
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/setting/CheckBox.java b/src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/setting/CheckBox.java
new file mode 100644
index 0000000..2dacd2f
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/setting/CheckBox.java
@@ -0,0 +1,50 @@
+package com.arslaancodes.arslaansmagichax.screens.clickgui.setting;
+
+import com.arslaancodes.arslaansmagichax.modules.settings.BooleanSetting;
+import com.arslaancodes.arslaansmagichax.modules.settings.Setting;
+import com.arslaancodes.arslaansmagichax.screens.clickgui.ModuleButton;
+import java.awt.*;
+import net.minecraft.client.gui.GuiGraphics;
+import net.minecraft.network.chat.Component;
+
+public class CheckBox extends Component {
+
+ private BooleanSetting booleanSetting = (BooleanSetting) setting;
+
+ public CheckBox(Setting setting, ModuleButton parent, int offset) {
+ super(setting, parent, offset);
+ this.booleanSetting = (BooleanSetting) setting;
+ }
+
+ @Override
+ public void render(GuiGraphics context, int mouseX, int mouseY, float deltaTicks) {
+ String displayText = booleanSetting.getName() + ": " + booleanSetting.isEnabled();
+ int textWidth = mc.font.width(displayText);
+ int padding = 5;
+ int boxWidth = Math.max(parent.parent.width, textWidth + (padding * 2));
+
+ int alpha = isHovered(mouseX, mouseY) ? 230 : 160;
+ context.fill(
+ parent.parent.x,
+ parent.parent.y + parent.offset + offset,
+ parent.parent.x + boxWidth,
+ parent.parent.y + parent.offset + offset + parent.parent.height,
+ new Color(30, 30, 47, alpha).getRGB()
+ );
+
+ context.drawString(
+ mc.font,
+ Component.literal(displayText),
+ parent.parent.x + padding,
+ parent.parent.y + parent.offset + offset + (parent.parent.height - mc.font.lineHeight) / 2,
+ Color.white.getRGB()
+ );
+ }
+
+ @Override
+ public void mouseClicked(double mouseX, double mouseY, int button) {
+ if (isHovered(mouseX, mouseY) && button == 0) {
+ booleanSetting.toggle();
+ }
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/setting/Component.java b/src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/setting/Component.java
new file mode 100644
index 0000000..96a3bbd
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/setting/Component.java
@@ -0,0 +1,37 @@
+package com.arslaancodes.arslaansmagichax.screens.clickgui.setting;
+
+import com.arslaancodes.arslaansmagichax.modules.settings.Setting;
+import com.arslaancodes.arslaansmagichax.screens.clickgui.ModuleButton;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiGraphics;
+
+public class Component {
+
+ public Setting setting;
+ public ModuleButton parent;
+ public int offset;
+
+ protected static Minecraft mc = Minecraft.getInstance();
+
+ public Component(Setting setting, ModuleButton parent, int offset) {
+ this.setting = setting;
+ this.parent = parent;
+ this.offset = offset;
+ }
+
+ public void render(GuiGraphics context, int mouseX, int mouseY, float deltaTicks) {
+
+ }
+
+ public void mouseClicked(double mouseX, double mouseY, int button) {
+
+ }
+
+ public void mouseReleased(double mouseX, double mouseY, int button) {
+
+ }
+
+ public boolean isHovered(double mouseX, double mouseY) {
+ return mouseX > parent.parent.x && mouseX < parent.parent.x + parent.parent.width && mouseY > parent.parent.y + parent.offset + offset && mouseY < parent.parent.y + parent.offset + offset + parent.parent.height;
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/setting/KeybindingSelector.java b/src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/setting/KeybindingSelector.java
new file mode 100644
index 0000000..a29c3a2
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/setting/KeybindingSelector.java
@@ -0,0 +1,74 @@
+package com.arslaancodes.arslaansmagichax.screens.clickgui.setting;
+
+import com.arslaancodes.arslaansmagichax.screens.clickgui.ModuleButton;
+import org.lwjgl.glfw.GLFW;
+
+import java.awt.*;
+import net.minecraft.client.gui.GuiGraphics;
+
+public class KeybindingSelector extends Component {
+
+ private boolean listening = false;
+
+ public KeybindingSelector(ModuleButton parent, int offset) {
+ super(null, parent, offset);
+ }
+
+ @Override
+ public void render(GuiGraphics context, int mouseX, int mouseY, float deltaTicks) {
+ int alpha = isHovered(mouseX, mouseY) ? 230 : 160;
+ context.fill(parent.parent.x, parent.parent.y + parent.offset + offset, parent.parent.x + parent.parent.width, parent.parent.y + parent.offset + offset + parent.parent.height, new Color(30, 30, 47, alpha).getRGB());
+
+ if (listening) {
+ context.fill(parent.parent.x, parent.parent.y + parent.offset + offset, parent.parent.x + parent.parent.width, parent.parent.y + parent.offset + offset + parent.parent.height, new Color(252, 210, 77, 255).getRGB());
+ }
+
+ String displayText = listening ? "Press a key..." : "Keybind: " + getKeyName(parent.module.getGlfwKeybinding());
+ context.drawString(mc.font, displayText, parent.parent.x + 5, parent.parent.y + parent.offset + offset + (parent.parent.height - mc.font.lineHeight) / 2, Color.white.getRGB());
+ }
+
+ @Override
+ public void mouseClicked(double mouseX, double mouseY, int button) {
+ if (isHovered(mouseX, mouseY) && button == 0) {
+ listening = !listening;
+ }
+ }
+
+ public void onKeyPressed(int keyCode) {
+ if (!listening) return;
+
+ listening = false;
+
+ if (keyCode == GLFW.GLFW_KEY_ESCAPE || keyCode == GLFW.GLFW_KEY_DELETE || keyCode == GLFW.GLFW_KEY_BACKSPACE) {
+ // remove bingdingd AHH I CANT SPELL
+ parent.module.setGlfwKeybinding(-1);
+ return;
+ }
+
+ parent.module.setGlfwKeybinding(keyCode);
+ }
+
+ private String getKeyName(int key) {
+ if (key == -1) return "NONE";
+ String name = GLFW.glfwGetKeyName(key, 0);
+
+ if (name != null) return name.toUpperCase();
+
+ return switch (key) {
+ case GLFW.GLFW_KEY_LEFT_SHIFT -> "LSHIFT";
+ case GLFW.GLFW_KEY_RIGHT_SHIFT -> "RSHIFT";
+ case GLFW.GLFW_KEY_LEFT_CONTROL -> "LCTRL";
+ case GLFW.GLFW_KEY_RIGHT_CONTROL -> "RCTRL";
+ case GLFW.GLFW_KEY_LEFT_ALT -> "LALT";
+ case GLFW.GLFW_KEY_RIGHT_ALT -> "RALT";
+ case GLFW.GLFW_KEY_SPACE -> "SPACE";
+ case GLFW.GLFW_KEY_TAB -> "TAB";
+ case GLFW.GLFW_KEY_ENTER -> "ENTER";
+ case GLFW.GLFW_KEY_UP -> "UP";
+ case GLFW.GLFW_KEY_DOWN -> "DOWN";
+ case GLFW.GLFW_KEY_LEFT -> "LEFT";
+ case GLFW.GLFW_KEY_RIGHT -> "RIGHT";
+ default -> "KEY_" + key;
+ };
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/setting/ModeBox.java b/src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/setting/ModeBox.java
new file mode 100644
index 0000000..1200fa0
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/setting/ModeBox.java
@@ -0,0 +1,56 @@
+package com.arslaancodes.arslaansmagichax.screens.clickgui.setting;
+
+import com.arslaancodes.arslaansmagichax.modules.settings.ModeSetting;
+import com.arslaancodes.arslaansmagichax.modules.settings.Setting;
+import com.arslaancodes.arslaansmagichax.screens.clickgui.ModuleButton;
+import java.awt.*;
+import net.minecraft.client.gui.GuiGraphics;
+import net.minecraft.network.chat.Component;
+
+public class ModeBox extends Component {
+
+ private ModeSetting modeSetting = (ModeSetting) setting;
+
+ public ModeBox(Setting setting, ModuleButton parent, int offset) {
+ super(setting, parent, offset);
+ this.modeSetting = (ModeSetting) setting;
+ }
+
+ @Override
+ public void render(GuiGraphics context, int mouseX, int mouseY, float deltaTicks) {
+ String displayText = modeSetting.getName() + ": " + modeSetting.getMode();
+ int textWidth = mc.font.width(displayText);
+
+ int padding = 5;
+ int boxWidth = Math.max(parent.parent.width, textWidth + padding * 2);
+
+ int alpha = isHovered(mouseX, mouseY) ? 230 : 160;
+ context.fill(
+ parent.parent.x,
+ parent.parent.y + parent.offset + offset,
+ parent.parent.x + boxWidth,
+ parent.parent.y + parent.offset + offset + parent.parent.height,
+ new Color(30, 30, 47, alpha).getRGB()
+ );
+
+ context.drawString(
+ mc.font,
+ Component.literal(displayText),
+ parent.parent.x + padding, // left padding
+ parent.parent.y + parent.offset + offset + (parent.parent.height - mc.font.lineHeight) / 2,
+ Color.white.getRGB()
+ );
+ }
+
+ @Override
+ public void mouseClicked(double mouseX, double mouseY, int button) {
+ if (isHovered(mouseX, mouseY) && button == 0) {
+ modeSetting.cycle();
+ }
+ }
+
+ @Override
+ public void mouseReleased(double mouseX, double mouseY, int button) {
+ super.mouseReleased(mouseX, mouseY, button);
+ }
+}
diff --git a/src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/setting/Slider.java b/src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/setting/Slider.java
new file mode 100644
index 0000000..bacefd6
--- /dev/null
+++ b/src/main/java/com/arslaancodes/arslaansmagichax/screens/clickgui/setting/Slider.java
@@ -0,0 +1,92 @@
+package com.arslaancodes.arslaansmagichax.screens.clickgui.setting;
+
+import com.arslaancodes.arslaansmagichax.modules.settings.NumberSetting;
+import com.arslaancodes.arslaansmagichax.modules.settings.Setting;
+import com.arslaancodes.arslaansmagichax.screens.clickgui.ModuleButton;
+import java.awt.*;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import net.minecraft.client.gui.GuiGraphics;
+import net.minecraft.network.chat.Component;
+
+public class Slider extends Component {
+
+ public NumberSetting numberSetting = (NumberSetting) setting;
+
+ private boolean sliding = false;
+
+ public Slider(Setting setting, ModuleButton parent, int offset) {
+ super(setting, parent, offset);
+ this.numberSetting = (NumberSetting) setting;
+ }
+
+ @Override
+ public void render(GuiGraphics context, int mouseX, int mouseY, float deltaTicks) {
+ String displayText = numberSetting.getName() + ": " + numberSetting.getValue();
+ int defaultPadding = 5;
+ int boxWidth = parent.parent.width;
+
+ int alpha = isHovered(mouseX, mouseY) ? 230 : 160;
+
+ context.fill(
+ parent.parent.x,
+ parent.parent.y + parent.offset + offset,
+ parent.parent.x + boxWidth,
+ parent.parent.y + parent.offset + offset + parent.parent.height,
+ new Color(30, 30, 47, alpha).getRGB()
+ );
+
+ double diff = Math.min(boxWidth, Math.max(0, mouseX - parent.parent.x));
+ int renderWidth = (int) (boxWidth * (numberSetting.getValue() - numberSetting.getMin()) / (numberSetting.getMax() - numberSetting.getMin()));
+
+ context.fill(
+ parent.parent.x,
+ parent.parent.y + parent.offset + offset,
+ parent.parent.x + renderWidth,
+ parent.parent.y + parent.offset + offset + parent.parent.height,
+ new Color(252, 210, 77, 255).getRGB()
+ );
+
+ if (sliding) {
+ if (diff == 0) {
+ numberSetting.setValue(numberSetting.getMin());
+ } else {
+ numberSetting.setValue(roundToPlace((diff / boxWidth) * (numberSetting.getMax() - numberSetting.getMin()) + numberSetting.getMin(), 1));
+ }
+ }
+
+ int textWidth = mc.font.width(displayText);
+ int leftPadding = defaultPadding;
+ if (textWidth + 2 * defaultPadding > boxWidth) {
+ leftPadding = Math.max(2, boxWidth - textWidth - 2);
+ }
+
+ context.drawString(
+ mc.font,
+ Component.literal(displayText),
+ parent.parent.x + leftPadding,
+ parent.parent.y + parent.offset + offset + (parent.parent.height - mc.font.lineHeight) / 2,
+ Color.white.getRGB()
+ );
+ }
+
+ @Override
+ public void mouseClicked(double mouseX, double mouseY, int button) {
+ if (isHovered(mouseX, mouseY)) sliding = true;
+ }
+
+ @Override
+ public void mouseReleased(double mouseX, double mouseY, int button) {
+ sliding = false;
+ }
+
+ private double roundToPlace(double value, int place) {
+ if (place < 0) {
+ return value;
+ }
+
+ BigDecimal bd = new BigDecimal(value);
+ bd = bd.setScale(place, RoundingMode.HALF_UP);
+ return bd.doubleValue();
+ }
+}