package net.minecraft.world.entity;

import net.minecraft.core.BlockPosition;
import net.minecraft.core.NonNullList;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.resources.RegistryOps;
import net.minecraft.nbt.DynamicOpsNBT;
import net.minecraft.world.effect.MobEffectList;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.entity.EntityEquipment;
import net.minecraft.world.entity.ai.attributes.AttributeBase;
import net.minecraft.world.entity.ai.attributes.AttributeDefaults;
import net.minecraft.world.entity.ai.attributes.AttributeMapBase;
import net.minecraft.world.entity.ai.attributes.AttributeModifiable;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.Vec3D;

import com.bergerkiller.bukkit.common.bases.IntVector3;
import com.bergerkiller.bukkit.common.nbt.CommonTagCompound;
import com.bergerkiller.bukkit.common.wrappers.DataWatcher;
import com.bergerkiller.bukkit.common.wrappers.DataWatcher.Key;
import com.bergerkiller.bukkit.common.wrappers.Holder;

import com.bergerkiller.generated.net.minecraft.world.entity.ai.attributes.AttributeBaseHandle;
import com.bergerkiller.generated.net.minecraft.world.entity.ai.attributes.AttributeMapBaseHandle;
import com.bergerkiller.generated.net.minecraft.world.entity.ai.attributes.AttributeModifiableHandle;
import com.bergerkiller.generated.net.minecraft.nbt.NBTTagCompoundHandle;
import com.bergerkiller.generated.net.minecraft.world.entity.EntityHandle;

import com.bergerkiller.generated.net.minecraft.world.effect.MobEffectHandle;
import com.bergerkiller.generated.net.minecraft.world.effect.MobEffectListHandle;

