package dev.crucifixbeta.mod.modules.impl.exploit;

import dev.crucifixbeta.api.events.eventbus.EventListener;
import dev.crucifixbeta.api.events.impl.GameLeftEvent;
import dev.crucifixbeta.api.events.impl.OpenScreenEvent;
import dev.crucifixbeta.api.events.impl.PacketEvent;
import dev.crucifixbeta.api.events.impl.Render3DEvent;
import dev.crucifixbeta.api.events.impl.UpdateEvent;
import dev.crucifixbeta.mod.modules.Module;
import dev.crucifixbeta.mod.modules.settings.impl.BooleanSetting;
import dev.crucifixbeta.mod.modules.settings.impl.ColorSetting;
import dev.crucifixbeta.mod.modules.settings.impl.EnumSetting;
import dev.crucifixbeta.mod.modules.settings.impl.SliderSetting;
import java.awt.Color;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.client.gui.screen.DisconnectedScreen;
import net.minecraft.client.gui.screen.DownloadingTerrainScreen;
import net.minecraft.fluid.FluidState;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.c2s.play.AcknowledgeChunksC2SPacket;
import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket;
import net.minecraft.network.packet.s2c.play.ChunkDataS2CPacket;
import net.minecraft.network.packet.s2c.play.ChunkDeltaUpdateS2CPacket;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraft.world.biome.BiomeKeys;
import net.minecraft.world.chunk.BiMapPalette;
import net.minecraft.world.chunk.ChunkSection;
import net.minecraft.world.chunk.Palette;
import net.minecraft.world.chunk.PalettedContainer;
import net.minecraft.world.chunk.ReadableContainer;
import net.minecraft.world.chunk.WorldChunk;

@Environment(EnvType.CLIENT)
public class ChunkESP extends Module {
   private static final ExecutorService taskExecutor;
   private static final Direction[] searchDirs;
   private static final Set<Block> ORE_BLOCKS;
   private static final Set<Block> NEW_OVERWORLD_BLOCKS;
   private static final Set<Block> NEW_NETHER_BLOCKS;
   public static int newchunksfound;
   public static int oldchunksfound;
   public static int beingUpdatedOldChunksfound;
   public static int OldGenerationOldChunksfound;
   public static int tickexploitchunksfound;
   public final EnumSetting<ChunkESP.DetectMode> detectmode = this.add(new EnumSetting<>("DetectMode", ChunkESP.DetectMode.Normal));
   public final SliderSetting renderDistance = this.add(new SliderSetting("Chunks-Distance", 128, 6, 1024));
   public final SliderSetting renderHeight = this.add(new SliderSetting("RenderHeight", 0, -112, 319));
   final Set<ChunkPos> newChunks = Collections.synchronizedSet(new HashSet<>());
   final Set<ChunkPos> oldChunks = Collections.synchronizedSet(new HashSet<>());
   final Set<ChunkPos> beingUpdatedOldChunks = Collections.synchronizedSet(new HashSet<>());
   final Set<ChunkPos> OldGenerationOldChunks = Collections.synchronizedSet(new HashSet<>());
   final Set<ChunkPos> tickexploitChunks = Collections.synchronizedSet(new HashSet<>());
   private final BooleanSetting PaletteExploit = this.add(new BooleanSetting("PaletteExploit", true));
   private final BooleanSetting beingUpdatedDetector = this.add(new BooleanSetting("BeingUpdated", true));
   private final BooleanSetting overworldOldChunksDetector = this.add(new BooleanSetting("OverworldOldChunks", true));
   private final BooleanSetting netherOldChunksDetector = this.add(new BooleanSetting("NetherOldChunks", true));
   private final BooleanSetting endOldChunksDetector = this.add(new BooleanSetting("EndOldChunks", true));
   private final BooleanSetting liquidexploit = this.add(new BooleanSetting("LiquidExploit", false));
   private final BooleanSetting blockupdateexploit = this.add(new BooleanSetting("blockUpdateExploit", false));
   private final BooleanSetting worldleaveremove = this.add(new BooleanSetting("WorldLeaveRemove", true));
   private final BooleanSetting removerenderdist = this.add(new BooleanSetting("RemoveRenderDist", false));
   private final ColorSetting newChunksSideColor = this.add(new ColorSetting("New", new Color(255, 0, 0, 95)));
   private final ColorSetting tickexploitChunksSideColor = this.add(new ColorSetting("BlockExploit", new Color(0, 0, 255, 75)));
   private final ColorSetting oldChunksSideColor = this.add(new ColorSetting("Old", new Color(0, 255, 0, 40)));
   private final ColorSetting beingUpdatedOldChunksSideColor = this.add(new ColorSetting("BeingUpdated", new Color(0, 255, 0, 40)));
   private final ColorSetting OldGenerationOldChunksSideColor = this.add(new ColorSetting("OldVersion", new Color(190, 255, 0, 40)));
   public int chunkcounterticks = 0;
   private int errticks = 0;

