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

import com.mojang.blaze3d.systems.RenderSystem;
import dev.crucifixbeta.CrucifixBeta;
import dev.crucifixbeta.api.events.eventbus.EventListener;
import dev.crucifixbeta.api.events.impl.PacketEvent;
import dev.crucifixbeta.api.events.impl.TotemEvent;
import dev.crucifixbeta.api.utils.math.MathUtil;
import dev.crucifixbeta.api.utils.render.ColorUtil;
import dev.crucifixbeta.api.utils.render.Render2DUtil;
import dev.crucifixbeta.api.utils.render.TextUtil;
import dev.crucifixbeta.core.impl.FontManager;
import dev.crucifixbeta.mod.modules.Module;
import dev.crucifixbeta.mod.modules.impl.client.Fonts;
import dev.crucifixbeta.mod.modules.impl.client.hud.TextRadar;
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.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.font.TextRenderer.TextLayerType;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.network.PlayerListEntry;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.BufferRenderer;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.DiffuseLighting;
import net.minecraft.client.render.GameRenderer;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.render.VertexConsumerProvider.Immediate;
import net.minecraft.client.render.VertexFormat.DrawMode;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.json.ModelTransformationMode;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.PotionContentsComponent;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.entity.Entity;
import net.minecraft.entity.effect.StatusEffect;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.effect.StatusEffects;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.thrown.PotionEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.network.packet.s2c.play.WorldEventS2CPacket;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.util.Formatting;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RotationAxis;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.GameMode;
import org.joml.Matrix4f;
import org.joml.Vector3f;
import org.joml.Vector4f;
import org.lwjgl.opengl.GL11;

@Environment(EnvType.CLIENT)
public class NameTags extends Module {
   public static NameTags INSTANCE;
   public static final String TURTLE_COLOR;
   public static final int TURTLE_COLOR_RGB;
   private final ColorSetting colorConfig = this.add(new ColorSetting("Color", new Color(255, 255, 255)));
   private final ColorSetting friendConfig = this.add(new ColorSetting("Friend", new Color(155, 155, 255)).injectBoolean(true));
   private final ColorSetting invisibleConfig = this.add(new ColorSetting("Invisible", new Color(200, 200, 200)).injectBoolean(true));
   private final ColorSetting died = this.add(new ColorSetting("Died", new Color(180, 0, 0)).injectBoolean(true));
   private final ColorSetting sneakingConfig = this.add(new ColorSetting("Sneaking", new Color(200, 200, 0)).injectBoolean(true));
   private final ColorSetting rectConfig = this.add(new ColorSetting("Rectangle", new Color(0, 0, 0, 100)).injectBoolean(true));
   private final BooleanSetting uiConfig = this.add(new BooleanSetting("UI", true).setParent());
   private final SliderSetting uiWidth = this.add(new SliderSetting("UIWidth", 0.0, 0.0, 30.0, 0.5, this.uiConfig::isOpen));
   private final SliderSetting uiHeight = this.add(new SliderSetting("UIHeight", 0.0, 0.0, 18.0, 0.5, this.uiConfig::isOpen));
   private final SliderSetting uiRadius = this.add(new SliderSetting("UIRadius", 0.0, 0.0, 10.0, 0.5, this.uiConfig::isOpen));
   private final BooleanSetting uiBlur = this.add(new BooleanSetting("UIBlur", false, this.uiConfig::isOpen).setParent());
   private final SliderSetting uiBlurRadius = this.add(
      new SliderSetting("UIBlurRadius", 3.0, 0.0, 20.0, 0.5, () -> this.uiConfig.isOpen() && this.uiBlur.isOpen())
   );
   private final BooleanSetting armorConfig = this.add(new BooleanSetting("Armor", true).setParent());
   private final BooleanSetting drawItemConfig = this.add(new BooleanSetting("DrawItem", true, this.armorConfig::isOpen));
   private final SliderSetting offsetConfig = this.add(new SliderSetting("Offset", -20.0, -30.0, 10.0, 0.01, this.armorConfig::isOpen));
   private final BooleanSetting enchantmentsConfig = this.add(new BooleanSetting("Enchantments", true).setParent());
   private final BooleanSetting protectionOnlyConfig = this.add(new BooleanSetting("Protection", false, this.enchantmentsConfig::isOpen));
   private final BooleanSetting durabilityConfig = this.add(new BooleanSetting("Durability", true).setParent());
   private final BooleanSetting forceBarConfig = this.add(new BooleanSetting("ForceBar", true, this.durabilityConfig::isOpen));
   private final BooleanSetting itemNameConfig = this.add(new BooleanSetting("ItemName", false));
   private final BooleanSetting entityIdConfig = this.add(new BooleanSetting("EntityId", false));
   private final BooleanSetting gamemodeConfig = this.add(new BooleanSetting("Gamemode", false));
   private final BooleanSetting pingConfig = this.add(new BooleanSetting("Ping", true));
   private final BooleanSetting healthConfig = this.add(new BooleanSetting("Health", true));
   private final BooleanSetting totemsConfig = this.add(new BooleanSetting("Totems", false));
   private final BooleanSetting turtleConfig = this.add(new BooleanSetting("PotionEffects", false).setParent());
   private final BooleanSetting showTurtleIcon = this.add(new BooleanSetting("ShowIcon", true, this.turtleConfig::isOpen));
   private final BooleanSetting turtleColorName = this.add(new BooleanSetting("ColorName", false, this.turtleConfig::isOpen).setParent());
   private final BooleanSetting ignoreFriend = this.add(new BooleanSetting("IgnoreFriend", false, this.turtleColorName::isOpen));
   private final EnumSetting<NameTags.ScaleMode> scaleModeConfig = this.add(new EnumSetting<>("ScaleMode", NameTags.ScaleMode.Original));
   private final SliderSetting scaleConfig = this.add(new SliderSetting("Scale", 1.0, 0.0, 3.0, 0.1));
   private final BooleanSetting factorConfig = this.add(new BooleanSetting("Factor", true).setParent());
   private final SliderSetting scalingConfig = this.add(new SliderSetting("Scaling", 1.0, 0.0, 3.0, 0.1, this.factorConfig::isOpen));
   private final SliderSetting distanceConfig = this.add(new SliderSetting("Distance", 6.0, 0.0, 20.0, 0.1, this.factorConfig::isOpen));
   private final SliderSetting heightConfig = this.add(new SliderSetting("Height", 0.0, -3.0, 3.0, 0.01));
   private final BooleanSetting potionStrength = this.add(new BooleanSetting("Potion_Strength", true, this.turtleConfig::isOpen));
   private final BooleanSetting potionTurtle = this.add(new BooleanSetting("Potion_Turtle", true, this.turtleConfig::isOpen));
   private final BooleanSetting potionRegen = this.add(new BooleanSetting("Potion_Regen", true, this.turtleConfig::isOpen));
   private final BooleanSetting potionFireRes = this.add(new BooleanSetting("Potion_FireRes", true, this.turtleConfig::isOpen));
   private final BooleanSetting potionAbsorption = this.add(new BooleanSetting("Potion_Absorption", true, this.turtleConfig::isOpen));
   private final BooleanSetting potionTotem = this.add(new BooleanSetting("Potion_Totem", true, this.turtleConfig::isOpen));
   private final BooleanSetting potionGapple = this.add(new BooleanSetting("Potion_Gapple", true, this.turtleConfig::isOpen));
   private final BooleanSetting potionModernDistance = this.add(new BooleanSetting("1.21.6+", false, this.turtleConfig::isOpen));
   private final BooleanSetting potionIcons = this.add(new BooleanSetting("PotionIcons", true, this.turtleConfig::isOpen));
   private final BooleanSetting potionLevels = this.add(new BooleanSetting("PotionLevels", true, this.turtleConfig::isOpen));
   private final EnumSetting<NameTags.PotionTimeStyle> potionTimeStyle = this.add(
      new EnumSetting<>("PotionStyle", NameTags.PotionTimeStyle.Mine, this.turtleConfig::isOpen)
   );
   private final BooleanSetting potionDecimal = this.add(new BooleanSetting("PotionDecimal", false, this.turtleConfig::isOpen));
   private final SliderSetting potionIconGap = this.add(
      new SliderSetting("PotionIconGap", 2.0, 0.0, 12.0, 0.5, () -> this.turtleConfig.isOpen() && this.potionIcons.getValue())
   );
   private final SliderSetting potionBlankGap = this.add(
      new SliderSetting("PotionBlankGap", 12.0, 4.0, 40.0, 0.5, () -> this.turtleConfig.isOpen() && this.potionIcons.getValue())
   );
   private final SliderSetting potionTextGap = this.add(
      new SliderSetting("PotionTextGap", 2.0, 0.0, 12.0, 0.5, () -> this.turtleConfig.isOpen() && this.potionIcons.getValue())
   );
   private final DecimalFormat decimalFormat = new DecimalFormat("0.0");
   private final Map<Integer, NameTags.EffectTimer> strengthTimers = new ConcurrentHashMap<>();
   private final Map<Integer, NameTags.EffectTimer> turtleTimers = new ConcurrentHashMap<>();
   private final Map<Integer, NameTags.EffectTimer> regenTimers = new ConcurrentHashMap<>();
   private final Map<Integer, NameTags.EffectTimer> fireResTimers = new ConcurrentHashMap<>();
   private final Map<Integer, NameTags.EffectTimer> absorptionTimers = new ConcurrentHashMap<>();
   private final Map<Integer, NameTags.EffectTimer> resistanceTimers = new ConcurrentHashMap<>();
   private final Map<Integer, String> lastEffects = new ConcurrentHashMap<>();