class EntityLiving extends Entity {

#if version >= 1.17
    protected static optional final (DataWatcher.Key<Byte>) DataWatcherObject<Byte> DATA_LIVING_FLAGS:DATA_LIVING_ENTITY_FLAGS;
    public static optional final (DataWatcher.Key<Float>) DataWatcherObject<Float> DATA_HEALTH:DATA_HEALTH_ID;
    //private static optional final (DataWatcher.Key<Integer>) DataWatcherObject<Integer> DATA_PARTICLES_COLOR_RGB:DATA_EFFECT_COLOR_ID;
    private static optional final (DataWatcher.Key<Boolean>) DataWatcherObject<Boolean> DATA_PARTICLES_HIDDEN:DATA_EFFECT_AMBIENCE_ID;
    private static optional final (DataWatcher.Key<Integer>) DataWatcherObject<Integer> DATA_ARROWCOUNT:DATA_ARROW_COUNT_ID;
    //TODO: DATA_STINGER_COUNT_ID data field was added
    private static optional final (DataWatcher.Key<IntVector3>) DataWatcherObject<Optional<BlockPosition>> DATA_BEDPOSITION:SLEEPING_POS_ID;
#elseif version >= 1.16.2
    protected static optional final (DataWatcher.Key<Byte>) DataWatcherObject<Byte> DATA_LIVING_FLAGS:ag;
    public static optional final (DataWatcher.Key<Float>) DataWatcherObject<Float> DATA_HEALTH:HEALTH;
    //private static optional final (DataWatcher.Key<Integer>) DataWatcherObject<Integer> DATA_PARTICLES_COLOR_RGB:f;
    private static optional final (DataWatcher.Key<Boolean>) DataWatcherObject<Boolean> DATA_PARTICLES_HIDDEN:g;
  #if version >= 1.16.3
    private static optional final (DataWatcher.Key<Integer>) DataWatcherObject<Integer> DATA_ARROWCOUNT:ARROWS_IN_BODY;
  #else
    private static optional final (DataWatcher.Key<Integer>) DataWatcherObject<Integer> DATA_ARROWCOUNT:bh;
  #endif
    private static optional final (DataWatcher.Key<IntVector3>) DataWatcherObject<Optional<BlockPosition>> DATA_BEDPOSITION:bj;
#elseif version >= 1.16
    protected static optional final (DataWatcher.Key<Byte>) DataWatcherObject<Byte> DATA_LIVING_FLAGS:an;
    public static optional final (DataWatcher.Key<Float>) DataWatcherObject<Float> DATA_HEALTH:HEALTH;
    //private static optional final (DataWatcher.Key<Integer>) DataWatcherObject<Integer> DATA_PARTICLES_COLOR_RGB:f;
    private static optional final (DataWatcher.Key<Boolean>) DataWatcherObject<Boolean> DATA_PARTICLES_HIDDEN:g;
    private static optional final (DataWatcher.Key<Integer>) DataWatcherObject<Integer> DATA_ARROWCOUNT:bo;
    private static optional final (DataWatcher.Key<IntVector3>) DataWatcherObject<Optional<BlockPosition>> DATA_BEDPOSITION:bq;
#elseif version >= 1.15
    protected static optional final (DataWatcher.Key<Byte>) DataWatcherObject<Byte> DATA_LIVING_FLAGS:ao;
    public static optional final (DataWatcher.Key<Float>) DataWatcherObject<Float> DATA_HEALTH:HEALTH;
    //private static optional final (DataWatcher.Key<Integer>) DataWatcherObject<Integer> DATA_PARTICLES_COLOR_RGB:e;
    private static optional final (DataWatcher.Key<Boolean>) DataWatcherObject<Boolean> DATA_PARTICLES_HIDDEN:f;
    private static optional final (DataWatcher.Key<Integer>) DataWatcherObject<Integer> DATA_ARROWCOUNT:g;
    private static optional final (DataWatcher.Key<IntVector3>) DataWatcherObject<Optional<BlockPosition>> DATA_BEDPOSITION:bq;
#elseif version >= 1.14
    protected static optional final (DataWatcher.Key<Byte>) DataWatcherObject<Byte> DATA_LIVING_FLAGS:ar;
    public static optional final (DataWatcher.Key<Float>) DataWatcherObject<Float> DATA_HEALTH:HEALTH;
    //private static optional final (DataWatcher.Key<Integer>) DataWatcherObject<Integer> DATA_PARTICLES_COLOR_RGB:e;
    private static optional final (DataWatcher.Key<Boolean>) DataWatcherObject<Boolean> DATA_PARTICLES_HIDDEN:f;
    private static optional final (DataWatcher.Key<Integer>) DataWatcherObject<Integer> DATA_ARROWCOUNT:g;
    private static optional final (DataWatcher.Key<IntVector3>) DataWatcherObject<Optional<BlockPosition>> DATA_BEDPOSITION:bs;
#elseif version >= 1.13
    protected static optional final (DataWatcher.Key<Byte>) DataWatcherObject<Byte> DATA_LIVING_FLAGS:aw;
    public static optional final (DataWatcher.Key<Float>) DataWatcherObject<Float> DATA_HEALTH:HEALTH;
    //private static optional final (DataWatcher.Key<Integer>) DataWatcherObject<Integer> DATA_PARTICLES_COLOR_RGB:g;
    private static optional final (DataWatcher.Key<Boolean>) DataWatcherObject<Boolean> DATA_PARTICLES_HIDDEN:h;
    private static optional final (DataWatcher.Key<Integer>) DataWatcherObject<Integer> DATA_ARROWCOUNT:bx;
    private static optional final (DataWatcher.Key<IntVector3>) DataWatcherObject<Optional<BlockPosition>> DATA_BEDPOSITION:###;
#elseif version >= 1.12
    protected static optional final (DataWatcher.Key<Byte>) DataWatcherObject<Byte> DATA_LIVING_FLAGS:at;
    public static optional final (DataWatcher.Key<Float>) DataWatcherObject<Float> DATA_HEALTH:HEALTH;
    //private static optional final (DataWatcher.Key<Integer>) DataWatcherObject<Integer> DATA_PARTICLES_COLOR_RGB:g;
    private static optional final (DataWatcher.Key<Boolean>) DataWatcherObject<Boolean> DATA_PARTICLES_HIDDEN:h;
    private static optional final (DataWatcher.Key<Integer>) DataWatcherObject<Integer> DATA_ARROWCOUNT:br;
    private static optional final (DataWatcher.Key<IntVector3>) DataWatcherObject<Optional<BlockPosition>> DATA_BEDPOSITION:###;
#elseif version >= 1.11
    protected static optional final (DataWatcher.Key<Byte>) DataWatcherObject<Byte> DATA_LIVING_FLAGS:at;
    public static optional final (DataWatcher.Key<Float>) DataWatcherObject<Float> DATA_HEALTH:HEALTH;
    //private static optional final (DataWatcher.Key<Integer>) DataWatcherObject<Integer> DATA_PARTICLES_COLOR_RGB:g;
    private static optional final (DataWatcher.Key<Boolean>) DataWatcherObject<Boolean> DATA_PARTICLES_HIDDEN:h;
    private static optional final (DataWatcher.Key<Integer>) DataWatcherObject<Integer> DATA_ARROWCOUNT:bq;
    private static optional final (DataWatcher.Key<IntVector3>) DataWatcherObject<Optional<BlockPosition>> DATA_BEDPOSITION:###;
#elseif version >= 1.10.2
    protected static optional final (DataWatcher.Key<Byte>) DataWatcherObject<Byte> DATA_LIVING_FLAGS:au;
    public static optional final (DataWatcher.Key<Float>) DataWatcherObject<Float> DATA_HEALTH:HEALTH;
    //private static optional final (DataWatcher.Key<Integer>) DataWatcherObject<Integer> DATA_PARTICLES_COLOR_RGB:f;
    private static optional final (DataWatcher.Key<Boolean>) DataWatcherObject<Boolean> DATA_PARTICLES_HIDDEN:g;
    private static optional final (DataWatcher.Key<Integer>) DataWatcherObject<Integer> DATA_ARROWCOUNT:h;
    private static optional final (DataWatcher.Key<IntVector3>) DataWatcherObject<Optional<BlockPosition>> DATA_BEDPOSITION:###;
#elseif version >= 1.9.4
    protected static optional final (DataWatcher.Key<Byte>) DataWatcherObject<Byte> DATA_LIVING_FLAGS:at;
    public static optional final (DataWatcher.Key<Float>) DataWatcherObject<Float> DATA_HEALTH:HEALTH;
    //private static optional final (DataWatcher.Key<Integer>) DataWatcherObject<Integer> DATA_PARTICLES_COLOR_RGB:f;
    private static optional final (DataWatcher.Key<Boolean>) DataWatcherObject<Boolean> DATA_PARTICLES_HIDDEN:g;
    private static optional final (DataWatcher.Key<Integer>) DataWatcherObject<Integer> DATA_ARROWCOUNT:h;
    private static optional final (DataWatcher.Key<IntVector3>) DataWatcherObject<Optional<BlockPosition>> DATA_BEDPOSITION:###;
#elseif version >= 1.9
    protected static optional final (DataWatcher.Key<Byte>) DataWatcherObject<Byte> DATA_LIVING_FLAGS:as;
    public static optional final (DataWatcher.Key<Float>) DataWatcherObject<Float> DATA_HEALTH:HEALTH;
    //private static optional final (DataWatcher.Key<Integer>) DataWatcherObject<Integer> DATA_PARTICLES_COLOR_RGB:f;
    private static optional final (DataWatcher.Key<Boolean>) DataWatcherObject<Boolean> DATA_PARTICLES_HIDDEN:g;
    private static optional final (DataWatcher.Key<Integer>) DataWatcherObject<Integer> DATA_ARROWCOUNT:h;
    private static optional final (DataWatcher.Key<IntVector3>) DataWatcherObject<Optional<BlockPosition>> DATA_BEDPOSITION:###;
#else
    protected static optional final (DataWatcher.Key<Byte>) DataWatcherObject<Byte> DATA_LIVING_FLAGS:###;
    public static optional final (DataWatcher.Key<Float>) DataWatcherObject<Float> DATA_HEALTH:###;
    //private static optional final (DataWatcher.Key<Integer>) DataWatcherObject<Integer> DATA_PARTICLES_COLOR_RGB:###;
    private static optional final (DataWatcher.Key<Boolean>) DataWatcherObject<Boolean> DATA_PARTICLES_HIDDEN:###;
    private static optional final (DataWatcher.Key<Integer>) DataWatcherObject<Integer> DATA_ARROWCOUNT:###;
    private static optional final (DataWatcher.Key<IntVector3>) DataWatcherObject<Optional<BlockPosition>> DATA_BEDPOSITION:###;
#endif

