import net.minecraft.world.level.block.state.IBlockData;
import net.minecraft.core.BlockPosition;
import net.minecraft.world.level.block.Block;
import net.minecraft.sounds.SoundEffect;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.level.storage.ValueOutput;

#if version >= 1.17
    #remap net.minecraft.world.entity.Entity private int remainingFireTicks;
#else
    #remap net.minecraft.world.entity.Entity private int remainingFireTicks:fireTicks;
#endif

// Portal handling fields exist in Entity from MC 1.8 to 1.20.6
#if version < 1.21
  #select version >=
  #case 1.17:   #remap net.minecraft.world.entity.Entity protected boolean insidePortalThisTick:isInsidePortal;
  #case 1.16:   #remap net.minecraft.world.entity.Entity protected boolean insidePortalThisTick:inPortal;
  #case 1.15:   #remap net.minecraft.world.entity.Entity protected boolean insidePortalThisTick:af;
  #case 1.14:   #remap net.minecraft.world.entity.Entity protected boolean insidePortalThisTick:ai;
  #case 1.13:   #remap net.minecraft.world.entity.Entity protected boolean insidePortalThisTick:an;
  #case 1.11:   #remap net.minecraft.world.entity.Entity protected boolean insidePortalThisTick:ak;
  #case 1.10.2: #remap net.minecraft.world.entity.Entity protected boolean insidePortalThisTick:al;
  #case else:   #remap net.minecraft.world.entity.Entity protected boolean insidePortalThisTick:ak;
  #endselect

  #select version >=
  #case 1.17:   #remap net.minecraft.world.entity.Entity protected int portalTime;
  #case 1.16:   #remap net.minecraft.world.entity.Entity protected int portalTime:portalTicks;
  #case 1.15:   #remap net.minecraft.world.entity.Entity protected int portalTime:ag;
  #case 1.14:   #remap net.minecraft.world.entity.Entity protected int portalTime:aj;
  #case 1.13:   #remap net.minecraft.world.entity.Entity protected int portalTime:ao;
  #case 1.11:   #remap net.minecraft.world.entity.Entity protected int portalTime:al;
  #case 1.10.2: #remap net.minecraft.world.entity.Entity protected int portalTime:am;
  #case else:   #remap net.minecraft.world.entity.Entity protected int portalTime:al;
  #endselect

  #select version >=
  #case 1.18:   #remap net.minecraft.world.entity.Entity public int getPortalWaitTime();
  #case 1.17:   #remap net.minecraft.world.entity.Entity public int getPortalWaitTime:am();
  #case 1.16.4: #remap net.minecraft.world.entity.Entity public int getPortalWaitTime:aj();
  #case 1.16.2: #remap net.minecraft.world.entity.Entity public int getPortalWaitTime:ai();
  #case 1.16:   #remap net.minecraft.world.entity.Entity public int getPortalWaitTime:ae();
  #case 1.14:   #remap net.minecraft.world.entity.Entity public int getPortalWaitTime:ab();
  #case 1.13:   #remap net.minecraft.world.entity.Entity public int getPortalWaitTime:X();
  #case 1.12:   #remap net.minecraft.world.entity.Entity public int getPortalWaitTime:Z();
  #case 1.9:    #remap net.minecraft.world.entity.Entity public int getPortalWaitTime:V();
  #case else:   #remap net.minecraft.world.entity.Entity public int getPortalWaitTime:L();
  #endselect
#endif

#select version >=
#case 1.18:  #remap net.minecraft.world.entity.Entity protected SoundEffect getSwimSound();
#case 1.14:  #remap net.minecraft.world.entity.Entity protected SoundEffect getSwimSound:getSoundSwim();
#case 1.13:  #remap net.minecraft.world.entity.Entity protected SoundEffect getSwimSound:ad();
#case 1.12:  #remap net.minecraft.world.entity.Entity protected SoundEffect getSwimSound:ae();
#case 1.9:   #remap net.minecraft.world.entity.Entity protected SoundEffect getSwimSound:aa();
#case else:  #remap net.minecraft.world.entity.Entity protected String getSwimSound:P();
#endselect