   public NameTags() {
      super("NameTags", "Renders Noxis style player nametags.", Module.Category.Render);
      this.setChinese("\u540d\u5b57\u6807\u7b7e");
      INSTANCE = this;
   }

   @Override
   public void onRender3D(MatrixStack ignored) {
      if (!nullCheck() && mc.gameRenderer != null && mc.getNetworkHandler() != null) {
         Camera var2 = mc.gameRenderer.getCamera();
         RenderSystem.enableBlend();
         GL11.glDepthFunc(519);
         MatrixStack var3 = new MatrixStack();

         for (PlayerEntity var5 : mc.world.getPlayers()) {
            if (this.shouldRender(var5)) {
               this.syncPotionState(var5, System.currentTimeMillis());
               ArrayList var6 = this.getPotionDisplays(
                  var5,
                  this.potionStrength.getValue(),
                  this.potionTurtle.getValue(),
                  this.potionRegen.getValue(),
                  this.potionFireRes.getValue(),
                  this.potionAbsorption.getValue(),
                  this.potionIcons.getValue(),
                  this.potionLevels.getValue(),
                  this.potionBlankGap.getValueFloat(),
                  this.potionTextGap.getValueFloat()
               );
               String var7 = this.getNametagInfo(var5);
               float var8 = this.getPotionSectionWidth(var6);
               float var9 = this.getTextWidth(var7);
               float var10 = var8 + (var8 > 0.0F && var9 > 0.0F ? this.getTextWidth(" ") : 0.0F) + var9;
               if (!(var10 <= 0.0F)) {
                  boolean var11 = this.turtleConfig.getValue() && this.hasTurtleEffect(var5);
                  boolean var12 = var11 && this.showTurtleIcon.getValue() && !this.potionIcons.getValue();
                  Vec3d var13 = MathUtil.getRenderPosition(var5, mc.getRenderTickCounter().getTickDelta(true));
                  this.renderInfo(var7, var10 / 2.0F, var5, var13.x, var13.y, var13.z, var2, var3, var11, var12, var6, var8);
               }
            }
         }

         GL11.glDepthFunc(515);
         RenderSystem.disableBlend();
      }
   }

   private boolean shouldRender(PlayerEntity player) {
      if (player == null) {
         return false;
      } else if (!this.died.booleanValue && !player.isAlive()) {
         return false;
      } else {
         return player == mc.player && mc.options.getPerspective().isFirstPerson() ? false : this.invisibleConfig.booleanValue || !player.isInvisible();
      }
   }