    <code>
    public static final Key<Byte> DATA_LIVING_FLAGS = Key.Type.BYTE.createKey(T.DATA_LIVING_FLAGS, -1);
    public static final Key<Float> DATA_HEALTH = Key.Type.FLOAT.createKey(T.DATA_HEALTH, 6);
    //public static final Key<Integer> DATA_PARTICLES_COLOR_RGB = Key.Type.INTEGER.createKey(T.DATA_PARTICLES_COLOR_RGB, 7);
    public static final Key<Boolean> DATA_PARTICLES_HIDDEN = Key.Type.BOOLEAN.createKey(T.DATA_PARTICLES_HIDDEN, 8);
    public static final Key<Integer> DATA_UNKNOWN1 = Key.Type.INTEGER.createKey(T.DATA_ARROWCOUNT, 9);
    public static final Key<IntVector3> DATA_BEDPOSITION = Key.Type.BLOCK_POSITION.createKey(T.DATA_BEDPOSITION, -1);
    </code>

    public void resetAttributes() {
#if version >= 1.17
        // Is only set in constructor, so we'll have to force it
        // TODO: Is there no cleaner way to do this? Maybe modify AttributeMapBase directly?
        #require net.minecraft.world.entity.EntityLiving private final AttributeMapBase attributeMapField:attributes;
        #require net.minecraft.world.entity.EntityLiving private final org.bukkit.craftbukkit.attribute.CraftAttributeMap craftAttributes;
  #if version >= 1.18
        AttributeMapBase new_attributes = new AttributeMapBase(AttributeDefaults.getSupplier(instance.getType()));
  #else
        AttributeMapBase new_attributes = new AttributeMapBase(AttributeDefaults.a(instance.getEntityType()));
  #endif
        org.bukkit.craftbukkit.attribute.CraftAttributeMap new_craftAttributes = new org.bukkit.craftbukkit.attribute.CraftAttributeMap(new_attributes);
        instance#attributeMapField = new_attributes;
        instance#craftAttributes = new_craftAttributes;

        // Item attributes need to be re-applied later, they are lost as part of this reset
        // If Inventory is also changed this is less important, as the item changes will trigger an update too.
        // But when the inventory does not change, no change will be detected.
        //
        // [MyWorlds] To reproduce, give yourself armor, then teleport between worlds where inventory is shared.
        // Your armor slots will go away when you go to the other world despite still wearing armor.
  #if version >= 1.21.5
        #require net.minecraft.world.entity.EntityLiving private final Map<EnumItemSlot, ItemStack> lastEquipmentItems;
        Map lastEquipmentItems = instance#lastEquipmentItems;
        java.util.Iterator slotTypesIter = EnumItemSlot.VALUES.iterator();
        while (slotTypesIter.hasNext()) {
            EnumItemSlot slot = (EnumItemSlot) slotTypesIter.next();
            if (lastEquipmentItems.containsKey(slot)) {
                lastEquipmentItems.put(slot, ItemStack.EMPTY);
            }
        }
  #else
        #require net.minecraft.world.entity.EntityLiving private final NonNullList<ItemStack> lastHandItemStacks;
        #require net.minecraft.world.entity.EntityLiving private final NonNullList<ItemStack> lastArmorItemStacks;
        NonNullList lastHandItemStacks = instance#lastHandItemStacks;
        NonNullList lastArmorItemStacks = instance#lastArmorItemStacks;
        lastHandItemStacks.clear();
        lastArmorItemStacks.clear();
  #endif
#elseif version >= 1.16
        // Is only set in constructor, so we'll have to force it
        // TODO: Is there no cleaner way to do this? Maybe modify AttributeMapBase directly?
        #require net.minecraft.world.entity.EntityLiving private final AttributeMapBase attributeMapField:attributeMap;
        #require net.minecraft.world.entity.EntityLiving private final org.bukkit.craftbukkit.attribute.CraftAttributeMap craftAttributes;
        AttributeMapBase new_attributes = new AttributeMapBase(AttributeDefaults.a(instance.getEntityType()));
        org.bukkit.craftbukkit.attribute.CraftAttributeMap new_craftAttributes = new org.bukkit.craftbukkit.attribute.CraftAttributeMap(new_attributes);
        instance#attributeMapField = new_attributes;
        instance#craftAttributes = new_craftAttributes;

        // Item attributes need to be re-applied later, they are lost as part of this reset
  #if version >= 1.16.2
        #require net.minecraft.world.entity.EntityLiving private final NonNullList<ItemStack> handItems:bn;
        #require net.minecraft.world.entity.EntityLiving private final NonNullList<ItemStack> armorItems:bo;
  #else
        #require net.minecraft.world.entity.EntityLiving private final NonNullList<ItemStack> handItems:bu;
        #require net.minecraft.world.entity.EntityLiving private final NonNullList<ItemStack> armorItems:bv;
  #endif
        NonNullList handItems = instance#handItems;
        NonNullList armorItems = instance#armorItems;
        handItems.clear();
        armorItems.clear();
#else
        // Set attributeMapField to null and call getAttributeMap()
        // This will initialize the field (and possibly related CraftAttributeMap >= 1.11)
        #if version >= 1.11
            #require net.minecraft.world.entity.EntityLiving private AttributeMapBase attributeMapField:attributeMap;
        #elseif version >= 1.10.2
            #require net.minecraft.world.entity.EntityLiving private AttributeMapBase attributeMapField:br;
        #elseif version >= 1.9.4
            #require net.minecraft.world.entity.EntityLiving private AttributeMapBase attributeMapField:bq;
        #elseif version >= 1.9
            #require net.minecraft.world.entity.EntityLiving private AttributeMapBase attributeMapField:bp;
        #else
            #require net.minecraft.world.entity.EntityLiving private AttributeMapBase attributeMapField:c;
        #endif
        instance#attributeMapField = null;
        instance.getAttributeMap();

        // Then call initAttributes() to initialize the values used by the entity
        #if version >= 1.8.3
            #require net.minecraft.world.entity.EntityLiving protected void initAttributes();
        #else
            #require net.minecraft.world.entity.EntityLiving protected void initAttributes:aW();
        #endif
        instance#initAttributes();
#endif
    }

#if version >= 1.21.5
  #if exists net.minecraft.world.entity.EntityLiving public net.minecraft.world.entity.EntityEquipment equipment;
    #require EntityLiving public EntityEquipment equipment;
  #else
    // Paper yay!
    #require EntityLiving protected EntityEquipment equipment;
  #endif
#endif