#select version >=
#case 1.16:    #remap net.minecraft.world.entity.Entity public void playSound(SoundEffect soundeffect, float volume, float pitch);
#case 1.9:     #remap net.minecraft.world.entity.Entity public void playSound:a(SoundEffect soundeffect, float volume, float pitch);
#case else:    #remap net.minecraft.world.entity.Entity public void playSound:makeSound(String soundeffect, float volume, float pitch);
#endselect

#select version >=
#case 1.18:    #remap net.minecraft.world.entity.Entity protected void playStepSound(BlockPosition position, IBlockData blockData);
#case 1.16.2:  #remap net.minecraft.world.entity.Entity protected void playStepSound:b(BlockPosition position, IBlockData blockData);
#case 1.13:    #remap net.minecraft.world.entity.Entity protected void playStepSound:a(BlockPosition position, IBlockData blockData);
#case else:    #remap net.minecraft.world.entity.Entity protected void playStepSound:a(BlockPosition position, Block block);
#endselect

#select version >=
#case 1.19.4:  #remap net.minecraft.world.entity.Entity public net.minecraft.world.entity.EntityLiving getControllingPassenger();
#case 1.18:    #remap net.minecraft.world.entity.Entity public Entity getControllingPassenger();
#case 1.14:    #remap net.minecraft.world.entity.Entity public Entity getControllingPassenger:getRidingPassenger();
#case 1.13:    #remap net.minecraft.world.entity.Entity public Entity getControllingPassenger:bO();
#case 1.12:    #remap net.minecraft.world.entity.Entity public Entity getControllingPassenger:bE();
#case 1.10.2:  #remap net.minecraft.world.entity.Entity public Entity getControllingPassenger:bw();
#case 1.9.4:   #remap net.minecraft.world.entity.Entity public Entity getControllingPassenger:bu();
#case 1.9:     #remap net.minecraft.world.entity.Entity public Entity getControllingPassenger:bt();
// Does not exist before 1.9
#endselect

// Save functions
#select version >=
#case 1.21.6:  #remap net.minecraft.world.entity.Entity public boolean saveAsPassenger(ValueOutput valueOutput);
#case 1.18:    #remap net.minecraft.world.entity.Entity public boolean saveAsPassenger(NBTTagCompound nbttagcompound);
#case 1.17:    #remap net.minecraft.world.entity.Entity public boolean saveAsPassenger:d(NBTTagCompound nbttagcompound);
#case 1.16:    #remap net.minecraft.world.entity.Entity public boolean saveAsPassenger:a_(NBTTagCompound nbttagcompound);
#case else:    #remap net.minecraft.world.entity.Entity public boolean saveAsPassenger:c(NBTTagCompound nbttagcompound);
#endselect

#select version >=
#case 1.21.6:  #remap net.minecraft.world.entity.Entity public void saveWithoutId(ValueOutput valueOutput);
#case 1.18:    #remap net.minecraft.world.entity.Entity public NBTTagCompound saveWithoutId(NBTTagCompound nbttagcompound);
#case 1.12:    #remap net.minecraft.world.entity.Entity public NBTTagCompound saveWithoutId:save(NBTTagCompound nbttagcompound);
#case 1.9.4:   #remap net.minecraft.world.entity.Entity public NBTTagCompound saveWithoutId:e(NBTTagCompound nbttagcompound);
#case else:    #remap net.minecraft.world.entity.Entity public void saveWithoutId:e(NBTTagCompound nbttagcompound);
#endselect

