package ARTheryx.modules.impl.movement;
import lombok.AccessLevel;
import lombok.experimental.FieldDefaults;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.EquippableComponent;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket;
import net.minecraft.network.packet.c2s.play.UpdatePlayerAbilitiesC2SPacket;
import net.minecraft.screen.slot.SlotActionType;
import ARTheryx.events.api.EventHandler;
import ARTheryx.events.impl.PacketEvent;
import ARTheryx.events.impl.TickEvent;
import ARTheryx.modules.module.ModuleStructure;
import ARTheryx.modules.module.category.ModuleCategory;
import ARTheryx.modules.module.setting.implement.BooleanSetting;
import ARTheryx.modules.module.setting.implement.SliderSettings;
@FieldDefaults(level = AccessLevel.PRIVATE)
public class AirStuckBug extends ModuleStructure {
private final BooleanSetting autoSwap = new BooleanSetting("Swap elytra", "Automatically swap elytra when enabled");
private final SliderSettings speed = new SliderSettings("Speed", "Movement speed when frozen");
public boolean isElytraState;
public AirStuckBug() {
super("Air Stuck", "Freezes player in air while allowing forward movement", ModuleCategory.MOVEMENT);
autoSwap.setValue(false);
speed.range(0.1f, 10.0f).setValue(2.0f);
settings(autoSwap, speed);
}
@Override
public void activate() {
if (mc.player == null) {
return;
}
isElytraState = mc.player.getEquippedStack(EquipmentSlot.CHEST).getItem() == Items.ELYTRA;
}
@Override
public void deactivate() {
if (mc.player == null) return;
if (isElytraState && autoSwap.isValue()) {
swap(false);
}
}
@EventHandler
public void onTick(TickEvent event) {
if (mc.player == null) return;
isElytraState = mc.player.getEquippedStack(EquipmentSlot.CHEST).getItem() == Items.ELYTRA;
if (isElytraState && autoSwap.isValue()) {
swap(true);
}
// Freeze player like original AirStuck but allow forward movement
if (!mc.player.isGliding()) {
if (mc.options.forwardKey.isPressed()) {
// Allow forward movement with enhanced speed
float yaw = mc.player.getYaw();
double motionX = -Math.sin(Math.toRadians(yaw)) * speed.getValue() * 0.1;
double motionZ = Math.cos(Math.toRadians(yaw)) * speed.getValue() * 0.1;
mc.player.setVelocity(motionX, 0, motionZ);
} else {
// Freeze completely when not moving forward
mc.player.setVelocity(0, 0, 0);
}
}
}
@EventHandler
public void onPacket(PacketEvent event) {
if (mc.player == null || mc.player.isGliding() || !event.isSend()) return;
// Block movement packets like original AirStuck
if (event.getPacket() instanceof PlayerMoveC2SPacket || event.getPacket() instanceof UpdatePlayerAbilitiesC2SPacket) {
event.cancel();
}
}
private void swap(boolean chestplate) {
int slot = chestplate ? findChestPlate() : findItem(Items.ELYTRA);
if (slot != -1) {
moveItem(slot, 6);
}
}
private int findChestPlate() {
for (int i = 0; i < 36; i++) {
ItemStack stack = mc.player.getInventory().getStack(i);
if (stack.isEmpty() || stack.getItem() == Items.ELYTRA) continue;
EquippableComponent equippable = stack.get(DataComponentTypes.EQUIPPABLE);
if (equippable != null && equippable.slot() == EquipmentSlot.CHEST) {
String itemId = stack.getItem().toString().toLowerCase();
if (itemId.contains("chestplate") || itemId.contains("tunic") || itemId.contains("jacket")) {
return i < 9 ? i + 36 : i;
}
}
}
return -1;
}
private int findItem(Item item) {
for (int i = 0; i < 36; i++) {
if (mc.player.getInventory().getStack(i).getItem() == item) {
return i < 9 ? i + 36 : i;
}
}
return -1;
}
private void moveItem(int slot, int targetSlot) {
if (mc.interactionManager != null) {
mc.interactionManager.clickSlot(0, slot, 0, SlotActionType.PICKUP, mc.player);
mc.interactionManager.clickSlot(0, targetSlot, 0, SlotActionType.PICKUP, mc.player);
mc.interactionManager.clickSlot(0, slot, 0, SlotActionType.PICKUP, mc.player);
}
}
}