base mod created

This commit is contained in:
Mohammad-Ali Minaie
2018-10-08 09:07:47 -04:00
parent 0a7700c356
commit b86dedad2f
7848 changed files with 584664 additions and 1 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,291 @@
package net.minecraft.entity;
import javax.annotation.Nullable;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Items;
import net.minecraft.item.ItemMonsterPlacer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.datasync.DataParameter;
import net.minecraft.network.datasync.DataSerializers;
import net.minecraft.network.datasync.EntityDataManager;
import net.minecraft.util.EnumHand;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.world.World;
public abstract class EntityAgeable extends EntityCreature
{
private static final DataParameter<Boolean> BABY = EntityDataManager.<Boolean>createKey(EntityAgeable.class, DataSerializers.BOOLEAN);
protected int growingAge;
protected int forcedAge;
protected int forcedAgeTimer;
private float ageWidth = -1.0F;
private float ageHeight;
public EntityAgeable(World worldIn)
{
super(worldIn);
}
@Nullable
public abstract EntityAgeable createChild(EntityAgeable ageable);
public boolean processInteract(EntityPlayer player, EnumHand hand)
{
ItemStack itemstack = player.getHeldItem(hand);
if (itemstack.getItem() == Items.SPAWN_EGG)
{
if (!this.world.isRemote)
{
Class <? extends Entity > oclass = EntityList.getClass(ItemMonsterPlacer.getNamedIdFrom(itemstack));
if (oclass != null && this.getClass() == oclass)
{
EntityAgeable entityageable = this.createChild(this);
if (entityageable != null)
{
entityageable.setGrowingAge(-24000);
entityageable.setLocationAndAngles(this.posX, this.posY, this.posZ, 0.0F, 0.0F);
this.world.spawnEntity(entityageable);
if (itemstack.hasDisplayName())
{
entityageable.setCustomNameTag(itemstack.getDisplayName());
}
if (!player.capabilities.isCreativeMode)
{
itemstack.shrink(1);
}
}
}
}
return true;
}
else
{
return false;
}
}
/**
* Checks if the given item is a spawn egg that spawns the given class of entity.
*/
protected boolean holdingSpawnEggOfClass(ItemStack stack, Class <? extends Entity > entityClass)
{
if (stack.getItem() != Items.SPAWN_EGG)
{
return false;
}
else
{
Class <? extends Entity > oclass = EntityList.getClass(ItemMonsterPlacer.getNamedIdFrom(stack));
return oclass != null && entityClass == oclass;
}
}
protected void entityInit()
{
super.entityInit();
this.dataManager.register(BABY, Boolean.valueOf(false));
}
/**
* The age value may be negative or positive or zero. If it's negative, it get's incremented on each tick, if it's
* positive, it get's decremented each tick. Don't confuse this with EntityLiving.getAge. With a negative value the
* Entity is considered a child.
*/
public int getGrowingAge()
{
if (this.world.isRemote)
{
return ((Boolean)this.dataManager.get(BABY)).booleanValue() ? -1 : 1;
}
else
{
return this.growingAge;
}
}
/**
* Increases this entity's age, optionally updating {@link #forcedAge}. If the entity is an adult (if the entity's
* age is greater than or equal to 0) then the entity's age will be set to {@link #forcedAge}.
*
* @param growthSeconds Number of seconds to grow this entity by. The entity's age will be increased by 20 times
* this number (i.e. this number converted to ticks).
* @param updateForcedAge If true, updates {@link #forcedAge} and {@link #forcedAgeTimer}
*/
public void ageUp(int growthSeconds, boolean updateForcedAge)
{
int i = this.getGrowingAge();
int j = i;
i = i + growthSeconds * 20;
if (i > 0)
{
i = 0;
if (j < 0)
{
this.onGrowingAdult();
}
}
int k = i - j;
this.setGrowingAge(i);
if (updateForcedAge)
{
this.forcedAge += k;
if (this.forcedAgeTimer == 0)
{
this.forcedAgeTimer = 40;
}
}
if (this.getGrowingAge() == 0)
{
this.setGrowingAge(this.forcedAge);
}
}
/**
* Increases this entity's age. If the entity is an adult (if the entity's age is greater than or equal to 0) then
* the entity's age will be set to {@link #forcedAge}. This method does not update {@link #forcedAge}.
*/
public void addGrowth(int growth)
{
this.ageUp(growth, false);
}
/**
* The age value may be negative or positive or zero. If it's negative, it get's incremented on each tick, if it's
* positive, it get's decremented each tick. With a negative value the Entity is considered a child.
*/
public void setGrowingAge(int age)
{
this.dataManager.set(BABY, Boolean.valueOf(age < 0));
this.growingAge = age;
this.setScaleForAge(this.isChild());
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound compound)
{
super.writeEntityToNBT(compound);
compound.setInteger("Age", this.getGrowingAge());
compound.setInteger("ForcedAge", this.forcedAge);
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound compound)
{
super.readEntityFromNBT(compound);
this.setGrowingAge(compound.getInteger("Age"));
this.forcedAge = compound.getInteger("ForcedAge");
}
public void notifyDataManagerChange(DataParameter<?> key)
{
if (BABY.equals(key))
{
this.setScaleForAge(this.isChild());
}
super.notifyDataManagerChange(key);
}
/**
* Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons
* use this to react to sunlight and start to burn.
*/
public void onLivingUpdate()
{
super.onLivingUpdate();
if (this.world.isRemote)
{
if (this.forcedAgeTimer > 0)
{
if (this.forcedAgeTimer % 4 == 0)
{
this.world.spawnParticle(EnumParticleTypes.VILLAGER_HAPPY, this.posX + (double)(this.rand.nextFloat() * this.width * 2.0F) - (double)this.width, this.posY + 0.5D + (double)(this.rand.nextFloat() * this.height), this.posZ + (double)(this.rand.nextFloat() * this.width * 2.0F) - (double)this.width, 0.0D, 0.0D, 0.0D);
}
--this.forcedAgeTimer;
}
}
else
{
int i = this.getGrowingAge();
if (i < 0)
{
++i;
this.setGrowingAge(i);
if (i == 0)
{
this.onGrowingAdult();
}
}
else if (i > 0)
{
--i;
this.setGrowingAge(i);
}
}
}
/**
* This is called when Entity's growing age timer reaches 0 (negative values are considered as a child, positive as
* an adult)
*/
protected void onGrowingAdult()
{
}
/**
* If Animal, checks if the age timer is negative
*/
public boolean isChild()
{
return this.getGrowingAge() < 0;
}
/**
* "Sets the scale for an ageable entity according to the boolean parameter, which says if it's a child."
*/
public void setScaleForAge(boolean child)
{
this.setScale(child ? 0.5F : 1.0F);
}
/**
* Sets the width and height of the entity.
*/
protected final void setSize(float width, float height)
{
boolean flag = this.ageWidth > 0.0F;
this.ageWidth = width;
this.ageHeight = height;
if (!flag)
{
this.setScale(1.0F);
}
}
protected final void setScale(float scale)
{
super.setSize(this.ageWidth * scale, this.ageHeight * scale);
}
}

View File