// CraftBukkit added an includeAll option flag
// Paper also added some extra flags in later versions
// This is here to validate as part of tests these these functions exist, as they're important for the
// EntityHook logic.
#if version >= 1.21.6 && paper
    #remap net.minecraft.world.entity.Entity public boolean saveAsPassenger(ValueOutput valueOutput, boolean includeAll, boolean includeNonSaveable, boolean forceSerialization);
    #remap net.minecraft.world.entity.Entity public void saveWithoutId(ValueOutput valueOutput, boolean includeAll, boolean includeNonSaveable, boolean forceSerialization);
#elseif version >= 1.21.6
    #remap net.minecraft.world.entity.Entity public boolean saveAsPassenger(ValueOutput valueOutput, boolean includeAll);
    #remap net.minecraft.world.entity.Entity public void saveWithoutId(ValueOutput valueOutput, boolean includeAll);
#elseif version >= 1.21.4 && paper
    #remap net.minecraft.world.entity.Entity public boolean saveAsPassenger(NBTTagCompound nbttagcompound, boolean includeAll, boolean includeNonSaveable, boolean forceSerialization);
    #remap net.minecraft.world.entity.Entity public NBTTagCompound saveWithoutId(NBTTagCompound nbttagcompound, boolean includeAll, boolean includeNonSaveable, boolean forceSerialization);
#elseif version >= 1.20.3
    #remap net.minecraft.world.entity.Entity public boolean saveAsPassenger(NBTTagCompound nbttagcompound, boolean includeAll);
    #remap net.minecraft.world.entity.Entity public NBTTagCompound saveWithoutId(NBTTagCompound nbttagcompound, boolean includeAll);
#endif

// This function is a nightmare, especially on forge...
#if version >= 1.18
    #remap net.minecraft.world.entity.Entity public boolean isOnFire();
#else
    #remap net.minecraft.world.entity.Entity public boolean isOnFire:isBurning();
#endif

#select version >=
#case 1.18:  #remap net.minecraft.world.entity.Entity public int getFireImmuneTicks();
#case 1.11:  #remap net.minecraft.world.entity.Entity public int getFireImmuneTicks:getMaxFireTicks();
#case 1.9:   #remap net.minecraft.world.entity.Entity public int getFireImmuneTicks:V();
#case else:  #remap net.minecraft.world.entity.Entity public int getFireImmuneTicks:L();
#endselect

#if version >= 1.21
    #remap net.minecraft.world.entity.Entity public final void igniteForSeconds(float seconds);
  #if forge && exists net.minecraft.world.entity.Entity public void setSecondsOnFire(float seconds, boolean callEvent);
    #remap net.minecraft.world.entity.Entity public final void igniteForSeconds:setSecondsOnFire(float seconds, boolean callEvent);
  #else
    #remap net.minecraft.world.entity.Entity public final void igniteForSeconds(float seconds, boolean callEvent);
  #endif
#elseif version >= 1.20.5
    #remap net.minecraft.world.entity.Entity public final void igniteForSeconds(int seconds);
  #if forge && exists net.minecraft.world.entity.Entity public void setSecondsOnFire(int seconds, boolean callEvent);
    #remap net.minecraft.world.entity.Entity public final void igniteForSeconds:setSecondsOnFire(int seconds, boolean callEvent);
  #else
    #remap net.minecraft.world.entity.Entity public final void igniteForSeconds(int seconds, boolean callEvent);
  #endif
#elseif version >= 1.18
    #remap net.minecraft.world.entity.Entity public void igniteForSeconds:setSecondsOnFire(int seconds);
    #remap net.minecraft.world.entity.Entity public void igniteForSeconds:setSecondsOnFire(int seconds, boolean callEvent);
#elseif version >= 1.13.2
    #remap net.minecraft.world.entity.Entity public void igniteForSeconds:setOnFire(int seconds);
    #remap net.minecraft.world.entity.Entity public void igniteForSeconds:setOnFire(int seconds, boolean callEvent);
#else
    #remap net.minecraft.world.entity.Entity public void igniteForSeconds:setOnFire(int seconds);
#endif