   public ChunkESP() {
      super("ChunkESP", Module.Category.Exploit);
      this.setChinese("\u533a\u5757\u663e\u793a");
   }

   private void resetCounterValues() {
      this.chunkcounterticks = 0;
      newchunksfound = 0;
      oldchunksfound = 0;
      beingUpdatedOldChunksfound = 0;
      OldGenerationOldChunksfound = 0;
      tickexploitchunksfound = 0;
   }

   private void clearChunkData() {
      this.newChunks.clear();
      this.oldChunks.clear();
      this.beingUpdatedOldChunks.clear();
      this.OldGenerationOldChunks.clear();
      this.tickexploitChunks.clear();
   }

   @Override
   public void onDisable() {
      this.chunkcounterticks = 0;
   }

   @EventListener
   private void onScreenOpen(OpenScreenEvent event) {
      if (event.screen instanceof DisconnectedScreen) {
         this.resetCounterValues();
         if (this.worldleaveremove.getValue()) {
            this.clearChunkData();
         }
      }

      if (event.screen instanceof DownloadingTerrainScreen) {
         this.resetCounterValues();
      }
   }

   @EventListener
   private void onGameLeft(GameLeftEvent event) {
      this.resetCounterValues();
      if (this.worldleaveremove.getValue()) {
         this.clearChunkData();
      }
   }

   @EventListener
   public void onUpdate(UpdateEvent event) {
      if (mc.player.getHealth() == 0.0F) {
         this.resetCounterValues();
      }

      if (this.detectmode.getValue() == ChunkESP.DetectMode.Normal && this.blockupdateexploit.getValue()) {
         if (this.errticks < 6) {
            this.errticks++;
         }

         if (this.errticks == 5) {
            this.sendMessage("\u00a74BlockExploitMode RECOMMENDED. Required to determine false positives from the Block Exploit from the OldChunks.");
         }
      } else {
         this.errticks = 0;
      }

      if (this.removerenderdist.getValue()) {
         this.removeChunksOutsideRenderDistance();
      }
   }