    public void loadEquipment((CommonTagCompound) NBTTagCompound data) {
#if version >= 1.21.5
        EntityEquipment equipment = instance#equipment;

        RegistryOps registryops = instance.registryAccess().createSerializationContext(DynamicOpsNBT.INSTANCE);

        EntityEquipment loadedEquipment = (EntityEquipment) EntityEquipment.CODEC.parse(registryops, data)
                        .resultOrPartial(NBTTagCompoundHandle.createPartialErrorLogger(data))
                        .orElse(null);
        if (loadedEquipment == null) {
            loadedEquipment = new EntityEquipment();
        }

        equipment.setAll(loadedEquipment);
#endif
    }

    public (CommonTagCompound) NBTTagCompound saveEquipment() {
#if version >= 1.21.5
        EntityEquipment equipment = instance#equipment;

        if (equipment.isEmpty()) {
            return null;
        }

        RegistryOps registryops = instance.registryAccess().createSerializationContext(DynamicOpsNBT.INSTANCE);

        return (NBTTagCompound) EntityEquipment.CODEC.encode(equipment, registryops, new NBTTagCompound());
#else
        return null;
#endif
    }

#if version >= 1.18
    public (AttributeMapBaseHandle) AttributeMapBase getAttributeMap:getAttributes();
#else
    public (AttributeMapBaseHandle) AttributeMapBase getAttributeMap();
#endif

#if version >= 1.20.5
    public (AttributeModifiableHandle) AttributeModifiable getAttribute((Holder<AttributeBaseHandle>) net.minecraft.core.Holder<AttributeBase> attribute);
#elseif version >= 1.18
    public (AttributeModifiableHandle) AttributeModifiable getAttribute((Holder<AttributeBaseHandle>) AttributeBase attribute);
#elseif version >= 1.16
    public (AttributeModifiableHandle) AttributeModifiable getAttribute:getAttributeInstance((Holder<AttributeBaseHandle>) AttributeBase attribute);
#else
    public (AttributeModifiableHandle) AttributeModifiable getAttribute((Holder<AttributeBaseHandle>) IAttribute attribute) {
        return (AttributeModifiable) instance.getAttributeInstance(attribute);
    }
#endif

#if version >= 1.20.5
    public final (Map<Holder<MobEffectListHandle>, MobEffectHandle>) Map<net.minecraft.core.Holder<MobEffectList>, MobEffect> mobEffects:activeEffects;
#elseif version >= 1.17
    public final (Map<Holder<MobEffectListHandle>, MobEffectHandle>) Map<MobEffectList, MobEffect> mobEffects:activeEffects;
#elseif version >= 1.9
    public final (Map<Holder<MobEffectListHandle>, MobEffectHandle>) Map<MobEffectList, MobEffect> mobEffects:effects;
#else
    public final (Map<Holder<MobEffectListHandle>, MobEffectHandle>) Map<Integer, MobEffect> mobEffects:effects;
#endif

#if version >= 1.17
    public float lastDamage:lastHurt;
#else
    public float lastDamage;
#endif

