content: package myau.module.modules;
  
  import myau.event.EventTarget;
  import myau.event.types.EventType;
  import myau.event.types.Priority;
  import myau.events.LeftClickMouseEvent;
  import myau.events.TickEvent;
  import myau.module.Module;
  import myau.util.ItemUtil;
  import myau.util.KeyBindUtil;
  import myau.util.RandomUtil;
  import myau.property.properties.BooleanProperty;
  import myau.property.properties.FloatProperty;
  import myau.property.properties.IntProperty;
  import net.minecraft.client.Minecraft;
  import net.minecraft.util.MovingObjectPosition.MovingObjectType;
  import net.minecraft.world.WorldSettings.GameType;
  
  import java.util.Objects;
  
  public class AutoClicker extends Module {
      private static final Minecraft mc = Minecraft.getMinecraft();
      private boolean clickPending = false;
      private long clickDelay = 0L;
      private boolean blockHitPending = false;
      private long blockHitDelay = 0L;
      public final IntProperty minCPS = new IntProperty("min-cps", 8, 1, 20);
      public final IntProperty maxCPS = new IntProperty("max-cps", 12, 1, 20);
      public final BooleanProperty blockHit = new BooleanProperty("block-hit", false);
      public final FloatProperty blockHitTicks = new FloatProperty("block-hit-ticks", 1.5F, 1.0F, 20.0F, this.blockHit::getValue);
      public final BooleanProperty weaponsOnly = new BooleanProperty("weapons-only", true);
      public final BooleanProperty allowTools = new BooleanProperty("allow-tools", false, this.weaponsOnly::getValue);
      public final BooleanProperty breakBlocks = new BooleanProperty("break-blocks", true);
  
      private long getNextClickDelay() {
          return 1000L / RandomUtil.nextLong(this.minCPS.getValue().intValue(), this.maxCPS.getValue().intValue());
      }
  
      private long getBlockHitDelay() {
          return (long) (50.0F * this.blockHitTicks.getValue());
      }
  
      private boolean isBreakingBlock() {
          return mc.objectMouseOver != null && mc.objectMouseOver.typeOfHit == MovingObjectType.BLOCK;
      }
  
      private boolean canClick() {
          if (!this.weaponsOnly.getValue()
                  || ItemUtil.hasRawUnbreakingEnchant()
                  || this.allowTools.getValue() && ItemUtil.isHoldingTool()) {
              if (this.breakBlocks.getValue() && this.isBreakingBlock()) {
                  GameType gameType12 = mc.playerController.getCurrentGameType();
                  return gameType12 != GameType.SURVIVAL && gameType12 != GameType.CREATIVE;
              } else {
                  return true;
              }
          } else {
              return false;
          }
      }
  
      public AutoClicker() {
          super("AutoClicker", false);
      }
  
      @EventTarget
      public void onTick(TickEvent event) {
          if (event.getType() == EventType.PRE) {
              if (this.clickDelay > 0L) {
                  this.clickDelay -= 50L;
              }
              if (this.blockHitDelay > 0L) {
                  this.blockHitDelay -= 50L;
              }
              if (mc.currentScreen != null) {
                  this.clickPending = false;
                  this.blockHitPending = false;
              } else {
                  if (this.clickPending) {
                      this.clickPending = false;
                      KeyBindUtil.updateKeyState(mc.gameSettings.keyBindAttack.getKeyCode());
                  }
                  if (this.blockHitPending) {
                      this.blockHitPending = false;
                      KeyBindUtil.updateKeyState(mc.gameSettings.keyBindUseItem.getKeyCode());
                  }
                  if (this.isEnabled() && this.canClick() && mc.gameSettings.keyBindAttack.isKeyDown()) {
                      if (!mc.thePlayer.isUsingItem()) {
                          while (this.clickDelay <= 0L) {
                              this.clickPending = true;
                              this.clickDelay = this.clickDelay + this.getNextClickDelay();
                              KeyBindUtil.setKeyBindState(mc.gameSettings.keyBindAttack.getKeyCode(), false);
                              KeyBindUtil.pressKeyOnce(mc.gameSettings.keyBindAttack.getKeyCode());
                          }
                      }
                      if (this.blockHit.getValue()
                              && this.blockHitDelay <= 0L
                              && mc.gameSettings.keyBindUseItem.isKeyDown()
                              && ItemUtil.isHoldingSword()) {
                          this.blockHitPending = true;
                          KeyBindUtil.setKeyBindState(mc.gameSettings.keyBindUseItem.getKeyCode(), false);
                          if (!mc.thePlayer.isUsingItem()) {
                              this.blockHitDelay = this.blockHitDelay + this.getBlockHitDelay();
                              KeyBindUtil.pressKeyOnce(mc.gameSettings.keyBindUseItem.getKeyCode());
                          }
                      }
                  }
              }
          }
      }
  
      @EventTarget(Priority.LOWEST)
      public void onCLick(LeftClickMouseEvent event) {
          if (this.isEnabled() && !event.isCancelled()) {
              if (!this.clickPending) {
                  this.clickDelay = this.clickDelay + this.getNextClickDelay();
              }
          }
      }
  
      @Override
      public void onEnabled() {
          this.clickDelay = 0L;
          this.blockHitDelay = 0L;
      }
  
      @Override
      public void verifyValue(String mode) {
          if (this.minCPS.getName().equals(mode)) {
              if (this.minCPS.getValue() > this.maxCPS.getValue()) {
                  this.maxCPS.setValue(this.minCPS.getValue());
              }
          } else {
              if (this.maxCPS.getName().equals(mode) && this.minCPS.getValue() > this.maxCPS.getValue()) {
                  this.minCPS.setValue(this.maxCPS.getValue());
              }
          }
      }
  
      @Override
      public String[] getSuffix() {
          return Objects.equals(this.minCPS.getValue(), this.maxCPS.getValue())
                  ? new String[]{this.minCPS.getValue().toString()}
                  : new String[]{String.format("%d-%d", this.minCPS.getValue(), this.maxCPS.getValue())};
      }
  }
  