   @EventListener
   private void onRender(Render3DEvent event) {
      Set var2 = this.newChunks;
      synchronized (var2) {
         for (ChunkPos var5 : this.newChunks) {
            if (var5 != null && mc.getCameraEntity().getBlockPos().isWithinDistance(var5.getStartPos(), this.renderDistance.getValue() * 16.0)) {
               event.drawFill(
                  new Box(
                     new Vec3d(
                        (double)var5.getStartPos().getX(), (double)var5.getStartPos().getY() + this.renderHeight.getValue(), (double)var5.getStartPos().getZ()
                     ),
                     new Vec3d(
                        (double)(var5.getStartPos().getX() + 16),
                        (double)var5.getStartPos().getY() + this.renderHeight.getValue(),
                        (double)(var5.getStartPos().getZ() + 16)
                     )
                  ),
                  this.newChunksSideColor.getValue()
               );
            }
         }
      }

      var2 = this.tickexploitChunks;
      synchronized (var2) {
         for (ChunkPos var24 : this.tickexploitChunks) {
            if (var24 != null && mc.getCameraEntity().getBlockPos().isWithinDistance(var24.getStartPos(), this.renderDistance.getValue() * 16.0)) {
               if (this.detectmode.getValue() == ChunkESP.DetectMode.BlockExploitMode && this.blockupdateexploit.getValue()) {
                  event.drawFill(
                     new Box(
                        new Vec3d(
                           (double)var24.getStartPos().getX(),
                           (double)var24.getStartPos().getY() + this.renderHeight.getValue(),
                           (double)var24.getStartPos().getZ()
                        ),
                        new Vec3d(
                           (double)(var24.getStartPos().getX() + 16),
                           (double)var24.getStartPos().getY() + this.renderHeight.getValue(),
                           (double)(var24.getStartPos().getZ() + 16)
                        )
                     ),
                     this.tickexploitChunksSideColor.getValue()
                  );
               } else if (this.detectmode.getValue() == ChunkESP.DetectMode.Normal && this.blockupdateexploit.getValue()) {
                  event.drawFill(
                     new Box(
                        new Vec3d(
                           (double)var24.getStartPos().getX(),
                           (double)var24.getStartPos().getY() + this.renderHeight.getValue(),
                           (double)var24.getStartPos().getZ()
                        ),
                        new Vec3d(
                           (double)(var24.getStartPos().getX() + 16),
                           (double)var24.getStartPos().getY() + this.renderHeight.getValue(),
                           (double)(var24.getStartPos().getZ() + 16)
                        )
                     ),
                     this.newChunksSideColor.getValue()
                  );
               } else if (this.detectmode.getValue() == ChunkESP.DetectMode.IgnoreBlockExploit && this.blockupdateexploit.getValue()) {
                  event.drawFill(
                     new Box(
                        new Vec3d(
                           (double)var24.getStartPos().getX(),
                           (double)var24.getStartPos().getY() + this.renderHeight.getValue(),
                           (double)var24.getStartPos().getZ()
                        ),
                        new Vec3d(
                           (double)(var24.getStartPos().getX() + 16),
                           (double)var24.getStartPos().getY() + this.renderHeight.getValue(),
                           (double)(var24.getStartPos().getZ() + 16)
                        )
                     ),
                     this.oldChunksSideColor.getValue()
                  );
               } else if (this.detectmode.getValue() == ChunkESP.DetectMode.BlockExploitMode
                  | this.detectmode.getValue() == ChunkESP.DetectMode.Normal
                  | this.detectmode.getValue() == ChunkESP.DetectMode.IgnoreBlockExploit) {
                  event.drawFill(
                     new Box(
                        new Vec3d(
                           (double)var24.getStartPos().getX(),
                           (double)var24.getStartPos().getY() + this.renderHeight.getValue(),
                           (double)var24.getStartPos().getZ()
                        ),
                        new Vec3d(
                           (double)(var24.getStartPos().getX() + 16),
                           (double)var24.getStartPos().getY() + this.renderHeight.getValue(),
                           (double)(var24.getStartPos().getZ() + 16)
                        )
                     ),
                     this.oldChunksSideColor.getValue()
                  );
               }
            }
         }
      }

      var2 = this.oldChunks;
      synchronized (var2) {
         for (ChunkPos var25 : this.oldChunks) {
            if (var25 != null && mc.getCameraEntity().getBlockPos().isWithinDistance(var25.getStartPos(), this.renderDistance.getValue() * 16.0)) {
               event.drawFill(
                  new Box(
                     new Vec3d(
                        (double)var25.getStartPos().getX(),
                        (double)var25.getStartPos().getY() + this.renderHeight.getValue(),
                        (double)var25.getStartPos().getZ()
                     ),
                     new Vec3d(
                        (double)(var25.getStartPos().getX() + 16),
                        (double)var25.getStartPos().getY() + this.renderHeight.getValue(),
                        (double)(var25.getStartPos().getZ() + 16)
                     )
                  ),
                  this.oldChunksSideColor.getValue()
               );
            }
         }
      }

      var2 = this.beingUpdatedOldChunks;
      synchronized (var2) {
         for (ChunkPos var26 : this.beingUpdatedOldChunks) {
            if (var26 != null && mc.getCameraEntity().getBlockPos().isWithinDistance(var26.getStartPos(), this.renderDistance.getValue() * 16.0)) {
               event.drawFill(
                  new Box(
                     new Vec3d(
                        (double)var26.getStartPos().getX(),
                        (double)var26.getStartPos().getY() + this.renderHeight.getValue(),
                        (double)var26.getStartPos().getZ()
                     ),
                     new Vec3d(
                        (double)(var26.getStartPos().getX() + 16),
                        (double)var26.getStartPos().getY() + this.renderHeight.getValue(),
                        (double)(var26.getStartPos().getZ() + 16)
                     )
                  ),
                  this.beingUpdatedOldChunksSideColor.getValue()
               );
            }
         }
      }

      var2 = this.OldGenerationOldChunks;
      synchronized (var2) {
         for (ChunkPos var27 : this.OldGenerationOldChunks) {
            if (var27 != null && mc.getCameraEntity().getBlockPos().isWithinDistance(var27.getStartPos(), this.renderDistance.getValue() * 16.0)) {
               event.drawFill(
                  new Box(
                     new Vec3d(
                        (double)var27.getStartPos().getX(),
                        (double)var27.getStartPos().getY() + this.renderHeight.getValue(),
                        (double)var27.getStartPos().getZ()
                     ),
                     new Vec3d(
                        (double)(var27.getStartPos().getX() + 16),
                        (double)var27.getStartPos().getY() + this.renderHeight.getValue(),
                        (double)(var27.getStartPos().getZ() + 16)
                     )
                  ),
                  this.OldGenerationOldChunksSideColor.getValue()
               );
            }
         }
      }
   }