   private void renderInfo(
      String info,
      float width,
      PlayerEntity entity,
      double x,
      double y,
      double z,
      Camera camera,
      MatrixStack matrices,
      boolean hasTurtle,
      boolean drawTurtleIcon,
      List<NameTags.PotionDisplay> potionDisplays,
      float potionWidth
   ) {
      Vec3d var16 = camera.getPos();
      double var17 = y + (double)entity.getHeight() + (double)(entity.isSneaking() ? 0.4F : 0.43F) + (double)this.heightConfig.getValueFloat();
      float var19 = this.getNameTagScale(var16, x, var17, z);
      matrices.push();
      matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(camera.getPitch()));
      matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(camera.getYaw() + 180.0F));
      matrices.translate(x - var16.x, var17 - var16.y + (double)((var19 / -0.025F - 1.0F) / 4.0F), z - var16.z);
      matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(-camera.getYaw()));
      matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(camera.getPitch()));
      matrices.scale(var19, var19, -1.0F);
      float var20 = drawTurtleIcon ? 10.0F : 4.0F;
      if (this.rectConfig.booleanValue) {
         float var21 = this.uiWidth.getValueFloat();
         float var22 = this.uiHeight.getValueFloat();
         float var23 = -width - 2.0F - var20 - var21;
         float var24 = -1.0F - var22 * 0.5F;
         float var25 = width * 2.0F + 3.0F + var20 + var21 * 2.0F;
         float var26 = this.getTextHeight() + 1.0F + var22;
         if (this.uiBlur.getValue()) {
            this.applyRectBlur(matrices, var23, var24, var25, var26);
         }

         if (this.uiRadius.getValueFloat() > 0.0F) {
            Render2DUtil.drawRoundedRect(matrices, var23, var24, var25, var26, this.uiRadius.getValueFloat(), this.rectConfig.getValue());
         } else {
            Render2DUtil.drawRect(matrices, var23, var24, var25, var26, this.rectConfig.getValue());
         }
      }

      int var27 = this.getTextColor(entity, hasTurtle);
      float var28 = -width;
      if (potionWidth > 0.0F) {
         this.drawPotionSection(matrices, potionDisplays, var28, 0.0F, var27);
         var28 += potionWidth;
         if (!info.isBlank()) {
            var28 += this.getTextWidth(" ");
         }
      }

      if (!info.isBlank()) {
         this.drawWithShadow(matrices, info, var28, 0.0F, var27);
      }

      if (drawTurtleIcon) {
         this.renderIconTexture(matrices, "resistance", -width - var20, -1.0F, 10.0F);
      }

      if (this.armorConfig.getValue()) {
         this.renderItems(matrices, entity);
      }

      matrices.pop();
   }

   private float getNameTagScale(Vec3d cameraPos, double x, double y, double z) {
      if (this.scaleModeConfig.getValue() == NameTags.ScaleMode.Current) {
         double var16 = Math.max(0.001, this.scaleConfig.getValue());
         double var17 = cameraPos.distanceTo(new Vec3d(x, y, z));
         double var18 = (double)mc.options.getFov().getValue().intValue() / 110.0;
         if (var18 < 1.0) {
            var18 = 1.0;
         }

         double var14 = var17 <= 10.0 / var16 ? Math.min(1.0, var16) * var18 : var17 * var16 * 0.1 * var18;
         return (float)(-0.025 * var14);
      } else {
         double var8 = cameraPos.squaredDistanceTo(x, y, z);
         double var10 = Math.sqrt(var8);
         double var12 = this.factorConfig.getValue() && var8 > (double)(this.distanceConfig.getValueFloat() * this.distanceConfig.getValueFloat())
            ? (var10 - (double)this.distanceConfig.getValueFloat()) * -0.0025F * (double)this.scalingConfig.getValueFloat()
            : 0.0;
         return -0.025F * this.scaleConfig.getValueFloat() + (float)var12;
      }
   }

   private void applyRectBlur(MatrixStack matrices, float x, float y, float width, float height) {
      if (CrucifixBeta.BLUR != null) {
         double[] var6 = this.getScreenRect(matrices, x, y, width, height);
         if (var6 != null) {
            float var7 = (float)var6[0];
            float var8 = (float)var6[1];
            float var9 = (float)(var6[2] - var6[0]);
            float var10 = (float)(var6[3] - var6[1]);
            if (!(var9 <= 0.5F) && !(var10 <= 0.5F)) {
               CrucifixBeta.BLUR.applyBlur(this.uiBlurRadius.getValueFloat(), var7, var8, var9, var10);
            }
         }
      }
   }

   private double[] getScreenRect(MatrixStack matrices, float x, float y, float width, float height) {
      Vec3d[] var6 = new Vec3d[]{
         this.localToScreen(matrices, x, y),
         this.localToScreen(matrices, x + width, y),
         this.localToScreen(matrices, x, y + height),
         this.localToScreen(matrices, x + width, y + height)
      };
      double var7 = Double.POSITIVE_INFINITY;
      double var9 = Double.POSITIVE_INFINITY;
      double var11 = Double.NEGATIVE_INFINITY;
      double var13 = Double.NEGATIVE_INFINITY;
      boolean var15 = false;

      for (Vec3d var19 : var6) {
         if (var19 != null && !(var19.z <= 0.0) && !(var19.z >= 1.0)) {
            var15 = true;
            var7 = Math.min(var7, var19.x);
            var9 = Math.min(var9, var19.y);
            var11 = Math.max(var11, var19.x);
            var13 = Math.max(var13, var19.y);
         }
      }

      if (!var15) {
         return null;
      } else {
         double var20 = (double)mc.getWindow().getScaledWidth();
         double var22 = (double)mc.getWindow().getScaledHeight();
         var7 = MathHelper.clamp(var7, 0.0, var20);
         var9 = MathHelper.clamp(var9, 0.0, var22);
         var11 = MathHelper.clamp(var11, 0.0, var20);
         var13 = MathHelper.clamp(var13, 0.0, var22);
         return new double[]{var7, var9, var11, var13};
      }
   }

   private Vec3d localToScreen(MatrixStack matrices, float x, float y) {
      int var4 = mc.getWindow().getHeight();
      int[] var5 = new int[4];
      GL11.glGetIntegerv(2978, var5);
      Vector3f var6 = new Vector3f();
      Vector4f var7 = new Vector4f(x, y, 0.0F, 1.0F).mul(matrices.peek().getPositionMatrix());
      Matrix4f var8 = new Matrix4f(TextUtil.lastProjMat);
      Matrix4f var9 = new Matrix4f(TextUtil.lastModMat);
      var8.mul(var9).project(var7.x(), var7.y(), var7.z(), var5, var6);
      return new Vec3d((double)var6.x / mc.getWindow().getScaleFactor(), (double)((float)var4 - var6.y) / mc.getWindow().getScaleFactor(), (double)var6.z);
   }

   private void drawWithShadow(MatrixStack matrices, String text, float x, float y, int color) {
      if (this.useFont()) {
         FontManager.ui.drawString(matrices, text, (double)x, (double)y, color, false);
      } else {
         Immediate var6 = mc.getBufferBuilders().getEntityVertexConsumers();
         Matrix4f var7 = matrices.peek().getPositionMatrix();
         String var8 = this.normalizeFormattingPrefixes(text);
         mc.textRenderer.draw(var8, x, y, color, false, var7, var6, TextLayerType.SEE_THROUGH, 0, 15728880);
         var6.draw();
      }
   }

   private String normalizeFormattingPrefixes(String text) {
      return text == null ? "" : text;
   }

   private void renderItems(MatrixStack matrices, PlayerEntity player) {
      ArrayList<ItemStack> var3 = new ArrayList<>();
      if (!player.getOffHandStack().isEmpty()) {
         var3.add(player.getOffHandStack());
      }

      for (ItemStack var5 : player.getArmorItems()) {
         if (!var5.isEmpty()) {
            var3.add(var5);
         }
      }

      if (!player.getMainHandStack().isEmpty()) {
         var3.add(player.getMainHandStack());
      }

      Collections.reverse(var3);
      float var10 = 0.0F;
      int var11 = 0;

      for (ItemStack var7 : var3) {
         var10 -= 8.0F;
      }

      if (this.enchantmentsConfig.getValue()) {
         for (ItemStack var14 : var3) {
            var11 = Math.max(var11, this.countDisplayedEnchants(var14));
         }
      }

      float var13 = this.offsetConfig.getValueFloat();

      for (ItemStack var8 : var3) {
         GL11.glDepthFunc(519);
         if (this.drawItemConfig.getValue()) {
            this.renderItemStack(matrices, var8, var10, var13 + 1.0F);
         }

         this.renderItemOverlay(matrices, var8, var10, var13 + 2.5F);
         matrices.push();
         matrices.scale(0.5F, 0.5F, 0.5F);
         float var9 = var13 - 3.0F;
         if (this.enchantmentsConfig.getValue() && this.durabilityConfig.getValue()) {
            this.renderEnchants(matrices, var8, var10 + 2.0F, var9 - 5.0F);
            this.renderDurability(matrices, var8, var10 + 2.0F, var9);
         } else if (this.enchantmentsConfig.getValue()) {
            this.renderEnchants(matrices, var8, var10 + 2.0F, var9);
         } else if (this.durabilityConfig.getValue()) {
            this.renderDurability(matrices, var8, var10 + 2.0F, var9);
         }

         matrices.pop();
         var10 += 16.0F;
         GL11.glDepthFunc(515);
      }

      ItemStack var16 = player.getMainHandStack();
      if (!var16.isEmpty() && this.itemNameConfig.getValue()) {
         matrices.push();
         matrices.scale(0.5F, 0.5F, 0.5F);
         float var17 = var13 - 4.5F + this.enchantOffset(var11);
         if (this.durabilityConfig.getValue() || this.enchantmentsConfig.getValue()) {
            float var18 = var13 - 3.0F;
            if (this.enchantmentsConfig.getValue() && var11 > 0) {
               if (this.durabilityConfig.getValue()) {
                  var18 -= 5.0F;
               }

               var18 -= 4.5F * (float)(var11 - 1);
            }

            var17 = var18 - 5.0F;
         }

         this.renderItemName(matrices, var16, var17);
         matrices.pop();
      }
   }

   private void renderItemStack(MatrixStack matrices, ItemStack stack, float x, float y) {
      matrices.push();
      matrices.translate(x, y, 0.0F);
      matrices.translate(8.0F, 8.0F, 0.0F);
      matrices.scale(16.0F, 16.0F, 1.0E-8F);
      matrices.multiplyPositionMatrix(new Matrix4f().scaling(1.0F, -1.0F, 1.0F));
      DiffuseLighting.disableGuiDepthLighting();
      BakedModel var5 = mc.getItemRenderer().getModel(stack, mc.world, null, 0);
      Immediate var6 = mc.getBufferBuilders().getEntityVertexConsumers();
      mc.getItemRenderer().renderItem(stack, ModelTransformationMode.GUI, false, matrices, var6, 15728880, OverlayTexture.DEFAULT_UV, var5);
      var6.draw();
      matrices.pop();
   }

   private void renderItemOverlay(MatrixStack matrices, ItemStack stack, float x, float y) {
      matrices.push();
      if (stack.getCount() != 1) {
         String var5 = String.valueOf(stack.getCount());
         this.drawWithShadow(matrices, var5, x + 17.0F - this.getTextWidth(var5), y + 9.0F, -1);
      }

      if (stack.isItemBarVisible() || stack.isDamageable() && this.forceBarConfig.getValue()) {
         int var9 = stack.getItemBarStep();
         int var6 = stack.getItemBarColor();
         float var7 = x + 2.0F;
         float var8 = y + 13.0F;
         Render2DUtil.drawRect(matrices, var7, var8, 13.0F, 2.0F, -16777216);
         Render2DUtil.drawRect(matrices, var7, var8, (float)var9, 1.0F, var6 | 0xFF000000);
      }

      matrices.pop();
   }

   private void renderDurability(MatrixStack matrices, ItemStack stack, float x, float y) {
      if (stack.isDamageable()) {
         int var5 = stack.getMaxDamage();
         int var6 = stack.getDamage();
         int var7 = (int)((float)(var5 - var6) / (float)var5 * 100.0F);
         int var8 = ColorUtil.hslToColor((float)(var5 - var6) / (float)var5 * 120.0F, 100.0F, 50.0F, 1.0F).getRGB();
         this.drawWithShadow(matrices, var7 + "%", x * 2.0F, y * 2.0F, var8);
      }
   }

   private void renderEnchants(MatrixStack matrices, ItemStack stack, float x, float y) {
      if (stack.isOf(Items.ENCHANTED_GOLDEN_APPLE)) {
         this.drawWithShadow(matrices, "God", x * 2.0F, y * 2.0F, new Color(195, 77, 65).getRGB());
      } else if (stack.hasEnchantments()) {
         float var5 = 0.0F;

         for (RegistryEntry<Enchantment> var7 : stack.getEnchantments().getEnchantments()) {
            if (this.protectionOnlyConfig.getValue()) {
               String var8 = var7.getKey().map(key -> key.getValue().getPath()).orElse("");
               if (!var8.contains("protection")) {
                  continue;
               }
            }

            int var10 = stack.getEnchantments().getLevel(var7);
            if (var10 > 0) {
               String var9 = this.getEnchantText(var7, var10);
               this.drawWithShadow(matrices, var9, x * 2.0F, (y + var5) * 2.0F, -1);
               var5 -= 4.5F;
            }
         }
      }
   }

   private int countDisplayedEnchants(ItemStack stack) {
      if (stack.isOf(Items.ENCHANTED_GOLDEN_APPLE)) {
         return 1;
      } else if (!stack.hasEnchantments()) {
         return 0;
      } else {
         int var2 = 0;

         for (RegistryEntry<Enchantment> var4 : stack.getEnchantments().getEnchantments()) {
            if (this.protectionOnlyConfig.getValue()) {
               String var5 = var4.getKey().map(key -> key.getValue().getPath()).orElse("");
               if (!var5.contains("protection")) {
                  continue;
               }
            }

            if (stack.getEnchantments().getLevel(var4) > 0) {
               var2++;
            }
         }

         return var2;
      }
   }

   private String getEnchantText(RegistryEntry<Enchantment> enchantment, int level) {
      String var3 = Enchantment.getName(enchantment, level).getString();
      if (var3.contains("Vanishing")) {
         return Formatting.RED + "Van";
      } else if (var3.contains("Binding")) {
         return Formatting.RED + "Bind";
      } else {
         String var4 = var3.replace("Curse of ", "")
            .replace(" ", "");
         int var5 = level > 1 ? 2 : 3;
         if (var4.length() > var5) {
            var4 = var4.substring(0, var5);
         }

         return var4 + level;
      }
   }

   private float enchantOffset(int count) {
      return this.enchantmentsConfig.getValue() && count > 2 ? -2.0F - (float)(count - 3) * 4.5F : 0.0F;
   }

   private void renderItemName(MatrixStack matrices, ItemStack stack, float y) {
      String var4 = stack.getName().getString();
      float var5 = this.getTextWidth(var4) / 4.0F;
      this.drawWithShadow(matrices, var4, -var5 * 2.0F, y * 2.0F, -1);
   }

   private boolean useFont() {
      return Fonts.INSTANCE != null && Fonts.INSTANCE.isOn() && FontManager.ui != null;
   }

   private float getTextWidth(String text) {
      return this.useFont() ? FontManager.ui.getWidth(text) : (float)mc.textRenderer.getWidth(this.normalizeFormattingPrefixes(text));
   }

   private float getTextHeight() {
      return this.useFont() ? FontManager.ui.getFontHeight() : 9.0F;
   }

   private String getNametagInfo(PlayerEntity player) {
      StringBuilder var2 = new StringBuilder();
      if (this.gamemodeConfig.getValue()) {
         GameMode var3 = getEntityGamemode(player);
         if (var3 == GameMode.CREATIVE) {
            var2.append(Formatting.DARK_PURPLE).append("[C] ");
         } else if (var3 == GameMode.SPECTATOR) {
            var2.append(Formatting.GRAY).append("[I] ");
         } else {
            var2.append(Formatting.YELLOW).append("[S] ");
         }
      }

      if (this.pingConfig.getValue()) {
         var2.append(getEntityPing(player)).append("ms ").append(Formatting.RESET);
      }

      var2.append(player.getName().getString()).append(" ");
      if (this.entityIdConfig.getValue()) {
         var2.append("ID: ").append(player.getId()).append(" ");
      }

      if (this.healthConfig.getValue()) {
         double var4 = (double)(player.getHealth() + player.getAbsorptionAmount());
         var2.append(this.getHealthColor(var4)).append(this.decimalFormat.format(var4)).append(" ");
      }

      if (this.totemsConfig.getValue()) {
         int var6 = CrucifixBeta.POP.getPop(player);
         if (var6 > 0) {
            var2.append(getPopColor(var6)).append(-var6).append(" ");
         }
      }

      return var2.toString().trim();
   }

   public static String getEntityPing(PlayerEntity entity) {
      if (mc.getNetworkHandler() == null) {
         return Formatting.GRAY + "-1";
      } else {
         PlayerListEntry var1 = mc.getNetworkHandler().getPlayerListEntry(entity.getUuid());
         if (var1 == null) {
            return Formatting.GRAY + "-1";
         } else {
            int var2 = var1.getLatency();
            Formatting var3 = var2 >= 200 ? Formatting.RED : (var2 >= 100 ? Formatting.YELLOW : Formatting.GREEN);
            return var3.toString() + var2;
         }
      }
   }

   public static GameMode getEntityGamemode(PlayerEntity entity) {
      if (entity != null && mc.getNetworkHandler() != null) {
         PlayerListEntry var1 = mc.getNetworkHandler().getPlayerListEntry(entity.getUuid());
         return var1 == null ? null : var1.getGameMode();
      } else {
         return null;
      }
   }

   private Formatting getHealthColor(double health) {
      if (health > 18.0) {
         return Formatting.GREEN;
      } else if (health > 16.0) {
         return Formatting.GOLD;
      } else if (health > 12.0) {
         return Formatting.YELLOW;
      } else if (health > 8.0) {
         return Formatting.RED;
      } else {
         return health > 4.0 ? Formatting.DARK_RED : Formatting.DARK_GRAY;
      }
   }

   private static Formatting getPopColor(int popCount) {
      if (TextRadar.INSTANCE != null && TextRadar.INSTANCE.red.getValue()) {
         return Formatting.RED;
      } else if (popCount > 10) {
         return Formatting.DARK_RED;
      } else if (popCount > 8) {
         return Formatting.RED;
      } else if (popCount > 6) {
         return Formatting.GOLD;
      } else if (popCount > 4) {
         return Formatting.YELLOW;
      } else {
         return popCount > 2 ? Formatting.DARK_GREEN : Formatting.GREEN;
      }
   }

   private int getTextColor(PlayerEntity player, boolean hasTurtle) {
      if (!hasTurtle || !this.turtleColorName.getValue() || this.ignoreFriend.getValue() && CrucifixBeta.FRIEND != null && CrucifixBeta.FRIEND.isFriend(player)
         )
       {
         if (this.friendConfig.booleanValue && player.getGameProfile() != null && CrucifixBeta.FRIEND != null && CrucifixBeta.FRIEND.isFriend(player)) {
            return this.friendConfig.getValue().getRGB();
         } else if (this.invisibleConfig.booleanValue && player.isInvisible()) {
            return this.invisibleConfig.getValue().getRGB();
         } else if (this.sneakingConfig.booleanValue && player.isSneaking()) {
            return this.sneakingConfig.getValue().getRGB();
         } else {
            return !player.isAlive() ? this.died.getValue().getRGB() : this.colorConfig.getValue().getRGB();
         }
      } else {
         return TURTLE_COLOR_RGB;
      }
   }

   private float getPotionSectionWidth(List<NameTags.PotionDisplay> displays) {
      if (displays.isEmpty()) {
         return 0.0F;
      } else if (!this.potionIcons.getValue()) {
         float var8 = 0.0F;
         boolean var9 = false;

         for (NameTags.PotionDisplay var11 : displays) {
            String var6 = this.stripFormattingCodes(var11.text().stripLeading());
            if (!var6.isBlank()) {
               if (var9) {
                  var8 += this.getTextWidth(" ");
               }

               var8 += this.getTextWidth(var6);
               var9 = true;
            }
         }

         return var8;
      } else {
         float var2 = 0.0F;

         for (NameTags.PotionDisplay var4 : displays) {
            String var5 = this.stripFormattingCodes(var4.text().stripLeading());
            var2 += 10.0F;
            if (!var4.level().isEmpty()) {
               var2 += this.potionIconGap.getValueFloat() + this.getTextWidth(var4.level());
            }

            if (!var5.isBlank()) {
               var2 += this.potionTextGap.getValueFloat() + this.getTextWidth(var5);
            }

            var2 += this.potionIconGap.getValueFloat();
         }

         return var2;
      }
   }

   private void drawPotionSection(MatrixStack matrices, List<NameTags.PotionDisplay> displays, float x, float y, int color) {
      if (!displays.isEmpty()) {
         if (!this.potionIcons.getValue()) {
            float var14 = x;
            boolean var15 = false;

            for (NameTags.PotionDisplay var17 : displays) {
               String var10 = this.stripFormattingCodes(var17.text().stripLeading());
               if (!var10.isBlank()) {
                  if (var15) {
                     var14 += this.getTextWidth(" ");
                  }

                  this.drawWithShadow(matrices, var10, var14, y, var17.color());
                  var14 += this.getTextWidth(var10);
                  var15 = true;
               }
            }
         } else {
            float var6 = x;

            for (NameTags.PotionDisplay var8 : displays) {
               String var9 = this.stripFormattingCodes(var8.text().stripLeading());
               this.renderIconTexture(matrices, var8.effectId(), var6, y - 1.0F, 10.0F);
               var6 += 10.0F;
               if (!var8.level().isEmpty()) {
                  var6 += this.potionIconGap.getValueFloat();
                  this.drawWithShadow(matrices, var8.level(), var6, y, var8.color());
                  var6 += this.getTextWidth(var8.level());
               }

               if (!var9.isBlank()) {
                  var6 += this.potionTextGap.getValueFloat();
                  this.drawWithShadow(matrices, var9, var6, y, var8.color());
                  var6 += this.getTextWidth(var9);
               }

               var6 += this.potionTextGap.getValueFloat();
            }
         }
      }
   }

   private String stripFormattingCodes(String text) {
      if (text != null && !text.isEmpty()) {
         StringBuilder var2 = new StringBuilder();

         for (int var3 = 0; var3 < text.length(); var3++) {
            char var4 = text.charAt(var3);
            if (var4 == 167 && var3 + 1 < text.length()) {
               var3++;
            } else {
               var2.append(var4);
            }
         }

         return var2.toString();
      } else {
         return "";
      }
   }

   private void renderIconTexture(MatrixStack matrices, String effectId, float x, float y, float size) {
      RenderSystem.enableBlend();
      RenderSystem.defaultBlendFunc();
      RenderSystem.setShader(GameRenderer::getPositionTexProgram);
      RenderSystem.setShaderTexture(0, Identifier.of("minecraft", "textures/mob_effect/" + effectId + ".png"));
      Matrix4f var6 = matrices.peek().getPositionMatrix();
      BufferBuilder var7 = Tessellator.getInstance().begin(DrawMode.QUADS, VertexFormats.POSITION_TEXTURE);
      var7.vertex(var6, x, y + size, 0.0F).texture(0.0F, 1.0F);
      var7.vertex(var6, x + size, y + size, 0.0F).texture(1.0F, 1.0F);
      var7.vertex(var6, x + size, y, 0.0F).texture(1.0F, 0.0F);
      var7.vertex(var6, x, y, 0.0F).texture(0.0F, 0.0F);
      BufferRenderer.drawWithGlobalProgram(var7.end());
      RenderSystem.disableBlend();
   }

   public void syncPotionState(PlayerEntity player, long now) {
      if (player != null) {
         int var4 = player.getId();
         if (player.isDead()) {
            this.clearPotionState(var4);
         } else {
            this.pruneExpired(now);
            if (this.potionGapple.getValue()) {
               this.detectGapple(player, var4, now);
            }
         }
      }
   }

   public boolean hasTurtleEffect(PlayerEntity player) {
      return player == null
         ? false
         : this.hasEffect(player, StatusEffects.RESISTANCE, this.turtleTimers, player.getId(), System.currentTimeMillis(), this.potionTurtle.getValue());
   }

   public ArrayList<NameTags.PotionDisplay> getPotionDisplays(
      PlayerEntity player,
      boolean showStrength,
      boolean showTurtle,
      boolean showRegen,
      boolean showFireRes,
      boolean showAbsorption,
      boolean showIcons,
      boolean showLevels
   ) {
      return this.getPotionDisplays(
         player,
         showStrength,
         showTurtle,
         showRegen,
         showFireRes,
         showAbsorption,
         showIcons,
         showLevels,
         this.potionBlankGap.getValueFloat(),
         this.potionTextGap.getValueFloat()
      );
   }

   private ArrayList<NameTags.PotionDisplay> getPotionDisplays(
      PlayerEntity player,
      boolean showStrength,
      boolean showTurtle,
      boolean showRegen,
      boolean showFireRes,
      boolean showAbsorption,
      boolean showIcons,
      boolean showLevels,
      float blankGap,
      float textGap
   ) {
      ArrayList var11 = new ArrayList();
      if (player == null) {
         return var11;
      } else {
         this.syncPotionState(player, System.currentTimeMillis());
         this.addPotionDisplay(
            var11,
            player,
            StatusEffects.STRENGTH,
            this.strengthTimers,
            showStrength,
            Formatting.YELLOW.toString(),
            Formatting.YELLOW.getColorValue(),
            "strength",
            NameTags.EffectLimit.STRENGTH,
            showIcons,
            showLevels,
            blankGap,
            textGap
         );
         this.addPotionDisplay(
            var11,
            player,
            StatusEffects.RESISTANCE,
            this.turtleTimers,
            showTurtle,
            TURTLE_COLOR,
            TURTLE_COLOR_RGB,
            "resistance",
            NameTags.EffectLimit.RESISTANCE,
            showIcons,
            showLevels,
            blankGap,
            textGap
         );
         this.addPotionDisplay(
            var11,
            player,
            StatusEffects.REGENERATION,
            this.regenTimers,
            showRegen,
            Formatting.LIGHT_PURPLE.toString(),
            Formatting.LIGHT_PURPLE.getColorValue(),
            "regeneration",
            NameTags.EffectLimit.NONE,
            showIcons,
            showLevels,
            blankGap,
            textGap
         );
         this.addPotionDisplay(
            var11,
            player,
            StatusEffects.FIRE_RESISTANCE,
            this.fireResTimers,
            showFireRes,
            Formatting.GOLD.toString(),
            Formatting.GOLD.getColorValue(),
            "fire_resistance",
            NameTags.EffectLimit.NONE,
            showIcons,
            showLevels,
            blankGap,
            textGap
         );
         this.addPotionDisplay(
            var11,
            player,
            StatusEffects.ABSORPTION,
            this.absorptionTimers,
            showAbsorption,
            Formatting.YELLOW.toString(),
            Formatting.YELLOW.getColorValue(),
            "absorption",
            NameTags.EffectLimit.NONE,
            showIcons,
            showLevels,
            blankGap,
            textGap
         );
         return var11;
      }
   }

   private void addPotionDisplay(
      ArrayList<NameTags.PotionDisplay> displays,
      PlayerEntity player,
      RegistryEntry<StatusEffect> effect,
      Map<Integer, NameTags.EffectTimer> timers,
      boolean enabled,
      String colorCode,
      int color,
      String effectId,
      NameTags.EffectLimit limit,
      boolean showIcons,
      boolean showLevels,
      float blankGap,
      float textGap
   ) {
      if (enabled) {
         NameTags.EffectSnapshot var14 = this.getEffectSnapshot(player, effect, timers, limit);
         if (var14 != null && !(var14.seconds <= 0.0)) {
            String var15 = this.potionTextPrefix(showIcons, blankGap, textGap) + colorCode + this.formatPotionTime(var14.seconds);
            String var16 = showLevels ? toRoman(var14.amplifier + 1) : "";
            displays.add(new NameTags.PotionDisplay(var15, var16, color, effectId));
         }
      }
   }

   private NameTags.EffectSnapshot getEffectSnapshot(PlayerEntity player, RegistryEntry<StatusEffect> effect, Map<Integer, NameTags.EffectTimer> timers) {
      return this.getEffectSnapshot(player, effect, timers, NameTags.EffectLimit.NONE);
   }

   private NameTags.EffectSnapshot getEffectSnapshot(
      PlayerEntity player, RegistryEntry<StatusEffect> effect, Map<Integer, NameTags.EffectTimer> timers, NameTags.EffectLimit limit
   ) {
      if (player == mc.player && mc.player != null) {
         StatusEffectInstance var5 = mc.player.getStatusEffect(effect);
         if (var5 != null && var5.getDuration() > 0) {
            double var6 = Math.min((double)var5.getDuration() / 20.0, (double)maxEffectSeconds(limit, var5.getAmplifier()));
            return new NameTags.EffectSnapshot(Math.max(1.0, var6), var5.getAmplifier());
         } else {
            return null;
         }
      } else {
         long var8 = System.currentTimeMillis();
         NameTags.EffectTimer var10 = (NameTags.EffectTimer)timers.get(player.getId());
         if (var10 == null) {
            return null;
         } else if (var10.expiry <= var8) {
            timers.remove(player.getId());
            return null;
         } else {
            double var11 = Math.min((double)(var10.expiry - var8) / 1000.0, (double)maxEffectSeconds(limit, var10.amplifier));
            return new NameTags.EffectSnapshot(Math.max(1.0, var11), var10.amplifier);
         }
      }
   }

   private boolean hasEffect(
      PlayerEntity player, RegistryEntry<StatusEffect> effect, Map<Integer, NameTags.EffectTimer> timers, int playerId, long now, boolean enabled
   ) {
      if (!enabled) {
         return false;
      } else if (player == mc.player && mc.player != null) {
         StatusEffectInstance var9 = mc.player.getStatusEffect(effect);
         return var9 != null && var9.getDuration() > 0;
      } else {
         NameTags.EffectTimer var8 = (NameTags.EffectTimer)timers.get(playerId);
         if (var8 != null && var8.expiry > now) {
            return true;
         } else {
            if (var8 != null) {
               timers.remove(playerId);
            }

            return false;
         }
      }
   }

   private String potionTextPrefix(boolean showIcons, float blankGap, float textGap) {
      if (!showIcons) {
         return " ";
      } else {
         int var4 = Math.max(1, Math.round((blankGap + textGap) / 3.5F));
         return (" ").repeat(var4);
      }
   }

   public String getPotionDisplayString(
      PlayerEntity player,
      String separator,
      boolean showStrength,
      boolean showTurtle,
      boolean showRegen,
      boolean showFireRes,
      boolean showAbsorption,
      boolean showIcons,
      boolean showLevels
   ) {
      return this.getPotionDisplayString(
         player, separator, showStrength, showTurtle, showRegen, showFireRes, showAbsorption, showIcons, showLevels, 25.0F, 4.0F
      );
   }

   public String getPotionDisplayString(
      PlayerEntity player,
      String separator,
      boolean showStrength,
      boolean showTurtle,
      boolean showRegen,
      boolean showFireRes,
      boolean showAbsorption,
      boolean showIcons,
      boolean showLevels,
      float blankGap,
      float textGap
   ) {
      StringBuilder var12 = new StringBuilder();

      for (NameTags.PotionDisplay var14 : this.getPotionDisplays(
         player, showStrength, showTurtle, showRegen, showFireRes, showAbsorption, showIcons, showLevels, blankGap, textGap
      )) {
         String var15 = var14.text();
         if (!showIcons && var15.startsWith(" ")) {
            var15 = separator + var15.substring(1);
         }

         var12.append(var15);
      }

      return var12.toString();
   }

   public void drawTextRadarPotionIcons(
      DrawContext context,
      PlayerEntity player,
      String renderedText,
      float textX,
      float textY,
      boolean fancyFont,
      boolean shadow,
      boolean showStrength,
      boolean showTurtle,
      boolean showRegen,
      boolean showFireRes,
      boolean showAbsorption,
      boolean showIcons,
      boolean showLevels
   ) {
      this.drawTextRadarPotionIcons(
         context,
         player,
         renderedText,
         textX,
         textY,
         fancyFont,
         shadow,
         showStrength,
         showTurtle,
         showRegen,
         showFireRes,
         showAbsorption,
         showIcons,
         showLevels,
         2.0F,
         4.0F
      );
   }

   public void drawTextRadarPotionIcons(
      DrawContext context,
      PlayerEntity player,
      String renderedText,
      float textX,
      float textY,
      boolean fancyFont,
      boolean shadow,
      boolean showStrength,
      boolean showTurtle,
      boolean showRegen,
      boolean showFireRes,
      boolean showAbsorption,
      boolean showIcons,
      boolean showLevels,
      float iconGap,
      float textGap
   ) {
      if (showIcons) {
         for (NameTags.PotionDisplay var18 : this.getPotionDisplays(
            player, showStrength, showTurtle, showRegen, showFireRes, showAbsorption, true, showLevels, 25.0F, textGap
         )) {
            int var19 = renderedText.indexOf(var18.text());
            if (var19 >= 0) {
               String var20 = renderedText.substring(0, var19);
               float var21 = fancyFont && FontManager.ui != null ? FontManager.ui.getWidth(var20) : (float)mc.textRenderer.getWidth(var20);
               float var22 = var18.level().isEmpty()
                  ? 0.0F
                  : (fancyFont && FontManager.ui != null ? FontManager.ui.getWidth(var18.level()) : (float)mc.textRenderer.getWidth(var18.level()));
               float var23 = textX + var21 + textGap;
               float var24 = textX + var21 + (var18.level().isEmpty() ? textGap : textGap + var22 + iconGap);
               if (!var18.level().isEmpty()) {
                  if (fancyFont && FontManager.ui != null) {
                     FontManager.ui.drawString(context.getMatrices(), var18.level(), (double)var23, (double)textY, var18.color(), false);
                  } else {
                     context.drawText(mc.textRenderer, var18.level(), Math.round(var23), Math.round(textY), var18.color(), false);
                  }
               }

               this.drawEffectIcon(context, var18.effectId(), Math.round(var24), Math.round(textY - 1.0F), 10);
            }
         }
      }
   }

   private void drawEffectIcon(DrawContext context, String effectId, int x, int y, int size) {
      try {
         context.drawTexture(Identifier.of("minecraft", "textures/mob_effect/" + effectId + ".png"), x, y, 0.0F, 0.0F, size, size, size, size);
      } catch (Exception var7) {
      }
   }

   @EventListener
   public void onPacketReceive(PacketEvent.Receive event) {
      if (this.potionStrength.getValue()
         || this.potionTurtle.getValue()
         || this.potionRegen.getValue()
         || this.potionFireRes.getValue()
         || this.potionAbsorption.getValue()) {
         if (!nullCheck()) {
            if (event.getPacket() instanceof WorldEventS2CPacket var3) {
               if (var3.getEventId() == 2002) {
                  this.trackSplashPotion(var3);
               }
            }
         }
      }
   }

   private void trackSplashPotion(WorldEventS2CPacket packet) {
      Vec3d var2 = Vec3d.ofCenter(packet.getPos());
      double var3 = packet.getData() == 1 ? 6.0 : 4.0;
      PotionEntity var5 = this.findSplashPotionEntity(var2);
      if (var5 != null) {
         ItemStack var6 = var5.getStack();
         PotionContentsComponent var7 = var6.getOrDefault(DataComponentTypes.POTION_CONTENTS, PotionContentsComponent.DEFAULT);
         if (var7 != PotionContentsComponent.DEFAULT) {
            ArrayList<NameTags.PotionInfo> var8 = new ArrayList<>();

            for (StatusEffectInstance var10 : var7.getEffects()) {
               RegistryEntry<StatusEffect> var11 = var10.getEffectType();
               Map<Integer, NameTags.EffectTimer> var12 = null;
               int var13 = 0;
               if (var11 != StatusEffects.STRENGTH || var10.getAmplifier() != 0 && var10.getAmplifier() != 1) {
                  if (var11 != StatusEffects.RESISTANCE || var10.getAmplifier() != 2 && var10.getAmplifier() != 3) {
                     if (var11 == StatusEffects.REGENERATION) {
                        var12 = this.regenTimers;
                        var13 = 900;
                     } else if (var11 == StatusEffects.FIRE_RESISTANCE) {
                        var12 = this.fireResTimers;
                        var13 = 800;
                     } else if (var11 == StatusEffects.ABSORPTION) {
                        var12 = this.absorptionTimers;
                        var13 = 100;
                     }
                  } else {
                     var12 = this.turtleTimers;
                     var13 = maxResistanceTicks(var10.getAmplifier());
                  }
               } else {
                  var12 = this.strengthTimers;
                  var13 = maxStrengthTicks(var10.getAmplifier());
               }

               if (var12 != null) {
                  var8.add(new NameTags.PotionInfo(var12, var10.getDuration(), var10.getAmplifier(), var13));
               }
            }

            if (!var8.isEmpty()) {
               long var14 = System.currentTimeMillis();

               for (PlayerEntity var25 : mc.world.getPlayers()) {
                  if (var25 != null && !var25.isSpectator() && !var25.isDead()) {
                     double var16 = this.potionModernDistance.getValue() ? this.getClosestDistanceToBox(var2, var25) : var2.distanceTo(var25.getPos());
                     if (!(var16 > var3)) {
                        double var18 = 1.0 - var16 / var3;
                        int var20 = var25.getId();

                        for (NameTags.PotionInfo var22 : var8) {
                           int var23 = (int)(var18 * (double)var22.baseDuration + 0.5);
                           if (var23 >= 20) {
                              var23 = Math.min(var23, var22.maxDuration);
                              this.mergePotionTimer(var22.map, var20, var14 + (long)var23 * 50L, var22.amplifier);
                           }
                        }
                     }
                  }
               }
            }
         }
      }
   }

   private PotionEntity findSplashPotionEntity(Vec3d splashPos) {
      PotionEntity var2 = null;
      double var3 = 4.0;

      for (Entity var6 : mc.world.getEntities()) {
         if (var6 instanceof PotionEntity) {
            PotionEntity var7 = (PotionEntity)var6;
            double var8 = var6.getPos().squaredDistanceTo(splashPos);
            if (var8 < var3) {
               var3 = var8;
               var2 = var7;
            }
         }
      }

      return var2;
   }

   private double getClosestDistanceToBox(Vec3d splashPos, PlayerEntity player) {
      Box var3 = player.getBoundingBox();
      double var4 = Math.max(0.0, Math.max(var3.minX - splashPos.x, splashPos.x - var3.maxX));
      double var6 = Math.max(0.0, Math.max(var3.minY - splashPos.y, splashPos.y - var3.maxY));
      double var8 = Math.max(0.0, Math.max(var3.minZ - splashPos.z, splashPos.z - var3.maxZ));
      return Math.sqrt(var4 * var4 + var6 * var6 + var8 * var8);
   }

   private void mergePotionTimer(Map<Integer, NameTags.EffectTimer> timers, int playerId, long expiry, int amplifier) {
      timers.merge(playerId, new NameTags.EffectTimer(expiry, amplifier), (oldTimer, newTimer) -> {
         if (newTimer.amplifier > oldTimer.amplifier) {
            return (NameTags.EffectTimer)newTimer;
         } else {
            return (NameTags.EffectTimer)(newTimer.amplifier == oldTimer.amplifier && newTimer.expiry > oldTimer.expiry ? newTimer : oldTimer);
         }
      });
   }

   private void detectGapple(PlayerEntity player, int playerId, long now) {
      StringBuilder var5 = new StringBuilder();
      StatusEffectInstance var6 = null;

      for (StatusEffectInstance var8 : player.getStatusEffects()) {
         var5.append(var8.getTranslationKey()).append(var8.getAmplifier()).append(';');
         if (var8.getEffectType() == StatusEffects.ABSORPTION) {
            var6 = var8;
         }
      }

      String var9 = this.lastEffects.getOrDefault(playerId, "");
      this.lastEffects.put(playerId, var5.toString());
      if (var6 != null) {
         String var10 = StatusEffects.ABSORPTION.value().getTranslationKey() + var6.getAmplifier();
         if (!var9.contains(var10)) {
            if (var6.getAmplifier() >= 3) {
               this.mergePotionTimer(this.resistanceTimers, playerId, now + 300000L, 0);
               this.mergePotionTimer(this.fireResTimers, playerId, now + 300000L, 0);
               this.mergePotionTimer(this.regenTimers, playerId, now + 20000L, 1);
               this.mergePotionTimer(this.absorptionTimers, playerId, now + 120000L, 3);
            } else {
               this.mergePotionTimer(this.absorptionTimers, playerId, now + 120000L, 0);
               this.mergePotionTimer(this.regenTimers, playerId, now + 5000L, 1);
            }
         }
      }
   }

   @EventListener
   public void onTotemPop(TotemEvent event) {
      PlayerEntity var2 = event.getPlayer();
      if (var2 != null) {
         int var3 = var2.getId();
         long var4 = System.currentTimeMillis();
         this.strengthTimers.remove(var3);
         this.turtleTimers.remove(var3);
         this.regenTimers.remove(var3);
         this.fireResTimers.remove(var3);
         this.absorptionTimers.remove(var3);
         this.resistanceTimers.remove(var3);
         this.mergePotionTimer(this.regenTimers, var3, var4 + 45000L, 1);
         this.mergePotionTimer(this.fireResTimers, var3, var4 + 40000L, 0);
         this.mergePotionTimer(this.absorptionTimers, var3, var4 + 5000L, 1);
      }
   }

   private void clearPotionState(int playerId) {
      this.strengthTimers.remove(playerId);
      this.turtleTimers.remove(playerId);
      this.regenTimers.remove(playerId);
      this.fireResTimers.remove(playerId);
      this.absorptionTimers.remove(playerId);
      this.resistanceTimers.remove(playerId);
      this.lastEffects.remove(playerId);
   }

   private void pruneExpired(long now) {
      this.strengthTimers.entrySet().removeIf(entry -> entry.getValue().expiry <= now);
      this.turtleTimers.entrySet().removeIf(entry -> entry.getValue().expiry <= now);
      this.regenTimers.entrySet().removeIf(entry -> entry.getValue().expiry <= now);
      this.fireResTimers.entrySet().removeIf(entry -> entry.getValue().expiry <= now);
      this.absorptionTimers.entrySet().removeIf(entry -> entry.getValue().expiry <= now);
      this.resistanceTimers.entrySet().removeIf(entry -> entry.getValue().expiry <= now);
   }

   private static String toRoman(int value) {
      return switch (value) {
         case 1 -> "I";
         case 2 -> "II";
         case 3 -> "III";
         case 4 -> "IV";
         case 5 -> "V";
         default -> Integer.toString(value);
      };
   }

   private String formatPotionTime(double seconds) {
      double var3 = Math.max(this.potionDecimal.getValue() ? 0.1 : 1.0, seconds);
      if (this.potionTimeStyle.getValue() == NameTags.PotionTimeStyle.Noxis) {
         int var5 = (int)(var3 / 60.0);
         double var6 = var3 - (double)var5 * 60.0;
         return this.potionDecimal.getValue()
            ? String.format(Locale.ROOT, "[%d:%04.1f]", var5, var6)
            : String.format(Locale.ROOT, "[%d:%02d]", var5, (int)var6);
      } else {
         return this.potionDecimal.getValue() ? String.format(Locale.ROOT, "%.1fs", var3) : (int)var3 + "s";
      }
   }

   private static long maxResistanceSeconds(int amplifier) {
      if (amplifier >= 3) {
         return 20L;
      } else {
         return amplifier >= 2 ? 40L : Long.MAX_VALUE;
      }
   }

   private static long maxStrengthSeconds(int amplifier) {
      return amplifier >= 1 ? 90L : 480L;
   }

   private static long maxEffectSeconds(NameTags.EffectLimit limit, int amplifier) {
      return switch (limit) {
         case NONE -> Long.MAX_VALUE;
         case RESISTANCE -> maxResistanceSeconds(amplifier);
         case STRENGTH -> maxStrengthSeconds(amplifier);
      };
   }

   private static int maxResistanceTicks(int amplifier) {
      long var1 = maxResistanceSeconds(amplifier);
      return var1 == Long.MAX_VALUE ? Integer.MAX_VALUE : (int)var1 * 20;
   }

   private static int maxStrengthTicks(int amplifier) {
      return (int)maxStrengthSeconds(amplifier) * 20;
   }

   static {

      TURTLE_COLOR = Formatting.BLUE.toString();
      TURTLE_COLOR_RGB = new Color(85, 85, 255).getRGB();
   }
@Environment(EnvType.CLIENT)
   private static enum EffectLimit {
      NONE,
      RESISTANCE,
      STRENGTH;

}

   @Environment(EnvType.CLIENT)
   private static record EffectSnapshot(double seconds, int amplifier) {
   }

   @Environment(EnvType.CLIENT)
   private static record EffectTimer(long expiry, int amplifier) {
   }

   @Environment(EnvType.CLIENT)
   public static record PotionDisplay(String text, String level, int color, String effectId) {
   }

   @Environment(EnvType.CLIENT)
   private static record PotionInfo(Map<Integer, NameTags.EffectTimer> map, int baseDuration, int amplifier, int maxDuration) {
   }

   @Environment(EnvType.CLIENT)
   public static enum PotionTimeStyle {
      Mine,
      Noxis;

}

   @Environment(EnvType.CLIENT)
   public static enum ScaleMode {
      Original,
      Current;

}
}