@@ -0,0 +1,544 @@
package net.minecraft.entity;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.Map.Entry;
import javax.annotation.Nullable;
import net.minecraft.block.material.EnumPushReaction;
import net.minecraft.init.PotionTypes;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.network.datasync.DataParameter;
import net.minecraft.network.datasync.DataSerializers;
import net.minecraft.network.datasync.EntityDataManager;
import net.minecraft.potion.PotionEffect;
import net.minecraft.potion.PotionType;
import net.minecraft.potion.PotionUtils;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
public class EntityAreaEffectCloud extends Entity
{
private static final DataParameter<Float> RADIUS = EntityDataManager.<Float>createKey(EntityAreaEffectCloud.class, DataSerializers.FLOAT);
private static final DataParameter<Integer> COLOR = EntityDataManager.<Integer>createKey(EntityAreaEffectCloud.class, DataSerializers.VARINT);
private static final DataParameter<Boolean> IGNORE_RADIUS = EntityDataManager.<Boolean>createKey(EntityAreaEffectCloud.class, DataSerializers.BOOLEAN);
private static final DataParameter<Integer> PARTICLE = EntityDataManager.<Integer>createKey(EntityAreaEffectCloud.class, DataSerializers.VARINT);
private static final DataParameter<Integer> PARTICLE_PARAM_1 = EntityDataManager.<Integer>createKey(EntityAreaEffectCloud.class, DataSerializers.VARINT);
private static final DataParameter<Integer> PARTICLE_PARAM_2 = EntityDataManager.<Integer>createKey(EntityAreaEffectCloud.class, DataSerializers.VARINT);
private PotionType potion;
private final List<PotionEffect> effects;
private final Map<Entity, Integer> reapplicationDelayMap;
private int duration;
private int waitTime;
private int reapplicationDelay;
private boolean colorSet;
private int durationOnUse;
private float radiusOnUse;
private float radiusPerTick;
private EntityLivingBase owner;
private UUID ownerUniqueId;
public EntityAreaEffectCloud(World worldIn)
{
super(worldIn);
this.potion = PotionTypes.EMPTY;
this.effects = Lists.<PotionEffect>newArrayList();
this.reapplicationDelayMap = Maps.<Entity, Integer>newHashMap();
this.duration = 600;
this.waitTime = 20;
this.reapplicationDelay = 20;
this.noClip = true;
this.isImmuneToFire = true;
this.setRadius(3.0F);
}
public EntityAreaEffectCloud(World worldIn, double x, double y, double z)
{
this(worldIn);
this.setPosition(x, y, z);
}
protected void entityInit()
{
this.getDataManager().register(COLOR, Integer.valueOf(0));
this.getDataManager().register(RADIUS, Float.valueOf(0.5F));
this.getDataManager().register(IGNORE_RADIUS, Boolean.valueOf(false));
this.getDataManager().register(PARTICLE, Integer.valueOf(EnumParticleTypes.SPELL_MOB.getParticleID()));
this.getDataManager().register(PARTICLE_PARAM_1, Integer.valueOf(0));
this.getDataManager().register(PARTICLE_PARAM_2, Integer.valueOf(0));
}
public void setRadius(float radiusIn)
{
double d0 = this.posX;
double d1 = this.posY;
double d2 = this.posZ;
this.setSize(radiusIn * 2.0F, 0.5F);
this.setPosition(d0, d1, d2);
if (!this.world.isRemote)
{
this.getDataManager().set(RADIUS, Float.valueOf(radiusIn));
}
}
public float getRadius()
{
return ((Float)this.getDataManager().get(RADIUS)).floatValue();
}
public void setPotion(PotionType potionIn)
{
this.potion = potionIn;
if (!this.colorSet)
{
this.updateFixedColor();
}
}
private void updateFixedColor()
{
if (this.potion == PotionTypes.EMPTY && this.effects.isEmpty())
{
this.getDataManager().set(COLOR, Integer.valueOf(0));
}
else
{
this.getDataManager().set(COLOR, Integer.valueOf(PotionUtils.getPotionColorFromEffectList(PotionUtils.mergeEffects(this.potion, this.effects))));
}
}
public void addEffect(PotionEffect effect)
{
this.effects.add(effect);
if (!this.colorSet)
{
this.updateFixedColor();
}
}
public int getColor()
{
return ((Integer)this.getDataManager().get(COLOR)).intValue();
}
public void setColor(int colorIn)
{
this.colorSet = true;
this.getDataManager().set(COLOR, Integer.valueOf(colorIn));
}
public EnumParticleTypes getParticle()
{
return EnumParticleTypes.getParticleFromId(((Integer)this.getDataManager().get(PARTICLE)).intValue());
}
public void setParticle(EnumParticleTypes particleIn)
{
this.getDataManager().set(PARTICLE, Integer.valueOf(particleIn.getParticleID()));
}
public int getParticleParam1()
{
return ((Integer)this.getDataManager().get(PARTICLE_PARAM_1)).intValue();
}
public void setParticleParam1(int particleParam)
{
this.getDataManager().set(PARTICLE_PARAM_1, Integer.valueOf(particleParam));
}
public int getParticleParam2()
{
return ((Integer)this.getDataManager().get(PARTICLE_PARAM_2)).intValue();
}
public void setParticleParam2(int particleParam)
{
this.getDataManager().set(PARTICLE_PARAM_2, Integer.valueOf(particleParam));
}
/**
* Sets if the radius should be ignored, and the effect should be shown in a single point instead of an area
*/
protected void setIgnoreRadius(boolean ignoreRadius)
{
this.getDataManager().set(IGNORE_RADIUS, Boolean.valueOf(ignoreRadius));
}
/**
* Returns true if the radius should be ignored, and the effect should be shown in a single point instead of an area
*/
public boolean shouldIgnoreRadius()
{
return ((Boolean)this.getDataManager().get(IGNORE_RADIUS)).booleanValue();
}
public int getDuration()
{
return this.duration;
}
public void setDuration(int durationIn)
{
this.duration = durationIn;
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
super.onUpdate();
boolean flag = this.shouldIgnoreRadius();
float f = this.getRadius();
if (this.world.isRemote)
{
EnumParticleTypes enumparticletypes = this.getParticle();
int[] aint = new int[enumparticletypes.getArgumentCount()];
if (aint.length > 0)
{
aint[0] = this.getParticleParam1();
}
if (aint.length > 1)
{
aint[1] = this.getParticleParam2();
}
if (flag)
{
if (this.rand.nextBoolean())
{
for (int i = 0; i < 2; ++i)
{
float f1 = this.rand.nextFloat() * ((float)Math.PI * 2F);
float f2 = MathHelper.sqrt(this.rand.nextFloat()) * 0.2F;
float f3 = MathHelper.cos(f1) * f2;
float f4 = MathHelper.sin(f1) * f2;
if (enumparticletypes == EnumParticleTypes.SPELL_MOB)
{
int j = this.rand.nextBoolean() ? 16777215 : this.getColor();
int k = j >> 16 & 255;
int l = j >> 8 & 255;
int i1 = j & 255;
this.world.spawnAlwaysVisibleParticle(EnumParticleTypes.SPELL_MOB.getParticleID(), this.posX + (double)f3, this.posY, this.posZ + (double)f4, (double)((float)k / 255.0F), (double)((float)l / 255.0F), (double)((float)i1 / 255.0F));
}
else
{
this.world.spawnAlwaysVisibleParticle(enumparticletypes.getParticleID(), this.posX + (double)f3, this.posY, this.posZ + (double)f4, 0.0D, 0.0D, 0.0D, aint);
}
}
}
}
else
{
float f5 = (float)Math.PI * f * f;
for (int k1 = 0; (float)k1 < f5; ++k1)
{
float f6 = this.rand.nextFloat() * ((float)Math.PI * 2F);
float f7 = MathHelper.sqrt(this.rand.nextFloat()) * f;
float f8 = MathHelper.cos(f6) * f7;
float f9 = MathHelper.sin(f6) * f7;
if (enumparticletypes == EnumParticleTypes.SPELL_MOB)
{
int l1 = this.getColor();
int i2 = l1 >> 16 & 255;
int j2 = l1 >> 8 & 255;
int j1 = l1 & 255;
this.world.spawnAlwaysVisibleParticle(EnumParticleTypes.SPELL_MOB.getParticleID(), this.posX + (double)f8, this.posY, this.posZ + (double)f9, (double)((float)i2 / 255.0F), (double)((float)j2 / 255.0F), (double)((float)j1 / 255.0F));
}
else
{
this.world.spawnAlwaysVisibleParticle(enumparticletypes.getParticleID(), this.posX + (double)f8, this.posY, this.posZ + (double)f9, (0.5D - this.rand.nextDouble()) * 0.15D, 0.009999999776482582D, (0.5D - this.rand.nextDouble()) * 0.15D, aint);
}
}
}
}
else
{
if (this.ticksExisted >= this.waitTime + this.duration)
{
this.setDead();
return;
}
boolean flag1 = this.ticksExisted < this.waitTime;
if (flag != flag1)
{
this.setIgnoreRadius(flag1);
}
if (flag1)
{
return;
}
if (this.radiusPerTick != 0.0F)
{
f += this.radiusPerTick;
if (f < 0.5F)
{
this.setDead();
return;
}
this.setRadius(f);
}
if (this.ticksExisted % 5 == 0)
{
Iterator<Entry<Entity, Integer>> iterator = this.reapplicationDelayMap.entrySet().iterator();
while (iterator.hasNext())
{
Entry<Entity, Integer> entry = (Entry)iterator.next();
if (this.ticksExisted >= ((Integer)entry.getValue()).intValue())
{
iterator.remove();
}
}
List<PotionEffect> potions = Lists.<PotionEffect>newArrayList();
for (PotionEffect potioneffect1 : this.potion.getEffects())
{
potions.add(new PotionEffect(potioneffect1.getPotion(), potioneffect1.getDuration() / 4, potioneffect1.getAmplifier(), potioneffect1.getIsAmbient(), potioneffect1.doesShowParticles()));
}
potions.addAll(this.effects);
if (potions.isEmpty())
{
this.reapplicationDelayMap.clear();
}
else
{
List<EntityLivingBase> list = this.world.<EntityLivingBase>getEntitiesWithinAABB(EntityLivingBase.class, this.getEntityBoundingBox());
if (!list.isEmpty())
{
for (EntityLivingBase entitylivingbase : list)
{
if (!this.reapplicationDelayMap.containsKey(entitylivingbase) && entitylivingbase.canBeHitWithPotion())
{
double d0 = entitylivingbase.posX - this.posX;
double d1 = entitylivingbase.posZ - this.posZ;
double d2 = d0 * d0 + d1 * d1;
if (d2 <= (double)(f * f))
{
this.reapplicationDelayMap.put(entitylivingbase, Integer.valueOf(this.ticksExisted + this.reapplicationDelay));
for (PotionEffect potioneffect : potions)
{
if (potioneffect.getPotion().isInstant())
{
potioneffect.getPotion().affectEntity(this, this.getOwner(), entitylivingbase, potioneffect.getAmplifier(), 0.5D);
}
else
{
entitylivingbase.addPotionEffect(new PotionEffect(potioneffect));
}
}
if (this.radiusOnUse != 0.0F)
{
f += this.radiusOnUse;
if (f < 0.5F)
{
this.setDead();
return;
}
this.setRadius(f);
}
if (this.durationOnUse != 0)
{
this.duration += this.durationOnUse;
if (this.duration <= 0)
{
this.setDead();
return;
}
}
}
}
}
}
}
}
}
}
public void setRadiusOnUse(float radiusOnUseIn)
{
this.radiusOnUse = radiusOnUseIn;
}
public void setRadiusPerTick(float radiusPerTickIn)
{
this.radiusPerTick = radiusPerTickIn;
}
public void setWaitTime(int waitTimeIn)
{
this.waitTime = waitTimeIn;
}
public void setOwner(@Nullable EntityLivingBase ownerIn)
{
this.owner = ownerIn;
this.ownerUniqueId = ownerIn == null ? null : ownerIn.getUniqueID();
}
@Nullable
public EntityLivingBase getOwner()
{
if (this.owner == null && this.ownerUniqueId != null && this.world instanceof WorldServer)
{
Entity entity = ((WorldServer)this.world).getEntityFromUuid(this.ownerUniqueId);
if (entity instanceof EntityLivingBase)
{
this.owner = (EntityLivingBase)entity;
}
}
return this.owner;
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
protected void readEntityFromNBT(NBTTagCompound compound)
{
this.ticksExisted = compound.getInteger("Age");
this.duration = compound.getInteger("Duration");
this.waitTime = compound.getInteger("WaitTime");
this.reapplicationDelay = compound.getInteger("ReapplicationDelay");
this.durationOnUse = compound.getInteger("DurationOnUse");
this.radiusOnUse = compound.getFloat("RadiusOnUse");
this.radiusPerTick = compound.getFloat("RadiusPerTick");
this.setRadius(compound.getFloat("Radius"));
this.ownerUniqueId = compound.getUniqueId("OwnerUUID");
if (compound.hasKey("Particle", 8))
{
EnumParticleTypes enumparticletypes = EnumParticleTypes.getByName(compound.getString("Particle"));
if (enumparticletypes != null)
{
this.setParticle(enumparticletypes);
this.setParticleParam1(compound.getInteger("ParticleParam1"));
this.setParticleParam2(compound.getInteger("ParticleParam2"));
}
}
if (compound.hasKey("Color", 99))
{
this.setColor(compound.getInteger("Color"));
}
if (compound.hasKey("Potion", 8))
{
this.setPotion(PotionUtils.getPotionTypeFromNBT(compound));
}
if (compound.hasKey("Effects", 9))
{
NBTTagList nbttaglist = compound.getTagList("Effects", 10);
this.effects.clear();
for (int i = 0; i < nbttaglist.tagCount(); ++i)
{
PotionEffect potioneffect = PotionEffect.readCustomPotionEffectFromNBT(nbttaglist.getCompoundTagAt(i));
if (potioneffect != null)
{
this.addEffect(potioneffect);
}
}
}
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
protected void writeEntityToNBT(NBTTagCompound compound)
{
compound.setInteger("Age", this.ticksExisted);
compound.setInteger("Duration", this.duration);
compound.setInteger("WaitTime", this.waitTime);
compound.setInteger("ReapplicationDelay", this.reapplicationDelay);
compound.setInteger("DurationOnUse", this.durationOnUse);
compound.setFloat("RadiusOnUse", this.radiusOnUse);
compound.setFloat("RadiusPerTick", this.radiusPerTick);
compound.setFloat("Radius", this.getRadius());
compound.setString("Particle", this.getParticle().getParticleName());
compound.setInteger("ParticleParam1", this.getParticleParam1());
compound.setInteger("ParticleParam2", this.getParticleParam2());
if (this.ownerUniqueId != null)
{
compound.setUniqueId("OwnerUUID", this.ownerUniqueId);
}
if (this.colorSet)
{
compound.setInteger("Color", this.getColor());
}
if (this.potion != PotionTypes.EMPTY && this.potion != null)
{
compound.setString("Potion", ((ResourceLocation)PotionType.REGISTRY.getNameForObject(this.potion)).toString());
}
if (!this.effects.isEmpty())
{
NBTTagList nbttaglist = new NBTTagList();
for (PotionEffect potioneffect : this.effects)
{
nbttaglist.appendTag(potioneffect.writeCustomPotionEffectToNBT(new NBTTagCompound()));
}
compound.setTag("Effects", nbttaglist);
}
}
public void notifyDataManagerChange(DataParameter<?> key)
{
if (RADIUS.equals(key))
{
this.setRadius(this.getRadius());
}
super.notifyDataManagerChange(key);
}
public EnumPushReaction getPushReaction()
{
return EnumPushReaction.IGNORE;
}
}

View File

@@ -0,0 +1,80 @@
package net.minecraft.entity;
import net.minecraft.util.math.MathHelper;
public class EntityBodyHelper
{
/** Instance of EntityLiving. */
private final EntityLivingBase living;
/** Used to progressively ajust the rotation of the body to the rotation of the head */
private int rotationTickCounter;
private float prevRenderYawHead;
public EntityBodyHelper(EntityLivingBase livingIn)
{
this.living = livingIn;
}
/**
* Update the Head and Body rendenring angles
*/
public void updateRenderAngles()
{
double d0 = this.living.posX - this.living.prevPosX;
double d1 = this.living.posZ - this.living.prevPosZ;
if (d0 * d0 + d1 * d1 > 2.500000277905201E-7D)
{
this.living.renderYawOffset = this.living.rotationYaw;
this.living.rotationYawHead = this.computeAngleWithBound(this.living.renderYawOffset, this.living.rotationYawHead, 75.0F);
this.prevRenderYawHead = this.living.rotationYawHead;
this.rotationTickCounter = 0;
}
else
{
if (this.living.getPassengers().isEmpty() || !(this.living.getPassengers().get(0) instanceof EntityLiving))
{
float f = 75.0F;
if (Math.abs(this.living.rotationYawHead - this.prevRenderYawHead) > 15.0F)
{
this.rotationTickCounter = 0;
this.prevRenderYawHead = this.living.rotationYawHead;
}
else
{
++this.rotationTickCounter;
int i = 10;
if (this.rotationTickCounter > 10)
{
f = Math.max(1.0F - (float)(this.rotationTickCounter - 10) / 10.0F, 0.0F) * 75.0F;
}
}
this.living.renderYawOffset = this.computeAngleWithBound(this.living.rotationYawHead, this.living.renderYawOffset, f);
}
}
}
/**
* Return the new angle2 such that the difference between angle1 and angle2 is lower than angleMax. Args : angle1,
* angle2, angleMax
*/
private float computeAngleWithBound(float p_75665_1_, float p_75665_2_, float p_75665_3_)
{
float f = MathHelper.wrapDegrees(p_75665_1_ - p_75665_2_);
if (f < -p_75665_3_)
{
f = -p_75665_3_;
}
if (f >= p_75665_3_)
{
f = p_75665_3_;
}
return p_75665_1_ - f;
}
}

View File

@@ -0,0 +1,152 @@
package net.minecraft.entity;
import java.util.UUID;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.entity.passive.EntityTameable;
import net.minecraft.pathfinding.PathNodeType;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public abstract class EntityCreature extends EntityLiving
{
public static final UUID FLEEING_SPEED_MODIFIER_UUID = UUID.fromString("E199AD21-BA8A-4C53-8D13-6182D5C69D3A");
public static final AttributeModifier FLEEING_SPEED_MODIFIER = (new AttributeModifier(FLEEING_SPEED_MODIFIER_UUID, "Fleeing speed bonus", 2.0D, 2)).setSaved(false);
private BlockPos homePosition = BlockPos.ORIGIN;
/** If -1 there is no maximum distance */
private float maximumHomeDistance = -1.0F;
private final float restoreWaterCost = PathNodeType.WATER.getPriority();
public EntityCreature(World worldIn)
{
super(worldIn);
}
public float getBlockPathWeight(BlockPos pos)
{
return 0.0F;
}
/**
* Checks if the entity's current position is a valid location to spawn this entity.
*/
public boolean getCanSpawnHere()
{
return super.getCanSpawnHere() && this.getBlockPathWeight(new BlockPos(this.posX, this.getEntityBoundingBox().minY, this.posZ)) >= 0.0F;
}
/**
* if the entity got a PathEntity it returns true, else false
*/
public boolean hasPath()
{
return !this.navigator.noPath();
}
public boolean isWithinHomeDistanceCurrentPosition()
{
return this.isWithinHomeDistanceFromPosition(new BlockPos(this));
}
public boolean isWithinHomeDistanceFromPosition(BlockPos pos)
{
if (this.maximumHomeDistance == -1.0F)
{
return true;
}
else
{
return this.homePosition.distanceSq(pos) < (double)(this.maximumHomeDistance * this.maximumHomeDistance);
}
}
/**
* Sets home position and max distance for it
*/
public void setHomePosAndDistance(BlockPos pos, int distance)
{
this.homePosition = pos;
this.maximumHomeDistance = (float)distance;
}
public BlockPos getHomePosition()
{
return this.homePosition;
}
public float getMaximumHomeDistance()
{
return this.maximumHomeDistance;
}
public void detachHome()
{
this.maximumHomeDistance = -1.0F;
}
/**
* Returns whether a home area is defined for this entity.
*/
public boolean hasHome()
{
return this.maximumHomeDistance != -1.0F;
}
/**
* Applies logic related to leashes, for example dragging the entity or breaking the leash.
*/
protected void updateLeashedState()
{
super.updateLeashedState();
if (this.getLeashed() && this.getLeashHolder() != null && this.getLeashHolder().world == this.world)
{
Entity entity = this.getLeashHolder();
this.setHomePosAndDistance(new BlockPos((int)entity.posX, (int)entity.posY, (int)entity.posZ), 5);
float f = this.getDistance(entity);
if (this instanceof EntityTameable && ((EntityTameable)this).isSitting())
{
if (f > 10.0F)
{
this.clearLeashed(true, true);
}
return;
}
this.onLeashDistance(f);
if (f > 10.0F)
{
this.clearLeashed(true, true);
this.tasks.disableControlFlag(1);
}
else if (f > 6.0F)
{
double d0 = (entity.posX - this.posX) / (double)f;
double d1 = (entity.posY - this.posY) / (double)f;
double d2 = (entity.posZ - this.posZ) / (double)f;
this.motionX += d0 * Math.abs(d0) * 0.4D;
this.motionY += d1 * Math.abs(d1) * 0.4D;
this.motionZ += d2 * Math.abs(d2) * 0.4D;
}
else
{
this.tasks.enableControlFlag(1);
float f1 = 2.0F;
Vec3d vec3d = (new Vec3d(entity.posX - this.posX, entity.posY - this.posY, entity.posZ - this.posZ)).normalize().scale((double)Math.max(f - 2.0F, 0.0F));
this.getNavigator().tryMoveToXYZ(this.posX + vec3d.x, this.posY + vec3d.y, this.posZ + vec3d.z, this.followLeashSpeed());
}
}
}
protected double followLeashSpeed()
{
return 1.0D;
}
protected void onLeashDistance(float p_142017_1_)
{
}
}

View File

@@ -0,0 +1,91 @@
package net.minecraft.entity;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
public abstract class EntityFlying extends EntityLiving
{
public EntityFlying(World worldIn)
{
super(worldIn);
}
public void fall(float distance, float damageMultiplier)
{
}
protected void updateFallState(double y, boolean onGroundIn, IBlockState state, BlockPos pos)
{
}
public void travel(float strafe, float vertical, float forward)
{
if (this.isInWater())
{
this.moveRelative(strafe, vertical, forward, 0.02F);
this.move(MoverType.SELF, this.motionX, this.motionY, this.motionZ);
this.motionX *= 0.800000011920929D;
this.motionY *= 0.800000011920929D;
this.motionZ *= 0.800000011920929D;
}
else if (this.isInLava())
{
this.moveRelative(strafe, vertical, forward, 0.02F);
this.move(MoverType.SELF, this.motionX, this.motionY, this.motionZ);
this.motionX *= 0.5D;
this.motionY *= 0.5D;
this.motionZ *= 0.5D;
}
else
{
float f = 0.91F;
if (this.onGround)
{
BlockPos underPos = new BlockPos(MathHelper.floor(this.posX), MathHelper.floor(this.getEntityBoundingBox().minY) - 1, MathHelper.floor(this.posZ));
IBlockState underState = this.world.getBlockState(underPos);
f = underState.getBlock().getSlipperiness(underState, this.world, underPos, this) * 0.91F;
}
float f1 = 0.16277136F / (f * f * f);
this.moveRelative(strafe, vertical, forward, this.onGround ? 0.1F * f1 : 0.02F);
f = 0.91F;
if (this.onGround)
{
BlockPos underPos = new BlockPos(MathHelper.floor(this.posX), MathHelper.floor(this.getEntityBoundingBox().minY) - 1, MathHelper.floor(this.posZ));
IBlockState underState = this.world.getBlockState(underPos);
f = underState.getBlock().getSlipperiness(underState, this.world, underPos, this) * 0.91F;
}
this.move(MoverType.SELF, this.motionX, this.motionY, this.motionZ);
this.motionX *= (double)f;
this.motionY *= (double)f;
this.motionZ *= (double)f;
}
this.prevLimbSwingAmount = this.limbSwingAmount;
double d1 = this.posX - this.prevPosX;
double d0 = this.posZ - this.prevPosZ;
float f2 = MathHelper.sqrt(d1 * d1 + d0 * d0) * 4.0F;
if (f2 > 1.0F)
{
f2 = 1.0F;
}
this.limbSwingAmount += (f2 - this.limbSwingAmount) * 0.4F;
this.limbSwing += this.limbSwingAmount;
}
/**
* Returns true if this entity should move as if it were on a ladder (either because it's actually on a ladder, or
* for AI reasons)
*/
public boolean isOnLadder()
{
return false;
}
}

View File

@@ -0,0 +1,357 @@
package net.minecraft.entity;
import com.google.common.base.Predicate;
import javax.annotation.Nullable;
import net.minecraft.block.BlockRedstoneDiode;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.effect.EntityLightningBolt;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.Mirror;
import net.minecraft.util.Rotation;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import org.apache.commons.lang3.Validate;
public abstract class EntityHanging extends Entity
{
private static final Predicate<Entity> IS_HANGING_ENTITY = new Predicate<Entity>()
{
public boolean apply(@Nullable Entity p_apply_1_)
{
return p_apply_1_ instanceof EntityHanging;
}
};
private int tickCounter1;
protected BlockPos hangingPosition;
/** The direction the entity is facing */
@Nullable
public EnumFacing facingDirection;
public EntityHanging(World worldIn)
{
super(worldIn);
this.setSize(0.5F, 0.5F);
}
public EntityHanging(World worldIn, BlockPos hangingPositionIn)
{
this(worldIn);
this.hangingPosition = hangingPositionIn;
}
protected void entityInit()
{
}
/**
* Updates facing and bounding box based on it
*/
protected void updateFacingWithBoundingBox(EnumFacing facingDirectionIn)
{
Validate.notNull(facingDirectionIn);
Validate.isTrue(facingDirectionIn.getAxis().isHorizontal());
this.facingDirection = facingDirectionIn;
this.rotationYaw = (float)(this.facingDirection.getHorizontalIndex() * 90);
this.prevRotationYaw = this.rotationYaw;
this.updateBoundingBox();
}
/**
* Updates the entity bounding box based on current facing
*/
protected void updateBoundingBox()
{
if (this.facingDirection != null)
{
double d0 = (double)this.hangingPosition.getX() + 0.5D;
double d1 = (double)this.hangingPosition.getY() + 0.5D;
double d2 = (double)this.hangingPosition.getZ() + 0.5D;
double d3 = 0.46875D;
double d4 = this.offs(this.getWidthPixels());
double d5 = this.offs(this.getHeightPixels());
d0 = d0 - (double)this.facingDirection.getFrontOffsetX() * 0.46875D;
d2 = d2 - (double)this.facingDirection.getFrontOffsetZ() * 0.46875D;
d1 = d1 + d5;
EnumFacing enumfacing = this.facingDirection.rotateYCCW();
d0 = d0 + d4 * (double)enumfacing.getFrontOffsetX();
d2 = d2 + d4 * (double)enumfacing.getFrontOffsetZ();
this.posX = d0;
this.posY = d1;
this.posZ = d2;
double d6 = (double)this.getWidthPixels();
double d7 = (double)this.getHeightPixels();
double d8 = (double)this.getWidthPixels();
if (this.facingDirection.getAxis() == EnumFacing.Axis.Z)
{
d8 = 1.0D;
}
else
{
d6 = 1.0D;
}
d6 = d6 / 32.0D;
d7 = d7 / 32.0D;
d8 = d8 / 32.0D;
this.setEntityBoundingBox(new AxisAlignedBB(d0 - d6, d1 - d7, d2 - d8, d0 + d6, d1 + d7, d2 + d8));
}
}
private double offs(int p_190202_1_)
{
return p_190202_1_ % 32 == 0 ? 0.5D : 0.0D;
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
if (this.tickCounter1++ == 100 && !this.world.isRemote)
{
this.tickCounter1 = 0;
if (!this.isDead && !this.onValidSurface())
{
this.setDead();
this.onBroken((Entity)null);
}
}
}
/**
* checks to make sure painting can be placed there
*/
public boolean onValidSurface()
{
if (!this.world.getCollisionBoxes(this, this.getEntityBoundingBox()).isEmpty())
{
return false;
}
else
{
int i = Math.max(1, this.getWidthPixels() / 16);
int j = Math.max(1, this.getHeightPixels() / 16);
BlockPos blockpos = this.hangingPosition.offset(this.facingDirection.getOpposite());
EnumFacing enumfacing = this.facingDirection.rotateYCCW();
BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos();
for (int k = 0; k < i; ++k)
{
for (int l = 0; l < j; ++l)
{
int i1 = (i - 1) / -2;
int j1 = (j - 1) / -2;
blockpos$mutableblockpos.setPos(blockpos).move(enumfacing, k + i1).move(EnumFacing.UP, l + j1);
IBlockState iblockstate = this.world.getBlockState(blockpos$mutableblockpos);
if (iblockstate.isSideSolid(this.world, blockpos$mutableblockpos, this.facingDirection))
continue;
if (!iblockstate.getMaterial().isSolid() && !BlockRedstoneDiode.isDiode(iblockstate))
{
return false;
}
}
}
return this.world.getEntitiesInAABBexcluding(this, this.getEntityBoundingBox(), IS_HANGING_ENTITY).isEmpty();
}
}
/**
* Returns true if other Entities should be prevented from moving through this Entity.
*/
public boolean canBeCollidedWith()
{
return true;
}
/**
* Called when a player attacks an entity. If this returns true the attack will not happen.
*/
public boolean hitByEntity(Entity entityIn)
{
return entityIn instanceof EntityPlayer ? this.attackEntityFrom(DamageSource.causePlayerDamage((EntityPlayer)entityIn), 0.0F) : false;
}
/**
* Gets the horizontal facing direction of this Entity.
*/
public EnumFacing getHorizontalFacing()
{
return this.facingDirection;
}
/**
* Called when the entity is attacked.
*/
public boolean attackEntityFrom(DamageSource source, float amount)
{
if (this.isEntityInvulnerable(source))
{
return false;
}
else
{
if (!this.isDead && !this.world.isRemote)
{
this.setDead();
this.markVelocityChanged();
this.onBroken(source.getTrueSource());
}
return true;
}
}
/**
* Tries to move the entity towards the specified location.
*/
public void move(MoverType type, double x, double y, double z)
{
if (!this.world.isRemote && !this.isDead && x * x + y * y + z * z > 0.0D)
{
this.setDead();
this.onBroken((Entity)null);
}
}
/**
* Adds to the current velocity of the entity, and sets {@link #isAirBorne} to true.
*/
public void addVelocity(double x, double y, double z)
{
if (!this.world.isRemote && !this.isDead && x * x + y * y + z * z > 0.0D)
{
this.setDead();
this.onBroken((Entity)null);
}
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound compound)
{
compound.setByte("Facing", (byte)this.facingDirection.getHorizontalIndex());
BlockPos blockpos = this.getHangingPosition();
compound.setInteger("TileX", blockpos.getX());
compound.setInteger("TileY", blockpos.getY());
compound.setInteger("TileZ", blockpos.getZ());
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound compound)
{
this.hangingPosition = new BlockPos(compound.getInteger("TileX"), compound.getInteger("TileY"), compound.getInteger("TileZ"));
this.updateFacingWithBoundingBox(EnumFacing.getHorizontal(compound.getByte("Facing")));
}
public abstract int getWidthPixels();
public abstract int getHeightPixels();
/**
* Called when this entity is broken. Entity parameter may be null.
*/
public abstract void onBroken(@Nullable Entity brokenEntity);
public abstract void playPlaceSound();
/**
* Drops an item at the position of the entity.
*/
public EntityItem entityDropItem(ItemStack stack, float offsetY)
{
EntityItem entityitem = new EntityItem(this.world, this.posX + (double)((float)this.facingDirection.getFrontOffsetX() * 0.15F), this.posY + (double)offsetY, this.posZ + (double)((float)this.facingDirection.getFrontOffsetZ() * 0.15F), stack);
entityitem.setDefaultPickupDelay();
this.world.spawnEntity(entityitem);
return entityitem;
}
protected boolean shouldSetPosAfterLoading()
{
return false;
}
/**
* Sets the x,y,z of the entity from the given parameters. Also seems to set up a bounding box.
*/
public void setPosition(double x, double y, double z)
{
this.hangingPosition = new BlockPos(x, y, z);
this.updateBoundingBox();
this.isAirBorne = true;
}
public BlockPos getHangingPosition()
{
return this.hangingPosition;
}
/**
* Transforms the entity's current yaw with the given Rotation and returns it. This does not have a side-effect.
*/
@SuppressWarnings("incomplete-switch")
public float getRotatedYaw(Rotation transformRotation)
{
if (this.facingDirection != null && this.facingDirection.getAxis() != EnumFacing.Axis.Y)
{
switch (transformRotation)
{
case CLOCKWISE_180:
this.facingDirection = this.facingDirection.getOpposite();
break;
case COUNTERCLOCKWISE_90:
this.facingDirection = this.facingDirection.rotateYCCW();
break;
case CLOCKWISE_90:
this.facingDirection = this.facingDirection.rotateY();
}
}
float f = MathHelper.wrapDegrees(this.rotationYaw);
switch (transformRotation)
{
case CLOCKWISE_180:
return f + 180.0F;
case COUNTERCLOCKWISE_90:
return f + 90.0F;
case CLOCKWISE_90:
return f + 270.0F;
default:
return f;
}
}
/**
* Transforms the entity's current yaw with the given Mirror and returns it. This does not have a side-effect.
*/
public float getMirroredYaw(Mirror transformMirror)
{
return this.getRotatedYaw(transformMirror.toRotation(this.facingDirection));
}
/**
* Called when a lightning bolt hits the entity.
*/
public void onStruckByLightning(EntityLightningBolt lightningBolt)
{
}
}

View File

@@ -0,0 +1,196 @@
package net.minecraft.entity;
import java.util.List;
import javax.annotation.Nullable;
import net.minecraft.block.BlockFence;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.SoundEvents;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class EntityLeashKnot extends EntityHanging
{
public EntityLeashKnot(World worldIn)
{
super(worldIn);
}
public EntityLeashKnot(World worldIn, BlockPos hangingPositionIn)
{
super(worldIn, hangingPositionIn);
this.setPosition((double)hangingPositionIn.getX() + 0.5D, (double)hangingPositionIn.getY() + 0.5D, (double)hangingPositionIn.getZ() + 0.5D);
float f = 0.125F;
float f1 = 0.1875F;
float f2 = 0.25F;
this.setEntityBoundingBox(new AxisAlignedBB(this.posX - 0.1875D, this.posY - 0.25D + 0.125D, this.posZ - 0.1875D, this.posX + 0.1875D, this.posY + 0.25D + 0.125D, this.posZ + 0.1875D));
this.forceSpawn = true;
}
/**
* Sets the x,y,z of the entity from the given parameters. Also seems to set up a bounding box.
*/
public void setPosition(double x, double y, double z)
{
super.setPosition((double)MathHelper.floor(x) + 0.5D, (double)MathHelper.floor(y) + 0.5D, (double)MathHelper.floor(z) + 0.5D);
}
/**
* Updates the entity bounding box based on current facing
*/
protected void updateBoundingBox()
{
this.posX = (double)this.hangingPosition.getX() + 0.5D;
this.posY = (double)this.hangingPosition.getY() + 0.5D;
this.posZ = (double)this.hangingPosition.getZ() + 0.5D;
}
/**
* Updates facing and bounding box based on it
*/
public void updateFacingWithBoundingBox(EnumFacing facingDirectionIn)
{
}
public int getWidthPixels()
{
return 9;
}
public int getHeightPixels()
{
return 9;
}
public float getEyeHeight()
{
return -0.0625F;
}
/**
* Checks if the entity is in range to render.
*/
@SideOnly(Side.CLIENT)
public boolean isInRangeToRenderDist(double distance)
{
return distance < 1024.0D;
}
/**
* Called when this entity is broken. Entity parameter may be null.
*/
public void onBroken(@Nullable Entity brokenEntity)
{
this.playSound(SoundEvents.ENTITY_LEASHKNOT_BREAK, 1.0F, 1.0F);
}
/**
* Either write this entity to the NBT tag given and return true, or return false without doing anything. If this
* returns false the entity is not saved on disk. Riding entities return false here as they are saved with their
* mount.
*/
public boolean writeToNBTOptional(NBTTagCompound compound)
{
return false;
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound compound)
{
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound compound)
{
}
public boolean processInitialInteract(EntityPlayer player, EnumHand hand)
{
if (this.world.isRemote)
{
return true;
}
else
{
boolean flag = false;
double d0 = 7.0D;
List<EntityLiving> list = this.world.<EntityLiving>getEntitiesWithinAABB(EntityLiving.class, new AxisAlignedBB(this.posX - 7.0D, this.posY - 7.0D, this.posZ - 7.0D, this.posX + 7.0D, this.posY + 7.0D, this.posZ + 7.0D));
for (EntityLiving entityliving : list)
{
if (entityliving.getLeashed() && entityliving.getLeashHolder() == player)
{
entityliving.setLeashHolder(this, true);
flag = true;
}
}
if (!flag)
{
this.setDead();
if (player.capabilities.isCreativeMode)
{
for (EntityLiving entityliving1 : list)
{
if (entityliving1.getLeashed() && entityliving1.getLeashHolder() == this)
{
entityliving1.clearLeashed(true, false);
}
}
}
}
return true;
}
}
/**
* checks to make sure painting can be placed there
*/
public boolean onValidSurface()
{
return this.world.getBlockState(this.hangingPosition).getBlock() instanceof BlockFence;
}
public static EntityLeashKnot createKnot(World worldIn, BlockPos fence)
{
EntityLeashKnot entityleashknot = new EntityLeashKnot(worldIn, fence);
worldIn.spawnEntity(entityleashknot);
entityleashknot.playPlaceSound();
return entityleashknot;
}
@Nullable
public static EntityLeashKnot getKnotForPosition(World worldIn, BlockPos pos)
{
int i = pos.getX();
int j = pos.getY();
int k = pos.getZ();
for (EntityLeashKnot entityleashknot : worldIn.getEntitiesWithinAABB(EntityLeashKnot.class, new AxisAlignedBB((double)i - 1.0D, (double)j - 1.0D, (double)k - 1.0D, (double)i + 1.0D, (double)j + 1.0D, (double)k + 1.0D)))
{
if (entityleashknot.getHangingPosition().equals(pos))
{
return entityleashknot;
}
}
return null;
}
public void playPlaceSound()
{
this.playSound(SoundEvents.ENTITY_LEASHKNOT_PLACE, 1.0F, 1.0F);
}
}

View File

@@ -0,0 +1,532 @@
package net.minecraft.entity;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import net.minecraft.entity.boss.EntityDragon;
import net.minecraft.entity.boss.EntityWither;
import net.minecraft.entity.effect.EntityLightningBolt;
import net.minecraft.entity.item.EntityArmorStand;
import net.minecraft.entity.item.EntityBoat;
import net.minecraft.entity.item.EntityEnderCrystal;
import net.minecraft.entity.item.EntityEnderEye;
import net.minecraft.entity.item.EntityEnderPearl;
import net.minecraft.entity.item.EntityExpBottle;
import net.minecraft.entity.item.EntityFallingBlock;
import net.minecraft.entity.item.EntityFireworkRocket;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.item.EntityItemFrame;
import net.minecraft.entity.item.EntityMinecart;
import net.minecraft.entity.item.EntityMinecartChest;
import net.minecraft.entity.item.EntityMinecartCommandBlock;
import net.minecraft.entity.item.EntityMinecartEmpty;
import net.minecraft.entity.item.EntityMinecartFurnace;
import net.minecraft.entity.item.EntityMinecartHopper;
import net.minecraft.entity.item.EntityMinecartMobSpawner;
import net.minecraft.entity.item.EntityMinecartTNT;
import net.minecraft.entity.item.EntityPainting;
import net.minecraft.entity.item.EntityTNTPrimed;
import net.minecraft.entity.item.EntityXPOrb;
import net.minecraft.entity.monster.EntityBlaze;
import net.minecraft.entity.monster.EntityCaveSpider;
import net.minecraft.entity.monster.EntityCreeper;
import net.minecraft.entity.monster.EntityElderGuardian;
import net.minecraft.entity.monster.EntityEnderman;
import net.minecraft.entity.monster.EntityEndermite;
import net.minecraft.entity.monster.EntityEvoker;
import net.minecraft.entity.monster.EntityGhast;
import net.minecraft.entity.monster.EntityGiantZombie;
import net.minecraft.entity.monster.EntityGuardian;
import net.minecraft.entity.monster.EntityHusk;
import net.minecraft.entity.monster.EntityIllusionIllager;
import net.minecraft.entity.monster.EntityIronGolem;
import net.minecraft.entity.monster.EntityMagmaCube;
import net.minecraft.entity.monster.EntityPigZombie;
import net.minecraft.entity.monster.EntityPolarBear;
import net.minecraft.entity.monster.EntityShulker;
import net.minecraft.entity.monster.EntitySilverfish;
import net.minecraft.entity.monster.EntitySkeleton;
import net.minecraft.entity.monster.EntitySlime;
import net.minecraft.entity.monster.EntitySnowman;
import net.minecraft.entity.monster.EntitySpider;
import net.minecraft.entity.monster.EntityStray;
import net.minecraft.entity.monster.EntityVex;
import net.minecraft.entity.monster.EntityVindicator;
import net.minecraft.entity.monster.EntityWitch;
import net.minecraft.entity.monster.EntityWitherSkeleton;
import net.minecraft.entity.monster.EntityZombie;
import net.minecraft.entity.monster.EntityZombieVillager;
import net.minecraft.entity.passive.EntityBat;
import net.minecraft.entity.passive.EntityChicken;
import net.minecraft.entity.passive.EntityCow;
import net.minecraft.entity.passive.EntityDonkey;
import net.minecraft.entity.passive.EntityHorse;
import net.minecraft.entity.passive.EntityLlama;
import net.minecraft.entity.passive.EntityMooshroom;
import net.minecraft.entity.passive.EntityMule;
import net.minecraft.entity.passive.EntityOcelot;
import net.minecraft.entity.passive.EntityParrot;
import net.minecraft.entity.passive.EntityPig;
import net.minecraft.entity.passive.EntityRabbit;
import net.minecraft.entity.passive.EntitySheep;
import net.minecraft.entity.passive.EntitySkeletonHorse;
import net.minecraft.entity.passive.EntitySquid;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.entity.passive.EntityWolf;
import net.minecraft.entity.passive.EntityZombieHorse;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.projectile.EntityDragonFireball;
import net.minecraft.entity.projectile.EntityEgg;
import net.minecraft.entity.projectile.EntityEvokerFangs;
import net.minecraft.entity.projectile.EntityLargeFireball;
import net.minecraft.entity.projectile.EntityLlamaSpit;
import net.minecraft.entity.projectile.EntityPotion;
import net.minecraft.entity.projectile.EntityShulkerBullet;
import net.minecraft.entity.projectile.EntitySmallFireball;
import net.minecraft.entity.projectile.EntitySnowball;
import net.minecraft.entity.projectile.EntitySpectralArrow;
import net.minecraft.entity.projectile.EntityTippedArrow;
import net.minecraft.entity.projectile.EntityWitherSkull;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.stats.StatBase;
import net.minecraft.stats.StatList;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.registry.RegistryNamespaced;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class EntityList
{
public static final ResourceLocation LIGHTNING_BOLT = new ResourceLocation("lightning_bolt");
private static final ResourceLocation PLAYER = new ResourceLocation("player");
private static final Logger LOGGER = LogManager.getLogger();
/** This is a HashMap of the Creative Entity Eggs/Spawners. */
public static final Map<ResourceLocation, EntityList.EntityEggInfo> ENTITY_EGGS = Maps.<ResourceLocation, EntityList.EntityEggInfo>newLinkedHashMap();
private static final Set<ResourceLocation> EXTRA_NAMES = Sets.newHashSet();
/**
* Gets the {@link ResourceLocation} that identifies the given entity's type.
*/
@Nullable
public static ResourceLocation getKey(Entity entityIn)
{
return getKey(entityIn.getClass());
}
/**
* Gets the {@link ResourceLocation} that identifies the given entity's type.
*
* @return The resource location, or null if the {@link #REGISTRY} does not contain a mapping for that class.
*/
@Nullable
public static ResourceLocation getKey(Class <? extends Entity > entityIn)
{
net.minecraftforge.fml.common.registry.EntityEntry entry = net.minecraftforge.fml.common.registry.EntityRegistry.getEntry(entityIn);
return entry == null ? null : entry.getRegistryName();
}
/**
* Gets the original name for the entity, used in versions prior to 1.11. This name is also used for translation
* strings.
*
* @return The entity's original name, or null if the given entity's type is not known.
*/
@Nullable
public static String getEntityString(Entity entityIn)
{
net.minecraftforge.fml.common.registry.EntityEntry entry = net.minecraftforge.fml.common.registry.EntityRegistry.getEntry(entityIn.getClass());
return entry == null ? null : entry.getName();
}
/**
* Gets the original name for the given entity type, used in versions prior to 1.11. Note that even entities added
* after 1.11 have old names as returned by this method.
* <p>
* This name is also used for translation strings; translate <code>"entity.$oldid.name"</code> (with
* <var>$oldid</var> being the result of this method) to get those names. Note that the name is upper-case in most
* situations.
*
* @return The original entity name, or null if there is no known entity for that type.
*/
@Nullable
public static String getTranslationName(@Nullable ResourceLocation entityType)
{
net.minecraftforge.fml.common.registry.EntityEntry entry = net.minecraftforge.fml.common.registry.ForgeRegistries.ENTITIES.getValue(entityType);
return entry == null ? null : entry.getName();
}
@Nullable
@SideOnly(Side.CLIENT)
public static Class <? extends Entity > getClassFromID(int entityID)
{
net.minecraftforge.fml.common.registry.EntityEntry entry = net.minecraftforge.registries.GameData.getEntityRegistry().getValue(entityID);
return entry == null ? null : entry.getEntityClass();
}
@Nullable
@SideOnly(Side.CLIENT)
public static Class <? extends Entity > getClassFromName(String p_192839_0_)
{
net.minecraftforge.fml.common.registry.EntityEntry entry = net.minecraftforge.fml.common.registry.ForgeRegistries.ENTITIES.getValue(new ResourceLocation(p_192839_0_));
return entry == null ? null : entry.getEntityClass();
}
public static int getID(Class<? extends Entity> cls)
{
net.minecraftforge.fml.common.registry.EntityEntry entry = net.minecraftforge.fml.common.registry.EntityRegistry.getEntry(cls);
return entry == null ? -1 : net.minecraftforge.registries.GameData.getEntityRegistry().getID(entry);
}
@Nullable
public static Class<? extends Entity> getClass(ResourceLocation key)
{
net.minecraftforge.fml.common.registry.EntityEntry entry = net.minecraftforge.fml.common.registry.ForgeRegistries.ENTITIES.getValue(key);
return entry == null ? null : entry.getEntityClass();
}
/**
* Creates a new entity of the given type in the given world.
*
* @return The newly created entity, or null if creation failed
*/
@Nullable
public static Entity newEntity(@Nullable Class <? extends Entity > clazz, World worldIn)
{
if (clazz == null)
{
return null;
}
else
{
try
{
net.minecraftforge.fml.common.registry.EntityEntry entry = net.minecraftforge.fml.common.registry.EntityRegistry.getEntry(clazz);
if (entry != null) return entry.newInstance(worldIn);
return clazz.getConstructor(World.class).newInstance(worldIn);
}
catch (Exception exception)
{
exception.printStackTrace();
return null;
}
}
}
/**
* Creates a new entity with the given numeric networked entity type ID in the given world.
*
* @return The newly created entity, or null if creation failed
*/
@Nullable
@SideOnly(Side.CLIENT)
public static Entity createEntityByID(int entityID, World worldIn)
{
net.minecraftforge.fml.common.registry.EntityEntry entry = net.minecraftforge.registries.GameData.getEntityRegistry().getValue(entityID);
return entry == null ? null : entry.newInstance(worldIn);
}
/**
* Creates a new entity of the given type in the given world.
*
* @return The newly created entity, or null if creation failed
*/
@Nullable
public static Entity createEntityByIDFromName(ResourceLocation name, World worldIn)
{
net.minecraftforge.fml.common.registry.EntityEntry entry = net.minecraftforge.fml.common.registry.ForgeRegistries.ENTITIES.getValue(name);
return entry == null ? null : entry.newInstance(worldIn);
}
/**
* Creates a new entity from the given NBT data in the given world.
* <p>
* If the entity fails to create, null will be returned and a warning will be logged.
*
* @return The newly created entity, or null
*/
@Nullable
public static Entity createEntityFromNBT(NBTTagCompound nbt, World worldIn)
{
ResourceLocation resourcelocation = new ResourceLocation(nbt.getString("id"));
Entity entity = createEntityByIDFromName(resourcelocation, worldIn);
if (entity == null)
{
LOGGER.warn("Skipping Entity with id {}", (Object)resourcelocation);
}
else
{
try
{
entity.readFromNBT(nbt);
}
catch (Exception e)
{
net.minecraftforge.fml.common.FMLLog.log.error("An Entity {}({}) has thrown an exception during loading, its state cannot be restored. Report this to the mod author",
nbt.getString("id"), entity.getName(), e);
entity = null;
}
}
return entity;
}
/**
* Gets a collection of all known entity types.
*
* @return A collection of all known entity types. Do not modify this collection.
*/
public static Set<ResourceLocation> getEntityNameList()
{
return Sets.union(net.minecraftforge.fml.common.registry.ForgeRegistries.ENTITIES.getKeys(), EXTRA_NAMES);
}
/**
* Checks if the given entity type matches the type of that entity, correctly handling behavior of players and
* lightning bolts.
*
* @return true if the type matches
*/
public static boolean isMatchingName(Entity entityIn, ResourceLocation entityName)
{
ResourceLocation resourcelocation = getKey(entityIn.getClass());
if (resourcelocation != null)
{
return resourcelocation.equals(entityName);
}
else if (entityIn instanceof EntityPlayer)
{
return PLAYER.equals(entityName);
}
else
{
return entityIn instanceof EntityLightningBolt ? LIGHTNING_BOLT.equals(entityName) : false;
}
}
/**
* Checks if the given resource location matches a registered entity type, correctly handling behavior of players
* and lightning bols.
*
* @return true if the type is an entity.
*/
public static boolean isRegistered(ResourceLocation entityName)
{
return PLAYER.equals(entityName) || getEntityNameList().contains(entityName);
}
public static String getValidTypeNames()
{
StringBuilder stringbuilder = new StringBuilder();
for (ResourceLocation resourcelocation : getEntityNameList())
{
stringbuilder.append((Object)resourcelocation).append(", ");
}
stringbuilder.append((Object)PLAYER);
return stringbuilder.toString();
}
public static void init()
{
register(1, "item", EntityItem.class, "Item");
register(2, "xp_orb", EntityXPOrb.class, "XPOrb");
register(3, "area_effect_cloud", EntityAreaEffectCloud.class, "AreaEffectCloud");
register(4, "elder_guardian", EntityElderGuardian.class, "ElderGuardian");
register(5, "wither_skeleton", EntityWitherSkeleton.class, "WitherSkeleton");
register(6, "stray", EntityStray.class, "Stray");
register(7, "egg", EntityEgg.class, "ThrownEgg");
register(8, "leash_knot", EntityLeashKnot.class, "LeashKnot");
register(9, "painting", EntityPainting.class, "Painting");
register(10, "arrow", EntityTippedArrow.class, "Arrow");
register(11, "snowball", EntitySnowball.class, "Snowball");
register(12, "fireball", EntityLargeFireball.class, "Fireball");
register(13, "small_fireball", EntitySmallFireball.class, "SmallFireball");
register(14, "ender_pearl", EntityEnderPearl.class, "ThrownEnderpearl");
register(15, "eye_of_ender_signal", EntityEnderEye.class, "EyeOfEnderSignal");
register(16, "potion", EntityPotion.class, "ThrownPotion");
register(17, "xp_bottle", EntityExpBottle.class, "ThrownExpBottle");
register(18, "item_frame", EntityItemFrame.class, "ItemFrame");
register(19, "wither_skull", EntityWitherSkull.class, "WitherSkull");
register(20, "tnt", EntityTNTPrimed.class, "PrimedTnt");
register(21, "falling_block", EntityFallingBlock.class, "FallingSand");
register(22, "fireworks_rocket", EntityFireworkRocket.class, "FireworksRocketEntity");
register(23, "husk", EntityHusk.class, "Husk");
register(24, "spectral_arrow", EntitySpectralArrow.class, "SpectralArrow");
register(25, "shulker_bullet", EntityShulkerBullet.class, "ShulkerBullet");
register(26, "dragon_fireball", EntityDragonFireball.class, "DragonFireball");
register(27, "zombie_villager", EntityZombieVillager.class, "ZombieVillager");
register(28, "skeleton_horse", EntitySkeletonHorse.class, "SkeletonHorse");
register(29, "zombie_horse", EntityZombieHorse.class, "ZombieHorse");
register(30, "armor_stand", EntityArmorStand.class, "ArmorStand");
register(31, "donkey", EntityDonkey.class, "Donkey");
register(32, "mule", EntityMule.class, "Mule");
register(33, "evocation_fangs", EntityEvokerFangs.class, "EvocationFangs");
register(34, "evocation_illager", EntityEvoker.class, "EvocationIllager");
register(35, "vex", EntityVex.class, "Vex");
register(36, "vindication_illager", EntityVindicator.class, "VindicationIllager");
register(37, "illusion_illager", EntityIllusionIllager.class, "IllusionIllager");
register(40, "commandblock_minecart", EntityMinecartCommandBlock.class, EntityMinecart.Type.COMMAND_BLOCK.getName());
register(41, "boat", EntityBoat.class, "Boat");
register(42, "minecart", EntityMinecartEmpty.class, EntityMinecart.Type.RIDEABLE.getName());
register(43, "chest_minecart", EntityMinecartChest.class, EntityMinecart.Type.CHEST.getName());
register(44, "furnace_minecart", EntityMinecartFurnace.class, EntityMinecart.Type.FURNACE.getName());
register(45, "tnt_minecart", EntityMinecartTNT.class, EntityMinecart.Type.TNT.getName());
register(46, "hopper_minecart", EntityMinecartHopper.class, EntityMinecart.Type.HOPPER.getName());
register(47, "spawner_minecart", EntityMinecartMobSpawner.class, EntityMinecart.Type.SPAWNER.getName());
register(50, "creeper", EntityCreeper.class, "Creeper");
register(51, "skeleton", EntitySkeleton.class, "Skeleton");
register(52, "spider", EntitySpider.class, "Spider");
register(53, "giant", EntityGiantZombie.class, "Giant");
register(54, "zombie", EntityZombie.class, "Zombie");
register(55, "slime", EntitySlime.class, "Slime");
register(56, "ghast", EntityGhast.class, "Ghast");
register(57, "zombie_pigman", EntityPigZombie.class, "PigZombie");
register(58, "enderman", EntityEnderman.class, "Enderman");
register(59, "cave_spider", EntityCaveSpider.class, "CaveSpider");
register(60, "silverfish", EntitySilverfish.class, "Silverfish");
register(61, "blaze", EntityBlaze.class, "Blaze");
register(62, "magma_cube", EntityMagmaCube.class, "LavaSlime");
register(63, "ender_dragon", EntityDragon.class, "EnderDragon");
register(64, "wither", EntityWither.class, "WitherBoss");
register(65, "bat", EntityBat.class, "Bat");
register(66, "witch", EntityWitch.class, "Witch");
register(67, "endermite", EntityEndermite.class, "Endermite");
register(68, "guardian", EntityGuardian.class, "Guardian");
register(69, "shulker", EntityShulker.class, "Shulker");
register(90, "pig", EntityPig.class, "Pig");
register(91, "sheep", EntitySheep.class, "Sheep");
register(92, "cow", EntityCow.class, "Cow");
register(93, "chicken", EntityChicken.class, "Chicken");
register(94, "squid", EntitySquid.class, "Squid");
register(95, "wolf", EntityWolf.class, "Wolf");
register(96, "mooshroom", EntityMooshroom.class, "MushroomCow");
register(97, "snowman", EntitySnowman.class, "SnowMan");
register(98, "ocelot", EntityOcelot.class, "Ozelot");
register(99, "villager_golem", EntityIronGolem.class, "VillagerGolem");
register(100, "horse", EntityHorse.class, "Horse");
register(101, "rabbit", EntityRabbit.class, "Rabbit");
register(102, "polar_bear", EntityPolarBear.class, "PolarBear");
register(103, "llama", EntityLlama.class, "Llama");
register(104, "llama_spit", EntityLlamaSpit.class, "LlamaSpit");
register(105, "parrot", EntityParrot.class, "Parrot");
register(120, "villager", EntityVillager.class, "Villager");
register(200, "ender_crystal", EntityEnderCrystal.class, "EnderCrystal");
addSpawnInfo("bat", 4996656, 986895);
addSpawnInfo("blaze", 16167425, 16775294);
addSpawnInfo("cave_spider", 803406, 11013646);
addSpawnInfo("chicken", 10592673, 16711680);
addSpawnInfo("cow", 4470310, 10592673);
addSpawnInfo("creeper", 894731, 0);
addSpawnInfo("donkey", 5457209, 8811878);
addSpawnInfo("elder_guardian", 13552826, 7632531);
addSpawnInfo("enderman", 1447446, 0);
addSpawnInfo("endermite", 1447446, 7237230);
addSpawnInfo("evocation_illager", 9804699, 1973274);
addSpawnInfo("ghast", 16382457, 12369084);
addSpawnInfo("guardian", 5931634, 15826224);
addSpawnInfo("horse", 12623485, 15656192);
addSpawnInfo("husk", 7958625, 15125652);
addSpawnInfo("llama", 12623485, 10051392);
addSpawnInfo("magma_cube", 3407872, 16579584);
addSpawnInfo("mooshroom", 10489616, 12040119);
addSpawnInfo("mule", 1769984, 5321501);
addSpawnInfo("ocelot", 15720061, 5653556);
addSpawnInfo("parrot", 894731, 16711680);
addSpawnInfo("pig", 15771042, 14377823);
addSpawnInfo("polar_bear", 15921906, 9803152);
addSpawnInfo("rabbit", 10051392, 7555121);
addSpawnInfo("sheep", 15198183, 16758197);
addSpawnInfo("shulker", 9725844, 5060690);
addSpawnInfo("silverfish", 7237230, 3158064);
addSpawnInfo("skeleton", 12698049, 4802889);
addSpawnInfo("skeleton_horse", 6842447, 15066584);
addSpawnInfo("slime", 5349438, 8306542);
addSpawnInfo("spider", 3419431, 11013646);
addSpawnInfo("squid", 2243405, 7375001);
addSpawnInfo("stray", 6387319, 14543594);
addSpawnInfo("vex", 8032420, 15265265);
addSpawnInfo("villager", 5651507, 12422002);
addSpawnInfo("vindication_illager", 9804699, 2580065);
addSpawnInfo("witch", 3407872, 5349438);
addSpawnInfo("wither_skeleton", 1315860, 4672845);
addSpawnInfo("wolf", 14144467, 13545366);
addSpawnInfo("zombie", 44975, 7969893);
addSpawnInfo("zombie_horse", 3232308, 9945732);
addSpawnInfo("zombie_pigman", 15373203, 5009705);
addSpawnInfo("zombie_villager", 5651507, 7969893);
EXTRA_NAMES.add(LIGHTNING_BOLT);
}
private static void register(int id, String name, Class <? extends Entity > clazz, String oldName)
{
try
{
clazz.getConstructor(World.class);
}
catch (NoSuchMethodException var5)
{
throw new RuntimeException("Invalid class " + clazz + " no constructor taking " + World.class.getName());
}
if ((clazz.getModifiers() & 1024) == 1024)
{
throw new RuntimeException("Invalid abstract class " + clazz);
}
else
{
ResourceLocation resourcelocation = new ResourceLocation(name);
net.minecraftforge.registries.GameData.registerEntity(id, resourcelocation, clazz, oldName);
}
}
protected static EntityList.EntityEggInfo addSpawnInfo(String id, int primaryColor, int secondaryColor)
{
ResourceLocation resourcelocation = new ResourceLocation(id);
EntityList.EntityEggInfo egg = new EntityList.EntityEggInfo(resourcelocation, primaryColor, secondaryColor);
net.minecraftforge.fml.common.registry.EntityEntry entry = net.minecraftforge.fml.common.registry.ForgeRegistries.ENTITIES.getValue(resourcelocation);
if (entry != null) entry.setEgg(egg);
return (EntityList.EntityEggInfo)ENTITY_EGGS.put(resourcelocation, egg);
}
public static class EntityEggInfo
{
/** The entityID of the spawned mob */
public final ResourceLocation spawnedID;
/** Base color of the egg */
public final int primaryColor;
/** Color of the egg spots */
public final int secondaryColor;
public final StatBase killEntityStat;
public final StatBase entityKilledByStat;
public EntityEggInfo(ResourceLocation idIn, int primaryColorIn, int secondaryColorIn)
{
this.spawnedID = idIn;
this.primaryColor = primaryColorIn;
this.secondaryColor = secondaryColorIn;
this.killEntityStat = StatList.getStatKillEntity(this);
this.entityKilledByStat = StatList.getStatEntityKilledBy(this);
}
// Forge start
public EntityEggInfo(ResourceLocation id, int primaryColor, int secondaryColor, StatBase killEntityStatistic, StatBase entityKilledByStatistic)
{
this.spawnedID = id;
this.primaryColor = primaryColor;
this.secondaryColor = secondaryColor;
this.killEntityStat = killEntityStatistic;
this.entityKilledByStat = entityKilledByStatistic;
}
// Forge end
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,105 @@
package net.minecraft.entity;
import com.google.common.collect.Maps;
import java.util.Map;
import net.minecraft.entity.boss.EntityDragon;
import net.minecraft.entity.boss.EntityWither;
import net.minecraft.entity.monster.EntityBlaze;
import net.minecraft.entity.monster.EntityCaveSpider;
import net.minecraft.entity.monster.EntityCreeper;
import net.minecraft.entity.monster.EntityEnderman;
import net.minecraft.entity.monster.EntityEndermite;
import net.minecraft.entity.monster.EntityGhast;
import net.minecraft.entity.monster.EntityGiantZombie;
import net.minecraft.entity.monster.EntityGuardian;
import net.minecraft.entity.monster.EntityHusk;
import net.minecraft.entity.monster.EntityIronGolem;
import net.minecraft.entity.monster.EntityMagmaCube;
import net.minecraft.entity.monster.EntityPigZombie;
import net.minecraft.entity.monster.EntitySilverfish;
import net.minecraft.entity.monster.EntitySkeleton;
import net.minecraft.entity.monster.EntitySlime;
import net.minecraft.entity.monster.EntitySnowman;
import net.minecraft.entity.monster.EntitySpider;
import net.minecraft.entity.monster.EntityStray;
import net.minecraft.entity.monster.EntityWitch;
import net.minecraft.entity.monster.EntityWitherSkeleton;
import net.minecraft.entity.monster.EntityZombie;
import net.minecraft.entity.monster.EntityZombieVillager;
import net.minecraft.entity.passive.EntityBat;
import net.minecraft.entity.passive.EntityChicken;
import net.minecraft.entity.passive.EntityCow;
import net.minecraft.entity.passive.EntityDonkey;
import net.minecraft.entity.passive.EntityHorse;
import net.minecraft.entity.passive.EntityMooshroom;
import net.minecraft.entity.passive.EntityMule;
import net.minecraft.entity.passive.EntityOcelot;
import net.minecraft.entity.passive.EntityParrot;
import net.minecraft.entity.passive.EntityPig;
import net.minecraft.entity.passive.EntityRabbit;
import net.minecraft.entity.passive.EntitySheep;
import net.minecraft.entity.passive.EntitySkeletonHorse;
import net.minecraft.entity.passive.EntitySquid;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.entity.passive.EntityWolf;
import net.minecraft.entity.passive.EntityZombieHorse;
public class EntitySpawnPlacementRegistry
{
private static final Map < Class<?>, EntityLiving.SpawnPlacementType > ENTITY_PLACEMENTS = Maps. < Class<?>, EntityLiving.SpawnPlacementType > newHashMap();
public static EntityLiving.SpawnPlacementType getPlacementForEntity(Class<?> entityClass)
{
return ENTITY_PLACEMENTS.getOrDefault(entityClass, EntityLiving.SpawnPlacementType.ON_GROUND);
}
public static void setPlacementType(Class<? extends Entity> entityClass, EntityLiving.SpawnPlacementType placementType)
{
ENTITY_PLACEMENTS.putIfAbsent(entityClass, placementType);
}
static
{
ENTITY_PLACEMENTS.put(EntityBat.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityChicken.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityCow.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityHorse.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntitySkeletonHorse.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityZombieHorse.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityDonkey.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityMule.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityMooshroom.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityOcelot.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityPig.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityRabbit.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityParrot.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntitySheep.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntitySnowman.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntitySquid.class, EntityLiving.SpawnPlacementType.IN_WATER);
ENTITY_PLACEMENTS.put(EntityIronGolem.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityWolf.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityVillager.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityDragon.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityWither.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityBlaze.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityCaveSpider.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityCreeper.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityEnderman.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityEndermite.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityGhast.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityGiantZombie.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityGuardian.class, EntityLiving.SpawnPlacementType.IN_WATER);
ENTITY_PLACEMENTS.put(EntityMagmaCube.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityPigZombie.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntitySilverfish.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntitySkeleton.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityWitherSkeleton.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityStray.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntitySlime.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntitySpider.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityWitch.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityZombie.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityZombieVillager.class, EntityLiving.SpawnPlacementType.ON_GROUND);
ENTITY_PLACEMENTS.put(EntityHusk.class, EntityLiving.SpawnPlacementType.ON_GROUND);
}
}

View File

@@ -0,0 +1,441 @@
package net.minecraft.entity;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import java.util.List;
import java.util.Set;
import net.minecraft.crash.CrashReport;
import net.minecraft.crash.CrashReportCategory;
import net.minecraft.crash.ICrashReportDetail;
import net.minecraft.entity.boss.EntityDragon;
import net.minecraft.entity.boss.EntityWither;
import net.minecraft.entity.item.EntityArmorStand;
import net.minecraft.entity.item.EntityBoat;
import net.minecraft.entity.item.EntityEnderCrystal;
import net.minecraft.entity.item.EntityEnderEye;
import net.minecraft.entity.item.EntityEnderPearl;
import net.minecraft.entity.item.EntityExpBottle;
import net.minecraft.entity.item.EntityFallingBlock;
import net.minecraft.entity.item.EntityFireworkRocket;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.item.EntityMinecart;
import net.minecraft.entity.item.EntityTNTPrimed;
import net.minecraft.entity.item.EntityXPOrb;
import net.minecraft.entity.passive.EntityBat;
import net.minecraft.entity.passive.EntitySquid;
import net.minecraft.entity.passive.IAnimals;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.entity.projectile.EntityArrow;
import net.minecraft.entity.projectile.EntityEgg;
import net.minecraft.entity.projectile.EntityEvokerFangs;
import net.minecraft.entity.projectile.EntityFireball;
import net.minecraft.entity.projectile.EntityFishHook;
import net.minecraft.entity.projectile.EntityLlamaSpit;
import net.minecraft.entity.projectile.EntityPotion;
import net.minecraft.entity.projectile.EntityShulkerBullet;
import net.minecraft.entity.projectile.EntitySmallFireball;
import net.minecraft.entity.projectile.EntitySnowball;
import net.minecraft.network.Packet;
import net.minecraft.network.play.server.SPacketEntityAttach;
import net.minecraft.network.play.server.SPacketSetPassengers;
import net.minecraft.util.IntHashMap;
import net.minecraft.util.ReportedException;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.WorldServer;
import net.minecraft.world.chunk.Chunk;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class EntityTracker
{
private static final Logger LOGGER = LogManager.getLogger();
private final WorldServer world;
/** List of tracked entities, used for iteration operations on tracked entities. */
private final Set<EntityTrackerEntry> entries = Sets.<EntityTrackerEntry>newHashSet();
/** Used for identity lookup of tracked entities. */
private final IntHashMap<EntityTrackerEntry> trackedEntityHashTable = new IntHashMap<EntityTrackerEntry>();
private int maxTrackingDistanceThreshold;
public EntityTracker(WorldServer theWorldIn)
{
this.world = theWorldIn;
this.maxTrackingDistanceThreshold = theWorldIn.getMinecraftServer().getPlayerList().getEntityViewDistance();
}
public static long getPositionLong(double value)
{
return MathHelper.lfloor(value * 4096.0D);
}
@SideOnly(Side.CLIENT)
public static void updateServerPosition(Entity entityIn, double x, double y, double z)
{
entityIn.serverPosX = getPositionLong(x);
entityIn.serverPosY = getPositionLong(y);
entityIn.serverPosZ = getPositionLong(z);
}
public void track(Entity entityIn)
{
if (net.minecraftforge.fml.common.registry.EntityRegistry.instance().tryTrackingEntity(this, entityIn)) return;
if (entityIn instanceof EntityPlayerMP)
{
this.track(entityIn, 512, 2);
EntityPlayerMP entityplayermp = (EntityPlayerMP)entityIn;
for (EntityTrackerEntry entitytrackerentry : this.entries)
{
if (entitytrackerentry.getTrackedEntity() != entityplayermp)
{
entitytrackerentry.updatePlayerEntity(entityplayermp);
}
}
}
else if (entityIn instanceof EntityFishHook)
{
this.track(entityIn, 64, 5, true);
}
else if (entityIn instanceof EntityArrow)
{
this.track(entityIn, 64, 20, false);
}
else if (entityIn instanceof EntitySmallFireball)
{
this.track(entityIn, 64, 10, false);
}
else if (entityIn instanceof EntityFireball)
{
this.track(entityIn, 64, 10, true);
}
else if (entityIn instanceof EntitySnowball)
{
this.track(entityIn, 64, 10, true);
}
else if (entityIn instanceof EntityLlamaSpit)
{
this.track(entityIn, 64, 10, false);
}
else if (entityIn instanceof EntityEnderPearl)
{
this.track(entityIn, 64, 10, true);
}
else if (entityIn instanceof EntityEnderEye)
{
this.track(entityIn, 64, 4, true);
}
else if (entityIn instanceof EntityEgg)
{
this.track(entityIn, 64, 10, true);
}
else if (entityIn instanceof EntityPotion)
{
this.track(entityIn, 64, 10, true);
}
else if (entityIn instanceof EntityExpBottle)
{
this.track(entityIn, 64, 10, true);
}
else if (entityIn instanceof EntityFireworkRocket)
{
this.track(entityIn, 64, 10, true);
}
else if (entityIn instanceof EntityItem)
{
this.track(entityIn, 64, 20, true);
}
else if (entityIn instanceof EntityMinecart)
{
this.track(entityIn, 80, 3, true);
}
else if (entityIn instanceof EntityBoat)
{
this.track(entityIn, 80, 3, true);
}
else if (entityIn instanceof EntitySquid)
{
this.track(entityIn, 64, 3, true);
}
else if (entityIn instanceof EntityWither)
{
this.track(entityIn, 80, 3, false);
}
else if (entityIn instanceof EntityShulkerBullet)
{
this.track(entityIn, 80, 3, true);
}
else if (entityIn instanceof EntityBat)
{
this.track(entityIn, 80, 3, false);
}
else if (entityIn instanceof EntityDragon)
{
this.track(entityIn, 160, 3, true);
}
else if (entityIn instanceof IAnimals)
{
this.track(entityIn, 80, 3, true);
}
else if (entityIn instanceof EntityTNTPrimed)
{
this.track(entityIn, 160, 10, true);
}
else if (entityIn instanceof EntityFallingBlock)
{
this.track(entityIn, 160, 20, true);
}
else if (entityIn instanceof EntityHanging)
{
this.track(entityIn, 160, Integer.MAX_VALUE, false);
}
else if (entityIn instanceof EntityArmorStand)
{
this.track(entityIn, 160, 3, true);
}
else if (entityIn instanceof EntityXPOrb)
{
this.track(entityIn, 160, 20, true);
}
else if (entityIn instanceof EntityAreaEffectCloud)
{
this.track(entityIn, 160, Integer.MAX_VALUE, true);
}
else if (entityIn instanceof EntityEnderCrystal)
{
this.track(entityIn, 256, Integer.MAX_VALUE, false);
}
else if (entityIn instanceof EntityEvokerFangs)
{
this.track(entityIn, 160, 2, false);
}
}
public void track(Entity entityIn, int trackingRange, int updateFrequency)
{
this.track(entityIn, trackingRange, updateFrequency, false);
}
/**
* Args : Entity, trackingRange, updateFrequency, sendVelocityUpdates
*/
public void track(Entity entityIn, int trackingRange, final int updateFrequency, boolean sendVelocityUpdates)
{
try
{
if (this.trackedEntityHashTable.containsItem(entityIn.getEntityId()))
{
throw new IllegalStateException("Entity is already tracked!");
}
EntityTrackerEntry entitytrackerentry = new EntityTrackerEntry(entityIn, trackingRange, this.maxTrackingDistanceThreshold, updateFrequency, sendVelocityUpdates);
this.entries.add(entitytrackerentry);
this.trackedEntityHashTable.addKey(entityIn.getEntityId(), entitytrackerentry);
entitytrackerentry.updatePlayerEntities(this.world.playerEntities);
}
catch (Throwable throwable)
{
CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Adding entity to track");
CrashReportCategory crashreportcategory = crashreport.makeCategory("Entity To Track");
crashreportcategory.addCrashSection("Tracking range", trackingRange + " blocks");
crashreportcategory.addDetail("Update interval", new ICrashReportDetail<String>()
{
public String call() throws Exception
{
String s = "Once per " + updateFrequency + " ticks";
if (updateFrequency == Integer.MAX_VALUE)
{
s = "Maximum (" + s + ")";
}
return s;
}
});
entityIn.addEntityCrashInfo(crashreportcategory);
((EntityTrackerEntry)this.trackedEntityHashTable.lookup(entityIn.getEntityId())).getTrackedEntity().addEntityCrashInfo(crashreport.makeCategory("Entity That Is Already Tracked"));
try
{
throw new ReportedException(crashreport);
}
catch (ReportedException reportedexception)
{
LOGGER.error("\"Silently\" catching entity tracking error.", (Throwable)reportedexception);
}
}
}
public void untrack(Entity entityIn)
{
if (entityIn instanceof EntityPlayerMP)
{
EntityPlayerMP entityplayermp = (EntityPlayerMP)entityIn;
for (EntityTrackerEntry entitytrackerentry : this.entries)
{
entitytrackerentry.removeFromTrackedPlayers(entityplayermp);
}
}
EntityTrackerEntry entitytrackerentry1 = this.trackedEntityHashTable.removeObject(entityIn.getEntityId());
if (entitytrackerentry1 != null)
{
this.entries.remove(entitytrackerentry1);
entitytrackerentry1.sendDestroyEntityPacketToTrackedPlayers();
}
}
public void tick()
{
List<EntityPlayerMP> list = Lists.<EntityPlayerMP>newArrayList();
for (EntityTrackerEntry entitytrackerentry : this.entries)
{
entitytrackerentry.updatePlayerList(this.world.playerEntities);
if (entitytrackerentry.playerEntitiesUpdated)
{
Entity entity = entitytrackerentry.getTrackedEntity();
if (entity instanceof EntityPlayerMP)
{
list.add((EntityPlayerMP)entity);
}
}
}
for (int i = 0; i < list.size(); ++i)
{
EntityPlayerMP entityplayermp = list.get(i);
for (EntityTrackerEntry entitytrackerentry1 : this.entries)
{
if (entitytrackerentry1.getTrackedEntity() != entityplayermp)
{
entitytrackerentry1.updatePlayerEntity(entityplayermp);
}
}
}
}
public void updateVisibility(EntityPlayerMP player)
{
for (EntityTrackerEntry entitytrackerentry : this.entries)
{
if (entitytrackerentry.getTrackedEntity() == player)
{
entitytrackerentry.updatePlayerEntities(this.world.playerEntities);
}
else
{
entitytrackerentry.updatePlayerEntity(player);
}
}
}
public void sendToTracking(Entity entityIn, Packet<?> packetIn)
{
EntityTrackerEntry entitytrackerentry = this.trackedEntityHashTable.lookup(entityIn.getEntityId());
if (entitytrackerentry != null)
{
entitytrackerentry.sendPacketToTrackedPlayers(packetIn);
}
}
/* ======================================== FORGE START =====================================*/
// don't expose the EntityTrackerEntry directly so mods can't mess with the data in there as easily
/**
* Get all players tracking the given Entity. The Entity must be part of the World that this Tracker belongs to.
* @param entity the Entity
* @return all players tracking the Entity
*/
public Set<? extends net.minecraft.entity.player.EntityPlayer> getTrackingPlayers(Entity entity)
{
EntityTrackerEntry entry = (EntityTrackerEntry) trackedEntityHashTable.lookup(entity.getEntityId());
if (entry == null)
return java.util.Collections.emptySet();
else
return java.util.Collections.unmodifiableSet(entry.trackingPlayers);
}
/* ======================================== FORGE END =====================================*/
public void sendToTrackingAndSelf(Entity entityIn, Packet<?> packetIn)
{
EntityTrackerEntry entitytrackerentry = this.trackedEntityHashTable.lookup(entityIn.getEntityId());
if (entitytrackerentry != null)
{
entitytrackerentry.sendToTrackingAndSelf(packetIn);
}
}
public void removePlayerFromTrackers(EntityPlayerMP player)
{
for (EntityTrackerEntry entitytrackerentry : this.entries)
{
entitytrackerentry.removeTrackedPlayerSymmetric(player);
}
}
/**
* Send packets to player for every tracked entity in this chunk that is either leashed to something or someone, or
* has passengers
*/
public void sendLeashedEntitiesInChunk(EntityPlayerMP player, Chunk chunkIn)
{
List<Entity> list = Lists.<Entity>newArrayList();
List<Entity> list1 = Lists.<Entity>newArrayList();
for (EntityTrackerEntry entitytrackerentry : this.entries)
{
Entity entity = entitytrackerentry.getTrackedEntity();
if (entity != player && entity.chunkCoordX == chunkIn.x && entity.chunkCoordZ == chunkIn.z)
{
entitytrackerentry.updatePlayerEntity(player);
if (entity instanceof EntityLiving && ((EntityLiving)entity).getLeashHolder() != null)
{
list.add(entity);
}
if (!entity.getPassengers().isEmpty())
{
list1.add(entity);
}
}
}
if (!list.isEmpty())
{
for (Entity entity1 : list)
{
player.connection.sendPacket(new SPacketEntityAttach(entity1, ((EntityLiving)entity1).getLeashHolder()));
}
}
if (!list1.isEmpty())
{
for (Entity entity2 : list1)
{
player.connection.sendPacket(new SPacketSetPassengers(entity2));
}
}
}
public void setViewDistance(int p_187252_1_)
{
this.maxTrackingDistanceThreshold = (p_187252_1_ - 1) * 16;
for (EntityTrackerEntry entitytrackerentry : this.entries)
{
entitytrackerentry.setMaxRange(this.maxTrackingDistanceThreshold);
}
}
}

View File

@@ -0,0 +1,712 @@
package net.minecraft.entity;
import com.google.common.collect.Sets;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import net.minecraft.block.Block;
import net.minecraft.entity.ai.attributes.AttributeMap;
import net.minecraft.entity.ai.attributes.IAttributeInstance;
import net.minecraft.entity.item.EntityArmorStand;
import net.minecraft.entity.item.EntityBoat;
import net.minecraft.entity.item.EntityEnderCrystal;
import net.minecraft.entity.item.EntityEnderEye;
import net.minecraft.entity.item.EntityEnderPearl;
import net.minecraft.entity.item.EntityExpBottle;
import net.minecraft.entity.item.EntityFallingBlock;
import net.minecraft.entity.item.EntityFireworkRocket;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.item.EntityItemFrame;
import net.minecraft.entity.item.EntityMinecart;
import net.minecraft.entity.item.EntityPainting;
import net.minecraft.entity.item.EntityTNTPrimed;
import net.minecraft.entity.item.EntityXPOrb;
import net.minecraft.entity.passive.IAnimals;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.entity.projectile.EntityArrow;
import net.minecraft.entity.projectile.EntityDragonFireball;
import net.minecraft.entity.projectile.EntityEgg;
import net.minecraft.entity.projectile.EntityEvokerFangs;
import net.minecraft.entity.projectile.EntityFireball;
import net.minecraft.entity.projectile.EntityFishHook;
import net.minecraft.entity.projectile.EntityLlamaSpit;
import net.minecraft.entity.projectile.EntityPotion;
import net.minecraft.entity.projectile.EntityShulkerBullet;
import net.minecraft.entity.projectile.EntitySmallFireball;
import net.minecraft.entity.projectile.EntitySnowball;
import net.minecraft.entity.projectile.EntitySpectralArrow;
import net.minecraft.entity.projectile.EntityTippedArrow;
import net.minecraft.entity.projectile.EntityWitherSkull;
import net.minecraft.init.Items;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.ItemMap;
import net.minecraft.item.ItemStack;
import net.minecraft.network.Packet;
import net.minecraft.network.datasync.EntityDataManager;
import net.minecraft.network.play.server.SPacketEntity;
import net.minecraft.network.play.server.SPacketEntityEffect;
import net.minecraft.network.play.server.SPacketEntityEquipment;
import net.minecraft.network.play.server.SPacketEntityHeadLook;
import net.minecraft.network.play.server.SPacketEntityMetadata;
import net.minecraft.network.play.server.SPacketEntityProperties;
import net.minecraft.network.play.server.SPacketEntityTeleport;
import net.minecraft.network.play.server.SPacketEntityVelocity;
import net.minecraft.network.play.server.SPacketSetPassengers;
import net.minecraft.network.play.server.SPacketSpawnExperienceOrb;
import net.minecraft.network.play.server.SPacketSpawnMob;
import net.minecraft.network.play.server.SPacketSpawnObject;
import net.minecraft.network.play.server.SPacketSpawnPainting;
import net.minecraft.network.play.server.SPacketSpawnPlayer;
import net.minecraft.network.play.server.SPacketUseBed;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.storage.MapData;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class EntityTrackerEntry
{
private static final Logger LOGGER = LogManager.getLogger();
/** The entity that this EntityTrackerEntry tracks. */
private final Entity trackedEntity;
private final int range;
private int maxRange;
/** check for sync when ticks % updateFrequency==0 */
private final int updateFrequency;
/** The encoded entity X position. */
private long encodedPosX;
/** The encoded entity Y position. */
private long encodedPosY;
/** The encoded entity Z position. */
private long encodedPosZ;
/** The encoded entity yaw rotation. */
private int encodedRotationYaw;
/** The encoded entity pitch rotation. */
private int encodedRotationPitch;
private int lastHeadMotion;
private double lastTrackedEntityMotionX;
private double lastTrackedEntityMotionY;
private double motionZ;
public int updateCounter;
private double lastTrackedEntityPosX;
private double lastTrackedEntityPosY;
private double lastTrackedEntityPosZ;
private boolean updatedPlayerVisibility;
private final boolean sendVelocityUpdates;
/**
* every 400 ticks a full teleport packet is sent, rather than just a "move me +x" command, so that position
* remains fully synced.
*/
private int ticksSinceLastForcedTeleport;
private List<Entity> passengers = Collections.<Entity>emptyList();
private boolean ridingEntity;
private boolean onGround;
public boolean playerEntitiesUpdated;
/** Holds references to all the players that are currently receiving position updates for this entity. */
public final Set<EntityPlayerMP> trackingPlayers = Sets.<EntityPlayerMP>newHashSet();
public EntityTrackerEntry(Entity entityIn, int rangeIn, int maxRangeIn, int updateFrequencyIn, boolean sendVelocityUpdatesIn)
{
this.trackedEntity = entityIn;
this.range = rangeIn;
this.maxRange = maxRangeIn;
this.updateFrequency = updateFrequencyIn;
this.sendVelocityUpdates = sendVelocityUpdatesIn;
this.encodedPosX = EntityTracker.getPositionLong(entityIn.posX);
this.encodedPosY = EntityTracker.getPositionLong(entityIn.posY);
this.encodedPosZ = EntityTracker.getPositionLong(entityIn.posZ);
this.encodedRotationYaw = MathHelper.floor(entityIn.rotationYaw * 256.0F / 360.0F);
this.encodedRotationPitch = MathHelper.floor(entityIn.rotationPitch * 256.0F / 360.0F);
this.lastHeadMotion = MathHelper.floor(entityIn.getRotationYawHead() * 256.0F / 360.0F);
this.onGround = entityIn.onGround;
}
public boolean equals(Object p_equals_1_)
{
if (p_equals_1_ instanceof EntityTrackerEntry)
{
return ((EntityTrackerEntry)p_equals_1_).trackedEntity.getEntityId() == this.trackedEntity.getEntityId();
}
else
{
return false;
}
}
public int hashCode()
{
return this.trackedEntity.getEntityId();
}
public void updatePlayerList(List<EntityPlayer> players)
{
this.playerEntitiesUpdated = false;
if (!this.updatedPlayerVisibility || this.trackedEntity.getDistanceSq(this.lastTrackedEntityPosX, this.lastTrackedEntityPosY, this.lastTrackedEntityPosZ) > 16.0D)
{
this.lastTrackedEntityPosX = this.trackedEntity.posX;
this.lastTrackedEntityPosY = this.trackedEntity.posY;
this.lastTrackedEntityPosZ = this.trackedEntity.posZ;
this.updatedPlayerVisibility = true;
this.playerEntitiesUpdated = true;
this.updatePlayerEntities(players);
}
List<Entity> list = this.trackedEntity.getPassengers();
if (!list.equals(this.passengers))
{
this.passengers = list;
this.sendPacketToTrackedPlayers(new SPacketSetPassengers(this.trackedEntity));
}
if (this.trackedEntity instanceof EntityItemFrame && this.updateCounter % 10 == 0)
{
EntityItemFrame entityitemframe = (EntityItemFrame)this.trackedEntity;
ItemStack itemstack = entityitemframe.getDisplayedItem();
if (itemstack.getItem() instanceof ItemMap)
{
MapData mapdata = ((ItemMap) itemstack.getItem()).getMapData(itemstack, this.trackedEntity.world);
for (EntityPlayer entityplayer : players)
{
EntityPlayerMP entityplayermp = (EntityPlayerMP)entityplayer;
mapdata.updateVisiblePlayers(entityplayermp, itemstack);
Packet<?> packet = ((ItemMap) itemstack.getItem()).createMapDataPacket(itemstack, this.trackedEntity.world, entityplayermp);
if (packet != null)
{
entityplayermp.connection.sendPacket(packet);
}
}
}
this.sendMetadata();
}
if (this.updateCounter % this.updateFrequency == 0 || this.trackedEntity.isAirBorne || this.trackedEntity.getDataManager().isDirty())
{
if (this.trackedEntity.isRiding())
{
int j1 = MathHelper.floor(this.trackedEntity.rotationYaw * 256.0F / 360.0F);
int l1 = MathHelper.floor(this.trackedEntity.rotationPitch * 256.0F / 360.0F);
boolean flag3 = Math.abs(j1 - this.encodedRotationYaw) >= 1 || Math.abs(l1 - this.encodedRotationPitch) >= 1;
if (flag3)
{
this.sendPacketToTrackedPlayers(new SPacketEntity.S16PacketEntityLook(this.trackedEntity.getEntityId(), (byte)j1, (byte)l1, this.trackedEntity.onGround));
this.encodedRotationYaw = j1;
this.encodedRotationPitch = l1;
}
this.encodedPosX = EntityTracker.getPositionLong(this.trackedEntity.posX);
this.encodedPosY = EntityTracker.getPositionLong(this.trackedEntity.posY);
this.encodedPosZ = EntityTracker.getPositionLong(this.trackedEntity.posZ);
this.sendMetadata();
this.ridingEntity = true;
}
else
{
++this.ticksSinceLastForcedTeleport;
long i1 = EntityTracker.getPositionLong(this.trackedEntity.posX);
long i2 = EntityTracker.getPositionLong(this.trackedEntity.posY);
long j2 = EntityTracker.getPositionLong(this.trackedEntity.posZ);
int k2 = MathHelper.floor(this.trackedEntity.rotationYaw * 256.0F / 360.0F);
int i = MathHelper.floor(this.trackedEntity.rotationPitch * 256.0F / 360.0F);
long j = i1 - this.encodedPosX;
long k = i2 - this.encodedPosY;
long l = j2 - this.encodedPosZ;
Packet<?> packet1 = null;
boolean flag = j * j + k * k + l * l >= 128L || this.updateCounter % 60 == 0;
boolean flag1 = Math.abs(k2 - this.encodedRotationYaw) >= 1 || Math.abs(i - this.encodedRotationPitch) >= 1;
if (this.updateCounter > 0 || this.trackedEntity instanceof EntityArrow)
{
if (j >= -32768L && j < 32768L && k >= -32768L && k < 32768L && l >= -32768L && l < 32768L && this.ticksSinceLastForcedTeleport <= 400 && !this.ridingEntity && this.onGround == this.trackedEntity.onGround)
{
if ((!flag || !flag1) && !(this.trackedEntity instanceof EntityArrow))
{
if (flag)
{
packet1 = new SPacketEntity.S15PacketEntityRelMove(this.trackedEntity.getEntityId(), j, k, l, this.trackedEntity.onGround);
}
else if (flag1)
{
packet1 = new SPacketEntity.S16PacketEntityLook(this.trackedEntity.getEntityId(), (byte)k2, (byte)i, this.trackedEntity.onGround);
}
}
else
{
packet1 = new SPacketEntity.S17PacketEntityLookMove(this.trackedEntity.getEntityId(), j, k, l, (byte)k2, (byte)i, this.trackedEntity.onGround);
}
}
else
{
this.onGround = this.trackedEntity.onGround;
this.ticksSinceLastForcedTeleport = 0;
this.resetPlayerVisibility();
packet1 = new SPacketEntityTeleport(this.trackedEntity);
}
}
boolean flag2 = this.sendVelocityUpdates;
if (this.trackedEntity instanceof EntityLivingBase && ((EntityLivingBase)this.trackedEntity).isElytraFlying())
{
flag2 = true;
}
if (flag2 && this.updateCounter > 0)
{
double d0 = this.trackedEntity.motionX - this.lastTrackedEntityMotionX;
double d1 = this.trackedEntity.motionY - this.lastTrackedEntityMotionY;
double d2 = this.trackedEntity.motionZ - this.motionZ;
double d3 = 0.02D;
double d4 = d0 * d0 + d1 * d1 + d2 * d2;
if (d4 > 4.0E-4D || d4 > 0.0D && this.trackedEntity.motionX == 0.0D && this.trackedEntity.motionY == 0.0D && this.trackedEntity.motionZ == 0.0D)
{
this.lastTrackedEntityMotionX = this.trackedEntity.motionX;
this.lastTrackedEntityMotionY = this.trackedEntity.motionY;
this.motionZ = this.trackedEntity.motionZ;
this.sendPacketToTrackedPlayers(new SPacketEntityVelocity(this.trackedEntity.getEntityId(), this.lastTrackedEntityMotionX, this.lastTrackedEntityMotionY, this.motionZ));
}
}
if (packet1 != null)
{
this.sendPacketToTrackedPlayers(packet1);
}
this.sendMetadata();
if (flag)
{
this.encodedPosX = i1;
this.encodedPosY = i2;
this.encodedPosZ = j2;
}
if (flag1)
{
this.encodedRotationYaw = k2;
this.encodedRotationPitch = i;
}
this.ridingEntity = false;
}
int k1 = MathHelper.floor(this.trackedEntity.getRotationYawHead() * 256.0F / 360.0F);
if (Math.abs(k1 - this.lastHeadMotion) >= 1)
{
this.sendPacketToTrackedPlayers(new SPacketEntityHeadLook(this.trackedEntity, (byte)k1));
this.lastHeadMotion = k1;
}
this.trackedEntity.isAirBorne = false;
}
++this.updateCounter;
if (this.trackedEntity.velocityChanged)
{
this.sendToTrackingAndSelf(new SPacketEntityVelocity(this.trackedEntity));
this.trackedEntity.velocityChanged = false;
}
}
/**
* Sends the entity metadata (DataWatcher) and attributes to all players tracking this entity, including the entity
* itself if a player.
*/
private void sendMetadata()
{
EntityDataManager entitydatamanager = this.trackedEntity.getDataManager();
if (entitydatamanager.isDirty())
{
this.sendToTrackingAndSelf(new SPacketEntityMetadata(this.trackedEntity.getEntityId(), entitydatamanager, false));
}
if (this.trackedEntity instanceof EntityLivingBase)
{
AttributeMap attributemap = (AttributeMap)((EntityLivingBase)this.trackedEntity).getAttributeMap();
Set<IAttributeInstance> set = attributemap.getDirtyInstances();
if (!set.isEmpty())
{
this.sendToTrackingAndSelf(new SPacketEntityProperties(this.trackedEntity.getEntityId(), set));
}
set.clear();
}
}
/**
* Send the given packet to all players tracking this entity.
*/
public void sendPacketToTrackedPlayers(Packet<?> packetIn)
{
for (EntityPlayerMP entityplayermp : this.trackingPlayers)
{
entityplayermp.connection.sendPacket(packetIn);
}
}
public void sendToTrackingAndSelf(Packet<?> packetIn)
{
this.sendPacketToTrackedPlayers(packetIn);
if (this.trackedEntity instanceof EntityPlayerMP)
{
((EntityPlayerMP)this.trackedEntity).connection.sendPacket(packetIn);
}
}
public void sendDestroyEntityPacketToTrackedPlayers()
{
for (EntityPlayerMP entityplayermp : this.trackingPlayers)
{
this.trackedEntity.removeTrackingPlayer(entityplayermp);
entityplayermp.removeEntity(this.trackedEntity);
}
}
public void removeFromTrackedPlayers(EntityPlayerMP playerMP)
{
if (this.trackingPlayers.contains(playerMP))
{
this.trackedEntity.removeTrackingPlayer(playerMP);
playerMP.removeEntity(this.trackedEntity);
this.trackingPlayers.remove(playerMP);
}
}
public void updatePlayerEntity(EntityPlayerMP playerMP)
{
if (playerMP != this.trackedEntity)
{
if (this.isVisibleTo(playerMP))
{
if (!this.trackingPlayers.contains(playerMP) && (this.isPlayerWatchingThisChunk(playerMP) || this.trackedEntity.forceSpawn))
{
this.trackingPlayers.add(playerMP);
Packet<?> packet = this.createSpawnPacket();
playerMP.connection.sendPacket(packet);
if (!this.trackedEntity.getDataManager().isEmpty())
{
playerMP.connection.sendPacket(new SPacketEntityMetadata(this.trackedEntity.getEntityId(), this.trackedEntity.getDataManager(), true));
}
boolean flag = this.sendVelocityUpdates;
if (this.trackedEntity instanceof EntityLivingBase)
{
AttributeMap attributemap = (AttributeMap)((EntityLivingBase)this.trackedEntity).getAttributeMap();
Collection<IAttributeInstance> collection = attributemap.getWatchedAttributes();
if (!collection.isEmpty())
{
playerMP.connection.sendPacket(new SPacketEntityProperties(this.trackedEntity.getEntityId(), collection));
}
if (((EntityLivingBase)this.trackedEntity).isElytraFlying())
{
flag = true;
}
}
this.lastTrackedEntityMotionX = this.trackedEntity.motionX;
this.lastTrackedEntityMotionY = this.trackedEntity.motionY;
this.motionZ = this.trackedEntity.motionZ;
if (flag && !(packet instanceof SPacketSpawnMob))
{
playerMP.connection.sendPacket(new SPacketEntityVelocity(this.trackedEntity.getEntityId(), this.trackedEntity.motionX, this.trackedEntity.motionY, this.trackedEntity.motionZ));
}
if (this.trackedEntity instanceof EntityLivingBase)
{
for (EntityEquipmentSlot entityequipmentslot : EntityEquipmentSlot.values())
{
ItemStack itemstack = ((EntityLivingBase)this.trackedEntity).getItemStackFromSlot(entityequipmentslot);
if (!itemstack.isEmpty())
{
playerMP.connection.sendPacket(new SPacketEntityEquipment(this.trackedEntity.getEntityId(), entityequipmentslot, itemstack));
}
}
}
if (this.trackedEntity instanceof EntityPlayer)
{
EntityPlayer entityplayer = (EntityPlayer)this.trackedEntity;
if (entityplayer.isPlayerSleeping())
{
playerMP.connection.sendPacket(new SPacketUseBed(entityplayer, new BlockPos(this.trackedEntity)));
}
}
if (this.trackedEntity instanceof EntityLivingBase)
{
EntityLivingBase entitylivingbase = (EntityLivingBase)this.trackedEntity;
for (PotionEffect potioneffect : entitylivingbase.getActivePotionEffects())
{
playerMP.connection.sendPacket(new SPacketEntityEffect(this.trackedEntity.getEntityId(), potioneffect));
}
}
if (!this.trackedEntity.getPassengers().isEmpty())
{
playerMP.connection.sendPacket(new SPacketSetPassengers(this.trackedEntity));
}
if (this.trackedEntity.isRiding())
{
playerMP.connection.sendPacket(new SPacketSetPassengers(this.trackedEntity.getRidingEntity()));
}
this.trackedEntity.addTrackingPlayer(playerMP);
playerMP.addEntity(this.trackedEntity);
net.minecraftforge.event.ForgeEventFactory.onStartEntityTracking(trackedEntity, playerMP);
}
}
else if (this.trackingPlayers.contains(playerMP))
{
this.trackingPlayers.remove(playerMP);
this.trackedEntity.removeTrackingPlayer(playerMP);
playerMP.removeEntity(this.trackedEntity);
net.minecraftforge.event.ForgeEventFactory.onStopEntityTracking(trackedEntity, playerMP);
}
}
}
public boolean isVisibleTo(EntityPlayerMP playerMP)
{
double d0 = playerMP.posX - (double)this.encodedPosX / 4096.0D;
double d1 = playerMP.posZ - (double)this.encodedPosZ / 4096.0D;
int i = Math.min(this.range, this.maxRange);
return d0 >= (double)(-i) && d0 <= (double)i && d1 >= (double)(-i) && d1 <= (double)i && this.trackedEntity.isSpectatedByPlayer(playerMP);
}
private boolean isPlayerWatchingThisChunk(EntityPlayerMP playerMP)
{
return playerMP.getServerWorld().getPlayerChunkMap().isPlayerWatchingChunk(playerMP, this.trackedEntity.chunkCoordX, this.trackedEntity.chunkCoordZ);
}
public void updatePlayerEntities(List<EntityPlayer> players)
{
for (int i = 0; i < players.size(); ++i)
{
this.updatePlayerEntity((EntityPlayerMP)players.get(i));
}
}
/**
* Creates a spawn packet for the entity managed by this entry.
*/
private Packet<?> createSpawnPacket()
{
if (this.trackedEntity.isDead)
{
LOGGER.warn("Fetching addPacket for removed entity");
}
Packet pkt = net.minecraftforge.fml.common.network.internal.FMLNetworkHandler.getEntitySpawningPacket(this.trackedEntity);
if (pkt != null) return pkt;
if (this.trackedEntity instanceof EntityPlayerMP)
{
return new SPacketSpawnPlayer((EntityPlayer)this.trackedEntity);
}
else if (this.trackedEntity instanceof IAnimals)
{
this.lastHeadMotion = MathHelper.floor(this.trackedEntity.getRotationYawHead() * 256.0F / 360.0F);
return new SPacketSpawnMob((EntityLivingBase)this.trackedEntity);
}
else if (this.trackedEntity instanceof EntityPainting)
{
return new SPacketSpawnPainting((EntityPainting)this.trackedEntity);
}
else if (this.trackedEntity instanceof EntityItem)
{
return new SPacketSpawnObject(this.trackedEntity, 2, 1);
}
else if (this.trackedEntity instanceof EntityMinecart)
{
EntityMinecart entityminecart = (EntityMinecart)this.trackedEntity;
return new SPacketSpawnObject(this.trackedEntity, 10, entityminecart.getType().getId());
}
else if (this.trackedEntity instanceof EntityBoat)
{
return new SPacketSpawnObject(this.trackedEntity, 1);
}
else if (this.trackedEntity instanceof EntityXPOrb)
{
return new SPacketSpawnExperienceOrb((EntityXPOrb)this.trackedEntity);
}
else if (this.trackedEntity instanceof EntityFishHook)
{
Entity entity2 = ((EntityFishHook)this.trackedEntity).getAngler();
return new SPacketSpawnObject(this.trackedEntity, 90, entity2 == null ? this.trackedEntity.getEntityId() : entity2.getEntityId());
}
else if (this.trackedEntity instanceof EntitySpectralArrow)
{
Entity entity1 = ((EntitySpectralArrow)this.trackedEntity).shootingEntity;
return new SPacketSpawnObject(this.trackedEntity, 91, 1 + (entity1 == null ? this.trackedEntity.getEntityId() : entity1.getEntityId()));
}
else if (this.trackedEntity instanceof EntityTippedArrow)
{
Entity entity = ((EntityArrow)this.trackedEntity).shootingEntity;
return new SPacketSpawnObject(this.trackedEntity, 60, 1 + (entity == null ? this.trackedEntity.getEntityId() : entity.getEntityId()));
}
else if (this.trackedEntity instanceof EntitySnowball)
{
return new SPacketSpawnObject(this.trackedEntity, 61);
}
else if (this.trackedEntity instanceof EntityLlamaSpit)
{
return new SPacketSpawnObject(this.trackedEntity, 68);
}
else if (this.trackedEntity instanceof EntityPotion)
{
return new SPacketSpawnObject(this.trackedEntity, 73);
}
else if (this.trackedEntity instanceof EntityExpBottle)
{
return new SPacketSpawnObject(this.trackedEntity, 75);
}
else if (this.trackedEntity instanceof EntityEnderPearl)
{
return new SPacketSpawnObject(this.trackedEntity, 65);
}
else if (this.trackedEntity instanceof EntityEnderEye)
{
return new SPacketSpawnObject(this.trackedEntity, 72);
}
else if (this.trackedEntity instanceof EntityFireworkRocket)
{
return new SPacketSpawnObject(this.trackedEntity, 76);
}
else if (this.trackedEntity instanceof EntityFireball)
{
EntityFireball entityfireball = (EntityFireball)this.trackedEntity;
SPacketSpawnObject spacketspawnobject = null;
int i = 63;
if (this.trackedEntity instanceof EntitySmallFireball)
{
i = 64;
}
else if (this.trackedEntity instanceof EntityDragonFireball)
{
i = 93;
}
else if (this.trackedEntity instanceof EntityWitherSkull)
{
i = 66;
}
if (entityfireball.shootingEntity != null)
{
spacketspawnobject = new SPacketSpawnObject(this.trackedEntity, i, ((EntityFireball)this.trackedEntity).shootingEntity.getEntityId());
}
else
{
spacketspawnobject = new SPacketSpawnObject(this.trackedEntity, i, 0);
}
spacketspawnobject.setSpeedX((int)(entityfireball.accelerationX * 8000.0D));
spacketspawnobject.setSpeedY((int)(entityfireball.accelerationY * 8000.0D));
spacketspawnobject.setSpeedZ((int)(entityfireball.accelerationZ * 8000.0D));
return spacketspawnobject;
}
else if (this.trackedEntity instanceof EntityShulkerBullet)
{
SPacketSpawnObject spacketspawnobject1 = new SPacketSpawnObject(this.trackedEntity, 67, 0);
spacketspawnobject1.setSpeedX((int)(this.trackedEntity.motionX * 8000.0D));
spacketspawnobject1.setSpeedY((int)(this.trackedEntity.motionY * 8000.0D));
spacketspawnobject1.setSpeedZ((int)(this.trackedEntity.motionZ * 8000.0D));
return spacketspawnobject1;
}
else if (this.trackedEntity instanceof EntityEgg)
{
return new SPacketSpawnObject(this.trackedEntity, 62);
}
else if (this.trackedEntity instanceof EntityEvokerFangs)
{
return new SPacketSpawnObject(this.trackedEntity, 79);
}
else if (this.trackedEntity instanceof EntityTNTPrimed)
{
return new SPacketSpawnObject(this.trackedEntity, 50);
}
else if (this.trackedEntity instanceof EntityEnderCrystal)
{
return new SPacketSpawnObject(this.trackedEntity, 51);
}
else if (this.trackedEntity instanceof EntityFallingBlock)
{
EntityFallingBlock entityfallingblock = (EntityFallingBlock)this.trackedEntity;
return new SPacketSpawnObject(this.trackedEntity, 70, Block.getStateId(entityfallingblock.getBlock()));
}
else if (this.trackedEntity instanceof EntityArmorStand)
{
return new SPacketSpawnObject(this.trackedEntity, 78);
}
else if (this.trackedEntity instanceof EntityItemFrame)
{
EntityItemFrame entityitemframe = (EntityItemFrame)this.trackedEntity;
return new SPacketSpawnObject(this.trackedEntity, 71, entityitemframe.facingDirection.getHorizontalIndex(), entityitemframe.getHangingPosition());
}
else if (this.trackedEntity instanceof EntityLeashKnot)
{
EntityLeashKnot entityleashknot = (EntityLeashKnot)this.trackedEntity;
return new SPacketSpawnObject(this.trackedEntity, 77, 0, entityleashknot.getHangingPosition());
}
else if (this.trackedEntity instanceof EntityAreaEffectCloud)
{
return new SPacketSpawnObject(this.trackedEntity, 3);
}
else
{
throw new IllegalArgumentException("Don't know how to add " + this.trackedEntity.getClass() + "!");
}
}
/**
* Remove a tracked player from our list and tell the tracked player to destroy us from their world.
*/
public void removeTrackedPlayerSymmetric(EntityPlayerMP playerMP)
{
if (this.trackingPlayers.contains(playerMP))
{
this.trackingPlayers.remove(playerMP);
this.trackedEntity.removeTrackingPlayer(playerMP);
playerMP.removeEntity(this.trackedEntity);
}
}
public Entity getTrackedEntity()
{
return this.trackedEntity;
}
public void setMaxRange(int maxRangeIn)
{
this.maxRange = maxRangeIn;
}
public void resetPlayerVisibility()
{
this.updatedPlayerVisibility = false;
}
}

View File

@@ -0,0 +1,9 @@
package net.minecraft.entity;
public enum EnumCreatureAttribute
{
UNDEFINED,
UNDEAD,
ARTHROPOD,
ILLAGER;
}

View File

@@ -0,0 +1,59 @@
package net.minecraft.entity;
import net.minecraft.block.material.Material;
import net.minecraft.entity.monster.IMob;
import net.minecraft.entity.passive.EntityAmbientCreature;
import net.minecraft.entity.passive.EntityAnimal;
import net.minecraft.entity.passive.EntityWaterMob;
import net.minecraft.entity.passive.IAnimals;
public enum EnumCreatureType
{
MONSTER(IMob.class, 70, Material.AIR, false, false),
CREATURE(EntityAnimal.class, 10, Material.AIR, true, true),
AMBIENT(EntityAmbientCreature.class, 15, Material.AIR, true, false),
WATER_CREATURE(EntityWaterMob.class, 5, Material.WATER, true, false);
private final Class <? extends IAnimals > creatureClass;
private final int maxNumberOfCreature;
private final Material creatureMaterial;
/** A flag indicating whether this creature type is peaceful. */
private final boolean isPeacefulCreature;
/** Whether this creature type is an animal. */
private final boolean isAnimal;
private EnumCreatureType(Class <? extends IAnimals > creatureClassIn, int maxNumberOfCreatureIn, Material creatureMaterialIn, boolean isPeacefulCreatureIn, boolean isAnimalIn)
{
this.creatureClass = creatureClassIn;
this.maxNumberOfCreature = maxNumberOfCreatureIn;
this.creatureMaterial = creatureMaterialIn;
this.isPeacefulCreature = isPeacefulCreatureIn;
this.isAnimal = isAnimalIn;
}
public Class <? extends IAnimals > getCreatureClass()
{
return this.creatureClass;
}
public int getMaxNumberOfCreature()
{
return this.maxNumberOfCreature;
}
/**
* Gets whether or not this creature type is peaceful.
*/
public boolean getPeacefulCreature()
{
return this.isPeacefulCreature;
}
/**
* Return whether this creature type is an animal.
*/
public boolean getAnimal()
{
return this.isAnimal;
}
}

View File

@@ -0,0 +1,5 @@
package net.minecraft.entity;
public interface IEntityLivingData
{
}

View File

@@ -0,0 +1,11 @@
package net.minecraft.entity;
import net.minecraft.util.DamageSource;
import net.minecraft.world.World;
public interface IEntityMultiPart
{
World getWorld();
boolean attackEntityFromPart(MultiPartEntityPart dragonPart, DamageSource source, float damage);
}

View File

@@ -0,0 +1,13 @@
package net.minecraft.entity;
import java.util.UUID;
import javax.annotation.Nullable;
public interface IEntityOwnable
{
@Nullable
UUID getOwnerId();
@Nullable
Entity getOwner();
}

View File

@@ -0,0 +1,16 @@
package net.minecraft.entity;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public interface IJumpingMount
{
@SideOnly(Side.CLIENT)
void setJumpPower(int jumpPowerIn);
boolean canJump();
void handleStartJump(int p_184775_1_);
void handleStopJump();
}

View File

@@ -0,0 +1,43 @@
package net.minecraft.entity;
import javax.annotation.Nullable;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.village.MerchantRecipe;
import net.minecraft.village.MerchantRecipeList;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public interface IMerchant
{
void setCustomer(@Nullable EntityPlayer player);
@Nullable
EntityPlayer getCustomer();
@Nullable
MerchantRecipeList getRecipes(EntityPlayer player);
@SideOnly(Side.CLIENT)
void setRecipes(@Nullable MerchantRecipeList recipeList);
void useRecipe(MerchantRecipe recipe);
/**
* Notifies the merchant of a possible merchantrecipe being fulfilled or not. Usually, this is just a sound byte
* being played depending if the suggested itemstack is not null.
*/
void verifySellingItem(ItemStack stack);
/**
* Get the formatted ChatComponent that will be used for the sender's username in chat
*/
ITextComponent getDisplayName();
World getWorld();
BlockPos getPos();
}

View File

@@ -0,0 +1,7 @@
package net.minecraft.entity;
import net.minecraft.entity.passive.IAnimals;
public interface INpc extends IAnimals
{
}

View File

@@ -0,0 +1,9 @@
package net.minecraft.entity;
public interface IProjectile
{
/**
* Similar to setArrowHeading, it's point the throwable entity to a x, y, z direction.
*/
void shoot(double x, double y, double z, float velocity, float inaccuracy);
}

View File

@@ -0,0 +1,11 @@
package net.minecraft.entity;
public interface IRangedAttackMob
{
/**
* Attack the specified entity using a ranged attack.
*/
void attackEntityWithRangedAttack(EntityLivingBase target, float distanceFactor);
void setSwingingArms(boolean swingingArms);
}

View File

@@ -0,0 +1,10 @@
package net.minecraft.entity;
public enum MoverType
{
SELF,
PLAYER,
PISTON,
SHULKER_BOX,
SHULKER;
}

View File

@@ -0,0 +1,61 @@
package net.minecraft.entity;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.DamageSource;
public class MultiPartEntityPart extends Entity
{
/** The dragon entity this dragon part belongs to */
public final IEntityMultiPart parent;
public final String partName;
public MultiPartEntityPart(IEntityMultiPart parent, String partName, float width, float height)
{
super(parent.getWorld());
this.setSize(width, height);
this.parent = parent;
this.partName = partName;
}
protected void entityInit()
{
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
protected void readEntityFromNBT(NBTTagCompound compound)
{
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
protected void writeEntityToNBT(NBTTagCompound compound)
{
}
/**
* Returns true if other Entities should be prevented from moving through this Entity.
*/
public boolean canBeCollidedWith()
{
return true;
}
/**
* Called when the entity is attacked.
*/
public boolean attackEntityFrom(DamageSource source, float amount)
{
return this.isEntityInvulnerable(source) ? false : this.parent.attackEntityFromPart(this, source, amount);
}
/**
* Returns true if Entity argument is equal to this Entity
*/
public boolean isEntityEqual(Entity entityIn)
{
return this == entityIn || this.parent == entityIn;
}
}

View File

@@ -0,0 +1,85 @@
package net.minecraft.entity;
import javax.annotation.Nullable;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.InventoryMerchant;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraft.village.MerchantRecipe;
import net.minecraft.village.MerchantRecipeList;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
public class NpcMerchant implements IMerchant
{
/** Instance of Merchants Inventory. */
private final InventoryMerchant merchantInventory;
/** This merchant's current player customer. */
private final EntityPlayer customer;
/** The MerchantRecipeList instance. */
private MerchantRecipeList recipeList;
private final ITextComponent name;
public NpcMerchant(EntityPlayer customerIn, ITextComponent nameIn)
{
this.customer = customerIn;
this.name = nameIn;
this.merchantInventory = new InventoryMerchant(customerIn, this);
}
@Nullable
public EntityPlayer getCustomer()
{
return this.customer;
}
public void setCustomer(@Nullable EntityPlayer player)
{
}
@Nullable
public MerchantRecipeList getRecipes(EntityPlayer player)
{
return this.recipeList;
}
public void setRecipes(@Nullable MerchantRecipeList recipeList)
{
this.recipeList = recipeList;
}
public void useRecipe(MerchantRecipe recipe)
{
recipe.incrementToolUses();
}
/**
* Notifies the merchant of a possible merchantrecipe being fulfilled or not. Usually, this is just a sound byte
* being played depending if the suggested itemstack is not null.
*/
public void verifySellingItem(ItemStack stack)
{
}
/**
* Get the formatted ChatComponent that will be used for the sender's username in chat
*/
public ITextComponent getDisplayName()
{
return (ITextComponent)(this.name != null ? this.name : new TextComponentTranslation("entity.Villager.name", new Object[0]));
}
public World getWorld()
{
return this.customer.world;
}
public BlockPos getPos()
{
return new BlockPos(this.customer);
}
}

View File

@@ -0,0 +1,150 @@
package net.minecraft.entity;
import java.util.Collection;
import java.util.UUID;
import javax.annotation.Nullable;
import net.minecraft.entity.ai.attributes.AbstractAttributeMap;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.entity.ai.attributes.IAttribute;
import net.minecraft.entity.ai.attributes.IAttributeInstance;
import net.minecraft.entity.ai.attributes.RangedAttribute;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class SharedMonsterAttributes
{
private static final Logger LOGGER = LogManager.getLogger();
public static final IAttribute MAX_HEALTH = (new RangedAttribute((IAttribute)null, "generic.maxHealth", 20.0D, Float.MIN_VALUE, 1024.0D)).setDescription("Max Health").setShouldWatch(true); // Forge: set smallest max-health value to fix MC-119183. This gets rounded to float so we use the smallest positive float value.
public static final IAttribute FOLLOW_RANGE = (new RangedAttribute((IAttribute)null, "generic.followRange", 32.0D, 0.0D, 2048.0D)).setDescription("Follow Range");
public static final IAttribute KNOCKBACK_RESISTANCE = (new RangedAttribute((IAttribute)null, "generic.knockbackResistance", 0.0D, 0.0D, 1.0D)).setDescription("Knockback Resistance");
public static final IAttribute MOVEMENT_SPEED = (new RangedAttribute((IAttribute)null, "generic.movementSpeed", 0.699999988079071D, 0.0D, 1024.0D)).setDescription("Movement Speed").setShouldWatch(true);
public static final IAttribute FLYING_SPEED = (new RangedAttribute((IAttribute)null, "generic.flyingSpeed", 0.4000000059604645D, 0.0D, 1024.0D)).setDescription("Flying Speed").setShouldWatch(true);
public static final IAttribute ATTACK_DAMAGE = new RangedAttribute((IAttribute)null, "generic.attackDamage", 2.0D, 0.0D, 2048.0D);
public static final IAttribute ATTACK_SPEED = (new RangedAttribute((IAttribute)null, "generic.attackSpeed", 4.0D, 0.0D, 1024.0D)).setShouldWatch(true);
public static final IAttribute ARMOR = (new RangedAttribute((IAttribute)null, "generic.armor", 0.0D, 0.0D, 30.0D)).setShouldWatch(true);
public static final IAttribute ARMOR_TOUGHNESS = (new RangedAttribute((IAttribute)null, "generic.armorToughness", 0.0D, 0.0D, 20.0D)).setShouldWatch(true);
public static final IAttribute LUCK = (new RangedAttribute((IAttribute)null, "generic.luck", 0.0D, -1024.0D, 1024.0D)).setShouldWatch(true);
/**
* Creates an NBTTagList from a BaseAttributeMap, including all its AttributeInstances
*/
public static NBTTagList writeBaseAttributeMapToNBT(AbstractAttributeMap map)
{
NBTTagList nbttaglist = new NBTTagList();
for (IAttributeInstance iattributeinstance : map.getAllAttributes())
{
nbttaglist.appendTag(writeAttributeInstanceToNBT(iattributeinstance));
}
return nbttaglist;
}
/**
* Creates an NBTTagCompound from an AttributeInstance, including its AttributeModifiers
*/
private static NBTTagCompound writeAttributeInstanceToNBT(IAttributeInstance instance)
{
NBTTagCompound nbttagcompound = new NBTTagCompound();
IAttribute iattribute = instance.getAttribute();
nbttagcompound.setString("Name", iattribute.getName());
nbttagcompound.setDouble("Base", instance.getBaseValue());
Collection<AttributeModifier> collection = instance.getModifiers();
if (collection != null && !collection.isEmpty())
{
NBTTagList nbttaglist = new NBTTagList();
for (AttributeModifier attributemodifier : collection)
{
if (attributemodifier.isSaved())
{
nbttaglist.appendTag(writeAttributeModifierToNBT(attributemodifier));
}
}
nbttagcompound.setTag("Modifiers", nbttaglist);
}
return nbttagcompound;
}
/**
* Creates an NBTTagCompound from an AttributeModifier
*/
public static NBTTagCompound writeAttributeModifierToNBT(AttributeModifier modifier)
{
NBTTagCompound nbttagcompound = new NBTTagCompound();
nbttagcompound.setString("Name", modifier.getName());
nbttagcompound.setDouble("Amount", modifier.getAmount());
nbttagcompound.setInteger("Operation", modifier.getOperation());
nbttagcompound.setUniqueId("UUID", modifier.getID());
return nbttagcompound;
}
public static void setAttributeModifiers(AbstractAttributeMap map, NBTTagList list)
{
for (int i = 0; i < list.tagCount(); ++i)
{
NBTTagCompound nbttagcompound = list.getCompoundTagAt(i);
IAttributeInstance iattributeinstance = map.getAttributeInstanceByName(nbttagcompound.getString("Name"));
if (iattributeinstance == null)
{
LOGGER.warn("Ignoring unknown attribute '{}'", (Object)nbttagcompound.getString("Name"));
}
else
{
applyModifiersToAttributeInstance(iattributeinstance, nbttagcompound);
}
}
}
private static void applyModifiersToAttributeInstance(IAttributeInstance instance, NBTTagCompound compound)
{
instance.setBaseValue(compound.getDouble("Base"));
if (compound.hasKey("Modifiers", 9))
{
NBTTagList nbttaglist = compound.getTagList("Modifiers", 10);
for (int i = 0; i < nbttaglist.tagCount(); ++i)
{
AttributeModifier attributemodifier = readAttributeModifierFromNBT(nbttaglist.getCompoundTagAt(i));
if (attributemodifier != null)
{
AttributeModifier attributemodifier1 = instance.getModifier(attributemodifier.getID());
if (attributemodifier1 != null)
{
instance.removeModifier(attributemodifier1);
}
instance.applyModifier(attributemodifier);
}
}
}
}
/**
* Creates an AttributeModifier from an NBTTagCompound
*/
@Nullable
public static AttributeModifier readAttributeModifierFromNBT(NBTTagCompound compound)
{
UUID uuid = compound.getUniqueId("UUID");
try
{
return new AttributeModifier(uuid, compound.getString("Name"), compound.getDouble("Amount"), compound.getInteger("Operation"));
}
catch (Exception exception)
{
LOGGER.warn("Unable to create attribute: {}", (Object)exception.getMessage());
return null;
}
}
}

View File

@@ -0,0 +1,205 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.pathfinding.Path;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public class EntityAIAttackMelee extends EntityAIBase
{
World world;
protected EntityCreature attacker;
/** An amount of decrementing ticks that allows the entity to attack once the tick reaches 0. */
protected int attackTick;
/** The speed with which the mob will approach the target */
double speedTowardsTarget;
/** When true, the mob will continue chasing its target, even if it can't find a path to them right now. */
boolean longMemory;
/** The PathEntity of our entity. */
Path path;
private int delayCounter;
private double targetX;
private double targetY;
private double targetZ;
protected final int attackInterval = 20;
private int failedPathFindingPenalty = 0;
private boolean canPenalize = false;
public EntityAIAttackMelee(EntityCreature creature, double speedIn, boolean useLongMemory)
{
this.attacker = creature;
this.world = creature.world;
this.speedTowardsTarget = speedIn;
this.longMemory = useLongMemory;
this.setMutexBits(3);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
EntityLivingBase entitylivingbase = this.attacker.getAttackTarget();
if (entitylivingbase == null)
{
return false;
}
else if (!entitylivingbase.isEntityAlive())
{
return false;
}
else
{
if (canPenalize)
{
if (--this.delayCounter <= 0)
{
this.path = this.attacker.getNavigator().getPathToEntityLiving(entitylivingbase);
this.delayCounter = 4 + this.attacker.getRNG().nextInt(7);
return this.path != null;
}
else
{
return true;
}
}
this.path = this.attacker.getNavigator().getPathToEntityLiving(entitylivingbase);
if (this.path != null)
{
return true;
}
else
{
return this.getAttackReachSqr(entitylivingbase) >= this.attacker.getDistanceSq(entitylivingbase.posX, entitylivingbase.getEntityBoundingBox().minY, entitylivingbase.posZ);
}
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
EntityLivingBase entitylivingbase = this.attacker.getAttackTarget();
if (entitylivingbase == null)
{
return false;
}
else if (!entitylivingbase.isEntityAlive())
{
return false;
}
else if (!this.longMemory)
{
return !this.attacker.getNavigator().noPath();
}
else if (!this.attacker.isWithinHomeDistanceFromPosition(new BlockPos(entitylivingbase)))
{
return false;
}
else
{
return !(entitylivingbase instanceof EntityPlayer) || !((EntityPlayer)entitylivingbase).isSpectator() && !((EntityPlayer)entitylivingbase).isCreative();
}
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.attacker.getNavigator().setPath(this.path, this.speedTowardsTarget);
this.delayCounter = 0;
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
EntityLivingBase entitylivingbase = this.attacker.getAttackTarget();
if (entitylivingbase instanceof EntityPlayer && (((EntityPlayer)entitylivingbase).isSpectator() || ((EntityPlayer)entitylivingbase).isCreative()))
{
this.attacker.setAttackTarget((EntityLivingBase)null);
}
this.attacker.getNavigator().clearPath();
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
EntityLivingBase entitylivingbase = this.attacker.getAttackTarget();
this.attacker.getLookHelper().setLookPositionWithEntity(entitylivingbase, 30.0F, 30.0F);
double d0 = this.attacker.getDistanceSq(entitylivingbase.posX, entitylivingbase.getEntityBoundingBox().minY, entitylivingbase.posZ);
--this.delayCounter;
if ((this.longMemory || this.attacker.getEntitySenses().canSee(entitylivingbase)) && this.delayCounter <= 0 && (this.targetX == 0.0D && this.targetY == 0.0D && this.targetZ == 0.0D || entitylivingbase.getDistanceSq(this.targetX, this.targetY, this.targetZ) >= 1.0D || this.attacker.getRNG().nextFloat() < 0.05F))
{
this.targetX = entitylivingbase.posX;
this.targetY = entitylivingbase.getEntityBoundingBox().minY;
this.targetZ = entitylivingbase.posZ;
this.delayCounter = 4 + this.attacker.getRNG().nextInt(7);
if (this.canPenalize)
{
this.delayCounter += failedPathFindingPenalty;
if (this.attacker.getNavigator().getPath() != null)
{
net.minecraft.pathfinding.PathPoint finalPathPoint = this.attacker.getNavigator().getPath().getFinalPathPoint();
if (finalPathPoint != null && entitylivingbase.getDistanceSq(finalPathPoint.x, finalPathPoint.y, finalPathPoint.z) < 1)
failedPathFindingPenalty = 0;
else
failedPathFindingPenalty += 10;
}
else
{
failedPathFindingPenalty += 10;
}
}
if (d0 > 1024.0D)
{
this.delayCounter += 10;
}
else if (d0 > 256.0D)
{
this.delayCounter += 5;
}
if (!this.attacker.getNavigator().tryMoveToEntityLiving(entitylivingbase, this.speedTowardsTarget))
{
this.delayCounter += 15;
}
}
this.attackTick = Math.max(this.attackTick - 1, 0);
this.checkAndPerformAttack(entitylivingbase, d0);
}
protected void checkAndPerformAttack(EntityLivingBase p_190102_1_, double p_190102_2_)
{
double d0 = this.getAttackReachSqr(p_190102_1_);
if (p_190102_2_ <= d0 && this.attackTick <= 0)
{
this.attackTick = 20;
this.attacker.swingArm(EnumHand.MAIN_HAND);
this.attacker.attackEntityAsMob(p_190102_1_);
}
}
protected double getAttackReachSqr(EntityLivingBase attackTarget)
{
return (double)(this.attacker.width * 2.0F * this.attacker.width * 2.0F + attackTarget.width);
}
}

View File

@@ -0,0 +1,136 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.IRangedAttackMob;
import net.minecraft.util.math.MathHelper;
public class EntityAIAttackRanged extends EntityAIBase
{
/** The entity the AI instance has been applied to */
private final EntityLiving entityHost;
/** The entity (as a RangedAttackMob) the AI instance has been applied to. */
private final IRangedAttackMob rangedAttackEntityHost;
private EntityLivingBase attackTarget;
/**
* A decrementing tick that spawns a ranged attack once this value reaches 0. It is then set back to the
* maxRangedAttackTime.
*/
private int rangedAttackTime;
private final double entityMoveSpeed;
private int seeTime;
private final int attackIntervalMin;
/** The maximum time the AI has to wait before peforming another ranged attack. */
private final int maxRangedAttackTime;
private final float attackRadius;
private final float maxAttackDistance;
public EntityAIAttackRanged(IRangedAttackMob attacker, double movespeed, int maxAttackTime, float maxAttackDistanceIn)
{
this(attacker, movespeed, maxAttackTime, maxAttackTime, maxAttackDistanceIn);
}
public EntityAIAttackRanged(IRangedAttackMob attacker, double movespeed, int p_i1650_4_, int maxAttackTime, float maxAttackDistanceIn)
{
this.rangedAttackTime = -1;
if (!(attacker instanceof EntityLivingBase))
{
throw new IllegalArgumentException("ArrowAttackGoal requires Mob implements RangedAttackMob");
}
else
{
this.rangedAttackEntityHost = attacker;
this.entityHost = (EntityLiving)attacker;
this.entityMoveSpeed = movespeed;
this.attackIntervalMin = p_i1650_4_;
this.maxRangedAttackTime = maxAttackTime;
this.attackRadius = maxAttackDistanceIn;
this.maxAttackDistance = maxAttackDistanceIn * maxAttackDistanceIn;
this.setMutexBits(3);
}
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
EntityLivingBase entitylivingbase = this.entityHost.getAttackTarget();
if (entitylivingbase == null)
{
return false;
}
else
{
this.attackTarget = entitylivingbase;
return true;
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return this.shouldExecute() || !this.entityHost.getNavigator().noPath();
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.attackTarget = null;
this.seeTime = 0;
this.rangedAttackTime = -1;
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
double d0 = this.entityHost.getDistanceSq(this.attackTarget.posX, this.attackTarget.getEntityBoundingBox().minY, this.attackTarget.posZ);
boolean flag = this.entityHost.getEntitySenses().canSee(this.attackTarget);
if (flag)
{
++this.seeTime;
}
else
{
this.seeTime = 0;
}
if (d0 <= (double)this.maxAttackDistance && this.seeTime >= 20)
{
this.entityHost.getNavigator().clearPath();
}
else
{
this.entityHost.getNavigator().tryMoveToEntityLiving(this.attackTarget, this.entityMoveSpeed);
}
this.entityHost.getLookHelper().setLookPositionWithEntity(this.attackTarget, 30.0F, 30.0F);
if (--this.rangedAttackTime == 0)
{
if (!flag)
{
return;
}
float f = MathHelper.sqrt(d0) / this.attackRadius;
float lvt_5_1_ = MathHelper.clamp(f, 0.1F, 1.0F);
this.rangedAttackEntityHost.attackEntityWithRangedAttack(this.attackTarget, lvt_5_1_);
this.rangedAttackTime = MathHelper.floor(f * (float)(this.maxRangedAttackTime - this.attackIntervalMin) + (float)this.attackIntervalMin);
}
else if (this.rangedAttackTime < 0)
{
float f2 = MathHelper.sqrt(d0) / this.attackRadius;
this.rangedAttackTime = MathHelper.floor(f2 * (float)(this.maxRangedAttackTime - this.attackIntervalMin) + (float)this.attackIntervalMin);
}
}
}

View File

@@ -0,0 +1,174 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.IRangedAttackMob;
import net.minecraft.entity.monster.EntityMob;
import net.minecraft.init.Items;
import net.minecraft.item.ItemBow;
import net.minecraft.util.EnumHand;
public class EntityAIAttackRangedBow<T extends EntityMob & IRangedAttackMob> extends EntityAIBase
{
private final T entity;
private final double moveSpeedAmp;
private int attackCooldown;
private final float maxAttackDistance;
private int attackTime = -1;
private int seeTime;
private boolean strafingClockwise;
private boolean strafingBackwards;
private int strafingTime = -1;
public EntityAIAttackRangedBow(T p_i47515_1_, double p_i47515_2_, int p_i47515_4_, float p_i47515_5_)
{
this.entity = p_i47515_1_;
this.moveSpeedAmp = p_i47515_2_;
this.attackCooldown = p_i47515_4_;
this.maxAttackDistance = p_i47515_5_ * p_i47515_5_;
this.setMutexBits(3);
}
public void setAttackCooldown(int p_189428_1_)
{
this.attackCooldown = p_189428_1_;
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
return this.entity.getAttackTarget() == null ? false : this.isBowInMainhand();
}
protected boolean isBowInMainhand()
{
return !this.entity.getHeldItemMainhand().isEmpty() && this.entity.getHeldItemMainhand().getItem() == Items.BOW;
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return (this.shouldExecute() || !this.entity.getNavigator().noPath()) && this.isBowInMainhand();
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
super.startExecuting();
((IRangedAttackMob)this.entity).setSwingingArms(true);
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
super.resetTask();
((IRangedAttackMob)this.entity).setSwingingArms(false);
this.seeTime = 0;
this.attackTime = -1;
this.entity.resetActiveHand();
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
EntityLivingBase entitylivingbase = this.entity.getAttackTarget();
if (entitylivingbase != null)
{
double d0 = this.entity.getDistanceSq(entitylivingbase.posX, entitylivingbase.getEntityBoundingBox().minY, entitylivingbase.posZ);
boolean flag = this.entity.getEntitySenses().canSee(entitylivingbase);
boolean flag1 = this.seeTime > 0;
if (flag != flag1)
{
this.seeTime = 0;
}
if (flag)
{
++this.seeTime;
}
else
{
--this.seeTime;
}
if (d0 <= (double)this.maxAttackDistance && this.seeTime >= 20)
{
this.entity.getNavigator().clearPath();
++this.strafingTime;
}
else
{
this.entity.getNavigator().tryMoveToEntityLiving(entitylivingbase, this.moveSpeedAmp);
this.strafingTime = -1;
}
if (this.strafingTime >= 20)
{
if ((double)this.entity.getRNG().nextFloat() < 0.3D)
{
this.strafingClockwise = !this.strafingClockwise;
}
if ((double)this.entity.getRNG().nextFloat() < 0.3D)
{
this.strafingBackwards = !this.strafingBackwards;
}
this.strafingTime = 0;
}
if (this.strafingTime > -1)
{
if (d0 > (double)(this.maxAttackDistance * 0.75F))
{
this.strafingBackwards = false;
}
else if (d0 < (double)(this.maxAttackDistance * 0.25F))
{
this.strafingBackwards = true;
}
this.entity.getMoveHelper().strafe(this.strafingBackwards ? -0.5F : 0.5F, this.strafingClockwise ? 0.5F : -0.5F);
this.entity.faceEntity(entitylivingbase, 30.0F, 30.0F);
}
else
{
this.entity.getLookHelper().setLookPositionWithEntity(entitylivingbase, 30.0F, 30.0F);
}
if (this.entity.isHandActive())
{
if (!flag && this.seeTime < -60)
{
this.entity.resetActiveHand();
}
else if (flag)
{
int i = this.entity.getItemInUseMaxCount();
if (i >= 20)
{
this.entity.resetActiveHand();
((IRangedAttackMob)this.entity).attackEntityWithRangedAttack(entitylivingbase, ItemBow.getArrowVelocity(i));
this.attackTime = this.attackCooldown;
}
}
}
else if (--this.attackTime <= 0 && this.seeTime >= -60)
{
this.entity.setActiveHand(EnumHand.MAIN_HAND);
}
}
}
}

View File

@@ -0,0 +1,125 @@
package net.minecraft.entity.ai;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import java.util.List;
import javax.annotation.Nullable;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityCreature;
import net.minecraft.pathfinding.Path;
import net.minecraft.pathfinding.PathNavigate;
import net.minecraft.util.EntitySelectors;
import net.minecraft.util.math.Vec3d;
public class EntityAIAvoidEntity<T extends Entity> extends EntityAIBase
{
private final Predicate<Entity> canBeSeenSelector;
/** The entity we are attached to */
protected EntityCreature entity;
private final double farSpeed;
private final double nearSpeed;
protected T closestLivingEntity;
private final float avoidDistance;
/** The PathEntity of our entity */
private Path path;
/** The PathNavigate of our entity */
private final PathNavigate navigation;
/** Class of entity this behavior seeks to avoid */
private final Class<T> classToAvoid;
private final Predicate <? super T > avoidTargetSelector;
public EntityAIAvoidEntity(EntityCreature entityIn, Class<T> classToAvoidIn, float avoidDistanceIn, double farSpeedIn, double nearSpeedIn)
{
this(entityIn, classToAvoidIn, Predicates.alwaysTrue(), avoidDistanceIn, farSpeedIn, nearSpeedIn);
}
public EntityAIAvoidEntity(EntityCreature entityIn, Class<T> classToAvoidIn, Predicate <? super T > avoidTargetSelectorIn, float avoidDistanceIn, double farSpeedIn, double nearSpeedIn)
{
this.canBeSeenSelector = new Predicate<Entity>()
{
public boolean apply(@Nullable Entity p_apply_1_)
{
return p_apply_1_.isEntityAlive() && EntityAIAvoidEntity.this.entity.getEntitySenses().canSee(p_apply_1_) && !EntityAIAvoidEntity.this.entity.isOnSameTeam(p_apply_1_);
}
};
this.entity = entityIn;
this.classToAvoid = classToAvoidIn;
this.avoidTargetSelector = avoidTargetSelectorIn;
this.avoidDistance = avoidDistanceIn;
this.farSpeed = farSpeedIn;
this.nearSpeed = nearSpeedIn;
this.navigation = entityIn.getNavigator();
this.setMutexBits(1);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
List<T> list = this.entity.world.<T>getEntitiesWithinAABB(this.classToAvoid, this.entity.getEntityBoundingBox().grow((double)this.avoidDistance, 3.0D, (double)this.avoidDistance), Predicates.and(EntitySelectors.CAN_AI_TARGET, this.canBeSeenSelector, this.avoidTargetSelector));
if (list.isEmpty())
{
return false;
}
else
{
this.closestLivingEntity = list.get(0);
Vec3d vec3d = RandomPositionGenerator.findRandomTargetBlockAwayFrom(this.entity, 16, 7, new Vec3d(this.closestLivingEntity.posX, this.closestLivingEntity.posY, this.closestLivingEntity.posZ));
if (vec3d == null)
{
return false;
}
else if (this.closestLivingEntity.getDistanceSq(vec3d.x, vec3d.y, vec3d.z) < this.closestLivingEntity.getDistanceSq(this.entity))
{
return false;
}
else
{
this.path = this.navigation.getPathToXYZ(vec3d.x, vec3d.y, vec3d.z);
return this.path != null;
}
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return !this.navigation.noPath();
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.navigation.setPath(this.path, this.farSpeed);
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.closestLivingEntity = null;
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
if (this.entity.getDistanceSq(this.closestLivingEntity) < 49.0D)
{
this.entity.getNavigator().setSpeed(this.nearSpeed);
}
else
{
this.entity.getNavigator().setSpeed(this.farSpeed);
}
}
}

View File

@@ -0,0 +1,72 @@
package net.minecraft.entity.ai;
public abstract class EntityAIBase
{
/**
* A bitmask telling which other tasks may not run concurrently. The test is a simple bitwise AND - if it yields
* zero, the two tasks may run concurrently, if not - they must run exclusively from each other.
*/
private int mutexBits;
/**
* Returns whether the EntityAIBase should begin execution.
*/
public abstract boolean shouldExecute();
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return this.shouldExecute();
}
/**
* Determine if this AI Task is interruptible by a higher (= lower value) priority task. All vanilla AITask have
* this value set to true.
*/
public boolean isInterruptible()
{
return true;
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
}
/**
* Sets the mutex bitflags, see getMutexBits. Flag 1 for motion, flag 2 for look/head movement, flag 4 for
* swimming/misc. Flags can be OR'ed.
*/
public void setMutexBits(int mutexBitsIn)
{
this.mutexBits = mutexBitsIn;
}
/**
* Get what actions this task will take that may potentially conflict with other tasks. The test is a simple bitwise
* AND - if it yields zero, the two tasks may run concurrently, if not - they must run exclusively from each other.
* See setMutextBits.
*/
public int getMutexBits()
{
return this.mutexBits;
}
}

View File

@@ -0,0 +1,103 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.passive.EntityWolf;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumHand;
import net.minecraft.world.World;
public class EntityAIBeg extends EntityAIBase
{
private final EntityWolf wolf;
private EntityPlayer player;
private final World world;
private final float minPlayerDistance;
private int timeoutCounter;
public EntityAIBeg(EntityWolf wolf, float minDistance)
{
this.wolf = wolf;
this.world = wolf.world;
this.minPlayerDistance = minDistance;
this.setMutexBits(2);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
this.player = this.world.getClosestPlayerToEntity(this.wolf, (double)this.minPlayerDistance);
return this.player == null ? false : this.hasTemptationItemInHand(this.player);
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
if (!this.player.isEntityAlive())
{
return false;
}
else if (this.wolf.getDistanceSq(this.player) > (double)(this.minPlayerDistance * this.minPlayerDistance))
{
return false;
}
else
{
return this.timeoutCounter > 0 && this.hasTemptationItemInHand(this.player);
}
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.wolf.setBegging(true);
this.timeoutCounter = 40 + this.wolf.getRNG().nextInt(40);
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.wolf.setBegging(false);
this.player = null;
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
this.wolf.getLookHelper().setLookPosition(this.player.posX, this.player.posY + (double)this.player.getEyeHeight(), this.player.posZ, 10.0F, (float)this.wolf.getVerticalFaceSpeed());
--this.timeoutCounter;
}
/**
* Gets if the Player has the Bone in the hand.
*/
private boolean hasTemptationItemInHand(EntityPlayer player)
{
for (EnumHand enumhand : EnumHand.values())
{
ItemStack itemstack = player.getHeldItem(enumhand);
if (this.wolf.isTamed() && itemstack.getItem() == Items.BONE)
{
return true;
}
if (this.wolf.isBreedingItem(itemstack))
{
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,107 @@
package net.minecraft.entity.ai;
import net.minecraft.block.Block;
import net.minecraft.block.BlockDoor;
import net.minecraft.entity.EntityLiving;
import net.minecraft.world.EnumDifficulty;
public class EntityAIBreakDoor extends EntityAIDoorInteract
{
private int breakingTime;
private int previousBreakProgress = -1;
public EntityAIBreakDoor(EntityLiving entityIn)
{
super(entityIn);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (!super.shouldExecute())
{
return false;
}
else if (!net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.entity.world, this.entity) || !this.entity.world.getBlockState(this.doorPosition).getBlock().canEntityDestroy(this.entity.world.getBlockState(this.doorPosition), this.entity.world, this.doorPosition, this.entity) || !net.minecraftforge.event.ForgeEventFactory.onEntityDestroyBlock(this.entity, this.doorPosition, this.entity.world.getBlockState(this.doorPosition)))
{
return false;
}
else
{
BlockDoor blockdoor = this.doorBlock;
return !BlockDoor.isOpen(this.entity.world, this.doorPosition);
}
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
super.startExecuting();
this.breakingTime = 0;
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
double d0 = this.entity.getDistanceSq(this.doorPosition);
boolean flag;
if (this.breakingTime <= 240)
{
BlockDoor blockdoor = this.doorBlock;
if (!BlockDoor.isOpen(this.entity.world, this.doorPosition) && d0 < 4.0D)
{
flag = true;
return flag;
}
}
flag = false;
return flag;
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
super.resetTask();
this.entity.world.sendBlockBreakProgress(this.entity.getEntityId(), this.doorPosition, -1);
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
super.updateTask();
if (this.entity.getRNG().nextInt(20) == 0)
{
this.entity.world.playEvent(1019, this.doorPosition, 0);
}
++this.breakingTime;
int i = (int)((float)this.breakingTime / 240.0F * 10.0F);
if (i != this.previousBreakProgress)
{
this.entity.world.sendBlockBreakProgress(this.entity.getEntityId(), this.doorPosition, i);
this.previousBreakProgress = i;
}
if (this.breakingTime == 240 && this.entity.world.getDifficulty() == EnumDifficulty.HARD)
{
this.entity.world.setBlockToAir(this.doorPosition);
this.entity.world.playEvent(1021, this.doorPosition, 0);
this.entity.world.playEvent(2001, this.doorPosition, Block.getIdFromBlock(this.doorBlock));
}
}
}

View File

@@ -0,0 +1,67 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.monster.EntityCreeper;
public class EntityAICreeperSwell extends EntityAIBase
{
/** The creeper that is swelling. */
EntityCreeper swellingCreeper;
/** The creeper's attack target. This is used for the changing of the creeper's state. */
EntityLivingBase creeperAttackTarget;
public EntityAICreeperSwell(EntityCreeper entitycreeperIn)
{
this.swellingCreeper = entitycreeperIn;
this.setMutexBits(1);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
EntityLivingBase entitylivingbase = this.swellingCreeper.getAttackTarget();
return this.swellingCreeper.getCreeperState() > 0 || entitylivingbase != null && this.swellingCreeper.getDistanceSq(entitylivingbase) < 9.0D;
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.swellingCreeper.getNavigator().clearPath();
this.creeperAttackTarget = this.swellingCreeper.getAttackTarget();
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.creeperAttackTarget = null;
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
if (this.creeperAttackTarget == null)
{
this.swellingCreeper.setCreeperState(-1);
}
else if (this.swellingCreeper.getDistanceSq(this.creeperAttackTarget) > 49.0D)
{
this.swellingCreeper.setCreeperState(-1);
}
else if (!this.swellingCreeper.getEntitySenses().canSee(this.creeperAttackTarget))
{
this.swellingCreeper.setCreeperState(-1);
}
else
{
this.swellingCreeper.setCreeperState(1);
}
}
}

View File

@@ -0,0 +1,64 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.monster.EntityCreeper;
import net.minecraft.entity.monster.EntityIronGolem;
import net.minecraft.village.Village;
public class EntityAIDefendVillage extends EntityAITarget
{
EntityIronGolem irongolem;
/** The aggressor of the iron golem's village which is now the golem's attack target. */
EntityLivingBase villageAgressorTarget;
public EntityAIDefendVillage(EntityIronGolem ironGolemIn)
{
super(ironGolemIn, false, true);
this.irongolem = ironGolemIn;
this.setMutexBits(1);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
Village village = this.irongolem.getVillage();
if (village == null)
{
return false;
}
else
{
this.villageAgressorTarget = village.findNearestVillageAggressor(this.irongolem);
if (this.villageAgressorTarget instanceof EntityCreeper)
{
return false;
}
else if (this.isSuitableTarget(this.villageAgressorTarget, false))
{
return true;
}
else if (this.taskOwner.getRNG().nextInt(20) == 0)
{
this.villageAgressorTarget = village.getNearestTargetPlayer(this.irongolem);
return this.isSuitableTarget(this.villageAgressorTarget, false);
}
else
{
return false;
}
}
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.irongolem.setAttackTarget(this.villageAgressorTarget);
super.startExecuting();
}
}

View File

@@ -0,0 +1,116 @@
package net.minecraft.entity.ai;
import net.minecraft.block.Block;
import net.minecraft.block.BlockDoor;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EntityLiving;
import net.minecraft.pathfinding.Path;
import net.minecraft.pathfinding.PathNavigateGround;
import net.minecraft.pathfinding.PathPoint;
import net.minecraft.util.math.BlockPos;
public abstract class EntityAIDoorInteract extends EntityAIBase
{
protected EntityLiving entity;
protected BlockPos doorPosition = BlockPos.ORIGIN;
/** The wooden door block */
protected BlockDoor doorBlock;
/** If is true then the Entity has stopped Door Interaction and compoleted the task. */
boolean hasStoppedDoorInteraction;
float entityPositionX;
float entityPositionZ;
public EntityAIDoorInteract(EntityLiving entityIn)
{
this.entity = entityIn;
if (!(entityIn.getNavigator() instanceof PathNavigateGround))
{
throw new IllegalArgumentException("Unsupported mob type for DoorInteractGoal");
}
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (!this.entity.collidedHorizontally)
{
return false;
}
else
{
PathNavigateGround pathnavigateground = (PathNavigateGround)this.entity.getNavigator();
Path path = pathnavigateground.getPath();
if (path != null && !path.isFinished() && pathnavigateground.getEnterDoors())
{
for (int i = 0; i < Math.min(path.getCurrentPathIndex() + 2, path.getCurrentPathLength()); ++i)
{
PathPoint pathpoint = path.getPathPointFromIndex(i);
this.doorPosition = new BlockPos(pathpoint.x, pathpoint.y + 1, pathpoint.z);
if (this.entity.getDistanceSq((double)this.doorPosition.getX(), this.entity.posY, (double)this.doorPosition.getZ()) <= 2.25D)
{
this.doorBlock = this.getBlockDoor(this.doorPosition);
if (this.doorBlock != null)
{
return true;
}
}
}
this.doorPosition = (new BlockPos(this.entity)).up();
this.doorBlock = this.getBlockDoor(this.doorPosition);
return this.doorBlock != null;
}
else
{
return false;
}
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return !this.hasStoppedDoorInteraction;
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.hasStoppedDoorInteraction = false;
this.entityPositionX = (float)((double)((float)this.doorPosition.getX() + 0.5F) - this.entity.posX);
this.entityPositionZ = (float)((double)((float)this.doorPosition.getZ() + 0.5F) - this.entity.posZ);
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
float f = (float)((double)((float)this.doorPosition.getX() + 0.5F) - this.entity.posX);
float f1 = (float)((double)((float)this.doorPosition.getZ() + 0.5F) - this.entity.posZ);
float f2 = this.entityPositionX * f + this.entityPositionZ * f1;
if (f2 < 0.0F)
{
this.hasStoppedDoorInteraction = true;
}
}
private BlockDoor getBlockDoor(BlockPos pos)
{
IBlockState iblockstate = this.entity.world.getBlockState(pos);
Block block = iblockstate.getBlock();
return block instanceof BlockDoor && iblockstate.getMaterial() == Material.WOOD ? (BlockDoor)block : null;
}
}

View File

@@ -0,0 +1,126 @@
package net.minecraft.entity.ai;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import net.minecraft.block.Block;
import net.minecraft.block.BlockTallGrass;
import net.minecraft.block.state.IBlockState;
import net.minecraft.block.state.pattern.BlockStateMatcher;
import net.minecraft.entity.EntityLiving;
import net.minecraft.init.Blocks;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public class EntityAIEatGrass extends EntityAIBase
{
private static final Predicate<IBlockState> IS_TALL_GRASS = BlockStateMatcher.forBlock(Blocks.TALLGRASS).where(BlockTallGrass.TYPE, Predicates.equalTo(BlockTallGrass.EnumType.GRASS));
/** The entity owner of this AITask */
private final EntityLiving grassEaterEntity;
/** The world the grass eater entity is eating from */
private final World entityWorld;
/** Number of ticks since the entity started to eat grass */
int eatingGrassTimer;
public EntityAIEatGrass(EntityLiving grassEaterEntityIn)
{
this.grassEaterEntity = grassEaterEntityIn;
this.entityWorld = grassEaterEntityIn.world;
this.setMutexBits(7);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (this.grassEaterEntity.getRNG().nextInt(this.grassEaterEntity.isChild() ? 50 : 1000) != 0)
{
return false;
}
else
{
BlockPos blockpos = new BlockPos(this.grassEaterEntity.posX, this.grassEaterEntity.posY, this.grassEaterEntity.posZ);
if (IS_TALL_GRASS.apply(this.entityWorld.getBlockState(blockpos)))
{
return true;
}
else
{
return this.entityWorld.getBlockState(blockpos.down()).getBlock() == Blocks.GRASS;
}
}
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.eatingGrassTimer = 40;
this.entityWorld.setEntityState(this.grassEaterEntity, (byte)10);
this.grassEaterEntity.getNavigator().clearPath();
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.eatingGrassTimer = 0;
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return this.eatingGrassTimer > 0;
}
/**
* Number of ticks since the entity started to eat grass
*/
public int getEatingGrassTimer()
{
return this.eatingGrassTimer;
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
this.eatingGrassTimer = Math.max(0, this.eatingGrassTimer - 1);
if (this.eatingGrassTimer == 4)
{
BlockPos blockpos = new BlockPos(this.grassEaterEntity.posX, this.grassEaterEntity.posY, this.grassEaterEntity.posZ);
if (IS_TALL_GRASS.apply(this.entityWorld.getBlockState(blockpos)))
{
if (net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.entityWorld, this.grassEaterEntity))
{
this.entityWorld.destroyBlock(blockpos, false);
}
this.grassEaterEntity.eatGrassBonus();
}
else
{
BlockPos blockpos1 = blockpos.down();
if (this.entityWorld.getBlockState(blockpos1).getBlock() == Blocks.GRASS)
{
if (net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.entityWorld, this.grassEaterEntity))
{
this.entityWorld.playEvent(2001, blockpos1, Block.getIdFromBlock(Blocks.GRASS));
this.entityWorld.setBlockState(blockpos1, Blocks.DIRT.getDefaultState(), 2);
}
this.grassEaterEntity.eatGrassBonus();
}
}
}
}
}

View File

@@ -0,0 +1,132 @@
package net.minecraft.entity.ai;
import com.google.common.base.Predicate;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nullable;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.attributes.IAttributeInstance;
import net.minecraft.entity.player.EntityPlayerMP;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class EntityAIFindEntityNearest extends EntityAIBase
{
private static final Logger LOGGER = LogManager.getLogger();
private final EntityLiving mob;
private final Predicate<EntityLivingBase> predicate;
private final EntityAINearestAttackableTarget.Sorter sorter;
private EntityLivingBase target;
private final Class <? extends EntityLivingBase > classToCheck;
public EntityAIFindEntityNearest(EntityLiving mobIn, Class <? extends EntityLivingBase > p_i45884_2_)
{
this.mob = mobIn;
this.classToCheck = p_i45884_2_;
if (mobIn instanceof EntityCreature)
{
LOGGER.warn("Use NearestAttackableTargetGoal.class for PathfinerMob mobs!");
}
this.predicate = new Predicate<EntityLivingBase>()
{
public boolean apply(@Nullable EntityLivingBase p_apply_1_)
{
double d0 = EntityAIFindEntityNearest.this.getFollowRange();
if (p_apply_1_.isSneaking())
{
d0 *= 0.800000011920929D;
}
if (p_apply_1_.isInvisible())
{
return false;
}
else
{
return (double)p_apply_1_.getDistance(EntityAIFindEntityNearest.this.mob) > d0 ? false : EntityAITarget.isSuitableTarget(EntityAIFindEntityNearest.this.mob, p_apply_1_, false, true);
}
}
};
this.sorter = new EntityAINearestAttackableTarget.Sorter(mobIn);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
double d0 = this.getFollowRange();
List<EntityLivingBase> list = this.mob.world.<EntityLivingBase>getEntitiesWithinAABB(this.classToCheck, this.mob.getEntityBoundingBox().grow(d0, 4.0D, d0), this.predicate);
Collections.sort(list, this.sorter);
if (list.isEmpty())
{
return false;
}
else
{
this.target = list.get(0);
return true;
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
EntityLivingBase entitylivingbase = this.mob.getAttackTarget();
if (entitylivingbase == null)
{
return false;
}
else if (!entitylivingbase.isEntityAlive())
{
return false;
}
else
{
double d0 = this.getFollowRange();
if (this.mob.getDistanceSq(entitylivingbase) > d0 * d0)
{
return false;
}
else
{
return !(entitylivingbase instanceof EntityPlayerMP) || !((EntityPlayerMP)entitylivingbase).interactionManager.isCreative();
}
}
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.mob.setAttackTarget(this.target);
super.startExecuting();
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.mob.setAttackTarget((EntityLivingBase)null);
super.startExecuting();
}
protected double getFollowRange()
{
IAttributeInstance iattributeinstance = this.mob.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE);
return iattributeinstance == null ? 16.0D : iattributeinstance.getAttributeValue();
}
}

View File

@@ -0,0 +1,170 @@
package net.minecraft.entity.ai;
import com.google.common.base.Predicate;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nullable;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.attributes.IAttributeInstance;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.scoreboard.Team;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class EntityAIFindEntityNearestPlayer extends EntityAIBase
{
private static final Logger LOGGER = LogManager.getLogger();
/** The entity that use this AI */
private final EntityLiving entityLiving;
/** Use to determine if an entity correspond to specification */
private final Predicate<Entity> predicate;
/** Used to compare two entities */
private final EntityAINearestAttackableTarget.Sorter sorter;
/** The current target */
private EntityLivingBase entityTarget;
public EntityAIFindEntityNearestPlayer(EntityLiving entityLivingIn)
{
this.entityLiving = entityLivingIn;
if (entityLivingIn instanceof EntityCreature)
{
LOGGER.warn("Use NearestAttackableTargetGoal.class for PathfinerMob mobs!");
}
this.predicate = new Predicate<Entity>()
{
public boolean apply(@Nullable Entity p_apply_1_)
{
if (!(p_apply_1_ instanceof EntityPlayer))
{
return false;
}
else if (((EntityPlayer)p_apply_1_).capabilities.disableDamage)
{
return false;
}
else
{
double d0 = EntityAIFindEntityNearestPlayer.this.maxTargetRange();
if (p_apply_1_.isSneaking())
{
d0 *= 0.800000011920929D;
}
if (p_apply_1_.isInvisible())
{
float f = ((EntityPlayer)p_apply_1_).getArmorVisibility();
if (f < 0.1F)
{
f = 0.1F;
}
d0 *= (double)(0.7F * f);
}
return (double)p_apply_1_.getDistance(EntityAIFindEntityNearestPlayer.this.entityLiving) > d0 ? false : EntityAITarget.isSuitableTarget(EntityAIFindEntityNearestPlayer.this.entityLiving, (EntityLivingBase)p_apply_1_, false, true);
}
}
};
this.sorter = new EntityAINearestAttackableTarget.Sorter(entityLivingIn);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
double d0 = this.maxTargetRange();
List<EntityPlayer> list = this.entityLiving.world.<EntityPlayer>getEntitiesWithinAABB(EntityPlayer.class, this.entityLiving.getEntityBoundingBox().grow(d0, 4.0D, d0), this.predicate);
Collections.sort(list, this.sorter);
if (list.isEmpty())
{
return false;
}
else
{
this.entityTarget = list.get(0);
return true;
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
EntityLivingBase entitylivingbase = this.entityLiving.getAttackTarget();
if (entitylivingbase == null)
{
return false;
}
else if (!entitylivingbase.isEntityAlive())
{
return false;
}
else if (entitylivingbase instanceof EntityPlayer && ((EntityPlayer)entitylivingbase).capabilities.disableDamage)
{
return false;
}
else
{
Team team = this.entityLiving.getTeam();
Team team1 = entitylivingbase.getTeam();
if (team != null && team1 == team)
{
return false;
}
else
{
double d0 = this.maxTargetRange();
if (this.entityLiving.getDistanceSq(entitylivingbase) > d0 * d0)
{
return false;
}
else
{
return !(entitylivingbase instanceof EntityPlayerMP) || !((EntityPlayerMP)entitylivingbase).interactionManager.isCreative();
}
}
}
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.entityLiving.setAttackTarget(this.entityTarget);
super.startExecuting();
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.entityLiving.setAttackTarget((EntityLivingBase)null);
super.startExecuting();
}
/**
* Return the max target range of the entiity (16 by default)
*/
protected double maxTargetRange()
{
IAttributeInstance iattributeinstance = this.entityLiving.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE);
return iattributeinstance == null ? 16.0D : iattributeinstance.getAttributeValue();
}
}

View File

@@ -0,0 +1,101 @@
package net.minecraft.entity.ai;
import java.util.Random;
import javax.annotation.Nullable;
import net.minecraft.entity.EntityCreature;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class EntityAIFleeSun extends EntityAIBase
{
private final EntityCreature creature;
private double shelterX;
private double shelterY;
private double shelterZ;
private final double movementSpeed;
private final World world;
public EntityAIFleeSun(EntityCreature theCreatureIn, double movementSpeedIn)
{
this.creature = theCreatureIn;
this.movementSpeed = movementSpeedIn;
this.world = theCreatureIn.world;
this.setMutexBits(1);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (!this.world.isDaytime())
{
return false;
}
else if (!this.creature.isBurning())
{
return false;
}
else if (!this.world.canSeeSky(new BlockPos(this.creature.posX, this.creature.getEntityBoundingBox().minY, this.creature.posZ)))
{
return false;
}
else if (!this.creature.getItemStackFromSlot(EntityEquipmentSlot.HEAD).isEmpty())
{
return false;
}
else
{
Vec3d vec3d = this.findPossibleShelter();
if (vec3d == null)
{
return false;
}
else
{
this.shelterX = vec3d.x;
this.shelterY = vec3d.y;
this.shelterZ = vec3d.z;
return true;
}
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return !this.creature.getNavigator().noPath();
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.creature.getNavigator().tryMoveToXYZ(this.shelterX, this.shelterY, this.shelterZ, this.movementSpeed);
}
@Nullable
private Vec3d findPossibleShelter()
{
Random random = this.creature.getRNG();
BlockPos blockpos = new BlockPos(this.creature.posX, this.creature.getEntityBoundingBox().minY, this.creature.posZ);
for (int i = 0; i < 10; ++i)
{
BlockPos blockpos1 = blockpos.add(random.nextInt(20) - 10, random.nextInt(6) - 3, random.nextInt(20) - 10);
if (!this.world.canSeeSky(blockpos1) && this.creature.getBlockPathWeight(blockpos1) < 0.0F)
{
return new Vec3d((double)blockpos1.getX(), (double)blockpos1.getY(), (double)blockpos1.getZ());
}
}
return null;
}
}

View File

@@ -0,0 +1,132 @@
package net.minecraft.entity.ai;
import com.google.common.base.Predicate;
import java.util.List;
import javax.annotation.Nullable;
import net.minecraft.entity.EntityLiving;
import net.minecraft.pathfinding.PathNavigate;
import net.minecraft.pathfinding.PathNavigateFlying;
import net.minecraft.pathfinding.PathNavigateGround;
import net.minecraft.pathfinding.PathNodeType;
public class EntityAIFollow extends EntityAIBase
{
private final EntityLiving entity;
private final Predicate<EntityLiving> followPredicate;
private EntityLiving followingEntity;
private final double speedModifier;
private final PathNavigate navigation;
private int timeToRecalcPath;
private final float stopDistance;
private float oldWaterCost;
private final float areaSize;
public EntityAIFollow(final EntityLiving p_i47417_1_, double p_i47417_2_, float p_i47417_4_, float p_i47417_5_)
{
this.entity = p_i47417_1_;
this.followPredicate = new Predicate<EntityLiving>()
{
public boolean apply(@Nullable EntityLiving p_apply_1_)
{
return p_apply_1_ != null && p_i47417_1_.getClass() != p_apply_1_.getClass();
}
};
this.speedModifier = p_i47417_2_;
this.navigation = p_i47417_1_.getNavigator();
this.stopDistance = p_i47417_4_;
this.areaSize = p_i47417_5_;
this.setMutexBits(3);
if (!(p_i47417_1_.getNavigator() instanceof PathNavigateGround) && !(p_i47417_1_.getNavigator() instanceof PathNavigateFlying))
{
throw new IllegalArgumentException("Unsupported mob type for FollowMobGoal");
}
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
List<EntityLiving> list = this.entity.world.<EntityLiving>getEntitiesWithinAABB(EntityLiving.class, this.entity.getEntityBoundingBox().grow((double)this.areaSize), this.followPredicate);
if (!list.isEmpty())
{
for (EntityLiving entityliving : list)
{
if (!entityliving.isInvisible())
{
this.followingEntity = entityliving;
return true;
}
}
}
return false;
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return this.followingEntity != null && !this.navigation.noPath() && this.entity.getDistanceSq(this.followingEntity) > (double)(this.stopDistance * this.stopDistance);
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.timeToRecalcPath = 0;
this.oldWaterCost = this.entity.getPathPriority(PathNodeType.WATER);
this.entity.setPathPriority(PathNodeType.WATER, 0.0F);
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.followingEntity = null;
this.navigation.clearPath();
this.entity.setPathPriority(PathNodeType.WATER, this.oldWaterCost);
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
if (this.followingEntity != null && !this.entity.getLeashed())
{
this.entity.getLookHelper().setLookPositionWithEntity(this.followingEntity, 10.0F, (float)this.entity.getVerticalFaceSpeed());
if (--this.timeToRecalcPath <= 0)
{
this.timeToRecalcPath = 10;
double d0 = this.entity.posX - this.followingEntity.posX;
double d1 = this.entity.posY - this.followingEntity.posY;
double d2 = this.entity.posZ - this.followingEntity.posZ;
double d3 = d0 * d0 + d1 * d1 + d2 * d2;
if (d3 > (double)(this.stopDistance * this.stopDistance))
{
this.navigation.tryMoveToEntityLiving(this.followingEntity, this.speedModifier);
}
else
{
this.navigation.clearPath();
EntityLookHelper entitylookhelper = this.followingEntity.getLookHelper();
if (d3 <= (double)this.stopDistance || entitylookhelper.getLookPosX() == this.entity.posX && entitylookhelper.getLookPosY() == this.entity.posY && entitylookhelper.getLookPosZ() == this.entity.posZ)
{
double d4 = this.followingEntity.posX - this.entity.posX;
double d5 = this.followingEntity.posZ - this.entity.posZ;
this.navigation.tryMoveToXYZ(this.entity.posX - d4, this.entity.posY, this.entity.posZ - d5, this.speedModifier);
}
}
}
}
}
}

View File

@@ -0,0 +1,103 @@
package net.minecraft.entity.ai;
import java.util.List;
import net.minecraft.entity.monster.EntityIronGolem;
import net.minecraft.entity.passive.EntityVillager;
public class EntityAIFollowGolem extends EntityAIBase
{
private final EntityVillager villager;
private EntityIronGolem ironGolem;
private int takeGolemRoseTick;
private boolean tookGolemRose;
public EntityAIFollowGolem(EntityVillager villagerIn)
{
this.villager = villagerIn;
this.setMutexBits(3);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (this.villager.getGrowingAge() >= 0)
{
return false;
}
else if (!this.villager.world.isDaytime())
{
return false;
}
else
{
List<EntityIronGolem> list = this.villager.world.<EntityIronGolem>getEntitiesWithinAABB(EntityIronGolem.class, this.villager.getEntityBoundingBox().grow(6.0D, 2.0D, 6.0D));
if (list.isEmpty())
{
return false;
}
else
{
for (EntityIronGolem entityirongolem : list)
{
if (entityirongolem.getHoldRoseTick() > 0)
{
this.ironGolem = entityirongolem;
break;
}
}
return this.ironGolem != null;
}
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return this.ironGolem.getHoldRoseTick() > 0;
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.takeGolemRoseTick = this.villager.getRNG().nextInt(320);
this.tookGolemRose = false;
this.ironGolem.getNavigator().clearPath();
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.ironGolem = null;
this.villager.getNavigator().clearPath();
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
this.villager.getLookHelper().setLookPositionWithEntity(this.ironGolem, 30.0F, 30.0F);
if (this.ironGolem.getHoldRoseTick() == this.takeGolemRoseTick)
{
this.villager.getNavigator().tryMoveToEntityLiving(this.ironGolem, 0.5D);
this.tookGolemRose = true;
}
if (this.tookGolemRose && this.villager.getDistanceSq(this.ironGolem) < 4.0D)
{
this.ironGolem.setHoldingRose(false);
this.villager.getNavigator().clearPath();
}
}
}

View File

@@ -0,0 +1,151 @@
package net.minecraft.entity.ai;
import net.minecraft.block.state.BlockFaceShape;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.passive.EntityTameable;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.pathfinding.PathNavigate;
import net.minecraft.pathfinding.PathNavigateFlying;
import net.minecraft.pathfinding.PathNavigateGround;
import net.minecraft.pathfinding.PathNodeType;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
public class EntityAIFollowOwner extends EntityAIBase
{
private final EntityTameable tameable;
private EntityLivingBase owner;
World world;
private final double followSpeed;
private final PathNavigate petPathfinder;
private int timeToRecalcPath;
float maxDist;
float minDist;
private float oldWaterCost;
public EntityAIFollowOwner(EntityTameable tameableIn, double followSpeedIn, float minDistIn, float maxDistIn)
{
this.tameable = tameableIn;
this.world = tameableIn.world;
this.followSpeed = followSpeedIn;
this.petPathfinder = tameableIn.getNavigator();
this.minDist = minDistIn;
this.maxDist = maxDistIn;
this.setMutexBits(3);
if (!(tameableIn.getNavigator() instanceof PathNavigateGround) && !(tameableIn.getNavigator() instanceof PathNavigateFlying))
{
throw new IllegalArgumentException("Unsupported mob type for FollowOwnerGoal");
}
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
EntityLivingBase entitylivingbase = this.tameable.getOwner();
if (entitylivingbase == null)
{
return false;
}
else if (entitylivingbase instanceof EntityPlayer && ((EntityPlayer)entitylivingbase).isSpectator())
{
return false;
}
else if (this.tameable.isSitting())
{
return false;
}
else if (this.tameable.getDistanceSq(entitylivingbase) < (double)(this.minDist * this.minDist))
{
return false;
}
else
{
this.owner = entitylivingbase;
return true;
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return !this.petPathfinder.noPath() && this.tameable.getDistanceSq(this.owner) > (double)(this.maxDist * this.maxDist) && !this.tameable.isSitting();
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.timeToRecalcPath = 0;
this.oldWaterCost = this.tameable.getPathPriority(PathNodeType.WATER);
this.tameable.setPathPriority(PathNodeType.WATER, 0.0F);
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.owner = null;
this.petPathfinder.clearPath();
this.tameable.setPathPriority(PathNodeType.WATER, this.oldWaterCost);
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
this.tameable.getLookHelper().setLookPositionWithEntity(this.owner, 10.0F, (float)this.tameable.getVerticalFaceSpeed());
if (!this.tameable.isSitting())
{
if (--this.timeToRecalcPath <= 0)
{
this.timeToRecalcPath = 10;
if (!this.petPathfinder.tryMoveToEntityLiving(this.owner, this.followSpeed))
{
if (!this.tameable.getLeashed() && !this.tameable.isRiding())
{
if (this.tameable.getDistanceSq(this.owner) >= 144.0D)
{
int i = MathHelper.floor(this.owner.posX) - 2;
int j = MathHelper.floor(this.owner.posZ) - 2;
int k = MathHelper.floor(this.owner.getEntityBoundingBox().minY);
for (int l = 0; l <= 4; ++l)
{
for (int i1 = 0; i1 <= 4; ++i1)
{
if ((l < 1 || i1 < 1 || l > 3 || i1 > 3) && this.isTeleportFriendlyBlock(i, j, k, l, i1))
{
this.tameable.setLocationAndAngles((double)((float)(i + l) + 0.5F), (double)k, (double)((float)(j + i1) + 0.5F), this.tameable.rotationYaw, this.tameable.rotationPitch);
this.petPathfinder.clearPath();
return;
}
}
}
}
}
}
}
}
}
protected boolean isTeleportFriendlyBlock(int x, int p_192381_2_, int y, int p_192381_4_, int p_192381_5_)
{
BlockPos blockpos = new BlockPos(x + p_192381_4_, y - 1, p_192381_2_ + p_192381_5_);
IBlockState iblockstate = this.world.getBlockState(blockpos);
return iblockstate.getBlockFaceShape(this.world, blockpos, EnumFacing.DOWN) == BlockFaceShape.SOLID && iblockstate.canEntitySpawn(this.tameable) && this.world.isAirBlock(blockpos.up()) && this.world.isAirBlock(blockpos.up(2));
}
}

View File

@@ -0,0 +1,20 @@
package net.minecraft.entity.ai;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.passive.EntityTameable;
import net.minecraft.util.math.BlockPos;
public class EntityAIFollowOwnerFlying extends EntityAIFollowOwner
{
public EntityAIFollowOwnerFlying(EntityTameable p_i47416_1_, double p_i47416_2_, float p_i47416_4_, float p_i47416_5_)
{
super(p_i47416_1_, p_i47416_2_, p_i47416_4_, p_i47416_5_);
}
protected boolean isTeleportFriendlyBlock(int x, int p_192381_2_, int y, int p_192381_4_, int p_192381_5_)
{
IBlockState iblockstate = this.world.getBlockState(new BlockPos(x + p_192381_4_, y - 1, p_192381_2_ + p_192381_5_));
return (iblockstate.isTopSolid() || iblockstate.getMaterial() == Material.LEAVES) && this.world.isAirBlock(new BlockPos(x + p_192381_4_, y, p_192381_2_ + p_192381_5_)) && this.world.isAirBlock(new BlockPos(x + p_192381_4_, y + 1, p_192381_2_ + p_192381_5_));
}
}

View File

@@ -0,0 +1,112 @@
package net.minecraft.entity.ai;
import java.util.List;
import net.minecraft.entity.passive.EntityAnimal;
public class EntityAIFollowParent extends EntityAIBase
{
/** The child that is following its parent. */
EntityAnimal childAnimal;
EntityAnimal parentAnimal;
double moveSpeed;
private int delayCounter;
public EntityAIFollowParent(EntityAnimal animal, double speed)
{
this.childAnimal = animal;
this.moveSpeed = speed;
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (this.childAnimal.getGrowingAge() >= 0)
{
return false;
}
else
{
List<EntityAnimal> list = this.childAnimal.world.<EntityAnimal>getEntitiesWithinAABB(this.childAnimal.getClass(), this.childAnimal.getEntityBoundingBox().grow(8.0D, 4.0D, 8.0D));
EntityAnimal entityanimal = null;
double d0 = Double.MAX_VALUE;
for (EntityAnimal entityanimal1 : list)
{
if (entityanimal1.getGrowingAge() >= 0)
{
double d1 = this.childAnimal.getDistanceSq(entityanimal1);
if (d1 <= d0)
{
d0 = d1;
entityanimal = entityanimal1;
}
}
}
if (entityanimal == null)
{
return false;
}
else if (d0 < 9.0D)
{
return false;
}
else
{
this.parentAnimal = entityanimal;
return true;
}
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
if (this.childAnimal.getGrowingAge() >= 0)
{
return false;
}
else if (!this.parentAnimal.isEntityAlive())
{
return false;
}
else
{
double d0 = this.childAnimal.getDistanceSq(this.parentAnimal);
return d0 >= 9.0D && d0 <= 256.0D;
}
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.delayCounter = 0;
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.parentAnimal = null;
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
if (--this.delayCounter <= 0)
{
this.delayCounter = 10;
this.childAnimal.getNavigator().tryMoveToEntityLiving(this.parentAnimal, this.moveSpeed);
}
}
}

View File

@@ -0,0 +1,163 @@
package net.minecraft.entity.ai;
import net.minecraft.block.Block;
import net.minecraft.block.BlockCrops;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.inventory.InventoryBasic;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public class EntityAIHarvestFarmland extends EntityAIMoveToBlock
{
/** Villager that is harvesting */
private final EntityVillager villager;
private boolean hasFarmItem;
private boolean wantsToReapStuff;
/** 0 => harvest, 1 => replant, -1 => none */
private int currentTask;
public EntityAIHarvestFarmland(EntityVillager villagerIn, double speedIn)
{
super(villagerIn, speedIn, 16);
this.villager = villagerIn;
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (this.runDelay <= 0)
{
if (!net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.villager.world, this.villager))
{
return false;
}
this.currentTask = -1;
this.hasFarmItem = this.villager.isFarmItemInInventory();
this.wantsToReapStuff = this.villager.wantsMoreFood();
}
return super.shouldExecute();
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return this.currentTask >= 0 && super.shouldContinueExecuting();
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
super.updateTask();
this.villager.getLookHelper().setLookPosition((double)this.destinationBlock.getX() + 0.5D, (double)(this.destinationBlock.getY() + 1), (double)this.destinationBlock.getZ() + 0.5D, 10.0F, (float)this.villager.getVerticalFaceSpeed());
if (this.getIsAboveDestination())
{
World world = this.villager.world;
BlockPos blockpos = this.destinationBlock.up();
IBlockState iblockstate = world.getBlockState(blockpos);
Block block = iblockstate.getBlock();
if (this.currentTask == 0 && block instanceof BlockCrops && ((BlockCrops)block).isMaxAge(iblockstate))
{
world.destroyBlock(blockpos, true);
}
else if (this.currentTask == 1 && iblockstate.getMaterial() == Material.AIR)
{
InventoryBasic inventorybasic = this.villager.getVillagerInventory();
for (int i = 0; i < inventorybasic.getSizeInventory(); ++i)
{
ItemStack itemstack = inventorybasic.getStackInSlot(i);
boolean flag = false;
if (!itemstack.isEmpty())
{
if (itemstack.getItem() == Items.WHEAT_SEEDS)
{
world.setBlockState(blockpos, Blocks.WHEAT.getDefaultState(), 3);
flag = true;
}
else if (itemstack.getItem() == Items.POTATO)
{
world.setBlockState(blockpos, Blocks.POTATOES.getDefaultState(), 3);
flag = true;
}
else if (itemstack.getItem() == Items.CARROT)
{
world.setBlockState(blockpos, Blocks.CARROTS.getDefaultState(), 3);
flag = true;
}
else if (itemstack.getItem() == Items.BEETROOT_SEEDS)
{
world.setBlockState(blockpos, Blocks.BEETROOTS.getDefaultState(), 3);
flag = true;
}
else if (itemstack.getItem() instanceof net.minecraftforge.common.IPlantable) {
if(((net.minecraftforge.common.IPlantable)itemstack.getItem()).getPlantType(world,blockpos) == net.minecraftforge.common.EnumPlantType.Crop) {
world.setBlockState(blockpos, ((net.minecraftforge.common.IPlantable)itemstack.getItem()).getPlant(world,blockpos),3);
flag = true;
}
}
}
if (flag)
{
itemstack.shrink(1);
if (itemstack.isEmpty())
{
inventorybasic.setInventorySlotContents(i, ItemStack.EMPTY);
}
break;
}
}
}
this.currentTask = -1;
this.runDelay = 10;
}
}
/**
* Return true to set given position as destination
*/
protected boolean shouldMoveTo(World worldIn, BlockPos pos)
{
Block block = worldIn.getBlockState(pos).getBlock();
if (block == Blocks.FARMLAND)
{
pos = pos.up();
IBlockState iblockstate = worldIn.getBlockState(pos);
block = iblockstate.getBlock();
if (block instanceof BlockCrops && ((BlockCrops)block).isMaxAge(iblockstate) && this.wantsToReapStuff && (this.currentTask == 0 || this.currentTask < 0))
{
this.currentTask = 0;
return true;
}
if (iblockstate.getMaterial() == Material.AIR && this.hasFarmItem && (this.currentTask == 1 || this.currentTask < 0))
{
this.currentTask = 1;
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,82 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.passive.EntityTameable;
import net.minecraft.util.math.AxisAlignedBB;
public class EntityAIHurtByTarget extends EntityAITarget
{
private final boolean entityCallsForHelp;
/** Store the previous revengeTimer value */
private int revengeTimerOld;
private final Class<?>[] excludedReinforcementTypes;
public EntityAIHurtByTarget(EntityCreature creatureIn, boolean entityCallsForHelpIn, Class<?>... excludedReinforcementTypes)
{
super(creatureIn, true);
this.entityCallsForHelp = entityCallsForHelpIn;
this.excludedReinforcementTypes = excludedReinforcementTypes;
this.setMutexBits(1);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
int i = this.taskOwner.getRevengeTimer();
EntityLivingBase entitylivingbase = this.taskOwner.getRevengeTarget();
return i != this.revengeTimerOld && entitylivingbase != null && this.isSuitableTarget(entitylivingbase, false);
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.taskOwner.setAttackTarget(this.taskOwner.getRevengeTarget());
this.target = this.taskOwner.getAttackTarget();
this.revengeTimerOld = this.taskOwner.getRevengeTimer();
this.unseenMemoryTicks = 300;
if (this.entityCallsForHelp)
{
this.alertOthers();
}
super.startExecuting();
}
protected void alertOthers()
{
double d0 = this.getTargetDistance();
for (EntityCreature entitycreature : this.taskOwner.world.getEntitiesWithinAABB(this.taskOwner.getClass(), (new AxisAlignedBB(this.taskOwner.posX, this.taskOwner.posY, this.taskOwner.posZ, this.taskOwner.posX + 1.0D, this.taskOwner.posY + 1.0D, this.taskOwner.posZ + 1.0D)).grow(d0, 10.0D, d0)))
{
if (this.taskOwner != entitycreature && entitycreature.getAttackTarget() == null && (!(this.taskOwner instanceof EntityTameable) || ((EntityTameable)this.taskOwner).getOwner() == ((EntityTameable)entitycreature).getOwner()) && !entitycreature.isOnSameTeam(this.taskOwner.getRevengeTarget()))
{
boolean flag = false;
for (Class<?> oclass : this.excludedReinforcementTypes)
{
if (entitycreature.getClass() == oclass)
{
flag = true;
break;
}
}
if (!flag)
{
this.setEntityAttackTarget(entitycreature, this.taskOwner.getRevengeTarget());
}
}
}
}
protected void setEntityAttackTarget(EntityCreature creatureIn, EntityLivingBase entityLivingBaseIn)
{
creatureIn.setAttackTarget(entityLivingBaseIn);
}
}

View File

@@ -0,0 +1,59 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.passive.EntityShoulderRiding;
import net.minecraft.entity.player.EntityPlayer;
public class EntityAILandOnOwnersShoulder extends EntityAIBase
{
private final EntityShoulderRiding entity;
private EntityPlayer owner;
private boolean isSittingOnShoulder;
public EntityAILandOnOwnersShoulder(EntityShoulderRiding p_i47415_1_)
{
this.entity = p_i47415_1_;
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
EntityLivingBase entitylivingbase = this.entity.getOwner();
boolean flag = entitylivingbase != null && !((EntityPlayer)entitylivingbase).isSpectator() && !((EntityPlayer)entitylivingbase).capabilities.isFlying && !entitylivingbase.isInWater();
return !this.entity.isSitting() && flag && this.entity.canSitOnShoulder();
}
/**
* Determine if this AI Task is interruptible by a higher (= lower value) priority task. All vanilla AITask have
* this value set to true.
*/
public boolean isInterruptible()
{
return !this.isSittingOnShoulder;
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.owner = (EntityPlayer)this.entity.getOwner();
this.isSittingOnShoulder = false;
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
if (!this.isSittingOnShoulder && !this.entity.isSitting() && !this.entity.getLeashed())
{
if (this.entity.getEntityBoundingBox().intersects(this.owner.getEntityBoundingBox()))
{
this.isSittingOnShoulder = this.entity.setEntityOnShoulder(this.owner);
}
}
}
}

View File

@@ -0,0 +1,81 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.math.MathHelper;
public class EntityAILeapAtTarget extends EntityAIBase
{
/** The entity that is leaping. */
EntityLiving leaper;
/** The entity that the leaper is leaping towards. */
EntityLivingBase leapTarget;
/** The entity's motionY after leaping. */
float leapMotionY;
public EntityAILeapAtTarget(EntityLiving leapingEntity, float leapMotionYIn)
{
this.leaper = leapingEntity;
this.leapMotionY = leapMotionYIn;
this.setMutexBits(5);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
this.leapTarget = this.leaper.getAttackTarget();
if (this.leapTarget == null)
{
return false;
}
else
{
double d0 = this.leaper.getDistanceSq(this.leapTarget);
if (d0 >= 4.0D && d0 <= 16.0D)
{
if (!this.leaper.onGround)
{
return false;
}
else
{
return this.leaper.getRNG().nextInt(5) == 0;
}
}
else
{
return false;
}
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return !this.leaper.onGround;
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
double d0 = this.leapTarget.posX - this.leaper.posX;
double d1 = this.leapTarget.posZ - this.leaper.posZ;
float f = MathHelper.sqrt(d0 * d0 + d1 * d1);
if ((double)f >= 1.0E-4D)
{
this.leaper.motionX += d0 / (double)f * 0.5D * 0.800000011920929D + this.leaper.motionX * 0.20000000298023224D;
this.leaper.motionZ += d1 / (double)f * 0.5D * 0.800000011920929D + this.leaper.motionZ * 0.20000000298023224D;
}
this.leaper.motionY = (double)this.leapMotionY;
}
}

View File

@@ -0,0 +1,171 @@
package net.minecraft.entity.ai;
import java.util.List;
import net.minecraft.entity.passive.EntityLlama;
import net.minecraft.util.math.Vec3d;
public class EntityAILlamaFollowCaravan extends EntityAIBase
{
public EntityLlama llama;
private double speedModifier;
private int distCheckCounter;
public EntityAILlamaFollowCaravan(EntityLlama llamaIn, double speedModifierIn)
{
this.llama = llamaIn;
this.speedModifier = speedModifierIn;
this.setMutexBits(1);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (!this.llama.getLeashed() && !this.llama.inCaravan())
{
List<EntityLlama> list = this.llama.world.<EntityLlama>getEntitiesWithinAABB(this.llama.getClass(), this.llama.getEntityBoundingBox().grow(9.0D, 4.0D, 9.0D));
EntityLlama entityllama = null;
double d0 = Double.MAX_VALUE;
for (EntityLlama entityllama1 : list)
{
if (entityllama1.inCaravan() && !entityllama1.hasCaravanTrail())
{
double d1 = this.llama.getDistanceSq(entityllama1);
if (d1 <= d0)
{
d0 = d1;
entityllama = entityllama1;
}
}
}
if (entityllama == null)
{
for (EntityLlama entityllama2 : list)
{
if (entityllama2.getLeashed() && !entityllama2.hasCaravanTrail())
{
double d2 = this.llama.getDistanceSq(entityllama2);
if (d2 <= d0)
{
d0 = d2;
entityllama = entityllama2;
}
}
}
}
if (entityllama == null)
{
return false;
}
else if (d0 < 4.0D)
{
return false;
}
else if (!entityllama.getLeashed() && !this.firstIsLeashed(entityllama, 1))
{
return false;
}
else
{
this.llama.joinCaravan(entityllama);
return true;
}
}
else
{
return false;
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
if (this.llama.inCaravan() && this.llama.getCaravanHead().isEntityAlive() && this.firstIsLeashed(this.llama, 0))
{
double d0 = this.llama.getDistanceSq(this.llama.getCaravanHead());
if (d0 > 676.0D)
{
if (this.speedModifier <= 3.0D)
{
this.speedModifier *= 1.2D;
this.distCheckCounter = 40;
return true;
}
if (this.distCheckCounter == 0)
{
return false;
}
}
if (this.distCheckCounter > 0)
{
--this.distCheckCounter;
}
return true;
}
else
{
return false;
}
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.llama.leaveCaravan();
this.speedModifier = 2.1D;
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
if (this.llama.inCaravan())
{
EntityLlama entityllama = this.llama.getCaravanHead();
double d0 = (double)this.llama.getDistance(entityllama);
float f = 2.0F;
Vec3d vec3d = (new Vec3d(entityllama.posX - this.llama.posX, entityllama.posY - this.llama.posY, entityllama.posZ - this.llama.posZ)).normalize().scale(Math.max(d0 - 2.0D, 0.0D));
this.llama.getNavigator().tryMoveToXYZ(this.llama.posX + vec3d.x, this.llama.posY + vec3d.y, this.llama.posZ + vec3d.z, this.speedModifier);
}
}
private boolean firstIsLeashed(EntityLlama p_190858_1_, int p_190858_2_)
{
if (p_190858_2_ > 8)
{
return false;
}
else if (p_190858_1_.inCaravan())
{
if (p_190858_1_.getCaravanHead().getLeashed())
{
return true;
}
else
{
EntityLlama entityllama = p_190858_1_.getCaravanHead();
++p_190858_2_;
return this.firstIsLeashed(entityllama, p_190858_2_);
}
}
else
{
return false;
}
}
}

View File

@@ -0,0 +1,31 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.entity.player.EntityPlayer;
public class EntityAILookAtTradePlayer extends EntityAIWatchClosest
{
private final EntityVillager villager;
public EntityAILookAtTradePlayer(EntityVillager villagerIn)
{
super(villagerIn, EntityPlayer.class, 8.0F);
this.villager = villagerIn;
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (this.villager.isTrading())
{
this.closestEntity = this.villager.getCustomer();
return true;
}
else
{
return false;
}
}
}

View File

@@ -0,0 +1,72 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.monster.EntityIronGolem;
import net.minecraft.entity.passive.EntityVillager;
public class EntityAILookAtVillager extends EntityAIBase
{
private final EntityIronGolem ironGolem;
private EntityVillager villager;
private int lookTime;
public EntityAILookAtVillager(EntityIronGolem ironGolemIn)
{
this.ironGolem = ironGolemIn;
this.setMutexBits(3);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (!this.ironGolem.world.isDaytime())
{
return false;
}
else if (this.ironGolem.getRNG().nextInt(8000) != 0)
{
return false;
}
else
{
this.villager = (EntityVillager)this.ironGolem.world.findNearestEntityWithinAABB(EntityVillager.class, this.ironGolem.getEntityBoundingBox().grow(6.0D, 2.0D, 6.0D), this.ironGolem);
return this.villager != null;
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return this.lookTime > 0;
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.lookTime = 400;
this.ironGolem.setHoldingRose(true);
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.ironGolem.setHoldingRose(false);
this.villager = null;
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
this.ironGolem.getLookHelper().setLookPositionWithEntity(this.villager, 30.0F, 30.0F);
--this.lookTime;
}
}

View File

@@ -0,0 +1,57 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.EntityLiving;
public class EntityAILookIdle extends EntityAIBase
{
/** The entity that is looking idle. */
private final EntityLiving idleEntity;
/** X offset to look at */
private double lookX;
/** Z offset to look at */
private double lookZ;
/** A decrementing tick that stops the entity from being idle once it reaches 0. */
private int idleTime;
public EntityAILookIdle(EntityLiving entitylivingIn)
{
this.idleEntity = entitylivingIn;
this.setMutexBits(3);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
return this.idleEntity.getRNG().nextFloat() < 0.02F;
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return this.idleTime >= 0;
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
double d0 = (Math.PI * 2D) * this.idleEntity.getRNG().nextDouble();
this.lookX = Math.cos(d0);
this.lookZ = Math.sin(d0);
this.idleTime = 20 + this.idleEntity.getRNG().nextInt(20);
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
--this.idleTime;
this.idleEntity.getLookHelper().setLookPosition(this.idleEntity.posX + this.lookX, this.idleEntity.posY + (double)this.idleEntity.getEyeHeight(), this.idleEntity.posZ + this.lookZ, (float)this.idleEntity.getHorizontalFaceSpeed(), (float)this.idleEntity.getVerticalFaceSpeed());
}
}

View File

@@ -0,0 +1,169 @@
package net.minecraft.entity.ai;
import java.util.List;
import java.util.Random;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.entity.EntityAgeable;
import net.minecraft.entity.item.EntityXPOrb;
import net.minecraft.entity.passive.EntityAnimal;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.stats.StatList;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.world.World;
public class EntityAIMate extends EntityAIBase
{
private final EntityAnimal animal;
private final Class <? extends EntityAnimal > mateClass;
World world;
private EntityAnimal targetMate;
/** Delay preventing a baby from spawning immediately when two mate-able animals find each other. */
int spawnBabyDelay;
/** The speed the creature moves at during mating behavior. */
double moveSpeed;
public EntityAIMate(EntityAnimal animal, double speedIn)
{
this(animal, speedIn, animal.getClass());
}
public EntityAIMate(EntityAnimal p_i47306_1_, double p_i47306_2_, Class <? extends EntityAnimal > p_i47306_4_)
{
this.animal = p_i47306_1_;
this.world = p_i47306_1_.world;
this.mateClass = p_i47306_4_;
this.moveSpeed = p_i47306_2_;
this.setMutexBits(3);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (!this.animal.isInLove())
{
return false;
}
else
{
this.targetMate = this.getNearbyMate();
return this.targetMate != null;
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return this.targetMate.isEntityAlive() && this.targetMate.isInLove() && this.spawnBabyDelay < 60;
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.targetMate = null;
this.spawnBabyDelay = 0;
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
this.animal.getLookHelper().setLookPositionWithEntity(this.targetMate, 10.0F, (float)this.animal.getVerticalFaceSpeed());
this.animal.getNavigator().tryMoveToEntityLiving(this.targetMate, this.moveSpeed);
++this.spawnBabyDelay;
if (this.spawnBabyDelay >= 60 && this.animal.getDistanceSq(this.targetMate) < 9.0D)
{
this.spawnBaby();
}
}
/**
* Loops through nearby animals and finds another animal of the same type that can be mated with. Returns the first
* valid mate found.
*/
private EntityAnimal getNearbyMate()
{
List<EntityAnimal> list = this.world.<EntityAnimal>getEntitiesWithinAABB(this.mateClass, this.animal.getEntityBoundingBox().grow(8.0D));
double d0 = Double.MAX_VALUE;
EntityAnimal entityanimal = null;
for (EntityAnimal entityanimal1 : list)
{
if (this.animal.canMateWith(entityanimal1) && this.animal.getDistanceSq(entityanimal1) < d0)
{
entityanimal = entityanimal1;
d0 = this.animal.getDistanceSq(entityanimal1);
}
}
return entityanimal;
}
/**
* Spawns a baby animal of the same type.
*/
private void spawnBaby()
{
EntityAgeable entityageable = this.animal.createChild(this.targetMate);
final net.minecraftforge.event.entity.living.BabyEntitySpawnEvent event = new net.minecraftforge.event.entity.living.BabyEntitySpawnEvent(animal, targetMate, entityageable);
final boolean cancelled = net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(event);
entityageable = event.getChild();
if (cancelled) {
//Reset the "inLove" state for the animals
this.animal.setGrowingAge(6000);
this.targetMate.setGrowingAge(6000);
this.animal.resetInLove();
this.targetMate.resetInLove();
return;
}
if (entityageable != null)
{
EntityPlayerMP entityplayermp = this.animal.getLoveCause();
if (entityplayermp == null && this.targetMate.getLoveCause() != null)
{
entityplayermp = this.targetMate.getLoveCause();
}
if (entityplayermp != null)
{
entityplayermp.addStat(StatList.ANIMALS_BRED);
CriteriaTriggers.BRED_ANIMALS.trigger(entityplayermp, this.animal, this.targetMate, entityageable);
}
this.animal.setGrowingAge(6000);
this.targetMate.setGrowingAge(6000);
this.animal.resetInLove();
this.targetMate.resetInLove();
entityageable.setGrowingAge(-24000);
entityageable.setLocationAndAngles(this.animal.posX, this.animal.posY, this.animal.posZ, 0.0F, 0.0F);
this.world.spawnEntity(entityageable);
Random random = this.animal.getRNG();
for (int i = 0; i < 7; ++i)
{
double d0 = random.nextGaussian() * 0.02D;
double d1 = random.nextGaussian() * 0.02D;
double d2 = random.nextGaussian() * 0.02D;
double d3 = random.nextDouble() * (double)this.animal.width * 2.0D - (double)this.animal.width;
double d4 = 0.5D + random.nextDouble() * (double)this.animal.height;
double d5 = random.nextDouble() * (double)this.animal.width * 2.0D - (double)this.animal.width;
this.world.spawnParticle(EnumParticleTypes.HEART, this.animal.posX + d3, this.animal.posY + d4, this.animal.posZ + d5, d0, d1, d2);
}
if (this.world.getGameRules().getBoolean("doMobLoot"))
{
this.world.spawnEntity(new EntityXPOrb(this.world, this.animal.posX, this.animal.posY, this.animal.posZ, random.nextInt(7) + 1));
}
}
}
}

View File

@@ -0,0 +1,103 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.EntityCreature;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.village.Village;
import net.minecraft.village.VillageDoorInfo;
public class EntityAIMoveIndoors extends EntityAIBase
{
private final EntityCreature entity;
private VillageDoorInfo doorInfo;
private int insidePosX = -1;
private int insidePosZ = -1;
public EntityAIMoveIndoors(EntityCreature entityIn)
{
this.entity = entityIn;
this.setMutexBits(1);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
BlockPos blockpos = new BlockPos(this.entity);
if ((!this.entity.world.isDaytime() || this.entity.world.isRaining() && !this.entity.world.getBiome(blockpos).canRain()) && this.entity.world.provider.hasSkyLight())
{
if (this.entity.getRNG().nextInt(50) != 0)
{
return false;
}
else if (this.insidePosX != -1 && this.entity.getDistanceSq((double)this.insidePosX, this.entity.posY, (double)this.insidePosZ) < 4.0D)
{
return false;
}
else
{
Village village = this.entity.world.getVillageCollection().getNearestVillage(blockpos, 14);
if (village == null)
{
return false;
}
else
{
this.doorInfo = village.getDoorInfo(blockpos);
return this.doorInfo != null;
}
}
}
else
{
return false;
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return !this.entity.getNavigator().noPath();
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.insidePosX = -1;
BlockPos blockpos = this.doorInfo.getInsideBlockPos();
int i = blockpos.getX();
int j = blockpos.getY();
int k = blockpos.getZ();
if (this.entity.getDistanceSq(blockpos) > 256.0D)
{
Vec3d vec3d = RandomPositionGenerator.findRandomTargetBlockTowards(this.entity, 14, 3, new Vec3d((double)i + 0.5D, (double)j, (double)k + 0.5D));
if (vec3d != null)
{
this.entity.getNavigator().tryMoveToXYZ(vec3d.x, vec3d.y, vec3d.z, 1.0D);
}
}
else
{
this.entity.getNavigator().tryMoveToXYZ((double)i + 0.5D, (double)j, (double)k + 0.5D, 1.0D);
}
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.insidePosX = this.doorInfo.getInsideBlockPos().getX();
this.insidePosZ = this.doorInfo.getInsideBlockPos().getZ();
this.doorInfo = null;
}
}

View File

@@ -0,0 +1,171 @@
package net.minecraft.entity.ai;
import com.google.common.collect.Lists;
import java.util.List;
import net.minecraft.entity.EntityCreature;
import net.minecraft.pathfinding.Path;
import net.minecraft.pathfinding.PathNavigateGround;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.village.Village;
import net.minecraft.village.VillageDoorInfo;
public class EntityAIMoveThroughVillage extends EntityAIBase
{
private final EntityCreature entity;
private final double movementSpeed;
/** The PathNavigate of our entity. */
private Path path;
private VillageDoorInfo doorInfo;
private final boolean isNocturnal;
private final List<VillageDoorInfo> doorList = Lists.<VillageDoorInfo>newArrayList();
public EntityAIMoveThroughVillage(EntityCreature entityIn, double movementSpeedIn, boolean isNocturnalIn)
{
this.entity = entityIn;
this.movementSpeed = movementSpeedIn;
this.isNocturnal = isNocturnalIn;
this.setMutexBits(1);
if (!(entityIn.getNavigator() instanceof PathNavigateGround))
{
throw new IllegalArgumentException("Unsupported mob for MoveThroughVillageGoal");
}
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
this.resizeDoorList();
if (this.isNocturnal && this.entity.world.isDaytime())
{
return false;
}
else
{
Village village = this.entity.world.getVillageCollection().getNearestVillage(new BlockPos(this.entity), 0);
if (village == null)
{
return false;
}
else
{
this.doorInfo = this.findNearestDoor(village);
if (this.doorInfo == null)
{
return false;
}
else
{
PathNavigateGround pathnavigateground = (PathNavigateGround)this.entity.getNavigator();
boolean flag = pathnavigateground.getEnterDoors();
pathnavigateground.setBreakDoors(false);
this.path = pathnavigateground.getPathToPos(this.doorInfo.getDoorBlockPos());
pathnavigateground.setBreakDoors(flag);
if (this.path != null)
{
return true;
}
else
{
Vec3d vec3d = RandomPositionGenerator.findRandomTargetBlockTowards(this.entity, 10, 7, new Vec3d((double)this.doorInfo.getDoorBlockPos().getX(), (double)this.doorInfo.getDoorBlockPos().getY(), (double)this.doorInfo.getDoorBlockPos().getZ()));
if (vec3d == null)
{
return false;
}
else
{
pathnavigateground.setBreakDoors(false);
this.path = this.entity.getNavigator().getPathToXYZ(vec3d.x, vec3d.y, vec3d.z);
pathnavigateground.setBreakDoors(flag);
return this.path != null;
}
}
}
}
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
if (this.entity.getNavigator().noPath())
{
return false;
}
else
{
float f = this.entity.width + 4.0F;
return this.entity.getDistanceSq(this.doorInfo.getDoorBlockPos()) > (double)(f * f);
}
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.entity.getNavigator().setPath(this.path, this.movementSpeed);
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
if (this.entity.getNavigator().noPath() || this.entity.getDistanceSq(this.doorInfo.getDoorBlockPos()) < 16.0D)
{
this.doorList.add(this.doorInfo);
}
}
private VillageDoorInfo findNearestDoor(Village villageIn)
{
VillageDoorInfo villagedoorinfo = null;
int i = Integer.MAX_VALUE;
for (VillageDoorInfo villagedoorinfo1 : villageIn.getVillageDoorInfoList())
{
int j = villagedoorinfo1.getDistanceSquared(MathHelper.floor(this.entity.posX), MathHelper.floor(this.entity.posY), MathHelper.floor(this.entity.posZ));
if (j < i && !this.doesDoorListContain(villagedoorinfo1))
{
villagedoorinfo = villagedoorinfo1;
i = j;
}
}
return villagedoorinfo;
}
private boolean doesDoorListContain(VillageDoorInfo doorInfoIn)
{
for (VillageDoorInfo villagedoorinfo : this.doorList)
{
if (doorInfoIn.getDoorBlockPos().equals(villagedoorinfo.getDoorBlockPos()))
{
return true;
}
}
return false;
}
private void resizeDoorList()
{
if (this.doorList.size() > 15)
{
this.doorList.remove(0);
}
}
}

View File

@@ -0,0 +1,128 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.EntityCreature;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public abstract class EntityAIMoveToBlock extends EntityAIBase
{
private final EntityCreature creature;
private final double movementSpeed;
/** Controls task execution delay */
protected int runDelay;
private int timeoutCounter;
private int maxStayTicks;
/** Block to move to */
protected BlockPos destinationBlock = BlockPos.ORIGIN;
private boolean isAboveDestination;
private final int searchLength;
public EntityAIMoveToBlock(EntityCreature creature, double speedIn, int length)
{
this.creature = creature;
this.movementSpeed = speedIn;
this.searchLength = length;
this.setMutexBits(5);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (this.runDelay > 0)
{
--this.runDelay;
return false;
}
else
{
this.runDelay = 200 + this.creature.getRNG().nextInt(200);
return this.searchForDestination();
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return this.timeoutCounter >= -this.maxStayTicks && this.timeoutCounter <= 1200 && this.shouldMoveTo(this.creature.world, this.destinationBlock);
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.creature.getNavigator().tryMoveToXYZ((double)((float)this.destinationBlock.getX()) + 0.5D, (double)(this.destinationBlock.getY() + 1), (double)((float)this.destinationBlock.getZ()) + 0.5D, this.movementSpeed);
this.timeoutCounter = 0;
this.maxStayTicks = this.creature.getRNG().nextInt(this.creature.getRNG().nextInt(1200) + 1200) + 1200;
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
if (this.creature.getDistanceSqToCenter(this.destinationBlock.up()) > 1.0D)
{
this.isAboveDestination = false;
++this.timeoutCounter;
if (this.timeoutCounter % 40 == 0)
{
this.creature.getNavigator().tryMoveToXYZ((double)((float)this.destinationBlock.getX()) + 0.5D, (double)(this.destinationBlock.getY() + 1), (double)((float)this.destinationBlock.getZ()) + 0.5D, this.movementSpeed);
}
}
else
{
this.isAboveDestination = true;
--this.timeoutCounter;
}
}
protected boolean getIsAboveDestination()
{
return this.isAboveDestination;
}
/**
* Searches and sets new destination block and returns true if a suitable block (specified in {@link
* net.minecraft.entity.ai.EntityAIMoveToBlock#shouldMoveTo(World, BlockPos) EntityAIMoveToBlock#shouldMoveTo(World,
* BlockPos)}) can be found.
*/
private boolean searchForDestination()
{
int i = this.searchLength;
int j = 1;
BlockPos blockpos = new BlockPos(this.creature);
for (int k = 0; k <= 1; k = k > 0 ? -k : 1 - k)
{
for (int l = 0; l < i; ++l)
{
for (int i1 = 0; i1 <= l; i1 = i1 > 0 ? -i1 : 1 - i1)
{
for (int j1 = i1 < l && i1 > -l ? l : 0; j1 <= l; j1 = j1 > 0 ? -j1 : 1 - j1)
{
BlockPos blockpos1 = blockpos.add(i1, k - 1, j1);
if (this.creature.isWithinHomeDistanceFromPosition(blockpos1) && this.shouldMoveTo(this.creature.world, blockpos1))
{
this.destinationBlock = blockpos1;
return true;
}
}
}
}
}
return false;
}
/**
* Return true to set given position as destination
*/
protected abstract boolean shouldMoveTo(World worldIn, BlockPos pos);
}

View File

@@ -0,0 +1,65 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.EntityCreature;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
public class EntityAIMoveTowardsRestriction extends EntityAIBase
{
private final EntityCreature creature;
private double movePosX;
private double movePosY;
private double movePosZ;
private final double movementSpeed;
public EntityAIMoveTowardsRestriction(EntityCreature creatureIn, double speedIn)
{
this.creature = creatureIn;
this.movementSpeed = speedIn;
this.setMutexBits(1);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (this.creature.isWithinHomeDistanceCurrentPosition())
{
return false;
}
else
{
BlockPos blockpos = this.creature.getHomePosition();
Vec3d vec3d = RandomPositionGenerator.findRandomTargetBlockTowards(this.creature, 16, 7, new Vec3d((double)blockpos.getX(), (double)blockpos.getY(), (double)blockpos.getZ()));
if (vec3d == null)
{
return false;
}
else
{
this.movePosX = vec3d.x;
this.movePosY = vec3d.y;
this.movePosZ = vec3d.z;
return true;
}
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return !this.creature.getNavigator().noPath();
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.creature.getNavigator().tryMoveToXYZ(this.movePosX, this.movePosY, this.movePosZ, this.movementSpeed);
}
}

View File

@@ -0,0 +1,82 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.math.Vec3d;
public class EntityAIMoveTowardsTarget extends EntityAIBase
{
private final EntityCreature creature;
private EntityLivingBase targetEntity;
private double movePosX;
private double movePosY;
private double movePosZ;
private final double speed;
/** If the distance to the target entity is further than this, this AI task will not run. */
private final float maxTargetDistance;
public EntityAIMoveTowardsTarget(EntityCreature creature, double speedIn, float targetMaxDistance)
{
this.creature = creature;
this.speed = speedIn;
this.maxTargetDistance = targetMaxDistance;
this.setMutexBits(1);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
this.targetEntity = this.creature.getAttackTarget();
if (this.targetEntity == null)
{
return false;
}
else if (this.targetEntity.getDistanceSq(this.creature) > (double)(this.maxTargetDistance * this.maxTargetDistance))
{
return false;
}
else
{
Vec3d vec3d = RandomPositionGenerator.findRandomTargetBlockTowards(this.creature, 16, 7, new Vec3d(this.targetEntity.posX, this.targetEntity.posY, this.targetEntity.posZ));
if (vec3d == null)
{
return false;
}
else
{
this.movePosX = vec3d.x;
this.movePosY = vec3d.y;
this.movePosZ = vec3d.z;
return true;
}
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return !this.creature.getNavigator().noPath() && this.targetEntity.isEntityAlive() && this.targetEntity.getDistanceSq(this.creature) < (double)(this.maxTargetDistance * this.maxTargetDistance);
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.targetEntity = null;
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.creature.getNavigator().tryMoveToXYZ(this.movePosX, this.movePosY, this.movePosZ, this.speed);
}
}

View File

@@ -0,0 +1,160 @@
package net.minecraft.entity.ai;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.annotation.Nullable;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.monster.EntityCreeper;
import net.minecraft.entity.monster.EntitySkeleton;
import net.minecraft.entity.monster.EntityZombie;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Items;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EntitySelectors;
import net.minecraft.util.math.AxisAlignedBB;
public class EntityAINearestAttackableTarget<T extends EntityLivingBase> extends EntityAITarget
{
protected final Class<T> targetClass;
private final int targetChance;
/** Instance of EntityAINearestAttackableTargetSorter. */
protected final EntityAINearestAttackableTarget.Sorter sorter;
protected final Predicate <? super T > targetEntitySelector;
protected T targetEntity;
public EntityAINearestAttackableTarget(EntityCreature creature, Class<T> classTarget, boolean checkSight)
{
this(creature, classTarget, checkSight, false);
}
public EntityAINearestAttackableTarget(EntityCreature creature, Class<T> classTarget, boolean checkSight, boolean onlyNearby)
{
this(creature, classTarget, 10, checkSight, onlyNearby, (Predicate)null);
}
public EntityAINearestAttackableTarget(EntityCreature creature, Class<T> classTarget, int chance, boolean checkSight, boolean onlyNearby, @Nullable final Predicate <? super T > targetSelector)
{
super(creature, checkSight, onlyNearby);
this.targetClass = classTarget;
this.targetChance = chance;
this.sorter = new EntityAINearestAttackableTarget.Sorter(creature);
this.setMutexBits(1);
this.targetEntitySelector = new Predicate<T>()
{
public boolean apply(@Nullable T p_apply_1_)
{
if (p_apply_1_ == null)
{
return false;
}
else if (targetSelector != null && !targetSelector.apply(p_apply_1_))
{
return false;
}
else
{
return !EntitySelectors.NOT_SPECTATING.apply(p_apply_1_) ? false : EntityAINearestAttackableTarget.this.isSuitableTarget(p_apply_1_, false);
}
}
};
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (this.targetChance > 0 && this.taskOwner.getRNG().nextInt(this.targetChance) != 0)
{
return false;
}
else if (this.targetClass != EntityPlayer.class && this.targetClass != EntityPlayerMP.class)
{
List<T> list = this.taskOwner.world.<T>getEntitiesWithinAABB(this.targetClass, this.getTargetableArea(this.getTargetDistance()), this.targetEntitySelector);
if (list.isEmpty())
{
return false;
}
else
{
Collections.sort(list, this.sorter);
this.targetEntity = list.get(0);
return true;
}
}
else
{
this.targetEntity = (T)this.taskOwner.world.getNearestAttackablePlayer(this.taskOwner.posX, this.taskOwner.posY + (double)this.taskOwner.getEyeHeight(), this.taskOwner.posZ, this.getTargetDistance(), this.getTargetDistance(), new Function<EntityPlayer, Double>()
{
@Nullable
public Double apply(@Nullable EntityPlayer p_apply_1_)
{
ItemStack itemstack = p_apply_1_.getItemStackFromSlot(EntityEquipmentSlot.HEAD);
if (itemstack.getItem() == Items.SKULL)
{
int i = itemstack.getItemDamage();
boolean flag = EntityAINearestAttackableTarget.this.taskOwner instanceof EntitySkeleton && i == 0;
boolean flag1 = EntityAINearestAttackableTarget.this.taskOwner instanceof EntityZombie && i == 2;
boolean flag2 = EntityAINearestAttackableTarget.this.taskOwner instanceof EntityCreeper && i == 4;
if (flag || flag1 || flag2)
{
return 0.5D;
}
}
return 1.0D;
}
}, (Predicate<EntityPlayer>)this.targetEntitySelector);
return this.targetEntity != null;
}
}
protected AxisAlignedBB getTargetableArea(double targetDistance)
{
return this.taskOwner.getEntityBoundingBox().grow(targetDistance, 4.0D, targetDistance);
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.taskOwner.setAttackTarget(this.targetEntity);
super.startExecuting();
}
public static class Sorter implements Comparator<Entity>
{
private final Entity entity;
public Sorter(Entity entityIn)
{
this.entity = entityIn;
}
public int compare(Entity p_compare_1_, Entity p_compare_2_)
{
double d0 = this.entity.getDistanceSq(p_compare_1_);
double d1 = this.entity.getDistanceSq(p_compare_2_);
if (d0 < d1)
{
return -1;
}
else
{
return d0 > d1 ? 1 : 0;
}
}
}
}

View File

@@ -0,0 +1,98 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.world.World;
public class EntityAIOcelotAttack extends EntityAIBase
{
World world;
EntityLiving entity;
EntityLivingBase target;
int attackCountdown;
public EntityAIOcelotAttack(EntityLiving theEntityIn)
{
this.entity = theEntityIn;
this.world = theEntityIn.world;
this.setMutexBits(3);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
EntityLivingBase entitylivingbase = this.entity.getAttackTarget();
if (entitylivingbase == null)
{
return false;
}
else
{
this.target = entitylivingbase;
return true;
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
if (!this.target.isEntityAlive())
{
return false;
}
else if (this.entity.getDistanceSq(this.target) > 225.0D)
{
return false;
}
else
{
return !this.entity.getNavigator().noPath() || this.shouldExecute();
}
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.target = null;
this.entity.getNavigator().clearPath();
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
this.entity.getLookHelper().setLookPositionWithEntity(this.target, 30.0F, 30.0F);
double d0 = (double)(this.entity.width * 2.0F * this.entity.width * 2.0F);
double d1 = this.entity.getDistanceSq(this.target.posX, this.target.getEntityBoundingBox().minY, this.target.posZ);
double d2 = 0.8D;
if (d1 > d0 && d1 < 16.0D)
{
d2 = 1.33D;
}
else if (d1 < 225.0D)
{
d2 = 0.6D;
}
this.entity.getNavigator().tryMoveToEntityLiving(this.target, d2);
this.attackCountdown = Math.max(this.attackCountdown - 1, 0);
if (d1 <= d0)
{
if (this.attackCountdown <= 0)
{
this.attackCountdown = 20;
this.entity.attackEntityAsMob(this.target);
}
}
}
}

View File

@@ -0,0 +1,106 @@
package net.minecraft.entity.ai;
import net.minecraft.block.Block;
import net.minecraft.block.BlockBed;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.passive.EntityOcelot;
import net.minecraft.init.Blocks;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityChest;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public class EntityAIOcelotSit extends EntityAIMoveToBlock
{
private final EntityOcelot ocelot;
public EntityAIOcelotSit(EntityOcelot ocelotIn, double p_i45315_2_)
{
super(ocelotIn, p_i45315_2_, 8);
this.ocelot = ocelotIn;
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
return this.ocelot.isTamed() && !this.ocelot.isSitting() && super.shouldExecute();
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
super.startExecuting();
this.ocelot.getAISit().setSitting(false);
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
super.resetTask();
this.ocelot.setSitting(false);
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
super.updateTask();
this.ocelot.getAISit().setSitting(false);
if (!this.getIsAboveDestination())
{
this.ocelot.setSitting(false);
}
else if (!this.ocelot.isSitting())
{
this.ocelot.setSitting(true);
}
}
/**
* Return true to set given position as destination
*/
protected boolean shouldMoveTo(World worldIn, BlockPos pos)
{
if (!worldIn.isAirBlock(pos.up()))
{
return false;
}
else
{
IBlockState iblockstate = worldIn.getBlockState(pos);
Block block = iblockstate.getBlock();
if (block == Blocks.CHEST)
{
TileEntity tileentity = worldIn.getTileEntity(pos);
if (tileentity instanceof TileEntityChest && ((TileEntityChest)tileentity).numPlayersUsing < 1)
{
return true;
}
}
else
{
if (block == Blocks.LIT_FURNACE)
{
return true;
}
if (block == Blocks.BED && iblockstate.getValue(BlockBed.PART) != BlockBed.EnumPartType.HEAD)
{
return true;
}
}
return false;
}
}
}

View File

@@ -0,0 +1,55 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.EntityLiving;
public class EntityAIOpenDoor extends EntityAIDoorInteract
{
/** If the entity close the door */
boolean closeDoor;
/** The temporisation before the entity close the door (in ticks, always 20 = 1 second) */
int closeDoorTemporisation;
public EntityAIOpenDoor(EntityLiving entitylivingIn, boolean shouldClose)
{
super(entitylivingIn);
this.entity = entitylivingIn;
this.closeDoor = shouldClose;
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return this.closeDoor && this.closeDoorTemporisation > 0 && super.shouldContinueExecuting();
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.closeDoorTemporisation = 20;
this.doorBlock.toggleDoor(this.entity.world, this.doorPosition, true);
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
if (this.closeDoor)
{
this.doorBlock.toggleDoor(this.entity.world, this.doorPosition, false);
}
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
--this.closeDoorTemporisation;
super.updateTask();
}
}

View File

@@ -0,0 +1,60 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.passive.EntityTameable;
public class EntityAIOwnerHurtByTarget extends EntityAITarget
{
EntityTameable tameable;
EntityLivingBase attacker;
private int timestamp;
public EntityAIOwnerHurtByTarget(EntityTameable theDefendingTameableIn)
{
super(theDefendingTameableIn, false);
this.tameable = theDefendingTameableIn;
this.setMutexBits(1);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (!this.tameable.isTamed())
{
return false;
}
else
{
EntityLivingBase entitylivingbase = this.tameable.getOwner();
if (entitylivingbase == null)
{
return false;
}
else
{
this.attacker = entitylivingbase.getRevengeTarget();
int i = entitylivingbase.getRevengeTimer();
return i != this.timestamp && this.isSuitableTarget(this.attacker, false) && this.tameable.shouldAttackEntity(this.attacker, entitylivingbase);
}
}
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.taskOwner.setAttackTarget(this.attacker);
EntityLivingBase entitylivingbase = this.tameable.getOwner();
if (entitylivingbase != null)
{
this.timestamp = entitylivingbase.getRevengeTimer();
}
super.startExecuting();
}
}

View File

@@ -0,0 +1,60 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.passive.EntityTameable;
public class EntityAIOwnerHurtTarget extends EntityAITarget
{
EntityTameable tameable;
EntityLivingBase attacker;
private int timestamp;
public EntityAIOwnerHurtTarget(EntityTameable theEntityTameableIn)
{
super(theEntityTameableIn, false);
this.tameable = theEntityTameableIn;
this.setMutexBits(1);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (!this.tameable.isTamed())
{
return false;
}
else
{
EntityLivingBase entitylivingbase = this.tameable.getOwner();
if (entitylivingbase == null)
{
return false;
}
else
{
this.attacker = entitylivingbase.getLastAttackedEntity();
int i = entitylivingbase.getLastAttackedEntityTime();
return i != this.timestamp && this.isSuitableTarget(this.attacker, false) && this.tameable.shouldAttackEntity(this.attacker, entitylivingbase);
}
}
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.taskOwner.setAttackTarget(this.attacker);
EntityLivingBase entitylivingbase = this.tameable.getOwner();
if (entitylivingbase != null)
{
this.timestamp = entitylivingbase.getLastAttackedEntityTime();
}
super.startExecuting();
}
}

View File

@@ -0,0 +1,124 @@
package net.minecraft.entity.ai;
import javax.annotation.Nullable;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityCreature;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class EntityAIPanic extends EntityAIBase
{
protected final EntityCreature creature;
protected double speed;
protected double randPosX;
protected double randPosY;
protected double randPosZ;
public EntityAIPanic(EntityCreature creature, double speedIn)
{
this.creature = creature;
this.speed = speedIn;
this.setMutexBits(1);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (this.creature.getRevengeTarget() == null && !this.creature.isBurning())
{
return false;
}
else
{
if (this.creature.isBurning())
{
BlockPos blockpos = this.getRandPos(this.creature.world, this.creature, 5, 4);
if (blockpos != null)
{
this.randPosX = (double)blockpos.getX();
this.randPosY = (double)blockpos.getY();
this.randPosZ = (double)blockpos.getZ();
return true;
}
}
return this.findRandomPosition();
}
}
protected boolean findRandomPosition()
{
Vec3d vec3d = RandomPositionGenerator.findRandomTarget(this.creature, 5, 4);
if (vec3d == null)
{
return false;
}
else
{
this.randPosX = vec3d.x;
this.randPosY = vec3d.y;
this.randPosZ = vec3d.z;
return true;
}
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.creature.getNavigator().tryMoveToXYZ(this.randPosX, this.randPosY, this.randPosZ, this.speed);
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return !this.creature.getNavigator().noPath();
}
@Nullable
private BlockPos getRandPos(World worldIn, Entity entityIn, int horizontalRange, int verticalRange)
{
BlockPos blockpos = new BlockPos(entityIn);
int i = blockpos.getX();
int j = blockpos.getY();
int k = blockpos.getZ();
float f = (float)(horizontalRange * horizontalRange * verticalRange * 2);
BlockPos blockpos1 = null;
BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos();
for (int l = i - horizontalRange; l <= i + horizontalRange; ++l)
{
for (int i1 = j - verticalRange; i1 <= j + verticalRange; ++i1)
{
for (int j1 = k - horizontalRange; j1 <= k + horizontalRange; ++j1)
{
blockpos$mutableblockpos.setPos(l, i1, j1);
IBlockState iblockstate = worldIn.getBlockState(blockpos$mutableblockpos);
if (iblockstate.getMaterial() == Material.WATER)
{
float f1 = (float)((l - i) * (l - i) + (i1 - j) * (i1 - j) + (j1 - k) * (j1 - k));
if (f1 < f)
{
f = f1;
blockpos1 = new BlockPos(blockpos$mutableblockpos);
}
}
}
}
}
return blockpos1;
}
}

View File

@@ -0,0 +1,124 @@
package net.minecraft.entity.ai;
import java.util.List;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.util.math.Vec3d;
public class EntityAIPlay extends EntityAIBase
{
private final EntityVillager villager;
private EntityLivingBase targetVillager;
private final double speed;
private int playTime;
public EntityAIPlay(EntityVillager villagerIn, double speedIn)
{
this.villager = villagerIn;
this.speed = speedIn;
this.setMutexBits(1);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (this.villager.getGrowingAge() >= 0)
{
return false;
}
else if (this.villager.getRNG().nextInt(400) != 0)
{
return false;
}
else
{
List<EntityVillager> list = this.villager.world.<EntityVillager>getEntitiesWithinAABB(EntityVillager.class, this.villager.getEntityBoundingBox().grow(6.0D, 3.0D, 6.0D));
double d0 = Double.MAX_VALUE;
for (EntityVillager entityvillager : list)
{
if (entityvillager != this.villager && !entityvillager.isPlaying() && entityvillager.getGrowingAge() < 0)
{
double d1 = entityvillager.getDistanceSq(this.villager);
if (d1 <= d0)
{
d0 = d1;
this.targetVillager = entityvillager;
}
}
}
if (this.targetVillager == null)
{
Vec3d vec3d = RandomPositionGenerator.findRandomTarget(this.villager, 16, 3);
if (vec3d == null)
{
return false;
}
}
return true;
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return this.playTime > 0;
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
if (this.targetVillager != null)
{
this.villager.setPlaying(true);
}
this.playTime = 1000;
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.villager.setPlaying(false);
this.targetVillager = null;
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
--this.playTime;
if (this.targetVillager != null)
{
if (this.villager.getDistanceSq(this.targetVillager) > 4.0D)
{
this.villager.getNavigator().tryMoveToEntityLiving(this.targetVillager, this.speed);
}
}
else if (this.villager.getNavigator().noPath())
{
Vec3d vec3d = RandomPositionGenerator.findRandomTarget(this.villager, 16, 3);
if (vec3d == null)
{
return;
}
this.villager.getNavigator().tryMoveToXYZ(vec3d.x, vec3d.y, vec3d.z, this.speed);
}
}
}

View File

@@ -0,0 +1,99 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.EntityCreature;
import net.minecraft.pathfinding.PathNavigateGround;
import net.minecraft.util.math.BlockPos;
import net.minecraft.village.Village;
import net.minecraft.village.VillageDoorInfo;
public class EntityAIRestrictOpenDoor extends EntityAIBase
{
private final EntityCreature entity;
private VillageDoorInfo frontDoor;
public EntityAIRestrictOpenDoor(EntityCreature creatureIn)
{
this.entity = creatureIn;
if (!(creatureIn.getNavigator() instanceof PathNavigateGround))
{
throw new IllegalArgumentException("Unsupported mob type for RestrictOpenDoorGoal");
}
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (this.entity.world.isDaytime())
{
return false;
}
else
{
BlockPos blockpos = new BlockPos(this.entity);
Village village = this.entity.world.getVillageCollection().getNearestVillage(blockpos, 16);
if (village == null)
{
return false;
}
else
{
this.frontDoor = village.getNearestDoor(blockpos);
if (this.frontDoor == null)
{
return false;
}
else
{
return (double)this.frontDoor.getDistanceToInsideBlockSq(blockpos) < 2.25D;
}
}
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
if (this.entity.world.isDaytime())
{
return false;
}
else
{
return !this.frontDoor.getIsDetachedFromVillageFlag() && this.frontDoor.isInsideSide(new BlockPos(this.entity));
}
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
((PathNavigateGround)this.entity.getNavigator()).setBreakDoors(false);
((PathNavigateGround)this.entity.getNavigator()).setEnterDoors(false);
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
((PathNavigateGround)this.entity.getNavigator()).setBreakDoors(true);
((PathNavigateGround)this.entity.getNavigator()).setEnterDoors(true);
this.frontDoor = null;
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
this.frontDoor.incrementDoorOpeningRestrictionCounter();
}
}

View File

@@ -0,0 +1,39 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.EntityCreature;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.pathfinding.PathNavigateGround;
public class EntityAIRestrictSun extends EntityAIBase
{
private final EntityCreature entity;
public EntityAIRestrictSun(EntityCreature creature)
{
this.entity = creature;
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
return this.entity.world.isDaytime() && this.entity.getItemStackFromSlot(EntityEquipmentSlot.HEAD).isEmpty();
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
((PathNavigateGround)this.entity.getNavigator()).setAvoidSun(true);
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
((PathNavigateGround)this.entity.getNavigator()).setAvoidSun(false);
}
}

View File

@@ -0,0 +1,99 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.Entity;
import net.minecraft.entity.passive.AbstractHorse;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.Vec3d;
public class EntityAIRunAroundLikeCrazy extends EntityAIBase
{
private final AbstractHorse horseHost;
private final double speed;
private double targetX;
private double targetY;
private double targetZ;
public EntityAIRunAroundLikeCrazy(AbstractHorse horse, double speedIn)
{
this.horseHost = horse;
this.speed = speedIn;
this.setMutexBits(1);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (!this.horseHost.isTame() && this.horseHost.isBeingRidden())
{
Vec3d vec3d = RandomPositionGenerator.findRandomTarget(this.horseHost, 5, 4);
if (vec3d == null)
{
return false;
}
else
{
this.targetX = vec3d.x;
this.targetY = vec3d.y;
this.targetZ = vec3d.z;
return true;
}
}
else
{
return false;
}
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.horseHost.getNavigator().tryMoveToXYZ(this.targetX, this.targetY, this.targetZ, this.speed);
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return !this.horseHost.isTame() && !this.horseHost.getNavigator().noPath() && this.horseHost.isBeingRidden();
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
if (!this.horseHost.isTame() && this.horseHost.getRNG().nextInt(50) == 0)
{
Entity entity = (Entity)this.horseHost.getPassengers().get(0);
if (entity == null)
{
return;
}
if (entity instanceof EntityPlayer)
{
int i = this.horseHost.getTemper();
int j = this.horseHost.getMaxTemper();
if (j > 0 && this.horseHost.getRNG().nextInt(j) < i && !net.minecraftforge.event.ForgeEventFactory.onAnimalTame(horseHost, (EntityPlayer)entity))
{
this.horseHost.setTamedBy((EntityPlayer)entity);
return;
}
this.horseHost.increaseTemper(5);
}
this.horseHost.removePassengers();
this.horseHost.makeMad();
this.horseHost.world.setEntityState(this.horseHost, (byte)6);
}
}
}

View File

@@ -0,0 +1,74 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.passive.EntityTameable;
public class EntityAISit extends EntityAIBase
{
private final EntityTameable tameable;
/** If the EntityTameable is sitting. */
private boolean isSitting;
public EntityAISit(EntityTameable entityIn)
{
this.tameable = entityIn;
this.setMutexBits(5);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (!this.tameable.isTamed())
{
return false;
}
else if (this.tameable.isInWater())
{
return false;
}
else if (!this.tameable.onGround)
{
return false;
}
else
{
EntityLivingBase entitylivingbase = this.tameable.getOwner();
if (entitylivingbase == null)
{
return true;
}
else
{
return this.tameable.getDistanceSq(entitylivingbase) < 144.0D && entitylivingbase.getRevengeTarget() != null ? false : this.isSitting;
}
}
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.tameable.getNavigator().clearPath();
this.tameable.setSitting(true);
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.tameable.setSitting(false);
}
/**
* Sets the sitting flag.
*/
public void setSitting(boolean sitting)
{
this.isSitting = sitting;
}
}

View File

@@ -0,0 +1,85 @@
package net.minecraft.entity.ai;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.IEntityLivingData;
import net.minecraft.entity.effect.EntityLightningBolt;
import net.minecraft.entity.monster.EntitySkeleton;
import net.minecraft.entity.passive.AbstractHorse;
import net.minecraft.entity.passive.EntitySkeletonHorse;
import net.minecraft.init.Items;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.DifficultyInstance;
public class EntityAISkeletonRiders extends EntityAIBase
{
private final EntitySkeletonHorse horse;
public EntityAISkeletonRiders(EntitySkeletonHorse horseIn)
{
this.horse = horseIn;
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
return this.horse.world.isAnyPlayerWithinRangeAt(this.horse.posX, this.horse.posY, this.horse.posZ, 10.0D);
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
DifficultyInstance difficultyinstance = this.horse.world.getDifficultyForLocation(new BlockPos(this.horse));
this.horse.setTrap(false);
this.horse.setHorseTamed(true);
this.horse.setGrowingAge(0);
this.horse.world.addWeatherEffect(new EntityLightningBolt(this.horse.world, this.horse.posX, this.horse.posY, this.horse.posZ, true));
EntitySkeleton entityskeleton = this.createSkeleton(difficultyinstance, this.horse);
entityskeleton.startRiding(this.horse);
for (int i = 0; i < 3; ++i)
{
AbstractHorse abstracthorse = this.createHorse(difficultyinstance);
EntitySkeleton entityskeleton1 = this.createSkeleton(difficultyinstance, abstracthorse);
entityskeleton1.startRiding(abstracthorse);
abstracthorse.addVelocity(this.horse.getRNG().nextGaussian() * 0.5D, 0.0D, this.horse.getRNG().nextGaussian() * 0.5D);
}
}
private AbstractHorse createHorse(DifficultyInstance p_188515_1_)
{
EntitySkeletonHorse entityskeletonhorse = new EntitySkeletonHorse(this.horse.world);
entityskeletonhorse.onInitialSpawn(p_188515_1_, (IEntityLivingData)null);
entityskeletonhorse.setPosition(this.horse.posX, this.horse.posY, this.horse.posZ);
entityskeletonhorse.hurtResistantTime = 60;
entityskeletonhorse.enablePersistence();
entityskeletonhorse.setHorseTamed(true);
entityskeletonhorse.setGrowingAge(0);
entityskeletonhorse.world.spawnEntity(entityskeletonhorse);
return entityskeletonhorse;
}
private EntitySkeleton createSkeleton(DifficultyInstance p_188514_1_, AbstractHorse p_188514_2_)
{
EntitySkeleton entityskeleton = new EntitySkeleton(p_188514_2_.world);
entityskeleton.onInitialSpawn(p_188514_1_, (IEntityLivingData)null);
entityskeleton.setPosition(p_188514_2_.posX, p_188514_2_.posY, p_188514_2_.posZ);
entityskeleton.hurtResistantTime = 60;
entityskeleton.enablePersistence();
if (entityskeleton.getItemStackFromSlot(EntityEquipmentSlot.HEAD).isEmpty())
{
entityskeleton.setItemStackToSlot(EntityEquipmentSlot.HEAD, new ItemStack(Items.IRON_HELMET));
}
entityskeleton.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, EnchantmentHelper.addRandomEnchantment(entityskeleton.getRNG(), entityskeleton.getHeldItemMainhand(), (int)(5.0F + p_188514_1_.getClampedAdditionalDifficulty() * (float)entityskeleton.getRNG().nextInt(18)), false));
entityskeleton.setItemStackToSlot(EntityEquipmentSlot.HEAD, EnchantmentHelper.addRandomEnchantment(entityskeleton.getRNG(), entityskeleton.getItemStackFromSlot(EntityEquipmentSlot.HEAD), (int)(5.0F + p_188514_1_.getClampedAdditionalDifficulty() * (float)entityskeleton.getRNG().nextInt(18)), false));
entityskeleton.world.spawnEntity(entityskeleton);
return entityskeleton;
}
}

View File

@@ -0,0 +1,44 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.EntityLiving;
import net.minecraft.pathfinding.PathNavigateFlying;
import net.minecraft.pathfinding.PathNavigateGround;
public class EntityAISwimming extends EntityAIBase
{
private final EntityLiving entity;
public EntityAISwimming(EntityLiving entityIn)
{
this.entity = entityIn;
this.setMutexBits(4);
if (entityIn.getNavigator() instanceof PathNavigateGround)
{
((PathNavigateGround)entityIn.getNavigator()).setCanSwim(true);
}
else if (entityIn.getNavigator() instanceof PathNavigateFlying)
{
((PathNavigateFlying)entityIn.getNavigator()).setCanFloat(true);
}
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
return this.entity.isInWater() || this.entity.isInLava();
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
if (this.entity.getRNG().nextFloat() < 0.8F)
{
this.entity.getJumpHelper().setJumping();
}
}
}

View File

@@ -0,0 +1,260 @@
package net.minecraft.entity.ai;
import javax.annotation.Nullable;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.IEntityOwnable;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.attributes.IAttributeInstance;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.pathfinding.Path;
import net.minecraft.pathfinding.PathPoint;
import net.minecraft.scoreboard.Team;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
public abstract class EntityAITarget extends EntityAIBase
{
/** The entity that this task belongs to */
protected final EntityCreature taskOwner;
/** If true, EntityAI targets must be able to be seen (cannot be blocked by walls) to be suitable targets. */
protected boolean shouldCheckSight;
/** When true, only entities that can be reached with minimal effort will be targetted. */
private final boolean nearbyOnly;
/** When nearbyOnly is true: 0 -> No target, but OK to search; 1 -> Nearby target found; 2 -> Target too far. */
private int targetSearchStatus;
/** When nearbyOnly is true, this throttles target searching to avoid excessive pathfinding. */
private int targetSearchDelay;
/**
* If @shouldCheckSight is true, the number of ticks before the interuption of this AITastk when the entity does't
* see the target
*/
private int targetUnseenTicks;
protected EntityLivingBase target;
protected int unseenMemoryTicks;
public EntityAITarget(EntityCreature creature, boolean checkSight)
{
this(creature, checkSight, false);
}
public EntityAITarget(EntityCreature creature, boolean checkSight, boolean onlyNearby)
{
this.unseenMemoryTicks = 60;
this.taskOwner = creature;
this.shouldCheckSight = checkSight;
this.nearbyOnly = onlyNearby;
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
EntityLivingBase entitylivingbase = this.taskOwner.getAttackTarget();
if (entitylivingbase == null)
{
entitylivingbase = this.target;
}
if (entitylivingbase == null)
{
return false;
}
else if (!entitylivingbase.isEntityAlive())
{
return false;
}
else
{
Team team = this.taskOwner.getTeam();
Team team1 = entitylivingbase.getTeam();
if (team != null && team1 == team)
{
return false;
}
else
{
double d0 = this.getTargetDistance();
if (this.taskOwner.getDistanceSq(entitylivingbase) > d0 * d0)
{
return false;
}
else
{
if (this.shouldCheckSight)
{
if (this.taskOwner.getEntitySenses().canSee(entitylivingbase))
{
this.targetUnseenTicks = 0;
}
else if (++this.targetUnseenTicks > this.unseenMemoryTicks)
{
return false;
}
}
if (entitylivingbase instanceof EntityPlayer && ((EntityPlayer)entitylivingbase).capabilities.disableDamage)
{
return false;
}
else
{
this.taskOwner.setAttackTarget(entitylivingbase);
return true;
}
}
}
}
}
protected double getTargetDistance()
{
IAttributeInstance iattributeinstance = this.taskOwner.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE);
return iattributeinstance == null ? 16.0D : iattributeinstance.getAttributeValue();
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.targetSearchStatus = 0;
this.targetSearchDelay = 0;
this.targetUnseenTicks = 0;
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.taskOwner.setAttackTarget((EntityLivingBase)null);
this.target = null;
}
/**
* A static method used to see if an entity is a suitable target through a number of checks.
*/
public static boolean isSuitableTarget(EntityLiving attacker, @Nullable EntityLivingBase target, boolean includeInvincibles, boolean checkSight)
{
if (target == null)
{
return false;
}
else if (target == attacker)
{
return false;
}
else if (!target.isEntityAlive())
{
return false;
}
else if (!attacker.canAttackClass(target.getClass()))
{
return false;
}
else if (attacker.isOnSameTeam(target))
{
return false;
}
else
{
if (attacker instanceof IEntityOwnable && ((IEntityOwnable)attacker).getOwnerId() != null)
{
if (target instanceof IEntityOwnable && ((IEntityOwnable)attacker).getOwnerId().equals(((IEntityOwnable)target).getOwnerId()))
{
return false;
}
if (target == ((IEntityOwnable)attacker).getOwner())
{
return false;
}
}
else if (target instanceof EntityPlayer && !includeInvincibles && ((EntityPlayer)target).capabilities.disableDamage)
{
return false;
}
return !checkSight || attacker.getEntitySenses().canSee(target);
}
}
/**
* A method used to see if an entity is a suitable target through a number of checks. Args : entity,
* canTargetInvinciblePlayer
*/
protected boolean isSuitableTarget(@Nullable EntityLivingBase target, boolean includeInvincibles)
{
if (!isSuitableTarget(this.taskOwner, target, includeInvincibles, this.shouldCheckSight))
{
return false;
}
else if (!this.taskOwner.isWithinHomeDistanceFromPosition(new BlockPos(target)))
{
return false;
}
else
{
if (this.nearbyOnly)
{
if (--this.targetSearchDelay <= 0)
{
this.targetSearchStatus = 0;
}
if (this.targetSearchStatus == 0)
{
this.targetSearchStatus = this.canEasilyReach(target) ? 1 : 2;
}
if (this.targetSearchStatus == 2)
{
return false;
}
}
return true;
}
}
/**
* Checks to see if this entity can find a short path to the given target.
*/
private boolean canEasilyReach(EntityLivingBase target)
{
this.targetSearchDelay = 10 + this.taskOwner.getRNG().nextInt(5);
Path path = this.taskOwner.getNavigator().getPathToEntityLiving(target);
if (path == null)
{
return false;
}
else
{
PathPoint pathpoint = path.getFinalPathPoint();
if (pathpoint == null)
{
return false;
}
else
{
int i = pathpoint.x - MathHelper.floor(target.posX);
int j = pathpoint.z - MathHelper.floor(target.posZ);
return (double)(i * i + j * j) <= 2.25D;
}
}
}
public EntityAITarget setUnseenMemoryTicks(int p_190882_1_)
{
this.unseenMemoryTicks = p_190882_1_;
return this;
}
}

View File

@@ -0,0 +1,24 @@
package net.minecraft.entity.ai;
import com.google.common.base.Predicate;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.passive.EntityTameable;
public class EntityAITargetNonTamed<T extends EntityLivingBase> extends EntityAINearestAttackableTarget<T>
{
private final EntityTameable tameable;
public EntityAITargetNonTamed(EntityTameable entityIn, Class<T> classTarget, boolean checkSight, Predicate <? super T > targetSelector)
{
super(entityIn, classTarget, 10, checkSight, false, targetSelector);
this.tameable = entityIn;
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
return !this.tameable.isTamed() && super.shouldExecute();
}
}

View File

@@ -0,0 +1,233 @@
package net.minecraft.entity.ai;
import com.google.common.collect.Sets;
import java.util.Iterator;
import java.util.Set;
import javax.annotation.Nullable;
import net.minecraft.profiler.Profiler;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class EntityAITasks
{
private static final Logger LOGGER = LogManager.getLogger();
/** A list of EntityAITaskEntrys in EntityAITasks. */
public final Set<EntityAITasks.EntityAITaskEntry> taskEntries = Sets.<EntityAITasks.EntityAITaskEntry>newLinkedHashSet();
/** A list of EntityAITaskEntrys that are currently being executed. */
private final Set<EntityAITasks.EntityAITaskEntry> executingTaskEntries = Sets.<EntityAITasks.EntityAITaskEntry>newLinkedHashSet();
/** Instance of Profiler. */
private final Profiler profiler;
private int tickCount;
private int tickRate = 3;
private int disabledControlFlags;
public EntityAITasks(Profiler profilerIn)
{
this.profiler = profilerIn;
}
/**
* Add a now AITask. Args : priority, task
*/
public void addTask(int priority, EntityAIBase task)
{
this.taskEntries.add(new EntityAITasks.EntityAITaskEntry(priority, task));
}
/**
* removes the indicated task from the entity's AI tasks.
*/
public void removeTask(EntityAIBase task)
{
Iterator<EntityAITasks.EntityAITaskEntry> iterator = this.taskEntries.iterator();
while (iterator.hasNext())
{
EntityAITasks.EntityAITaskEntry entityaitasks$entityaitaskentry = iterator.next();
EntityAIBase entityaibase = entityaitasks$entityaitaskentry.action;
if (entityaibase == task)
{
if (entityaitasks$entityaitaskentry.using)
{
entityaitasks$entityaitaskentry.using = false;
entityaitasks$entityaitaskentry.action.resetTask();
this.executingTaskEntries.remove(entityaitasks$entityaitaskentry);
}
iterator.remove();
return;
}
}
}
public void onUpdateTasks()
{
this.profiler.startSection("goalSetup");
if (this.tickCount++ % this.tickRate == 0)
{
for (EntityAITasks.EntityAITaskEntry entityaitasks$entityaitaskentry : this.taskEntries)
{
if (entityaitasks$entityaitaskentry.using)
{
if (!this.canUse(entityaitasks$entityaitaskentry) || !this.canContinue(entityaitasks$entityaitaskentry))
{
entityaitasks$entityaitaskentry.using = false;
entityaitasks$entityaitaskentry.action.resetTask();
this.executingTaskEntries.remove(entityaitasks$entityaitaskentry);
}
}
else if (this.canUse(entityaitasks$entityaitaskentry) && entityaitasks$entityaitaskentry.action.shouldExecute())
{
entityaitasks$entityaitaskentry.using = true;
entityaitasks$entityaitaskentry.action.startExecuting();
this.executingTaskEntries.add(entityaitasks$entityaitaskentry);
}
}
}
else
{
Iterator<EntityAITasks.EntityAITaskEntry> iterator = this.executingTaskEntries.iterator();
while (iterator.hasNext())
{
EntityAITasks.EntityAITaskEntry entityaitasks$entityaitaskentry1 = iterator.next();
if (!this.canContinue(entityaitasks$entityaitaskentry1))
{
entityaitasks$entityaitaskentry1.using = false;
entityaitasks$entityaitaskentry1.action.resetTask();
iterator.remove();
}
}
}
this.profiler.endSection();
if (!this.executingTaskEntries.isEmpty())
{
this.profiler.startSection("goalTick");
for (EntityAITasks.EntityAITaskEntry entityaitasks$entityaitaskentry2 : this.executingTaskEntries)
{
entityaitasks$entityaitaskentry2.action.updateTask();
}
this.profiler.endSection();
}
}
/**
* Determine if a specific AI Task should continue being executed.
*/
private boolean canContinue(EntityAITasks.EntityAITaskEntry taskEntry)
{
return taskEntry.action.shouldContinueExecuting();
}
/**
* Determine if a specific AI Task can be executed, which means that all running higher (= lower int value) priority
* tasks are compatible with it or all lower priority tasks can be interrupted.
*/
private boolean canUse(EntityAITasks.EntityAITaskEntry taskEntry)
{
if (this.executingTaskEntries.isEmpty())
{
return true;
}
else if (this.isControlFlagDisabled(taskEntry.action.getMutexBits()))
{
return false;
}
else
{
for (EntityAITasks.EntityAITaskEntry entityaitasks$entityaitaskentry : this.executingTaskEntries)
{
if (entityaitasks$entityaitaskentry != taskEntry)
{
if (taskEntry.priority >= entityaitasks$entityaitaskentry.priority)
{
if (!this.areTasksCompatible(taskEntry, entityaitasks$entityaitaskentry))
{
return false;
}
}
else if (!entityaitasks$entityaitaskentry.action.isInterruptible())
{
return false;
}
}
}
return true;
}
}
/**
* Returns whether two EntityAITaskEntries can be executed concurrently
*/
private boolean areTasksCompatible(EntityAITasks.EntityAITaskEntry taskEntry1, EntityAITasks.EntityAITaskEntry taskEntry2)
{
return (taskEntry1.action.getMutexBits() & taskEntry2.action.getMutexBits()) == 0;
}
public boolean isControlFlagDisabled(int p_188528_1_)
{
return (this.disabledControlFlags & p_188528_1_) > 0;
}
public void disableControlFlag(int p_188526_1_)
{
this.disabledControlFlags |= p_188526_1_;
}
public void enableControlFlag(int p_188525_1_)
{
this.disabledControlFlags &= ~p_188525_1_;
}
public void setControlFlag(int p_188527_1_, boolean p_188527_2_)
{
if (p_188527_2_)
{
this.enableControlFlag(p_188527_1_);
}
else
{
this.disableControlFlag(p_188527_1_);
}
}
public class EntityAITaskEntry
{
/** The EntityAIBase object. */
public final EntityAIBase action;
/** Priority of the EntityAIBase */
public final int priority;
public boolean using;
public EntityAITaskEntry(int priorityIn, EntityAIBase task)
{
this.priority = priorityIn;
this.action = task;
}
public boolean equals(@Nullable Object p_equals_1_)
{
if (this == p_equals_1_)
{
return true;
}
else
{
return p_equals_1_ != null && this.getClass() == p_equals_1_.getClass() ? this.action.equals(((EntityAITasks.EntityAITaskEntry)p_equals_1_).action) : false;
}
}
public int hashCode()
{
return this.action.hashCode();
}
}
}

View File

@@ -0,0 +1,167 @@
package net.minecraft.entity.ai;
import com.google.common.collect.Sets;
import java.util.Set;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.pathfinding.PathNavigateGround;
public class EntityAITempt extends EntityAIBase
{
/** The entity using this AI that is tempted by the player. */
private final EntityCreature temptedEntity;
private final double speed;
/** X position of player tempting this mob */
private double targetX;
/** Y position of player tempting this mob */
private double targetY;
/** Z position of player tempting this mob */
private double targetZ;
/** Tempting player's pitch */
private double pitch;
/** Tempting player's yaw */
private double yaw;
/** The player that is tempting the entity that is using this AI. */
private EntityPlayer temptingPlayer;
/**
* A counter that is decremented each time the shouldExecute method is called. The shouldExecute method will always
* return false if delayTemptCounter is greater than 0.
*/
private int delayTemptCounter;
/** True if this EntityAITempt task is running */
private boolean isRunning;
private final Set<Item> temptItem;
/** Whether the entity using this AI will be scared by the tempter's sudden movement. */
private final boolean scaredByPlayerMovement;
public EntityAITempt(EntityCreature temptedEntityIn, double speedIn, Item temptItemIn, boolean scaredByPlayerMovementIn)
{
this(temptedEntityIn, speedIn, scaredByPlayerMovementIn, Sets.newHashSet(temptItemIn));
}
public EntityAITempt(EntityCreature temptedEntityIn, double speedIn, boolean scaredByPlayerMovementIn, Set<Item> temptItemIn)
{
this.temptedEntity = temptedEntityIn;
this.speed = speedIn;
this.temptItem = temptItemIn;
this.scaredByPlayerMovement = scaredByPlayerMovementIn;
this.setMutexBits(3);
if (!(temptedEntityIn.getNavigator() instanceof PathNavigateGround))
{
throw new IllegalArgumentException("Unsupported mob type for TemptGoal");
}
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (this.delayTemptCounter > 0)
{
--this.delayTemptCounter;
return false;
}
else
{
this.temptingPlayer = this.temptedEntity.world.getClosestPlayerToEntity(this.temptedEntity, 10.0D);
if (this.temptingPlayer == null)
{
return false;
}
else
{
return this.isTempting(this.temptingPlayer.getHeldItemMainhand()) || this.isTempting(this.temptingPlayer.getHeldItemOffhand());
}
}
}
protected boolean isTempting(ItemStack stack)
{
return this.temptItem.contains(stack.getItem());
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
if (this.scaredByPlayerMovement)
{
if (this.temptedEntity.getDistanceSq(this.temptingPlayer) < 36.0D)
{
if (this.temptingPlayer.getDistanceSq(this.targetX, this.targetY, this.targetZ) > 0.010000000000000002D)
{
return false;
}
if (Math.abs((double)this.temptingPlayer.rotationPitch - this.pitch) > 5.0D || Math.abs((double)this.temptingPlayer.rotationYaw - this.yaw) > 5.0D)
{
return false;
}
}
else
{
this.targetX = this.temptingPlayer.posX;
this.targetY = this.temptingPlayer.posY;
this.targetZ = this.temptingPlayer.posZ;
}
this.pitch = (double)this.temptingPlayer.rotationPitch;
this.yaw = (double)this.temptingPlayer.rotationYaw;
}
return this.shouldExecute();
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.targetX = this.temptingPlayer.posX;
this.targetY = this.temptingPlayer.posY;
this.targetZ = this.temptingPlayer.posZ;
this.isRunning = true;
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.temptingPlayer = null;
this.temptedEntity.getNavigator().clearPath();
this.delayTemptCounter = 100;
this.isRunning = false;
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
this.temptedEntity.getLookHelper().setLookPositionWithEntity(this.temptingPlayer, (float)(this.temptedEntity.getHorizontalFaceSpeed() + 20), (float)this.temptedEntity.getVerticalFaceSpeed());
if (this.temptedEntity.getDistanceSq(this.temptingPlayer) < 6.25D)
{
this.temptedEntity.getNavigator().clearPath();
}
else
{
this.temptedEntity.getNavigator().tryMoveToEntityLiving(this.temptingPlayer, this.speed);
}
}
/**
* @see #isRunning
*/
public boolean isRunning()
{
return this.isRunning;
}
}

View File

@@ -0,0 +1,71 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.entity.player.EntityPlayer;
public class EntityAITradePlayer extends EntityAIBase
{
private final EntityVillager villager;
public EntityAITradePlayer(EntityVillager villagerIn)
{
this.villager = villagerIn;
this.setMutexBits(5);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (!this.villager.isEntityAlive())
{
return false;
}
else if (this.villager.isInWater())
{
return false;
}
else if (!this.villager.onGround)
{
return false;
}
else if (this.villager.velocityChanged)
{
return false;
}
else
{
EntityPlayer entityplayer = this.villager.getCustomer();
if (entityplayer == null)
{
return false;
}
else if (this.villager.getDistanceSq(entityplayer) > 16.0D)
{
return false;
}
else
{
return entityplayer.openContainer != null;
}
}
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.villager.getNavigator().clearPath();
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.villager.setCustomer((EntityPlayer)null);
}
}

View File

@@ -0,0 +1,102 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.init.Items;
import net.minecraft.inventory.InventoryBasic;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.MathHelper;
public class EntityAIVillagerInteract extends EntityAIWatchClosest2
{
/** The delay before the villager throws an itemstack (in ticks) */
private int interactionDelay;
private final EntityVillager villager;
public EntityAIVillagerInteract(EntityVillager villagerIn)
{
super(villagerIn, EntityVillager.class, 3.0F, 0.02F);
this.villager = villagerIn;
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
super.startExecuting();
if (this.villager.canAbondonItems() && this.closestEntity instanceof EntityVillager && ((EntityVillager)this.closestEntity).wantsMoreFood())
{
this.interactionDelay = 10;
}
else
{
this.interactionDelay = 0;
}
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
super.updateTask();
if (this.interactionDelay > 0)
{
--this.interactionDelay;
if (this.interactionDelay == 0)
{
InventoryBasic inventorybasic = this.villager.getVillagerInventory();
for (int i = 0; i < inventorybasic.getSizeInventory(); ++i)
{
ItemStack itemstack = inventorybasic.getStackInSlot(i);
ItemStack itemstack1 = ItemStack.EMPTY;
if (!itemstack.isEmpty())
{
Item item = itemstack.getItem();
if ((item == Items.BREAD || item == Items.POTATO || item == Items.CARROT || item == Items.BEETROOT) && itemstack.getCount() > 3)
{
int l = itemstack.getCount() / 2;
itemstack.shrink(l);
itemstack1 = new ItemStack(item, l, itemstack.getMetadata());
}
else if (item == Items.WHEAT && itemstack.getCount() > 5)
{
int j = itemstack.getCount() / 2 / 3 * 3;
int k = j / 3;
itemstack.shrink(j);
itemstack1 = new ItemStack(Items.BREAD, k, 0);
}
if (itemstack.isEmpty())
{
inventorybasic.setInventorySlotContents(i, ItemStack.EMPTY);
}
}
if (!itemstack1.isEmpty())
{
double d0 = this.villager.posY - 0.30000001192092896D + (double)this.villager.getEyeHeight();
EntityItem entityitem = new EntityItem(this.villager.world, this.villager.posX, d0, this.villager.posZ, itemstack1);
float f = 0.3F;
float f1 = this.villager.rotationYawHead;
float f2 = this.villager.rotationPitch;
entityitem.motionX = (double)(-MathHelper.sin(f1 * 0.017453292F) * MathHelper.cos(f2 * 0.017453292F) * 0.3F);
entityitem.motionZ = (double)(MathHelper.cos(f1 * 0.017453292F) * MathHelper.cos(f2 * 0.017453292F) * 0.3F);
entityitem.motionY = (double)(-MathHelper.sin(f2 * 0.017453292F) * 0.3F + 0.1F);
entityitem.setDefaultPickupDelay();
this.villager.world.spawnEntity(entityitem);
break;
}
}
}
}
}
}

View File

@@ -0,0 +1,145 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.Entity;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.util.math.BlockPos;
import net.minecraft.village.Village;
import net.minecraft.world.World;
public class EntityAIVillagerMate extends EntityAIBase
{
private final EntityVillager villager;
private EntityVillager mate;
private final World world;
private int matingTimeout;
Village village;
public EntityAIVillagerMate(EntityVillager villagerIn)
{
this.villager = villagerIn;
this.world = villagerIn.world;
this.setMutexBits(3);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (this.villager.getGrowingAge() != 0)
{
return false;
}
else if (this.villager.getRNG().nextInt(500) != 0)
{
return false;
}
else
{
this.village = this.world.getVillageCollection().getNearestVillage(new BlockPos(this.villager), 0);
if (this.village == null)
{
return false;
}
else if (this.checkSufficientDoorsPresentForNewVillager() && this.villager.getIsWillingToMate(true))
{
Entity entity = this.world.findNearestEntityWithinAABB(EntityVillager.class, this.villager.getEntityBoundingBox().grow(8.0D, 3.0D, 8.0D), this.villager);
if (entity == null)
{
return false;
}
else
{
this.mate = (EntityVillager)entity;
return this.mate.getGrowingAge() == 0 && this.mate.getIsWillingToMate(true);
}
}
else
{
return false;
}
}
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.matingTimeout = 300;
this.villager.setMating(true);
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.village = null;
this.mate = null;
this.villager.setMating(false);
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return this.matingTimeout >= 0 && this.checkSufficientDoorsPresentForNewVillager() && this.villager.getGrowingAge() == 0 && this.villager.getIsWillingToMate(false);
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
--this.matingTimeout;
this.villager.getLookHelper().setLookPositionWithEntity(this.mate, 10.0F, 30.0F);
if (this.villager.getDistanceSq(this.mate) > 2.25D)
{
this.villager.getNavigator().tryMoveToEntityLiving(this.mate, 0.25D);
}
else if (this.matingTimeout == 0 && this.mate.isMating())
{
this.giveBirth();
}
if (this.villager.getRNG().nextInt(35) == 0)
{
this.world.setEntityState(this.villager, (byte)12);
}
}
private boolean checkSufficientDoorsPresentForNewVillager()
{
if (!this.village.isMatingSeason())
{
return false;
}
else
{
int i = (int)((double)((float)this.village.getNumVillageDoors()) * 0.35D);
return this.village.getNumVillagers() < i;
}
}
private void giveBirth()
{
net.minecraft.entity.EntityAgeable entityvillager = this.villager.createChild(this.mate);
this.mate.setGrowingAge(6000);
this.villager.setGrowingAge(6000);
this.mate.setIsWillingToMate(false);
this.villager.setIsWillingToMate(false);
final net.minecraftforge.event.entity.living.BabyEntitySpawnEvent event = new net.minecraftforge.event.entity.living.BabyEntitySpawnEvent(villager, mate, entityvillager);
if (net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(event) || event.getChild() == null) { return; }
entityvillager = event.getChild();
entityvillager.setGrowingAge(-24000);
entityvillager.setLocationAndAngles(this.villager.posX, this.villager.posY, this.villager.posZ, 0.0F, 0.0F);
this.world.spawnEntity(entityvillager);
this.world.setEntityState(entityvillager, (byte)12);
}
}

View File

@@ -0,0 +1,101 @@
package net.minecraft.entity.ai;
import javax.annotation.Nullable;
import net.minecraft.entity.EntityCreature;
import net.minecraft.util.math.Vec3d;
public class EntityAIWander extends EntityAIBase
{
protected final EntityCreature entity;
protected double x;
protected double y;
protected double z;
protected final double speed;
protected int executionChance;
protected boolean mustUpdate;
public EntityAIWander(EntityCreature creatureIn, double speedIn)
{
this(creatureIn, speedIn, 120);
}
public EntityAIWander(EntityCreature creatureIn, double speedIn, int chance)
{
this.entity = creatureIn;
this.speed = speedIn;
this.executionChance = chance;
this.setMutexBits(1);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (!this.mustUpdate)
{
if (this.entity.getIdleTime() >= 100)
{
return false;
}
if (this.entity.getRNG().nextInt(this.executionChance) != 0)
{
return false;
}
}
Vec3d vec3d = this.getPosition();
if (vec3d == null)
{
return false;
}
else
{
this.x = vec3d.x;
this.y = vec3d.y;
this.z = vec3d.z;
this.mustUpdate = false;
return true;
}
}
@Nullable
protected Vec3d getPosition()
{
return RandomPositionGenerator.findRandomTarget(this.entity, 10, 7);
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return !this.entity.getNavigator().noPath();
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.entity.getNavigator().tryMoveToXYZ(this.x, this.y, this.z, this.speed);
}
/**
* Makes task to bypass chance
*/
public void makeUpdate()
{
this.mustUpdate = true;
}
/**
* Changes task random possibility for execution
*/
public void setExecutionChance(int newchance)
{
this.executionChance = newchance;
}
}

View File

@@ -0,0 +1,35 @@
package net.minecraft.entity.ai;
import javax.annotation.Nullable;
import net.minecraft.entity.EntityCreature;
import net.minecraft.util.math.Vec3d;
public class EntityAIWanderAvoidWater extends EntityAIWander
{
protected final float probability;
public EntityAIWanderAvoidWater(EntityCreature p_i47301_1_, double p_i47301_2_)
{
this(p_i47301_1_, p_i47301_2_, 0.001F);
}
public EntityAIWanderAvoidWater(EntityCreature p_i47302_1_, double p_i47302_2_, float p_i47302_4_)
{
super(p_i47302_1_, p_i47302_2_);
this.probability = p_i47302_4_;
}
@Nullable
protected Vec3d getPosition()
{
if (this.entity.isInWater())
{
Vec3d vec3d = RandomPositionGenerator.getLandPos(this.entity, 15, 7);
return vec3d == null ? super.getPosition() : vec3d;
}
else
{
return this.entity.getRNG().nextFloat() >= this.probability ? RandomPositionGenerator.getLandPos(this.entity, 10, 7) : super.getPosition();
}
}
}

View File

@@ -0,0 +1,72 @@
package net.minecraft.entity.ai;
import java.util.Iterator;
import javax.annotation.Nullable;
import net.minecraft.block.Block;
import net.minecraft.block.BlockLeaves;
import net.minecraft.entity.EntityCreature;
import net.minecraft.init.Blocks;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
public class EntityAIWanderAvoidWaterFlying extends EntityAIWanderAvoidWater
{
public EntityAIWanderAvoidWaterFlying(EntityCreature p_i47413_1_, double p_i47413_2_)
{
super(p_i47413_1_, p_i47413_2_);
}
@Nullable
protected Vec3d getPosition()
{
Vec3d vec3d = null;
if (this.entity.isInWater() || this.entity.isOverWater())
{
vec3d = RandomPositionGenerator.getLandPos(this.entity, 15, 15);
}
if (this.entity.getRNG().nextFloat() >= this.probability)
{
vec3d = this.getTreePos();
}
return vec3d == null ? super.getPosition() : vec3d;
}
@Nullable
private Vec3d getTreePos()
{
BlockPos blockpos = new BlockPos(this.entity);
BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos();
BlockPos.MutableBlockPos blockpos$mutableblockpos1 = new BlockPos.MutableBlockPos();
Iterable<BlockPos.MutableBlockPos> iterable = BlockPos.MutableBlockPos.getAllInBoxMutable(MathHelper.floor(this.entity.posX - 3.0D), MathHelper.floor(this.entity.posY - 6.0D), MathHelper.floor(this.entity.posZ - 3.0D), MathHelper.floor(this.entity.posX + 3.0D), MathHelper.floor(this.entity.posY + 6.0D), MathHelper.floor(this.entity.posZ + 3.0D));
Iterator iterator = iterable.iterator();
BlockPos blockpos1;
while (true)
{
if (!iterator.hasNext())
{
return null;
}
blockpos1 = (BlockPos)iterator.next();
if (!blockpos.equals(blockpos1))
{
Block block = this.entity.world.getBlockState(blockpos$mutableblockpos1.setPos(blockpos1).move(EnumFacing.DOWN)).getBlock();
boolean flag = block instanceof BlockLeaves || block == Blocks.LOG || block == Blocks.LOG2;
if (flag && this.entity.world.isAirBlock(blockpos1) && this.entity.world.isAirBlock(blockpos$mutableblockpos.setPos(blockpos1).move(EnumFacing.UP)))
{
break;
}
}
}
return new Vec3d((double)blockpos1.getX(), (double)blockpos1.getY(), (double)blockpos1.getZ());
}
}

View File

@@ -0,0 +1,110 @@
package net.minecraft.entity.ai;
import com.google.common.base.Predicates;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EntitySelectors;
public class EntityAIWatchClosest extends EntityAIBase
{
protected EntityLiving entity;
/** The closest entity which is being watched by this one. */
protected Entity closestEntity;
/** This is the Maximum distance that the AI will look for the Entity */
protected float maxDistanceForPlayer;
private int lookTime;
private final float chance;
protected Class <? extends Entity > watchedClass;
public EntityAIWatchClosest(EntityLiving entityIn, Class <? extends Entity > watchTargetClass, float maxDistance)
{
this.entity = entityIn;
this.watchedClass = watchTargetClass;
this.maxDistanceForPlayer = maxDistance;
this.chance = 0.02F;
this.setMutexBits(2);
}
public EntityAIWatchClosest(EntityLiving entityIn, Class <? extends Entity > watchTargetClass, float maxDistance, float chanceIn)
{
this.entity = entityIn;
this.watchedClass = watchTargetClass;
this.maxDistanceForPlayer = maxDistance;
this.chance = chanceIn;
this.setMutexBits(2);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (this.entity.getRNG().nextFloat() >= this.chance)
{
return false;
}
else
{
if (this.entity.getAttackTarget() != null)
{
this.closestEntity = this.entity.getAttackTarget();
}
if (this.watchedClass == EntityPlayer.class)
{
this.closestEntity = this.entity.world.getClosestPlayer(this.entity.posX, this.entity.posY, this.entity.posZ, (double)this.maxDistanceForPlayer, Predicates.and(EntitySelectors.NOT_SPECTATING, EntitySelectors.notRiding(this.entity)));
}
else
{
this.closestEntity = this.entity.world.findNearestEntityWithinAABB(this.watchedClass, this.entity.getEntityBoundingBox().grow((double)this.maxDistanceForPlayer, 3.0D, (double)this.maxDistanceForPlayer), this.entity);
}
return this.closestEntity != null;
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
if (!this.closestEntity.isEntityAlive())
{
return false;
}
else if (this.entity.getDistanceSq(this.closestEntity) > (double)(this.maxDistanceForPlayer * this.maxDistanceForPlayer))
{
return false;
}
else
{
return this.lookTime > 0;
}
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.lookTime = 40 + this.entity.getRNG().nextInt(40);
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.closestEntity = null;
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
this.entity.getLookHelper().setLookPosition(this.closestEntity.posX, this.closestEntity.posY + (double)this.closestEntity.getEyeHeight(), this.closestEntity.posZ, (float)this.entity.getHorizontalFaceSpeed(), (float)this.entity.getVerticalFaceSpeed());
--this.lookTime;
}
}

View File

@@ -0,0 +1,13 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
public class EntityAIWatchClosest2 extends EntityAIWatchClosest
{
public EntityAIWatchClosest2(EntityLiving entitylivingIn, Class <? extends Entity > watchTargetClass, float maxDistance, float chanceIn)
{
super(entitylivingIn, watchTargetClass, maxDistance, chanceIn);
this.setMutexBits(3);
}
}

View File

@@ -0,0 +1,51 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.monster.EntityZombie;
public class EntityAIZombieAttack extends EntityAIAttackMelee
{
private final EntityZombie zombie;
private int raiseArmTicks;
public EntityAIZombieAttack(EntityZombie zombieIn, double speedIn, boolean longMemoryIn)
{
super(zombieIn, speedIn, longMemoryIn);
this.zombie = zombieIn;
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
super.startExecuting();
this.raiseArmTicks = 0;
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
super.resetTask();
this.zombie.setArmsRaised(false);
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
super.updateTask();
++this.raiseArmTicks;
if (this.raiseArmTicks >= 5 && this.attackTick < 10)
{
this.zombie.setArmsRaised(true);
}
else
{
this.zombie.setArmsRaised(false);
}
}
}

View File

@@ -0,0 +1,58 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.util.math.MathHelper;
public class EntityFlyHelper extends EntityMoveHelper
{
public EntityFlyHelper(EntityLiving p_i47418_1_)
{
super(p_i47418_1_);
}
public void onUpdateMoveHelper()
{
if (this.action == EntityMoveHelper.Action.MOVE_TO)
{
this.action = EntityMoveHelper.Action.WAIT;
this.entity.setNoGravity(true);
double d0 = this.posX - this.entity.posX;
double d1 = this.posY - this.entity.posY;
double d2 = this.posZ - this.entity.posZ;
double d3 = d0 * d0 + d1 * d1 + d2 * d2;
if (d3 < 2.500000277905201E-7D)
{
this.entity.setMoveVertical(0.0F);
this.entity.setMoveForward(0.0F);
return;
}
float f = (float)(MathHelper.atan2(d2, d0) * (180D / Math.PI)) - 90.0F;
this.entity.rotationYaw = this.limitAngle(this.entity.rotationYaw, f, 10.0F);
float f1;
if (this.entity.onGround)
{
f1 = (float)(this.speed * this.entity.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).getAttributeValue());
}
else
{
f1 = (float)(this.speed * this.entity.getEntityAttribute(SharedMonsterAttributes.FLYING_SPEED).getAttributeValue());
}
this.entity.setAIMoveSpeed(f1);
double d4 = (double)MathHelper.sqrt(d0 * d0 + d2 * d2);
float f2 = (float)(-(MathHelper.atan2(d1, d4) * (180D / Math.PI)));
this.entity.rotationPitch = this.limitAngle(this.entity.rotationPitch, f2, 10.0F);
this.entity.setMoveVertical(d1 > 0.0D ? f1 : -f1);
}
else
{
this.entity.setNoGravity(false);
this.entity.setMoveVertical(0.0F);
this.entity.setMoveForward(0.0F);
}
}
}

View File

@@ -0,0 +1,28 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.EntityLiving;
public class EntityJumpHelper
{
private final EntityLiving entity;
protected boolean isJumping;
public EntityJumpHelper(EntityLiving entityIn)
{
this.entity = entityIn;
}
public void setJumping()
{
this.isJumping = true;
}
/**
* Called to actually make the entity jump if isJumping is true.
*/
public void doJump()
{
this.entity.setJumping(this.isJumping);
this.isJumping = false;
}
}

View File

@@ -0,0 +1,137 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.math.MathHelper;
public class EntityLookHelper
{
private final EntityLiving entity;
/** The amount of change that is made each update for an entity facing a direction. */
private float deltaLookYaw;
/** The amount of change that is made each update for an entity facing a direction. */
private float deltaLookPitch;
/** Whether or not the entity is trying to look at something. */
private boolean isLooking;
private double posX;
private double posY;
private double posZ;
public EntityLookHelper(EntityLiving entitylivingIn)
{
this.entity = entitylivingIn;
}
/**
* Sets position to look at using entity
*/
public void setLookPositionWithEntity(Entity entityIn, float deltaYaw, float deltaPitch)
{
this.posX = entityIn.posX;
if (entityIn instanceof EntityLivingBase)
{
this.posY = entityIn.posY + (double)entityIn.getEyeHeight();
}
else
{
this.posY = (entityIn.getEntityBoundingBox().minY + entityIn.getEntityBoundingBox().maxY) / 2.0D;
}
this.posZ = entityIn.posZ;
this.deltaLookYaw = deltaYaw;
this.deltaLookPitch = deltaPitch;
this.isLooking = true;
}
/**
* Sets position to look at
*/
public void setLookPosition(double x, double y, double z, float deltaYaw, float deltaPitch)
{
this.posX = x;
this.posY = y;
this.posZ = z;
this.deltaLookYaw = deltaYaw;
this.deltaLookPitch = deltaPitch;
this.isLooking = true;
}
/**
* Updates look
*/
public void onUpdateLook()
{
this.entity.rotationPitch = 0.0F;
if (this.isLooking)
{
this.isLooking = false;
double d0 = this.posX - this.entity.posX;
double d1 = this.posY - (this.entity.posY + (double)this.entity.getEyeHeight());
double d2 = this.posZ - this.entity.posZ;
double d3 = (double)MathHelper.sqrt(d0 * d0 + d2 * d2);
float f = (float)(MathHelper.atan2(d2, d0) * (180D / Math.PI)) - 90.0F;
float f1 = (float)(-(MathHelper.atan2(d1, d3) * (180D / Math.PI)));
this.entity.rotationPitch = this.updateRotation(this.entity.rotationPitch, f1, this.deltaLookPitch);
this.entity.rotationYawHead = this.updateRotation(this.entity.rotationYawHead, f, this.deltaLookYaw);
}
else
{
this.entity.rotationYawHead = this.updateRotation(this.entity.rotationYawHead, this.entity.renderYawOffset, 10.0F);
}
float f2 = MathHelper.wrapDegrees(this.entity.rotationYawHead - this.entity.renderYawOffset);
if (!this.entity.getNavigator().noPath())
{
if (f2 < -75.0F)
{
this.entity.rotationYawHead = this.entity.renderYawOffset - 75.0F;
}
if (f2 > 75.0F)
{
this.entity.rotationYawHead = this.entity.renderYawOffset + 75.0F;
}
}
}
private float updateRotation(float p_75652_1_, float p_75652_2_, float p_75652_3_)
{
float f = MathHelper.wrapDegrees(p_75652_2_ - p_75652_1_);
if (f > p_75652_3_)
{
f = p_75652_3_;
}
if (f < -p_75652_3_)
{
f = -p_75652_3_;
}
return p_75652_1_ + f;
}
public boolean getIsLooking()
{
return this.isLooking;
}
public double getLookPosX()
{
return this.posX;
}
public double getLookPosY()
{
return this.posY;
}
public double getLookPosZ()
{
return this.posZ;
}
}

View File

@@ -0,0 +1,203 @@
package net.minecraft.entity.ai;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.pathfinding.NodeProcessor;
import net.minecraft.pathfinding.PathNavigate;
import net.minecraft.pathfinding.PathNodeType;
import net.minecraft.util.math.MathHelper;
public class EntityMoveHelper
{
/** The EntityLiving that is being moved */
protected final EntityLiving entity;
protected double posX;
protected double posY;
protected double posZ;
/** Multiplier for the entity's speed attribute value */
protected double speed;
protected float moveForward;
protected float moveStrafe;
public EntityMoveHelper.Action action = EntityMoveHelper.Action.WAIT;
public EntityMoveHelper(EntityLiving entitylivingIn)
{
this.entity = entitylivingIn;
}
public boolean isUpdating()
{
return this.action == EntityMoveHelper.Action.MOVE_TO;
}
public double getSpeed()
{
return this.speed;
}
/**
* Sets the speed and location to move to
*/
public void setMoveTo(double x, double y, double z, double speedIn)
{
this.posX = x;
this.posY = y;
this.posZ = z;
this.speed = speedIn;
this.action = EntityMoveHelper.Action.MOVE_TO;
}
public void strafe(float forward, float strafe)
{
this.action = EntityMoveHelper.Action.STRAFE;
this.moveForward = forward;
this.moveStrafe = strafe;
this.speed = 0.25D;
}
public void read(EntityMoveHelper that)
{
this.action = that.action;
this.posX = that.posX;
this.posY = that.posY;
this.posZ = that.posZ;
this.speed = Math.max(that.speed, 1.0D);
this.moveForward = that.moveForward;
this.moveStrafe = that.moveStrafe;
}
public void onUpdateMoveHelper()
{
if (this.action == EntityMoveHelper.Action.STRAFE)
{
float f = (float)this.entity.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).getAttributeValue();
float f1 = (float)this.speed * f;
float f2 = this.moveForward;
float f3 = this.moveStrafe;
float f4 = MathHelper.sqrt(f2 * f2 + f3 * f3);
if (f4 < 1.0F)
{
f4 = 1.0F;
}
f4 = f1 / f4;
f2 = f2 * f4;
f3 = f3 * f4;
float f5 = MathHelper.sin(this.entity.rotationYaw * 0.017453292F);
float f6 = MathHelper.cos(this.entity.rotationYaw * 0.017453292F);
float f7 = f2 * f6 - f3 * f5;
float f8 = f3 * f6 + f2 * f5;
PathNavigate pathnavigate = this.entity.getNavigator();
if (pathnavigate != null)
{
NodeProcessor nodeprocessor = pathnavigate.getNodeProcessor();
if (nodeprocessor != null && nodeprocessor.getPathNodeType(this.entity.world, MathHelper.floor(this.entity.posX + (double)f7), MathHelper.floor(this.entity.posY), MathHelper.floor(this.entity.posZ + (double)f8)) != PathNodeType.WALKABLE)
{
this.moveForward = 1.0F;
this.moveStrafe = 0.0F;
f1 = f;
}
}
this.entity.setAIMoveSpeed(f1);
this.entity.setMoveForward(this.moveForward);
this.entity.setMoveStrafing(this.moveStrafe);
this.action = EntityMoveHelper.Action.WAIT;
}
else if (this.action == EntityMoveHelper.Action.MOVE_TO)
{
this.action = EntityMoveHelper.Action.WAIT;
double d0 = this.posX - this.entity.posX;
double d1 = this.posZ - this.entity.posZ;
double d2 = this.posY - this.entity.posY;
double d3 = d0 * d0 + d2 * d2 + d1 * d1;
if (d3 < 2.500000277905201E-7D)
{
this.entity.setMoveForward(0.0F);
return;
}
float f9 = (float)(MathHelper.atan2(d1, d0) * (180D / Math.PI)) - 90.0F;
this.entity.rotationYaw = this.limitAngle(this.entity.rotationYaw, f9, 90.0F);
this.entity.setAIMoveSpeed((float)(this.speed * this.entity.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).getAttributeValue()));
if (d2 > (double)this.entity.stepHeight && d0 * d0 + d1 * d1 < (double)Math.max(1.0F, this.entity.width))
{
this.entity.getJumpHelper().setJumping();
this.action = EntityMoveHelper.Action.JUMPING;
}
}
else if (this.action == EntityMoveHelper.Action.JUMPING)
{
this.entity.setAIMoveSpeed((float)(this.speed * this.entity.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).getAttributeValue()));
if (this.entity.onGround)
{
this.action = EntityMoveHelper.Action.WAIT;
}
}
else
{
this.entity.setMoveForward(0.0F);
}
}
/**
* Attempt to rotate the first angle to become the second angle, but only allow overall direction change to at max
* be third parameter
*/
protected float limitAngle(float sourceAngle, float targetAngle, float maximumChange)
{
float f = MathHelper.wrapDegrees(targetAngle - sourceAngle);
if (f > maximumChange)
{
f = maximumChange;
}
if (f < -maximumChange)
{
f = -maximumChange;
}
float f1 = sourceAngle + f;
if (f1 < 0.0F)
{
f1 += 360.0F;
}
else if (f1 > 360.0F)
{
f1 -= 360.0F;
}
return f1;
}
public double getX()
{
return this.posX;
}
public double getY()
{
return this.posY;
}
public double getZ()
{
return this.posZ;
}
public static enum Action
{
WAIT,
MOVE_TO,
STRAFE,
JUMPING;
}
}

View File

@@ -0,0 +1,61 @@
package net.minecraft.entity.ai;
import com.google.common.collect.Lists;
import java.util.List;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
public class EntitySenses
{
EntityLiving entity;
/** Cache of entities which we can see */
List<Entity> seenEntities = Lists.<Entity>newArrayList();
/** Cache of entities which we cannot see */
List<Entity> unseenEntities = Lists.<Entity>newArrayList();
public EntitySenses(EntityLiving entityIn)
{
this.entity = entityIn;
}
/**
* Clears canSeeCachePositive and canSeeCacheNegative.
*/
public void clearSensingCache()
{
this.seenEntities.clear();
this.unseenEntities.clear();
}
/**
* Checks, whether 'our' entity can see the entity given as argument (true) or not (false), caching the result.
*/
public boolean canSee(Entity entityIn)
{
if (this.seenEntities.contains(entityIn))
{
return true;
}
else if (this.unseenEntities.contains(entityIn))
{
return false;
}
else
{
this.entity.world.profiler.startSection("canSee");
boolean flag = this.entity.canEntityBeSeen(entityIn);
this.entity.world.profiler.endSection();
if (flag)
{
this.seenEntities.add(entityIn);
}
else
{
this.unseenEntities.add(entityIn);
}
return flag;
}
}
}

View File

@@ -0,0 +1,181 @@
package net.minecraft.entity.ai;
import java.util.Random;
import javax.annotation.Nullable;
import net.minecraft.block.material.Material;
import net.minecraft.entity.EntityCreature;
import net.minecraft.pathfinding.PathNavigate;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
public class RandomPositionGenerator
{
/**
* used to store a driection when the user passes a point to move towards or away from. WARNING: NEVER THREAD SAFE.
* MULTIPLE findTowards and findAway calls, will share this var
*/
private static Vec3d staticVector = Vec3d.ZERO;
/**
* finds a random target within par1(x,z) and par2 (y) blocks
*/
@Nullable
public static Vec3d findRandomTarget(EntityCreature entitycreatureIn, int xz, int y)
{
return findRandomTargetBlock(entitycreatureIn, xz, y, (Vec3d)null);
}
@Nullable
public static Vec3d getLandPos(EntityCreature p_191377_0_, int p_191377_1_, int p_191377_2_)
{
return generateRandomPos(p_191377_0_, p_191377_1_, p_191377_2_, (Vec3d)null, false);
}
/**
* finds a random target within par1(x,z) and par2 (y) blocks in the direction of the point par3
*/
@Nullable
public static Vec3d findRandomTargetBlockTowards(EntityCreature entitycreatureIn, int xz, int y, Vec3d targetVec3)
{
staticVector = targetVec3.subtract(entitycreatureIn.posX, entitycreatureIn.posY, entitycreatureIn.posZ);
return findRandomTargetBlock(entitycreatureIn, xz, y, staticVector);
}
/**
* finds a random target within par1(x,z) and par2 (y) blocks in the reverse direction of the point par3
*/
@Nullable
public static Vec3d findRandomTargetBlockAwayFrom(EntityCreature entitycreatureIn, int xz, int y, Vec3d targetVec3)
{
staticVector = (new Vec3d(entitycreatureIn.posX, entitycreatureIn.posY, entitycreatureIn.posZ)).subtract(targetVec3);
return findRandomTargetBlock(entitycreatureIn, xz, y, staticVector);
}
/**
* searches 10 blocks at random in a within par1(x,z) and par2 (y) distance, ignores those not in the direction of
* par3Vec3, then points to the tile for which creature.getBlockPathWeight returns the highest number
*/
@Nullable
private static Vec3d findRandomTargetBlock(EntityCreature entitycreatureIn, int xz, int y, @Nullable Vec3d targetVec3)
{
return generateRandomPos(entitycreatureIn, xz, y, targetVec3, true);
}
@Nullable
private static Vec3d generateRandomPos(EntityCreature p_191379_0_, int p_191379_1_, int p_191379_2_, @Nullable Vec3d p_191379_3_, boolean p_191379_4_)
{
PathNavigate pathnavigate = p_191379_0_.getNavigator();
Random random = p_191379_0_.getRNG();
boolean flag;
if (p_191379_0_.hasHome())
{
double d0 = p_191379_0_.getHomePosition().distanceSq((double)MathHelper.floor(p_191379_0_.posX), (double)MathHelper.floor(p_191379_0_.posY), (double)MathHelper.floor(p_191379_0_.posZ)) + 4.0D;
double d1 = (double)(p_191379_0_.getMaximumHomeDistance() + (float)p_191379_1_);
flag = d0 < d1 * d1;
}
else
{
flag = false;
}
boolean flag1 = false;
float f = -99999.0F;
int k1 = 0;
int i = 0;
int j = 0;
for (int k = 0; k < 10; ++k)
{
int l = random.nextInt(2 * p_191379_1_ + 1) - p_191379_1_;
int i1 = random.nextInt(2 * p_191379_2_ + 1) - p_191379_2_;
int j1 = random.nextInt(2 * p_191379_1_ + 1) - p_191379_1_;
if (p_191379_3_ == null || (double)l * p_191379_3_.x + (double)j1 * p_191379_3_.z >= 0.0D)
{
if (p_191379_0_.hasHome() && p_191379_1_ > 1)
{
BlockPos blockpos = p_191379_0_.getHomePosition();
if (p_191379_0_.posX > (double)blockpos.getX())
{
l -= random.nextInt(p_191379_1_ / 2);
}
else
{
l += random.nextInt(p_191379_1_ / 2);
}
if (p_191379_0_.posZ > (double)blockpos.getZ())
{
j1 -= random.nextInt(p_191379_1_ / 2);
}
else
{
j1 += random.nextInt(p_191379_1_ / 2);
}
}
BlockPos blockpos1 = new BlockPos((double)l + p_191379_0_.posX, (double)i1 + p_191379_0_.posY, (double)j1 + p_191379_0_.posZ);
if ((!flag || p_191379_0_.isWithinHomeDistanceFromPosition(blockpos1)) && pathnavigate.canEntityStandOnPos(blockpos1))
{
if (!p_191379_4_)
{
blockpos1 = moveAboveSolid(blockpos1, p_191379_0_);
if (isWaterDestination(blockpos1, p_191379_0_))
{
continue;
}
}
float f1 = p_191379_0_.getBlockPathWeight(blockpos1);
if (f1 > f)
{
f = f1;
k1 = l;
i = i1;
j = j1;
flag1 = true;
}
}
}
}
if (flag1)
{
return new Vec3d((double)k1 + p_191379_0_.posX, (double)i + p_191379_0_.posY, (double)j + p_191379_0_.posZ);
}
else
{
return null;
}
}
private static BlockPos moveAboveSolid(BlockPos p_191378_0_, EntityCreature p_191378_1_)
{
if (!p_191378_1_.world.getBlockState(p_191378_0_).getMaterial().isSolid())
{
return p_191378_0_;
}
else
{
BlockPos blockpos;
for (blockpos = p_191378_0_.up(); blockpos.getY() < p_191378_1_.world.getHeight() && p_191378_1_.world.getBlockState(blockpos).getMaterial().isSolid(); blockpos = blockpos.up())
{
;
}
return blockpos;
}
}
private static boolean isWaterDestination(BlockPos p_191380_0_, EntityCreature p_191380_1_)
{
return p_191380_1_.world.getBlockState(p_191380_0_).getMaterial() == Material.WATER;
}
}

View File

@@ -0,0 +1,90 @@
package net.minecraft.entity.ai.attributes;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.Nullable;
import net.minecraft.util.LowerStringMap;
public abstract class AbstractAttributeMap
{
protected final Map<IAttribute, IAttributeInstance> attributes = Maps.<IAttribute, IAttributeInstance>newHashMap();
protected final Map<String, IAttributeInstance> attributesByName = new LowerStringMap();
protected final Multimap<IAttribute, IAttribute> descendantsByParent = HashMultimap.<IAttribute, IAttribute>create();
public IAttributeInstance getAttributeInstance(IAttribute attribute)
{
return this.attributes.get(attribute);
}
@Nullable
public IAttributeInstance getAttributeInstanceByName(String attributeName)
{
return this.attributesByName.get(attributeName);
}
/**
* Registers an attribute with this AttributeMap, returns a modifiable AttributeInstance associated with this map
*/
public IAttributeInstance registerAttribute(IAttribute attribute)
{
if (this.attributesByName.containsKey(attribute.getName()))
{
throw new IllegalArgumentException("Attribute is already registered!");
}
else
{
IAttributeInstance iattributeinstance = this.createInstance(attribute);
this.attributesByName.put(attribute.getName(), iattributeinstance);
this.attributes.put(attribute, iattributeinstance);
for (IAttribute iattribute = attribute.getParent(); iattribute != null; iattribute = iattribute.getParent())
{
this.descendantsByParent.put(iattribute, attribute);
}
return iattributeinstance;
}
}
protected abstract IAttributeInstance createInstance(IAttribute attribute);
public Collection<IAttributeInstance> getAllAttributes()
{
return this.attributesByName.values();
}
public void onAttributeModified(IAttributeInstance instance)
{
}
public void removeAttributeModifiers(Multimap<String, AttributeModifier> modifiers)
{
for (Entry<String, AttributeModifier> entry : modifiers.entries())
{
IAttributeInstance iattributeinstance = this.getAttributeInstanceByName(entry.getKey());
if (iattributeinstance != null)
{
iattributeinstance.removeModifier(entry.getValue());
}
}
}
public void applyAttributeModifiers(Multimap<String, AttributeModifier> modifiers)
{
for (Entry<String, AttributeModifier> entry : modifiers.entries())
{
IAttributeInstance iattributeinstance = this.getAttributeInstanceByName(entry.getKey());
if (iattributeinstance != null)
{
iattributeinstance.removeModifier(entry.getValue());
iattributeinstance.applyModifier(entry.getValue());
}
}
}
}

View File

@@ -0,0 +1,88 @@
package net.minecraft.entity.ai.attributes;
import com.google.common.collect.Sets;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import net.minecraft.util.LowerStringMap;
public class AttributeMap extends AbstractAttributeMap
{
private final Set<IAttributeInstance> dirtyInstances = Sets.<IAttributeInstance>newHashSet();
protected final Map<String, IAttributeInstance> instancesByName = new LowerStringMap();
public ModifiableAttributeInstance getAttributeInstance(IAttribute attribute)
{
return (ModifiableAttributeInstance)super.getAttributeInstance(attribute);
}
public ModifiableAttributeInstance getAttributeInstanceByName(String attributeName)
{
IAttributeInstance iattributeinstance = super.getAttributeInstanceByName(attributeName);
if (iattributeinstance == null)
{
iattributeinstance = this.instancesByName.get(attributeName);
}
return (ModifiableAttributeInstance)iattributeinstance;
}
/**
* Registers an attribute with this AttributeMap, returns a modifiable AttributeInstance associated with this map
*/
public IAttributeInstance registerAttribute(IAttribute attribute)
{
IAttributeInstance iattributeinstance = super.registerAttribute(attribute);
if (attribute instanceof RangedAttribute && ((RangedAttribute)attribute).getDescription() != null)
{
this.instancesByName.put(((RangedAttribute)attribute).getDescription(), iattributeinstance);
}
return iattributeinstance;
}
protected IAttributeInstance createInstance(IAttribute attribute)
{
return new ModifiableAttributeInstance(this, attribute);
}
public void onAttributeModified(IAttributeInstance instance)
{
if (instance.getAttribute().getShouldWatch())
{
this.dirtyInstances.add(instance);
}
for (IAttribute iattribute : this.descendantsByParent.get(instance.getAttribute()))
{
ModifiableAttributeInstance modifiableattributeinstance = this.getAttributeInstance(iattribute);
if (modifiableattributeinstance != null)
{
modifiableattributeinstance.flagForUpdate();
}
}
}
public Set<IAttributeInstance> getDirtyInstances()
{
return this.dirtyInstances;
}
public Collection<IAttributeInstance> getWatchedAttributes()
{
Set<IAttributeInstance> set = Sets.<IAttributeInstance>newHashSet();
for (IAttributeInstance iattributeinstance : this.getAllAttributes())
{
if (iattributeinstance.getAttribute().getShouldWatch())
{
set.add(iattributeinstance);
}
}
return set;
}
}

View File

@@ -0,0 +1,109 @@
package net.minecraft.entity.ai.attributes;
import io.netty.util.internal.ThreadLocalRandom;
import java.util.UUID;
import net.minecraft.util.math.MathHelper;
import org.apache.commons.lang3.Validate;
public class AttributeModifier
{
private final double amount;
private final int operation;
private final String name;
private final UUID id;
/** If false, this modifier is not saved in NBT. Used for "natural" modifiers like speed boost from sprinting */
private boolean isSaved;
public AttributeModifier(String nameIn, double amountIn, int operationIn)
{
this(MathHelper.getRandomUUID(ThreadLocalRandom.current()), nameIn, amountIn, operationIn);
}
public AttributeModifier(UUID idIn, String nameIn, double amountIn, int operationIn)
{
this.isSaved = true;
this.id = idIn;
this.name = nameIn;
this.amount = amountIn;
this.operation = operationIn;
Validate.notEmpty(nameIn, "Modifier name cannot be empty");
Validate.inclusiveBetween(0L, 2L, (long)operationIn, "Invalid operation");
}
public UUID getID()
{
return this.id;
}
public String getName()
{
return this.name;
}
public int getOperation()
{
return this.operation;
}
public double getAmount()
{
return this.amount;
}
/**
* @see #isSaved
*/
public boolean isSaved()
{
return this.isSaved;
}
/**
* @see #isSaved
*/
public AttributeModifier setSaved(boolean saved)
{
this.isSaved = saved;
return this;
}
public boolean equals(Object p_equals_1_)
{
if (this == p_equals_1_)
{
return true;
}
else if (p_equals_1_ != null && this.getClass() == p_equals_1_.getClass())
{
AttributeModifier attributemodifier = (AttributeModifier)p_equals_1_;
if (this.id != null)
{
if (!this.id.equals(attributemodifier.id))
{
return false;
}
}
else if (attributemodifier.id != null)
{
return false;
}
return true;
}
else
{
return false;
}
}
public int hashCode()
{
return this.id != null ? this.id.hashCode() : 0;
}
public String toString()
{
return "AttributeModifier{amount=" + this.amount + ", operation=" + this.operation + ", name='" + this.name + '\'' + ", id=" + this.id + ", serialize=" + this.isSaved + '}';
}
}

View File

@@ -0,0 +1,60 @@
package net.minecraft.entity.ai.attributes;
import javax.annotation.Nullable;
public abstract class BaseAttribute implements IAttribute
{
private final IAttribute parent;
private final String unlocalizedName;
private final double defaultValue;
private boolean shouldWatch;
protected BaseAttribute(@Nullable IAttribute parentIn, String unlocalizedNameIn, double defaultValueIn)
{
this.parent = parentIn;
this.unlocalizedName = unlocalizedNameIn;
this.defaultValue = defaultValueIn;
if (unlocalizedNameIn == null)
{
throw new IllegalArgumentException("Name cannot be null!");
}
}
public String getName()
{
return this.unlocalizedName;
}
public double getDefaultValue()
{
return this.defaultValue;
}
public boolean getShouldWatch()
{
return this.shouldWatch;
}
public BaseAttribute setShouldWatch(boolean shouldWatchIn)
{
this.shouldWatch = shouldWatchIn;
return this;
}
@Nullable
public IAttribute getParent()
{
return this.parent;
}
public int hashCode()
{
return this.unlocalizedName.hashCode();
}
public boolean equals(Object p_equals_1_)
{
return p_equals_1_ instanceof IAttribute && this.unlocalizedName.equals(((IAttribute)p_equals_1_).getName());
}
}

View File

@@ -0,0 +1,17 @@
package net.minecraft.entity.ai.attributes;
import javax.annotation.Nullable;
public interface IAttribute
{
String getName();
double clampValue(double value);
double getDefaultValue();
boolean getShouldWatch();
@Nullable
IAttribute getParent();
}

View File

@@ -0,0 +1,42 @@
package net.minecraft.entity.ai.attributes;
import java.util.Collection;
import java.util.UUID;
import javax.annotation.Nullable;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public interface IAttributeInstance
{
/**
* Get the Attribute this is an instance of
*/
IAttribute getAttribute();
double getBaseValue();
void setBaseValue(double baseValue);
Collection<AttributeModifier> getModifiersByOperation(int operation);
Collection<AttributeModifier> getModifiers();
boolean hasModifier(AttributeModifier modifier);
/**
* Returns attribute modifier, if any, by the given UUID
*/
@Nullable
AttributeModifier getModifier(UUID uuid);
void applyModifier(AttributeModifier modifier);
void removeModifier(AttributeModifier modifier);
void removeModifier(UUID p_188479_1_);
@SideOnly(Side.CLIENT)
void removeAllModifiers();
double getAttributeValue();
}

Some files were not shown because too many files have changed in this diff Show More