   @EventListener
   private void onReadPacket(PacketEvent.Receive event) {
      if (!(event.getPacket() instanceof AcknowledgeChunksC2SPacket)) {
         if (event.getPacket() instanceof ChunkDeltaUpdateS2CPacket var3 && this.liquidexploit.getValue()) {
            var3.visitUpdates(
               (pos, state) -> {
                  ChunkPos var3x = new ChunkPos(pos);
                  if (!state.getFluidState().isEmpty() && !state.getFluidState().isStill()) {
                     for (Direction var7x : searchDirs) {
                        try {
                           if (mc.world.getBlockState(pos.offset(var7x)).getFluidState().isStill()
                              && !this.OldGenerationOldChunks.contains(var3x)
                              && !this.beingUpdatedOldChunks.contains(var3x)
                              && !this.newChunks.contains(var3x)
                              && !this.oldChunks.contains(var3x)) {
                              this.tickexploitChunks.remove(var3x);
                              this.newChunks.add(var3x);
                              return;
                           }
                        } catch (Exception var9x) {
                           var9x.printStackTrace();
                        }
                     }
                  }
               }
            );
            return;
         }

         Packet var54;
         if (!((var54 = event.getPacket()) instanceof BlockUpdateS2CPacket)) {
            if (event.getPacket() instanceof ChunkDataS2CPacket) {
               ChunkDataS2CPacket var55 = (ChunkDataS2CPacket)event.getPacket();
               if (mc.world != null) {
                  ChunkPos var56 = new ChunkPos(var55.getChunkX(), var55.getChunkZ());
                  if (mc.world.getChunkManager().getChunk(var55.getChunkX(), var55.getChunkZ()) == null) {
                     WorldChunk var10 = new WorldChunk(mc.world, var56);

                     try {
                        CompletableFuture var11 = CompletableFuture.runAsync(
                           () -> var10.loadFromPacket(
                                 var55.getChunkData().getSectionsDataBuf(),
                                 new NbtCompound(),
                                 var55.getChunkData().getBlockEntities(var55.getChunkX(), var55.getChunkZ())
                              ),
                           taskExecutor
                        );
                        var11.join();
                     } catch (CompletionException var50) {
                        var50.printStackTrace();
                     }

                     boolean var64 = false;
                     boolean var12 = false;
                     boolean var13 = false;
                     boolean var14 = false;
                     boolean var15 = false;
                     boolean var16 = false;
                     ChunkSection[] var17 = var10.getSectionArray();
                     if (this.overworldOldChunksDetector.getValue() && mc.world.getRegistryKey() == World.OVERWORLD) {
                        for (int var18 = 0; var18 < 17; var18++) {
                           ChunkSection var19 = var17[var18];
                           if (var19 != null && !var19.isEmpty()) {
                              for (int var20 = 0; var20 < 16; var20++) {
                                 for (int var9 = 0; var9 < 16; var9++) {
                                    for (int var8 = 0; var8 < 16; var8++) {
                                       if (!var14 && ORE_BLOCKS.contains(var19.getBlockState(var20, var9, var8).getBlock())) {
                                          var14 = true;
                                       }

                                       if (!var15 && NEW_OVERWORLD_BLOCKS.contains(var19.getBlockState(var20, var9, var8).getBlock())) {
                                          var15 = true;
                                          break;
                                       }
                                    }
                                 }
                              }
                           }
                        }

                        if (var14 && !var15) {
                           var12 = true;
                        }
                     }

                     if (this.netherOldChunksDetector.getValue() && mc.world.getRegistryKey() == World.NETHER) {
                        for (int var65 = 0; var65 < 8; var65++) {
                           ChunkSection var66 = var17[var65];
                           if (var66 != null && !var66.isEmpty()) {
                              for (int var67 = 0; var67 < 16; var67++) {
                                 for (int var63 = 0; var63 < 16; var63++) {
                                    for (int var61 = 0; var61 < 16; var61++) {
                                       if (!var16 && NEW_NETHER_BLOCKS.contains(var66.getBlockState(var67, var63, var61).getBlock())) {
                                          var16 = true;
                                          break;
                                       }
                                    }
                                 }
                              }
                           }
                        }

                        if (!var12 && !var16) {
                           var12 = true;
                        }
                     }

                     ReadableContainer var7;
                     if (this.endOldChunksDetector.getValue()
                        && mc.world.getRegistryKey() == World.END
                        && (var7 = var10.getSection(0).getBiomeContainer()) instanceof PalettedContainer) {
                        PalettedContainer var21 = (PalettedContainer)var7;
                        Palette var22 = var21.data.palette();

                        for (int var5 = 0; var5 < var22.getSize(); var5++) {
                           if (((RegistryEntry)var22.get(var5)).getKey().get() == BiomeKeys.THE_END) {
                              var12 = true;
                              break;
                           }
                        }
                     }

                     if (this.PaletteExploit.getValue()) {
                        boolean var68 = true;
                        boolean var70 = false;
                        int var23 = 0;
                        int var24 = 0;
                        int var25 = 0;

                        try {
                           for (int var58 = 0; var58 < 8; var58++) {
                              ChunkSection var26 = var17[var58];
                              if (var26 != null) {
                                 int var27 = 0;
                                 int var28 = 0;
                                 if (!var26.isEmpty()) {
                                    PalettedContainer var29 = var26.getBlockStateContainer();
                                    Palette var30 = var29.data.palette();
                                    int var31 = var30.getSize();
                                    if (var30 instanceof BiMapPalette) {
                                       HashSet var32 = new HashSet();

                                       for (int var33 = 0; var33 < 16; var33++) {
                                          for (int var34 = 0; var34 < 16; var34++) {
                                             for (int var35 = 0; var35 < 16; var35++) {
                                                var32.add((BlockState)var29.get(var33, var34, var35));
                                             }
                                          }
                                       }

                                       int var78 = var32.size();
                                       if (var78 <= 1) {
                                          var78 = var31;
                                       }

                                       if (var78 < var31) {
                                          var27 = 2;
                                          var24++;
                                       }
                                    }

                                    for (int var77 = 0; var77 < var31; var77++) {
                                       BlockState var79 = (BlockState)var30.get(var77);
                                       if (var77 == 0 && var23 == 0 && var79.getBlock() == Blocks.AIR && mc.world.getRegistryKey() != World.END) {
                                          var70 = true;
                                       }

                                       if (var77 == 0
                                          && var79.getBlock() == Blocks.AIR
                                          && mc.world.getRegistryKey() != World.NETHER
                                          && mc.world.getRegistryKey() != World.END) {
                                          var27++;
                                       }

                                       if (var77 == 1
                                          && (
                                             var79.getBlock() == Blocks.WATER
                                                || var79.getBlock() == Blocks.STONE
                                                || var79.getBlock() == Blocks.GRASS_BLOCK
                                                || var79.getBlock() == Blocks.SNOW_BLOCK
                                          )
                                          && mc.world.getRegistryKey() != World.NETHER
                                          && mc.world.getRegistryKey() != World.END) {
                                          var27++;
                                       }

                                       if (var77 == 2
                                          && (
                                             var79.getBlock() == Blocks.SNOW_BLOCK || var79.getBlock() == Blocks.DIRT || var79.getBlock() == Blocks.POWDER_SNOW
                                          )
                                          && mc.world.getRegistryKey() != World.NETHER
                                          && mc.world.getRegistryKey() != World.END) {
                                          var27++;
                                       }

                                       if (var23 == 4
                                          && var79.getBlock() == Blocks.BEDROCK
                                          && mc.world.getRegistryKey() != World.NETHER
                                          && mc.world.getRegistryKey() != World.END
                                          && !var13
                                          && this.beingUpdatedDetector.getValue()) {
                                          var13 = true;
                                       }

                                       if (var79.getBlock() == Blocks.AIR
                                          && (mc.world.getRegistryKey() == World.NETHER || mc.world.getRegistryKey() == World.END)) {
                                          var28++;
                                       }
                                    }

                                    if (var28 >= 2) {
                                       var25++;
                                    }

                                    if (var27 >= 2) {
                                       var24++;
                                    }
                                 }

                                 ReadableContainer var36;
                                 if (mc.world.getRegistryKey() == World.END && (var36 = var26.getBiomeContainer()) instanceof PalettedContainer) {
                                    PalettedContainer var74 = (PalettedContainer)var36;
                                    Palette var75 = var74.data.palette();

                                    for (int var76 = 0; var76 < var75.getSize(); var76++) {
                                       if (var76 == 0 && ((RegistryEntry)var75.get(var76)).getKey().get() == BiomeKeys.PLAINS) {
                                          var64 = true;
                                       }

                                       if (!var64 && var76 == 0 && ((RegistryEntry)var75.get(var76)).getKey().get() != BiomeKeys.THE_END) {
                                          var64 = false;
                                       }
                                    }
                                 }

                                 if (!var26.isEmpty()) {
                                    var23++;
                                 }
                              }
                           }

                           if (var23 > 0) {
                              if (this.beingUpdatedDetector.getValue() && (mc.world.getRegistryKey() == World.NETHER || mc.world.getRegistryKey() == World.END)
                                 )
                               {
                                 double var37 = (double)var25 / (double)var23 * 100.0;
                                 if (var37 >= 25.0) {
                                    var13 = true;
                                 }
                              } else if (mc.world.getRegistryKey() != World.NETHER
                                 && mc.world.getRegistryKey() != World.END
                                 && (double)var24 / (double)var23 * 100.0 >= 65.0) {
                                 var64 = true;
                              }
                           }
                        } catch (Exception var53) {
                           if (this.beingUpdatedDetector.getValue() && (mc.world.getRegistryKey() == World.NETHER || mc.world.getRegistryKey() == World.END)) {
                              double var41 = (double)var25 / (double)var23 * 100.0;
                              if (var41 >= 25.0) {
                                 var13 = true;
                              }
                           }

                           if (mc.world.getRegistryKey() != World.NETHER
                              && mc.world.getRegistryKey() != World.END
                              && (double)var24 / (double)var23 * 100.0 >= 65.0) {
                              var64 = true;
                           }
                        }

                        if (var70) {
                           var64 = true;
                        }

                        if (mc.world.getRegistryKey() != World.END) {
                           var68 = !var12;
                        }

                        if (var64 && !var13 && var68) {
                           try {
                              if (!this.OldGenerationOldChunks.contains(var56)
                                 && !this.beingUpdatedOldChunks.contains(var56)
                                 && !this.tickexploitChunks.contains(var56)
                                 && !this.oldChunks.contains(var56)
                                 && !this.newChunks.contains(var56)) {
                                 this.newChunks.add(var56);
                                 return;
                              }
                           } catch (Exception var49) {
                              var49.printStackTrace();
                           }
                        } else if (!var64 && !var13 && var12) {
                           try {
                              if (!this.OldGenerationOldChunks.contains(var56)
                                 && !this.beingUpdatedOldChunks.contains(var56)
                                 && !this.oldChunks.contains(var56)
                                 && !this.tickexploitChunks.contains(var56)
                                 && !this.newChunks.contains(var56)) {
                                 this.OldGenerationOldChunks.add(var56);
                                 return;
                              }
                           } catch (Exception var48) {
                              var48.printStackTrace();
                           }
                        } else if (var13) {
                           try {
                              if (!this.OldGenerationOldChunks.contains(var56)
                                 && !this.beingUpdatedOldChunks.contains(var56)
                                 && !this.oldChunks.contains(var56)
                                 && !this.tickexploitChunks.contains(var56)
                                 && !this.newChunks.contains(var56)) {
                                 this.beingUpdatedOldChunks.add(var56);
                                 return;
                              }
                           } catch (Exception var47) {
                              var47.printStackTrace();
                           }
                        } else if (!var64) {
                           try {
                              if (!this.OldGenerationOldChunks.contains(var56)
                                 && !this.beingUpdatedOldChunks.contains(var56)
                                 && !this.tickexploitChunks.contains(var56)
                                 && !this.oldChunks.contains(var56)
                                 && !this.newChunks.contains(var56)) {
                                 this.oldChunks.add(var56);
                                 return;
                              }
                           } catch (Exception var46) {
                              var46.printStackTrace();
                           }
                        }
                     }

                     if (this.liquidexploit.getValue()) {
                        for (int var69 = 0; var69 < 16; var69++) {
                           for (int var71 = mc.world.getBottomY(); var71 < mc.world.getTopY(); var71++) {
                              for (int var72 = 0; var72 < 16; var72++) {
                                 FluidState var73 = var10.getFluidState(var69, var71, var72);

                                 try {
                                    if (!this.OldGenerationOldChunks.contains(var56)
                                       && !this.beingUpdatedOldChunks.contains(var56)
                                       && !this.oldChunks.contains(var56)
                                       && !this.tickexploitChunks.contains(var56)
                                       && !this.newChunks.contains(var56)
                                       && !var73.isEmpty()
                                       && !var73.isStill()) {
                                       this.oldChunks.add(var56);
                                       return;
                                    }
                                 } catch (Exception var45) {
                                    var45.printStackTrace();
                                 }
                              }
                           }
                        }
                     }
                  }
               }
            }
         } else {
            BlockUpdateS2CPacket var57 = (BlockUpdateS2CPacket)var54;
            ChunkPos var4 = new ChunkPos(var57.getPos());
            if (this.blockupdateexploit.getValue()) {
               try {
                  if (!this.OldGenerationOldChunks.contains(var4)
                     && !this.beingUpdatedOldChunks.contains(var4)
                     && !this.tickexploitChunks.contains(var4)
                     && !this.oldChunks.contains(var4)
                     && !this.newChunks.contains(var4)) {
                     this.tickexploitChunks.add(var4);
                  }
               } catch (Exception var52) {
                  var52.printStackTrace();
               }
            }

            if (!var57.getState().getFluidState().isEmpty() && !var57.getState().getFluidState().isStill() && this.liquidexploit.getValue()) {
               for (Direction var62 : searchDirs) {
                  try {
                     if (mc.world.getBlockState(var57.getPos().offset(var62)).getFluidState().isStill()
                        && !this.OldGenerationOldChunks.contains(var4)
                        && !this.beingUpdatedOldChunks.contains(var4)
                        && !this.newChunks.contains(var4)
                        && !this.oldChunks.contains(var4)) {
                        this.tickexploitChunks.remove(var4);
                        this.newChunks.add(var4);
                        return;
                     }
                  } catch (Exception var51) {
                     var51.printStackTrace();
                  }
               }
            }
         }
      }
   }