    public (org.bukkit.util.Vector) Vec3D getMoveIntent() {
#if version >= 1.21.2
        if (instance instanceof net.minecraft.server.level.EntityPlayer) {
            return ((net.minecraft.server.level.EntityPlayer) instance).getLastClientMoveIntent();
        }
#endif

#if version >= 1.17
        #require EntityLiving public readonly float moveIntentX:xxa;
        #require EntityLiving public readonly float moveIntentY:yya;
        #require EntityLiving public readonly float moveIntentZ:yya;
#elseif version >= 1.16.2
        #require EntityLiving public readonly float moveIntentX:aR;
        #require EntityLiving public readonly float moveIntentY:aS;
        #require EntityLiving public readonly float moveIntentZ:aT;
#elseif version >= 1.16
        #require EntityLiving public readonly float moveIntentX:aY;
        #require EntityLiving public readonly float moveIntentY:aZ;
        #require EntityLiving public readonly float moveIntentZ:ba;
#elseif version >= 1.15
        #require EntityLiving public readonly float moveIntentX:aZ;
        #require EntityLiving public readonly float moveIntentY:ba;
        #require EntityLiving public readonly float moveIntentZ:bb;
#elseif version >= 1.14
        #require EntityLiving public readonly float moveIntentX:bb;
        #require EntityLiving public readonly float moveIntentY:bc;
        #require EntityLiving public readonly float moveIntentZ:bd;
#elseif version >= 1.13
        #require EntityLiving public readonly float moveIntentX:bh;
        #require EntityLiving public readonly float moveIntentY:bi;
        #require EntityLiving public readonly float moveIntentZ:bj;
#elseif version >= 1.12
        #require EntityLiving public readonly float moveIntentX:be;
        #require EntityLiving public readonly float moveIntentY:bf;
        #require EntityLiving public readonly float moveIntentZ:bg;
#elseif version >= 1.11
        #require EntityLiving public readonly float moveIntentX:be;
        #require EntityLiving public readonly float moveIntentZ:bf;
#elseif version >= 1.10.2
        #require EntityLiving public readonly float moveIntentX:bf;
        #require EntityLiving public readonly float moveIntentZ:bg;
#elseif version >= 1.9.4
        #require EntityLiving public readonly float moveIntentX:be;
        #require EntityLiving public readonly float moveIntentZ:bf;
#elseif version >= 1.9
        #require EntityLiving public readonly float moveIntentX:bd;
        #require EntityLiving public readonly float moveIntentZ:be;
#elseif version >= 1.8.3
        #require EntityLiving public readonly float moveIntentX:aZ;
        #require EntityLiving public readonly float moveIntentZ:ba;
#else
        #require EntityLiving public readonly float moveIntentX:aX;
        #require EntityLiving public readonly float moveIntentZ:aY;
#endif

        float x = instance#moveIntentX;
#if version >= 1.12
        float y = instance#moveIntentY;
#else
        float y = 0.0f;
#endif
        float z = instance#moveIntentZ;

        return new Vec3D((double) x, (double) y, (double) z);
    }

    <code>
    public float getSideMovement() {
        return (float) getMoveIntent().getX();
    }

    public float getForwardMovement() {
        return (float) getMoveIntent().getZ();
    }
    </code>

#if version >= 1.17
    public boolean updateEffects:effectsDirty;
#else
    public boolean updateEffects;
#endif

#if version >= 1.18
    public (Collection<MobEffectHandle>) Collection<MobEffect> getEffects:getActiveEffects();
#else
    public (Collection<MobEffectHandle>) Collection<MobEffect> getEffects();
#endif

#if version >= 1.18
    public abstract (org.bukkit.inventory.ItemStack) ItemStack getEquipment:getItemBySlot((org.bukkit.inventory.EquipmentSlot) EnumItemSlot paramEnumItemSlot);
#elseif version >= 1.9
    public abstract (org.bukkit.inventory.ItemStack) ItemStack getEquipment((org.bukkit.inventory.EquipmentSlot) EnumItemSlot paramEnumItemSlot);
#else
    public (org.bukkit.inventory.ItemStack) ItemStack getEquipment((org.bukkit.inventory.EquipmentSlot) EnumItemSlot paramEnumItemSlot) {
        if (instance instanceof EntityHuman) {
            if (paramEnumItemSlot == EnumItemSlot.MAINHAND) {
                // Technically not supported, we implement a workaround
                return ((EntityHuman) instance).inventory.getItemInHand();
            } else {
                return instance.getEquipment(paramEnumItemSlot.b());
            }
        } else {
            return instance.getEquipment(paramEnumItemSlot.c());
        }
    }
#endif

    public final float getHealth();

    public final float getMaxHealth();

#if version >= 1.18
    public float getAbsorptionAmount();
    public void setAbsorptionAmount(float extraHealth);
#else
    public float getAbsorptionAmount:getAbsorptionHearts();
    public void setAbsorptionAmount:setAbsorptionHearts(float extraHealth);
#endif

    <code>
    public static EntityLivingHandle fromBukkit(org.bukkit.entity.LivingEntity livingEntity) {
        return createHandle(com.bergerkiller.bukkit.common.conversion.type.HandleConversion.toEntityHandle(livingEntity));
    }
    </code>
}