   private void removeChunksOutsideRenderDistance() {
      BlockPos var1 = mc.getCameraEntity().getBlockPos();
      double var2 = this.renderDistance.getValue() * 16.0;
      this.removeChunksOutsideRenderDistance(this.newChunks, var1, var2);
      this.removeChunksOutsideRenderDistance(this.oldChunks, var1, var2);
      this.removeChunksOutsideRenderDistance(this.beingUpdatedOldChunks, var1, var2);
      this.removeChunksOutsideRenderDistance(this.OldGenerationOldChunks, var1, var2);
      this.removeChunksOutsideRenderDistance(this.tickexploitChunks, var1, var2);
   }

   private void removeChunksOutsideRenderDistance(Set<ChunkPos> chunkSet, BlockPos cameraPos, double renderDistanceBlocks) {
      chunkSet.removeIf(chunkPos -> !cameraPos.isWithinDistance(chunkPos.getStartPos(), renderDistanceBlocks));
   }

   static {

      taskExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
      searchDirs = new Direction[]{Direction.EAST, Direction.NORTH, Direction.WEST, Direction.SOUTH, Direction.UP};
      ORE_BLOCKS = new HashSet<>();
      NEW_OVERWORLD_BLOCKS = new HashSet<>();
      NEW_NETHER_BLOCKS = new HashSet<>();
      newchunksfound = 0;
      oldchunksfound = 0;
      beingUpdatedOldChunksfound = 0;
      OldGenerationOldChunksfound = 0;
      tickexploitchunksfound = 0;
      ORE_BLOCKS.add(Blocks.COAL_ORE);
      ORE_BLOCKS.add(Blocks.DEEPSLATE_COAL_ORE);
      ORE_BLOCKS.add(Blocks.COPPER_ORE);
      ORE_BLOCKS.add(Blocks.DEEPSLATE_COPPER_ORE);
      ORE_BLOCKS.add(Blocks.IRON_ORE);
      ORE_BLOCKS.add(Blocks.DEEPSLATE_IRON_ORE);
      ORE_BLOCKS.add(Blocks.GOLD_ORE);
      ORE_BLOCKS.add(Blocks.DEEPSLATE_GOLD_ORE);
      ORE_BLOCKS.add(Blocks.LAPIS_ORE);
      ORE_BLOCKS.add(Blocks.DEEPSLATE_LAPIS_ORE);
      ORE_BLOCKS.add(Blocks.DIAMOND_ORE);
      ORE_BLOCKS.add(Blocks.DEEPSLATE_DIAMOND_ORE);
      ORE_BLOCKS.add(Blocks.REDSTONE_ORE);
      ORE_BLOCKS.add(Blocks.DEEPSLATE_REDSTONE_ORE);
      ORE_BLOCKS.add(Blocks.EMERALD_ORE);
      ORE_BLOCKS.add(Blocks.DEEPSLATE_EMERALD_ORE);
      NEW_OVERWORLD_BLOCKS.add(Blocks.DEEPSLATE);
      NEW_OVERWORLD_BLOCKS.add(Blocks.AMETHYST_BLOCK);
      NEW_OVERWORLD_BLOCKS.add(Blocks.BUDDING_AMETHYST);
      NEW_OVERWORLD_BLOCKS.add(Blocks.AZALEA);
      NEW_OVERWORLD_BLOCKS.add(Blocks.FLOWERING_AZALEA);
      NEW_OVERWORLD_BLOCKS.add(Blocks.BIG_DRIPLEAF);
      NEW_OVERWORLD_BLOCKS.add(Blocks.BIG_DRIPLEAF_STEM);
      NEW_OVERWORLD_BLOCKS.add(Blocks.SMALL_DRIPLEAF);
      NEW_OVERWORLD_BLOCKS.add(Blocks.CAVE_VINES);
      NEW_OVERWORLD_BLOCKS.add(Blocks.CAVE_VINES_PLANT);
      NEW_OVERWORLD_BLOCKS.add(Blocks.SPORE_BLOSSOM);
      NEW_OVERWORLD_BLOCKS.add(Blocks.COPPER_ORE);
      NEW_OVERWORLD_BLOCKS.add(Blocks.DEEPSLATE_COPPER_ORE);
      NEW_OVERWORLD_BLOCKS.add(Blocks.DEEPSLATE_IRON_ORE);
      NEW_OVERWORLD_BLOCKS.add(Blocks.DEEPSLATE_COAL_ORE);
      NEW_OVERWORLD_BLOCKS.add(Blocks.DEEPSLATE_REDSTONE_ORE);
      NEW_OVERWORLD_BLOCKS.add(Blocks.DEEPSLATE_EMERALD_ORE);
      NEW_OVERWORLD_BLOCKS.add(Blocks.DEEPSLATE_GOLD_ORE);
      NEW_OVERWORLD_BLOCKS.add(Blocks.DEEPSLATE_LAPIS_ORE);
      NEW_OVERWORLD_BLOCKS.add(Blocks.DEEPSLATE_DIAMOND_ORE);
      NEW_OVERWORLD_BLOCKS.add(Blocks.GLOW_LICHEN);
      NEW_OVERWORLD_BLOCKS.add(Blocks.RAW_COPPER_BLOCK);
      NEW_OVERWORLD_BLOCKS.add(Blocks.RAW_IRON_BLOCK);
      NEW_OVERWORLD_BLOCKS.add(Blocks.DRIPSTONE_BLOCK);
      NEW_OVERWORLD_BLOCKS.add(Blocks.MOSS_BLOCK);
      NEW_OVERWORLD_BLOCKS.add(Blocks.MOSS_CARPET);
      NEW_OVERWORLD_BLOCKS.add(Blocks.POINTED_DRIPSTONE);
      NEW_OVERWORLD_BLOCKS.add(Blocks.SMOOTH_BASALT);
      NEW_OVERWORLD_BLOCKS.add(Blocks.TUFF);
      NEW_OVERWORLD_BLOCKS.add(Blocks.CALCITE);
      NEW_OVERWORLD_BLOCKS.add(Blocks.HANGING_ROOTS);
      NEW_OVERWORLD_BLOCKS.add(Blocks.ROOTED_DIRT);
      NEW_OVERWORLD_BLOCKS.add(Blocks.AZALEA_LEAVES);
      NEW_OVERWORLD_BLOCKS.add(Blocks.FLOWERING_AZALEA_LEAVES);
      NEW_OVERWORLD_BLOCKS.add(Blocks.POWDER_SNOW);
      NEW_NETHER_BLOCKS.add(Blocks.ANCIENT_DEBRIS);
      NEW_NETHER_BLOCKS.add(Blocks.BASALT);
      NEW_NETHER_BLOCKS.add(Blocks.BLACKSTONE);
      NEW_NETHER_BLOCKS.add(Blocks.GILDED_BLACKSTONE);
      NEW_NETHER_BLOCKS.add(Blocks.POLISHED_BLACKSTONE_BRICKS);
      NEW_NETHER_BLOCKS.add(Blocks.CRIMSON_STEM);
      NEW_NETHER_BLOCKS.add(Blocks.CRIMSON_NYLIUM);
      NEW_NETHER_BLOCKS.add(Blocks.NETHER_GOLD_ORE);
      NEW_NETHER_BLOCKS.add(Blocks.WARPED_NYLIUM);
      NEW_NETHER_BLOCKS.add(Blocks.WARPED_STEM);
      NEW_NETHER_BLOCKS.add(Blocks.TWISTING_VINES);
      NEW_NETHER_BLOCKS.add(Blocks.WEEPING_VINES);
      NEW_NETHER_BLOCKS.add(Blocks.BONE_BLOCK);
      NEW_NETHER_BLOCKS.add(Blocks.CHAIN);
      NEW_NETHER_BLOCKS.add(Blocks.OBSIDIAN);
      NEW_NETHER_BLOCKS.add(Blocks.CRYING_OBSIDIAN);
      NEW_NETHER_BLOCKS.add(Blocks.SOUL_SOIL);
      NEW_NETHER_BLOCKS.add(Blocks.SOUL_FIRE);
   }
@Environment(EnvType.CLIENT)
   public static enum DetectMode {
      Normal,
      IgnoreBlockExploit,
      BlockExploitMode;

}
}
