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

View File

@@ -0,0 +1,71 @@
package net.minecraft.entity.monster;
import net.minecraft.entity.EnumCreatureAttribute;
import net.minecraft.network.datasync.DataParameter;
import net.minecraft.network.datasync.DataSerializers;
import net.minecraft.network.datasync.EntityDataManager;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public abstract class AbstractIllager extends EntityMob
{
protected static final DataParameter<Byte> AGGRESSIVE = EntityDataManager.<Byte>createKey(AbstractIllager.class, DataSerializers.BYTE);
public AbstractIllager(World p_i47509_1_)
{
super(p_i47509_1_);
}
protected void entityInit()
{
super.entityInit();
this.dataManager.register(AGGRESSIVE, Byte.valueOf((byte)0));
}
@SideOnly(Side.CLIENT)
protected boolean isAggressive(int mask)
{
int i = ((Byte)this.dataManager.get(AGGRESSIVE)).byteValue();
return (i & mask) != 0;
}
protected void setAggressive(int mask, boolean value)
{
int i = ((Byte)this.dataManager.get(AGGRESSIVE)).byteValue();
if (value)
{
i = i | mask;
}
else
{
i = i & ~mask;
}
this.dataManager.set(AGGRESSIVE, Byte.valueOf((byte)(i & 255)));
}
/**
* Get this Entity's EnumCreatureAttribute
*/
public EnumCreatureAttribute getCreatureAttribute()
{
return EnumCreatureAttribute.ILLAGER;
}
@SideOnly(Side.CLIENT)
public AbstractIllager.IllagerArmPose getArmPose()
{
return AbstractIllager.IllagerArmPose.CROSSED;
}
@SideOnly(Side.CLIENT)
public static enum IllagerArmPose
{
CROSSED,
ATTACKING,
SPELLCASTING,
BOW_AND_ARROW;
}
}

View File

@@ -0,0 +1,304 @@
package net.minecraft.entity.monster;
import java.util.Calendar;
import javax.annotation.Nullable;
import net.minecraft.block.Block;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.EnumCreatureAttribute;
import net.minecraft.entity.IEntityLivingData;
import net.minecraft.entity.IRangedAttackMob;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIAttackMelee;
import net.minecraft.entity.ai.EntityAIAttackRangedBow;
import net.minecraft.entity.ai.EntityAIAvoidEntity;
import net.minecraft.entity.ai.EntityAIFleeSun;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAIRestrictSun;
import net.minecraft.entity.ai.EntityAISwimming;
import net.minecraft.entity.ai.EntityAIWanderAvoidWater;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.item.EntityBoat;
import net.minecraft.entity.passive.EntityWolf;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.projectile.EntityArrow;
import net.minecraft.entity.projectile.EntityTippedArrow;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.init.SoundEvents;
import net.minecraft.inventory.EntityEquipmentSlot;
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.SoundEvent;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.EnumDifficulty;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public abstract class AbstractSkeleton extends EntityMob implements IRangedAttackMob
{
private static final DataParameter<Boolean> SWINGING_ARMS = EntityDataManager.<Boolean>createKey(AbstractSkeleton.class, DataSerializers.BOOLEAN);
private final EntityAIAttackRangedBow<AbstractSkeleton> aiArrowAttack = new EntityAIAttackRangedBow<AbstractSkeleton>(this, 1.0D, 20, 15.0F);
private final EntityAIAttackMelee aiAttackOnCollide = new EntityAIAttackMelee(this, 1.2D, false)
{
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
super.resetTask();
AbstractSkeleton.this.setSwingingArms(false);
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
super.startExecuting();
AbstractSkeleton.this.setSwingingArms(true);
}
};
public AbstractSkeleton(World worldIn)
{
super(worldIn);
this.setSize(0.6F, 1.99F);
this.setCombatTask();
}
protected void initEntityAI()
{
this.tasks.addTask(1, new EntityAISwimming(this));
this.tasks.addTask(2, new EntityAIRestrictSun(this));
this.tasks.addTask(3, new EntityAIFleeSun(this, 1.0D));
this.tasks.addTask(3, new EntityAIAvoidEntity(this, EntityWolf.class, 6.0F, 1.0D, 1.2D));
this.tasks.addTask(5, new EntityAIWanderAvoidWater(this, 1.0D));
this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
this.tasks.addTask(6, new EntityAILookIdle(this));
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false, new Class[0]));
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityPlayer.class, true));
this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityIronGolem.class, true));
}
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.25D);
}
protected void entityInit()
{
super.entityInit();
this.dataManager.register(SWINGING_ARMS, Boolean.valueOf(false));
}
protected void playStepSound(BlockPos pos, Block blockIn)
{
this.playSound(this.getStepSound(), 0.15F, 1.0F);
}
protected abstract SoundEvent getStepSound();
/**
* Get this Entity's EnumCreatureAttribute
*/
public EnumCreatureAttribute getCreatureAttribute()
{
return EnumCreatureAttribute.UNDEAD;
}
/**
* 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()
{
if (this.world.isDaytime() && !this.world.isRemote)
{
float f = this.getBrightness();
BlockPos blockpos = this.getRidingEntity() instanceof EntityBoat ? (new BlockPos(this.posX, (double)Math.round(this.posY), this.posZ)).up() : new BlockPos(this.posX, (double)Math.round(this.posY), this.posZ);
if (f > 0.5F && this.rand.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.world.canSeeSky(blockpos))
{
boolean flag = true;
ItemStack itemstack = this.getItemStackFromSlot(EntityEquipmentSlot.HEAD);
if (!itemstack.isEmpty())
{
if (itemstack.isItemStackDamageable())
{
itemstack.setItemDamage(itemstack.getItemDamage() + this.rand.nextInt(2));
if (itemstack.getItemDamage() >= itemstack.getMaxDamage())
{
this.renderBrokenItemStack(itemstack);
this.setItemStackToSlot(EntityEquipmentSlot.HEAD, ItemStack.EMPTY);
}
}
flag = false;
}
if (flag)
{
this.setFire(8);
}
}
}
super.onLivingUpdate();
}
/**
* Handles updating while riding another entity
*/
public void updateRidden()
{
super.updateRidden();
if (this.getRidingEntity() instanceof EntityCreature)
{
EntityCreature entitycreature = (EntityCreature)this.getRidingEntity();
this.renderYawOffset = entitycreature.renderYawOffset;
}
}
/**
* Gives armor or weapon for entity based on given DifficultyInstance
*/
protected void setEquipmentBasedOnDifficulty(DifficultyInstance difficulty)
{
super.setEquipmentBasedOnDifficulty(difficulty);
this.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(Items.BOW));
}
/**
* Called only once on an entity when first time spawned, via egg, mob spawner, natural spawning etc, but not called
* when entity is reloaded from nbt. Mainly used for initializing attributes and inventory
*/
@Nullable
public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, @Nullable IEntityLivingData livingdata)
{
livingdata = super.onInitialSpawn(difficulty, livingdata);
this.setEquipmentBasedOnDifficulty(difficulty);
this.setEnchantmentBasedOnDifficulty(difficulty);
this.setCombatTask();
this.setCanPickUpLoot(this.rand.nextFloat() < 0.55F * difficulty.getClampedAdditionalDifficulty());
if (this.getItemStackFromSlot(EntityEquipmentSlot.HEAD).isEmpty())
{
Calendar calendar = this.world.getCurrentDate();
if (calendar.get(2) + 1 == 10 && calendar.get(5) == 31 && this.rand.nextFloat() < 0.25F)
{
this.setItemStackToSlot(EntityEquipmentSlot.HEAD, new ItemStack(this.rand.nextFloat() < 0.1F ? Blocks.LIT_PUMPKIN : Blocks.PUMPKIN));
this.inventoryArmorDropChances[EntityEquipmentSlot.HEAD.getIndex()] = 0.0F;
}
}
return livingdata;
}
/**
* sets this entity's combat AI.
*/
public void setCombatTask()
{
if (this.world != null && !this.world.isRemote)
{
this.tasks.removeTask(this.aiAttackOnCollide);
this.tasks.removeTask(this.aiArrowAttack);
ItemStack itemstack = this.getHeldItemMainhand();
if (itemstack.getItem() == Items.BOW)
{
int i = 20;
if (this.world.getDifficulty() != EnumDifficulty.HARD)
{
i = 40;
}
this.aiArrowAttack.setAttackCooldown(i);
this.tasks.addTask(4, this.aiArrowAttack);
}
else
{
this.tasks.addTask(4, this.aiAttackOnCollide);
}
}
}
/**
* Attack the specified entity using a ranged attack.
*/
public void attackEntityWithRangedAttack(EntityLivingBase target, float distanceFactor)
{
EntityArrow entityarrow = this.getArrow(distanceFactor);
double d0 = target.posX - this.posX;
double d1 = target.getEntityBoundingBox().minY + (double)(target.height / 3.0F) - entityarrow.posY;
double d2 = target.posZ - this.posZ;
double d3 = (double)MathHelper.sqrt(d0 * d0 + d2 * d2);
entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float)(14 - this.world.getDifficulty().getDifficultyId() * 4));
this.playSound(SoundEvents.ENTITY_SKELETON_SHOOT, 1.0F, 1.0F / (this.getRNG().nextFloat() * 0.4F + 0.8F));
this.world.spawnEntity(entityarrow);
}
protected EntityArrow getArrow(float p_190726_1_)
{
EntityTippedArrow entitytippedarrow = new EntityTippedArrow(this.world, this);
entitytippedarrow.setEnchantmentEffectsFromEntity(this, p_190726_1_);
return entitytippedarrow;
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound compound)
{
super.readEntityFromNBT(compound);
this.setCombatTask();
}
public void setItemStackToSlot(EntityEquipmentSlot slotIn, ItemStack stack)
{
super.setItemStackToSlot(slotIn, stack);
if (!this.world.isRemote && slotIn == EntityEquipmentSlot.MAINHAND)
{
this.setCombatTask();
}
}
public float getEyeHeight()
{
return 1.74F;
}
/**
* Returns the Y Offset of this entity.
*/
public double getYOffset()
{
return -0.6D;
}
@SideOnly(Side.CLIENT)
public boolean isSwingingArms()
{
return ((Boolean)this.dataManager.get(SWINGING_ARMS)).booleanValue();
}
public void setSwingingArms(boolean swingingArms)
{
this.dataManager.set(SWINGING_ARMS, Boolean.valueOf(swingingArms));
}
}

View File

@@ -0,0 +1,325 @@
package net.minecraft.entity.monster;
import javax.annotation.Nullable;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIBase;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAIMoveTowardsRestriction;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAIWanderAvoidWater;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.ai.attributes.IAttributeInstance;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.projectile.EntitySmallFireball;
import net.minecraft.init.SoundEvents;
import net.minecraft.network.datasync.DataParameter;
import net.minecraft.network.datasync.DataSerializers;
import net.minecraft.network.datasync.EntityDataManager;
import net.minecraft.pathfinding.PathNodeType;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootTableList;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class EntityBlaze extends EntityMob
{
/** Random offset used in floating behaviour */
private float heightOffset = 0.5F;
/** ticks until heightOffset is randomized */
private int heightOffsetUpdateTime;
private static final DataParameter<Byte> ON_FIRE = EntityDataManager.<Byte>createKey(EntityBlaze.class, DataSerializers.BYTE);
public EntityBlaze(World worldIn)
{
super(worldIn);
this.setPathPriority(PathNodeType.WATER, -1.0F);
this.setPathPriority(PathNodeType.LAVA, 8.0F);
this.setPathPriority(PathNodeType.DANGER_FIRE, 0.0F);
this.setPathPriority(PathNodeType.DAMAGE_FIRE, 0.0F);
this.isImmuneToFire = true;
this.experienceValue = 10;
}
public static void registerFixesBlaze(DataFixer fixer)
{
EntityLiving.registerFixesMob(fixer, EntityBlaze.class);
}
protected void initEntityAI()
{
this.tasks.addTask(4, new EntityBlaze.AIFireballAttack(this));
this.tasks.addTask(5, new EntityAIMoveTowardsRestriction(this, 1.0D));
this.tasks.addTask(7, new EntityAIWanderAvoidWater(this, 1.0D, 0.0F));
this.tasks.addTask(8, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
this.tasks.addTask(8, new EntityAILookIdle(this));
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true, new Class[0]));
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityPlayer.class, true));
}
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(6.0D);
this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.23000000417232513D);
this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(48.0D);
}
protected void entityInit()
{
super.entityInit();
this.dataManager.register(ON_FIRE, Byte.valueOf((byte)0));
}
protected SoundEvent getAmbientSound()
{
return SoundEvents.ENTITY_BLAZE_AMBIENT;
}
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return SoundEvents.ENTITY_BLAZE_HURT;
}
protected SoundEvent getDeathSound()
{
return SoundEvents.ENTITY_BLAZE_DEATH;
}
@SideOnly(Side.CLIENT)
public int getBrightnessForRender()
{
return 15728880;
}
/**
* Gets how bright this entity is.
*/
public float getBrightness()
{
return 1.0F;
}
/**
* 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()
{
if (!this.onGround && this.motionY < 0.0D)
{
this.motionY *= 0.6D;
}
if (this.world.isRemote)
{
if (this.rand.nextInt(24) == 0 && !this.isSilent())
{
this.world.playSound(this.posX + 0.5D, this.posY + 0.5D, this.posZ + 0.5D, SoundEvents.ENTITY_BLAZE_BURN, this.getSoundCategory(), 1.0F + this.rand.nextFloat(), this.rand.nextFloat() * 0.7F + 0.3F, false);
}
for (int i = 0; i < 2; ++i)
{
this.world.spawnParticle(EnumParticleTypes.SMOKE_LARGE, this.posX + (this.rand.nextDouble() - 0.5D) * (double)this.width, this.posY + this.rand.nextDouble() * (double)this.height, this.posZ + (this.rand.nextDouble() - 0.5D) * (double)this.width, 0.0D, 0.0D, 0.0D);
}
}
super.onLivingUpdate();
}
protected void updateAITasks()
{
if (this.isWet())
{
this.attackEntityFrom(DamageSource.DROWN, 1.0F);
}
--this.heightOffsetUpdateTime;
if (this.heightOffsetUpdateTime <= 0)
{
this.heightOffsetUpdateTime = 100;
this.heightOffset = 0.5F + (float)this.rand.nextGaussian() * 3.0F;
}
EntityLivingBase entitylivingbase = this.getAttackTarget();
if (entitylivingbase != null && entitylivingbase.posY + (double)entitylivingbase.getEyeHeight() > this.posY + (double)this.getEyeHeight() + (double)this.heightOffset)
{
this.motionY += (0.30000001192092896D - this.motionY) * 0.30000001192092896D;
this.isAirBorne = true;
}
super.updateAITasks();
}
public void fall(float distance, float damageMultiplier)
{
}
/**
* Returns true if the entity is on fire. Used by render to add the fire effect on rendering.
*/
public boolean isBurning()
{
return this.isCharged();
}
@Nullable
protected ResourceLocation getLootTable()
{
return LootTableList.ENTITIES_BLAZE;
}
public boolean isCharged()
{
return (((Byte)this.dataManager.get(ON_FIRE)).byteValue() & 1) != 0;
}
public void setOnFire(boolean onFire)
{
byte b0 = ((Byte)this.dataManager.get(ON_FIRE)).byteValue();
if (onFire)
{
b0 = (byte)(b0 | 1);
}
else
{
b0 = (byte)(b0 & -2);
}
this.dataManager.set(ON_FIRE, Byte.valueOf(b0));
}
/**
* Checks to make sure the light is not too bright where the mob is spawning
*/
protected boolean isValidLightLevel()
{
return true;
}
static class AIFireballAttack extends EntityAIBase
{
private final EntityBlaze blaze;
private int attackStep;
private int attackTime;
public AIFireballAttack(EntityBlaze blazeIn)
{
this.blaze = blazeIn;
this.setMutexBits(3);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
EntityLivingBase entitylivingbase = this.blaze.getAttackTarget();
return entitylivingbase != null && entitylivingbase.isEntityAlive();
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.attackStep = 0;
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.blaze.setOnFire(false);
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
--this.attackTime;
EntityLivingBase entitylivingbase = this.blaze.getAttackTarget();
double d0 = this.blaze.getDistanceSq(entitylivingbase);
if (d0 < 4.0D)
{
if (this.attackTime <= 0)
{
this.attackTime = 20;
this.blaze.attackEntityAsMob(entitylivingbase);
}
this.blaze.getMoveHelper().setMoveTo(entitylivingbase.posX, entitylivingbase.posY, entitylivingbase.posZ, 1.0D);
}
else if (d0 < this.getFollowDistance() * this.getFollowDistance())
{
double d1 = entitylivingbase.posX - this.blaze.posX;
double d2 = entitylivingbase.getEntityBoundingBox().minY + (double)(entitylivingbase.height / 2.0F) - (this.blaze.posY + (double)(this.blaze.height / 2.0F));
double d3 = entitylivingbase.posZ - this.blaze.posZ;
if (this.attackTime <= 0)
{
++this.attackStep;
if (this.attackStep == 1)
{
this.attackTime = 60;
this.blaze.setOnFire(true);
}
else if (this.attackStep <= 4)
{
this.attackTime = 6;
}
else
{
this.attackTime = 100;
this.attackStep = 0;
this.blaze.setOnFire(false);
}
if (this.attackStep > 1)
{
float f = MathHelper.sqrt(MathHelper.sqrt(d0)) * 0.5F;
this.blaze.world.playEvent((EntityPlayer)null, 1018, new BlockPos((int)this.blaze.posX, (int)this.blaze.posY, (int)this.blaze.posZ), 0);
for (int i = 0; i < 1; ++i)
{
EntitySmallFireball entitysmallfireball = new EntitySmallFireball(this.blaze.world, this.blaze, d1 + this.blaze.getRNG().nextGaussian() * (double)f, d2, d3 + this.blaze.getRNG().nextGaussian() * (double)f);
entitysmallfireball.posY = this.blaze.posY + (double)(this.blaze.height / 2.0F) + 0.5D;
this.blaze.world.spawnEntity(entitysmallfireball);
}
}
}
this.blaze.getLookHelper().setLookPositionWithEntity(entitylivingbase, 10.0F, 10.0F);
}
else
{
this.blaze.getNavigator().clearPath();
this.blaze.getMoveHelper().setMoveTo(entitylivingbase.posX, entitylivingbase.posY, entitylivingbase.posZ, 1.0D);
}
super.updateTask();
}
private double getFollowDistance()
{
IAttributeInstance iattributeinstance = this.blaze.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE);
return iattributeinstance == null ? 16.0D : iattributeinstance.getAttributeValue();
}
}
}

View File

@@ -0,0 +1,88 @@
package net.minecraft.entity.monster;
import javax.annotation.Nullable;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.IEntityLivingData;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.init.MobEffects;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.EnumDifficulty;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootTableList;
public class EntityCaveSpider extends EntitySpider
{
public EntityCaveSpider(World worldIn)
{
super(worldIn);
this.setSize(0.7F, 0.5F);
}
public static void registerFixesCaveSpider(DataFixer fixer)
{
EntityLiving.registerFixesMob(fixer, EntityCaveSpider.class);
}
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(12.0D);
}
public boolean attackEntityAsMob(Entity entityIn)
{
if (super.attackEntityAsMob(entityIn))
{
if (entityIn instanceof EntityLivingBase)
{
int i = 0;
if (this.world.getDifficulty() == EnumDifficulty.NORMAL)
{
i = 7;
}
else if (this.world.getDifficulty() == EnumDifficulty.HARD)
{
i = 15;
}
if (i > 0)
{
((EntityLivingBase)entityIn).addPotionEffect(new PotionEffect(MobEffects.POISON, i * 20, 0));
}
}
return true;
}
else
{
return false;
}
}
/**
* Called only once on an entity when first time spawned, via egg, mob spawner, natural spawning etc, but not called
* when entity is reloaded from nbt. Mainly used for initializing attributes and inventory
*/
@Nullable
public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, @Nullable IEntityLivingData livingdata)
{
return livingdata;
}
public float getEyeHeight()
{
return 0.45F;
}
@Nullable
protected ResourceLocation getLootTable()
{
return LootTableList.ENTITIES_CAVE_SPIDER;
}
}

View File

@@ -0,0 +1,362 @@
package net.minecraft.entity.monster;
import java.util.Collection;
import javax.annotation.Nullable;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityAreaEffectCloud;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIAttackMelee;
import net.minecraft.entity.ai.EntityAIAvoidEntity;
import net.minecraft.entity.ai.EntityAICreeperSwell;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAISwimming;
import net.minecraft.entity.ai.EntityAIWanderAvoidWater;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.effect.EntityLightningBolt;
import net.minecraft.entity.passive.EntityOcelot;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Items;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.Item;
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.potion.PotionEffect;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootTableList;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class EntityCreeper extends EntityMob
{
private static final DataParameter<Integer> STATE = EntityDataManager.<Integer>createKey(EntityCreeper.class, DataSerializers.VARINT);
private static final DataParameter<Boolean> POWERED = EntityDataManager.<Boolean>createKey(EntityCreeper.class, DataSerializers.BOOLEAN);
private static final DataParameter<Boolean> IGNITED = EntityDataManager.<Boolean>createKey(EntityCreeper.class, DataSerializers.BOOLEAN);
/**
* Time when this creeper was last in an active state (Messed up code here, probably causes creeper animation to go
* weird)
*/
private int lastActiveTime;
/** The amount of time since the creeper was close enough to the player to ignite */
private int timeSinceIgnited;
private int fuseTime = 30;
/** Explosion radius for this creeper. */
private int explosionRadius = 3;
private int droppedSkulls;
public EntityCreeper(World worldIn)
{
super(worldIn);
this.setSize(0.6F, 1.7F);
}
protected void initEntityAI()
{
this.tasks.addTask(1, new EntityAISwimming(this));
this.tasks.addTask(2, new EntityAICreeperSwell(this));
this.tasks.addTask(3, new EntityAIAvoidEntity(this, EntityOcelot.class, 6.0F, 1.0D, 1.2D));
this.tasks.addTask(4, new EntityAIAttackMelee(this, 1.0D, false));
this.tasks.addTask(5, new EntityAIWanderAvoidWater(this, 0.8D));
this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
this.tasks.addTask(6, new EntityAILookIdle(this));
this.targetTasks.addTask(1, new EntityAINearestAttackableTarget(this, EntityPlayer.class, true));
this.targetTasks.addTask(2, new EntityAIHurtByTarget(this, false, new Class[0]));
}
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.25D);
}
/**
* The maximum height from where the entity is alowed to jump (used in pathfinder)
*/
public int getMaxFallHeight()
{
return this.getAttackTarget() == null ? 3 : 3 + (int)(this.getHealth() - 1.0F);
}
public void fall(float distance, float damageMultiplier)
{
super.fall(distance, damageMultiplier);
this.timeSinceIgnited = (int)((float)this.timeSinceIgnited + distance * 1.5F);
if (this.timeSinceIgnited > this.fuseTime - 5)
{
this.timeSinceIgnited = this.fuseTime - 5;
}
}
protected void entityInit()
{
super.entityInit();
this.dataManager.register(STATE, Integer.valueOf(-1));
this.dataManager.register(POWERED, Boolean.valueOf(false));
this.dataManager.register(IGNITED, Boolean.valueOf(false));
}
public static void registerFixesCreeper(DataFixer fixer)
{
EntityLiving.registerFixesMob(fixer, EntityCreeper.class);
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound compound)
{
super.writeEntityToNBT(compound);
if (((Boolean)this.dataManager.get(POWERED)).booleanValue())
{
compound.setBoolean("powered", true);
}
compound.setShort("Fuse", (short)this.fuseTime);
compound.setByte("ExplosionRadius", (byte)this.explosionRadius);
compound.setBoolean("ignited", this.hasIgnited());
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound compound)
{
super.readEntityFromNBT(compound);
this.dataManager.set(POWERED, Boolean.valueOf(compound.getBoolean("powered")));
if (compound.hasKey("Fuse", 99))
{
this.fuseTime = compound.getShort("Fuse");
}
if (compound.hasKey("ExplosionRadius", 99))
{
this.explosionRadius = compound.getByte("ExplosionRadius");
}
if (compound.getBoolean("ignited"))
{
this.ignite();
}
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
if (this.isEntityAlive())
{
this.lastActiveTime = this.timeSinceIgnited;
if (this.hasIgnited())
{
this.setCreeperState(1);
}
int i = this.getCreeperState();
if (i > 0 && this.timeSinceIgnited == 0)
{
this.playSound(SoundEvents.ENTITY_CREEPER_PRIMED, 1.0F, 0.5F);
}
this.timeSinceIgnited += i;
if (this.timeSinceIgnited < 0)
{
this.timeSinceIgnited = 0;
}
if (this.timeSinceIgnited >= this.fuseTime)
{
this.timeSinceIgnited = this.fuseTime;
this.explode();
}
}
super.onUpdate();
}
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return SoundEvents.ENTITY_CREEPER_HURT;
}
protected SoundEvent getDeathSound()
{
return SoundEvents.ENTITY_CREEPER_DEATH;
}
/**
* Called when the mob's health reaches 0.
*/
public void onDeath(DamageSource cause)
{
super.onDeath(cause);
if (this.world.getGameRules().getBoolean("doMobLoot"))
{
if (cause.getTrueSource() instanceof EntitySkeleton)
{
int i = Item.getIdFromItem(Items.RECORD_13);
int j = Item.getIdFromItem(Items.RECORD_WAIT);
int k = i + this.rand.nextInt(j - i + 1);
this.dropItem(Item.getItemById(k), 1);
}
else if (cause.getTrueSource() instanceof EntityCreeper && cause.getTrueSource() != this && ((EntityCreeper)cause.getTrueSource()).getPowered() && ((EntityCreeper)cause.getTrueSource()).ableToCauseSkullDrop())
{
((EntityCreeper)cause.getTrueSource()).incrementDroppedSkulls();
this.entityDropItem(new ItemStack(Items.SKULL, 1, 4), 0.0F);
}
}
}
public boolean attackEntityAsMob(Entity entityIn)
{
return true;
}
/**
* Returns true if the creeper is powered by a lightning bolt.
*/
public boolean getPowered()
{
return ((Boolean)this.dataManager.get(POWERED)).booleanValue();
}
/**
* Params: (Float)Render tick. Returns the intensity of the creeper's flash when it is ignited.
*/
@SideOnly(Side.CLIENT)
public float getCreeperFlashIntensity(float p_70831_1_)
{
return ((float)this.lastActiveTime + (float)(this.timeSinceIgnited - this.lastActiveTime) * p_70831_1_) / (float)(this.fuseTime - 2);
}
@Nullable
protected ResourceLocation getLootTable()
{
return LootTableList.ENTITIES_CREEPER;
}
/**
* Returns the current state of creeper, -1 is idle, 1 is 'in fuse'
*/
public int getCreeperState()
{
return ((Integer)this.dataManager.get(STATE)).intValue();
}
/**
* Sets the state of creeper, -1 to idle and 1 to be 'in fuse'
*/
public void setCreeperState(int state)
{
this.dataManager.set(STATE, Integer.valueOf(state));
}
/**
* Called when a lightning bolt hits the entity.
*/
public void onStruckByLightning(EntityLightningBolt lightningBolt)
{
super.onStruckByLightning(lightningBolt);
this.dataManager.set(POWERED, Boolean.valueOf(true));
}
protected boolean processInteract(EntityPlayer player, EnumHand hand)
{
ItemStack itemstack = player.getHeldItem(hand);
if (itemstack.getItem() == Items.FLINT_AND_STEEL)
{
this.world.playSound(player, this.posX, this.posY, this.posZ, SoundEvents.ITEM_FLINTANDSTEEL_USE, this.getSoundCategory(), 1.0F, this.rand.nextFloat() * 0.4F + 0.8F);
player.swingArm(hand);
if (!this.world.isRemote)
{
this.ignite();
itemstack.damageItem(1, player);
return true;
}
}
return super.processInteract(player, hand);
}
/**
* Creates an explosion as determined by this creeper's power and explosion radius.
*/
private void explode()
{
if (!this.world.isRemote)
{
boolean flag = net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.world, this);
float f = this.getPowered() ? 2.0F : 1.0F;
this.dead = true;
this.world.createExplosion(this, this.posX, this.posY, this.posZ, (float)this.explosionRadius * f, flag);
this.setDead();
this.spawnLingeringCloud();
}
}
private void spawnLingeringCloud()
{
Collection<PotionEffect> collection = this.getActivePotionEffects();
if (!collection.isEmpty())
{
EntityAreaEffectCloud entityareaeffectcloud = new EntityAreaEffectCloud(this.world, this.posX, this.posY, this.posZ);
entityareaeffectcloud.setRadius(2.5F);
entityareaeffectcloud.setRadiusOnUse(-0.5F);
entityareaeffectcloud.setWaitTime(10);
entityareaeffectcloud.setDuration(entityareaeffectcloud.getDuration() / 2);
entityareaeffectcloud.setRadiusPerTick(-entityareaeffectcloud.getRadius() / (float)entityareaeffectcloud.getDuration());
for (PotionEffect potioneffect : collection)
{
entityareaeffectcloud.addEffect(new PotionEffect(potioneffect));
}
this.world.spawnEntity(entityareaeffectcloud);
}
}
public boolean hasIgnited()
{
return ((Boolean)this.dataManager.get(IGNITED)).booleanValue();
}
public void ignite()
{
this.dataManager.set(IGNITED, Boolean.valueOf(true));
}
/**
* Returns true if an entity is able to drop its skull due to being blown up by this creeper.
*
* Does not test if this creeper is charged; the caller must do that. However, does test the doMobLoot gamerule.
*/
public boolean ableToCauseSkullDrop()
{
return this.droppedSkulls < 1 && this.world.getGameRules().getBoolean("doMobLoot");
}
public void incrementDroppedSkulls()
{
++this.droppedSkulls;
}
}

View File

@@ -0,0 +1,123 @@
package net.minecraft.entity.monster;
import com.google.common.base.Predicate;
import java.util.List;
import javax.annotation.Nullable;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.MobEffects;
import net.minecraft.init.SoundEvents;
import net.minecraft.network.play.server.SPacketChangeGameState;
import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.DamageSource;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootTableList;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class EntityElderGuardian extends EntityGuardian
{
public EntityElderGuardian(World worldIn)
{
super(worldIn);
this.setSize(this.width * 2.35F, this.height * 2.35F);
this.enablePersistence();
if (this.wander != null)
{
this.wander.setExecutionChance(400);
}
}
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.30000001192092896D);
this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(8.0D);
this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(80.0D);
}
public static void registerFixesElderGuardian(DataFixer fixer)
{
EntityLiving.registerFixesMob(fixer, EntityElderGuardian.class);
}
@Nullable
protected ResourceLocation getLootTable()
{
return LootTableList.ENTITIES_ELDER_GUARDIAN;
}
public int getAttackDuration()
{
return 60;
}
@SideOnly(Side.CLIENT)
public void setGhost()
{
this.clientSideSpikesAnimation = 1.0F;
this.clientSideSpikesAnimationO = this.clientSideSpikesAnimation;
}
protected SoundEvent getAmbientSound()
{
return this.isInWater() ? SoundEvents.ENTITY_ELDER_GUARDIAN_AMBIENT : SoundEvents.ENTITY_ELDERGUARDIAN_AMBIENTLAND;
}
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return this.isInWater() ? SoundEvents.ENTITY_ELDER_GUARDIAN_HURT : SoundEvents.ENTITY_ELDER_GUARDIAN_HURT_LAND;
}
protected SoundEvent getDeathSound()
{
return this.isInWater() ? SoundEvents.ENTITY_ELDER_GUARDIAN_DEATH : SoundEvents.ENTITY_ELDER_GUARDIAN_DEATH_LAND;
}
protected SoundEvent getFlopSound()
{
return SoundEvents.ENTITY_ELDER_GUARDIAN_FLOP;
}
protected void updateAITasks()
{
super.updateAITasks();
int i = 1200;
if ((this.ticksExisted + this.getEntityId()) % 1200 == 0)
{
Potion potion = MobEffects.MINING_FATIGUE;
List<EntityPlayerMP> list = this.world.<EntityPlayerMP>getPlayers(EntityPlayerMP.class, new Predicate<EntityPlayerMP>()
{
public boolean apply(@Nullable EntityPlayerMP p_apply_1_)
{
return EntityElderGuardian.this.getDistanceSq(p_apply_1_) < 2500.0D && p_apply_1_.interactionManager.survivalOrAdventure();
}
});
int j = 2;
int k = 6000;
int l = 1200;
for (EntityPlayerMP entityplayermp : list)
{
if (!entityplayermp.isPotionActive(potion) || entityplayermp.getActivePotionEffect(potion).getAmplifier() < 2 || entityplayermp.getActivePotionEffect(potion).getDuration() < 1200)
{
entityplayermp.connection.sendPacket(new SPacketChangeGameState(10, 0.0F));
entityplayermp.addPotionEffect(new PotionEffect(potion, 6000, 2));
}
}
}
if (!this.hasHome())
{
this.setHomePosAndDistance(new BlockPos(this), 16);
}
}
}

View File

@@ -0,0 +1,663 @@
package net.minecraft.entity.monster;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.Sets;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import javax.annotation.Nullable;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIAttackMelee;
import net.minecraft.entity.ai.EntityAIBase;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAISwimming;
import net.minecraft.entity.ai.EntityAIWanderAvoidWater;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.entity.ai.attributes.IAttributeInstance;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.Item;
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.pathfinding.PathNodeType;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EntityDamageSourceIndirect;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootTableList;
public class EntityEnderman extends EntityMob
{
private static final UUID ATTACKING_SPEED_BOOST_ID = UUID.fromString("020E0DFB-87AE-4653-9556-831010E291A0");
private static final AttributeModifier ATTACKING_SPEED_BOOST = (new AttributeModifier(ATTACKING_SPEED_BOOST_ID, "Attacking speed boost", 0.15000000596046448D, 0)).setSaved(false);
private static final Set<Block> CARRIABLE_BLOCKS = Sets.<Block>newIdentityHashSet();
private static final DataParameter<Optional<IBlockState>> CARRIED_BLOCK = EntityDataManager.<Optional<IBlockState>>createKey(EntityEnderman.class, DataSerializers.OPTIONAL_BLOCK_STATE);
private static final DataParameter<Boolean> SCREAMING = EntityDataManager.<Boolean>createKey(EntityEnderman.class, DataSerializers.BOOLEAN);
private int lastCreepySound;
private int targetChangeTime;
public EntityEnderman(World worldIn)
{
super(worldIn);
this.setSize(0.6F, 2.9F);
this.stepHeight = 1.0F;
this.setPathPriority(PathNodeType.WATER, -1.0F);
}
protected void initEntityAI()
{
this.tasks.addTask(0, new EntityAISwimming(this));
this.tasks.addTask(2, new EntityAIAttackMelee(this, 1.0D, false));
this.tasks.addTask(7, new EntityAIWanderAvoidWater(this, 1.0D, 0.0F));
this.tasks.addTask(8, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
this.tasks.addTask(8, new EntityAILookIdle(this));
this.tasks.addTask(10, new EntityEnderman.AIPlaceBlock(this));
this.tasks.addTask(11, new EntityEnderman.AITakeBlock(this));
this.targetTasks.addTask(1, new EntityEnderman.AIFindPlayer(this));
this.targetTasks.addTask(2, new EntityAIHurtByTarget(this, false, new Class[0]));
this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityEndermite.class, 10, true, false, new Predicate<EntityEndermite>()
{
public boolean apply(@Nullable EntityEndermite p_apply_1_)
{
return p_apply_1_.isSpawnedByPlayer();
}
}));
}
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(40.0D);
this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.30000001192092896D);
this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(7.0D);
this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(64.0D);
}
/**
* Sets the active target the Task system uses for tracking
*/
public void setAttackTarget(@Nullable EntityLivingBase entitylivingbaseIn)
{
super.setAttackTarget(entitylivingbaseIn);
IAttributeInstance iattributeinstance = this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED);
if (entitylivingbaseIn == null)
{
this.targetChangeTime = 0;
this.dataManager.set(SCREAMING, Boolean.valueOf(false));
iattributeinstance.removeModifier(ATTACKING_SPEED_BOOST);
}
else
{
this.targetChangeTime = this.ticksExisted;
this.dataManager.set(SCREAMING, Boolean.valueOf(true));
if (!iattributeinstance.hasModifier(ATTACKING_SPEED_BOOST))
{
iattributeinstance.applyModifier(ATTACKING_SPEED_BOOST);
}
}
}
protected void entityInit()
{
super.entityInit();
this.dataManager.register(CARRIED_BLOCK, Optional.absent());
this.dataManager.register(SCREAMING, Boolean.valueOf(false));
}
public void playEndermanSound()
{
if (this.ticksExisted >= this.lastCreepySound + 400)
{
this.lastCreepySound = this.ticksExisted;
if (!this.isSilent())
{
this.world.playSound(this.posX, this.posY + (double)this.getEyeHeight(), this.posZ, SoundEvents.ENTITY_ENDERMEN_STARE, this.getSoundCategory(), 2.5F, 1.0F, false);
}
}
}
public void notifyDataManagerChange(DataParameter<?> key)
{
if (SCREAMING.equals(key) && this.isScreaming() && this.world.isRemote)
{
this.playEndermanSound();
}
super.notifyDataManagerChange(key);
}
public static void registerFixesEnderman(DataFixer fixer)
{
EntityLiving.registerFixesMob(fixer, EntityEnderman.class);
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound compound)
{
super.writeEntityToNBT(compound);
IBlockState iblockstate = this.getHeldBlockState();
if (iblockstate != null)
{
compound.setShort("carried", (short)Block.getIdFromBlock(iblockstate.getBlock()));
compound.setShort("carriedData", (short)iblockstate.getBlock().getMetaFromState(iblockstate));
}
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound compound)
{
super.readEntityFromNBT(compound);
IBlockState iblockstate;
if (compound.hasKey("carried", 8))
{
iblockstate = Block.getBlockFromName(compound.getString("carried")).getStateFromMeta(compound.getShort("carriedData") & 65535);
}
else
{
iblockstate = Block.getBlockById(compound.getShort("carried")).getStateFromMeta(compound.getShort("carriedData") & 65535);
}
if (iblockstate == null || iblockstate.getBlock() == null || iblockstate.getMaterial() == Material.AIR)
{
iblockstate = null;
}
this.setHeldBlockState(iblockstate);
}
/**
* Checks to see if this enderman should be attacking this player
*/
private boolean shouldAttackPlayer(EntityPlayer player)
{
ItemStack itemstack = player.inventory.armorInventory.get(3);
if (itemstack.getItem() == Item.getItemFromBlock(Blocks.PUMPKIN))
{
return false;
}
else
{
Vec3d vec3d = player.getLook(1.0F).normalize();
Vec3d vec3d1 = new Vec3d(this.posX - player.posX, this.getEntityBoundingBox().minY + (double)this.getEyeHeight() - (player.posY + (double)player.getEyeHeight()), this.posZ - player.posZ);
double d0 = vec3d1.lengthVector();
vec3d1 = vec3d1.normalize();
double d1 = vec3d.dotProduct(vec3d1);
return d1 > 1.0D - 0.025D / d0 ? player.canEntityBeSeen(this) : false;
}
}
public float getEyeHeight()
{
return 2.55F;
}
/**
* 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()
{
if (this.world.isRemote)
{
for (int i = 0; i < 2; ++i)
{
this.world.spawnParticle(EnumParticleTypes.PORTAL, this.posX + (this.rand.nextDouble() - 0.5D) * (double)this.width, this.posY + this.rand.nextDouble() * (double)this.height - 0.25D, this.posZ + (this.rand.nextDouble() - 0.5D) * (double)this.width, (this.rand.nextDouble() - 0.5D) * 2.0D, -this.rand.nextDouble(), (this.rand.nextDouble() - 0.5D) * 2.0D);
}
}
this.isJumping = false;
super.onLivingUpdate();
}
protected void updateAITasks()
{
if (this.isWet())
{
this.attackEntityFrom(DamageSource.DROWN, 1.0F);
}
if (this.world.isDaytime() && this.ticksExisted >= this.targetChangeTime + 600)
{
float f = this.getBrightness();
if (f > 0.5F && this.world.canSeeSky(new BlockPos(this)) && this.rand.nextFloat() * 30.0F < (f - 0.4F) * 2.0F)
{
this.setAttackTarget((EntityLivingBase)null);
this.teleportRandomly();
}
}
super.updateAITasks();
}
/**
* Teleport the enderman to a random nearby position
*/
protected boolean teleportRandomly()
{
double d0 = this.posX + (this.rand.nextDouble() - 0.5D) * 64.0D;
double d1 = this.posY + (double)(this.rand.nextInt(64) - 32);
double d2 = this.posZ + (this.rand.nextDouble() - 0.5D) * 64.0D;
return this.teleportTo(d0, d1, d2);
}
/**
* Teleport the enderman to another entity
*/
protected boolean teleportToEntity(Entity p_70816_1_)
{
Vec3d vec3d = new Vec3d(this.posX - p_70816_1_.posX, this.getEntityBoundingBox().minY + (double)(this.height / 2.0F) - p_70816_1_.posY + (double)p_70816_1_.getEyeHeight(), this.posZ - p_70816_1_.posZ);
vec3d = vec3d.normalize();
double d0 = 16.0D;
double d1 = this.posX + (this.rand.nextDouble() - 0.5D) * 8.0D - vec3d.x * 16.0D;
double d2 = this.posY + (double)(this.rand.nextInt(16) - 8) - vec3d.y * 16.0D;
double d3 = this.posZ + (this.rand.nextDouble() - 0.5D) * 8.0D - vec3d.z * 16.0D;
return this.teleportTo(d1, d2, d3);
}
/**
* Teleport the enderman
*/
private boolean teleportTo(double x, double y, double z)
{
net.minecraftforge.event.entity.living.EnderTeleportEvent event = new net.minecraftforge.event.entity.living.EnderTeleportEvent(this, x, y, z, 0);
if (net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(event)) return false;
boolean flag = this.attemptTeleport(event.getTargetX(), event.getTargetY(), event.getTargetZ());
if (flag)
{
this.world.playSound((EntityPlayer)null, this.prevPosX, this.prevPosY, this.prevPosZ, SoundEvents.ENTITY_ENDERMEN_TELEPORT, this.getSoundCategory(), 1.0F, 1.0F);
this.playSound(SoundEvents.ENTITY_ENDERMEN_TELEPORT, 1.0F, 1.0F);
}
return flag;
}
protected SoundEvent getAmbientSound()
{
return this.isScreaming() ? SoundEvents.ENTITY_ENDERMEN_SCREAM : SoundEvents.ENTITY_ENDERMEN_AMBIENT;
}
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return SoundEvents.ENTITY_ENDERMEN_HURT;
}
protected SoundEvent getDeathSound()
{
return SoundEvents.ENTITY_ENDERMEN_DEATH;
}
/**
* Drop the equipment for this entity.
*/
protected void dropEquipment(boolean wasRecentlyHit, int lootingModifier)
{
super.dropEquipment(wasRecentlyHit, lootingModifier);
IBlockState iblockstate = this.getHeldBlockState();
if (iblockstate != null)
{
Item item = Item.getItemFromBlock(iblockstate.getBlock());
int i = item.getHasSubtypes() ? iblockstate.getBlock().getMetaFromState(iblockstate) : 0;
this.entityDropItem(new ItemStack(item, 1, i), 0.0F);
}
}
@Nullable
protected ResourceLocation getLootTable()
{
return LootTableList.ENTITIES_ENDERMAN;
}
/**
* Sets this enderman's held block state
*/
public void setHeldBlockState(@Nullable IBlockState state)
{
this.dataManager.set(CARRIED_BLOCK, Optional.fromNullable(state));
}
/**
* Gets this enderman's held block state
*/
@Nullable
public IBlockState getHeldBlockState()
{
return (IBlockState)((Optional)this.dataManager.get(CARRIED_BLOCK)).orNull();
}
/**
* Called when the entity is attacked.
*/
public boolean attackEntityFrom(DamageSource source, float amount)
{
if (this.isEntityInvulnerable(source))
{
return false;
}
else if (source instanceof EntityDamageSourceIndirect)
{
for (int i = 0; i < 64; ++i)
{
if (this.teleportRandomly())
{
return true;
}
}
return false;
}
else
{
boolean flag = super.attackEntityFrom(source, amount);
if (source.isUnblockable() && this.rand.nextInt(10) != 0)
{
this.teleportRandomly();
}
return flag;
}
}
/*===================================== Forge Start ==============================*/
public static void setCarriable(Block block, boolean canCarry)
{
if (canCarry) CARRIABLE_BLOCKS.add(block);
else CARRIABLE_BLOCKS.remove(block);
}
public static boolean getCarriable(Block block)
{
return CARRIABLE_BLOCKS.contains(block);
}
/*===================================== Forge End ==============================*/
public boolean isScreaming()
{
return ((Boolean)this.dataManager.get(SCREAMING)).booleanValue();
}
static
{
CARRIABLE_BLOCKS.add(Blocks.GRASS);
CARRIABLE_BLOCKS.add(Blocks.DIRT);
CARRIABLE_BLOCKS.add(Blocks.SAND);
CARRIABLE_BLOCKS.add(Blocks.GRAVEL);
CARRIABLE_BLOCKS.add(Blocks.YELLOW_FLOWER);
CARRIABLE_BLOCKS.add(Blocks.RED_FLOWER);
CARRIABLE_BLOCKS.add(Blocks.BROWN_MUSHROOM);
CARRIABLE_BLOCKS.add(Blocks.RED_MUSHROOM);
CARRIABLE_BLOCKS.add(Blocks.TNT);
CARRIABLE_BLOCKS.add(Blocks.CACTUS);
CARRIABLE_BLOCKS.add(Blocks.CLAY);
CARRIABLE_BLOCKS.add(Blocks.PUMPKIN);
CARRIABLE_BLOCKS.add(Blocks.MELON_BLOCK);
CARRIABLE_BLOCKS.add(Blocks.MYCELIUM);
CARRIABLE_BLOCKS.add(Blocks.NETHERRACK);
}
static class AIFindPlayer extends EntityAINearestAttackableTarget<EntityPlayer>
{
private final EntityEnderman enderman;
/** The player */
private EntityPlayer player;
private int aggroTime;
private int teleportTime;
public AIFindPlayer(EntityEnderman p_i45842_1_)
{
super(p_i45842_1_, EntityPlayer.class, false);
this.enderman = p_i45842_1_;
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
double d0 = this.getTargetDistance();
this.player = this.enderman.world.getNearestAttackablePlayer(this.enderman.posX, this.enderman.posY, this.enderman.posZ, d0, d0, (Function)null, new Predicate<EntityPlayer>()
{
public boolean apply(@Nullable EntityPlayer p_apply_1_)
{
return p_apply_1_ != null && AIFindPlayer.this.enderman.shouldAttackPlayer(p_apply_1_);
}
});
return this.player != null;
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.aggroTime = 5;
this.teleportTime = 0;
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.player = null;
super.resetTask();
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
if (this.player != null)
{
if (!this.enderman.shouldAttackPlayer(this.player))
{
return false;
}
else
{
this.enderman.faceEntity(this.player, 10.0F, 10.0F);
return true;
}
}
else
{
return this.targetEntity != null && ((EntityPlayer)this.targetEntity).isEntityAlive() ? true : super.shouldContinueExecuting();
}
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
if (this.player != null)
{
if (--this.aggroTime <= 0)
{
this.targetEntity = this.player;
this.player = null;
super.startExecuting();
}
}
else
{
if (this.targetEntity != null)
{
if (this.enderman.shouldAttackPlayer((EntityPlayer)this.targetEntity))
{
if (((EntityPlayer)this.targetEntity).getDistanceSq(this.enderman) < 16.0D)
{
this.enderman.teleportRandomly();
}
this.teleportTime = 0;
}
else if (((EntityPlayer)this.targetEntity).getDistanceSq(this.enderman) > 256.0D && this.teleportTime++ >= 30 && this.enderman.teleportToEntity(this.targetEntity))
{
this.teleportTime = 0;
}
}
super.updateTask();
}
}
}
static class AIPlaceBlock extends EntityAIBase
{
private final EntityEnderman enderman;
public AIPlaceBlock(EntityEnderman p_i45843_1_)
{
this.enderman = p_i45843_1_;
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (this.enderman.getHeldBlockState() == null)
{
return false;
}
else if (!net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.enderman.world, this.enderman))
{
return false;
}
else
{
return this.enderman.getRNG().nextInt(2000) == 0;
}
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
Random random = this.enderman.getRNG();
World world = this.enderman.world;
int i = MathHelper.floor(this.enderman.posX - 1.0D + random.nextDouble() * 2.0D);
int j = MathHelper.floor(this.enderman.posY + random.nextDouble() * 2.0D);
int k = MathHelper.floor(this.enderman.posZ - 1.0D + random.nextDouble() * 2.0D);
BlockPos blockpos = new BlockPos(i, j, k);
IBlockState iblockstate = world.getBlockState(blockpos);
IBlockState iblockstate1 = world.getBlockState(blockpos.down());
IBlockState iblockstate2 = this.enderman.getHeldBlockState();
if (iblockstate2 != null && this.canPlaceBlock(world, blockpos, iblockstate2.getBlock(), iblockstate, iblockstate1))
{
world.setBlockState(blockpos, iblockstate2, 3);
this.enderman.setHeldBlockState((IBlockState)null);
}
}
private boolean canPlaceBlock(World p_188518_1_, BlockPos p_188518_2_, Block p_188518_3_, IBlockState p_188518_4_, IBlockState p_188518_5_)
{
if (!p_188518_3_.canPlaceBlockAt(p_188518_1_, p_188518_2_))
{
return false;
}
else if (p_188518_4_.getMaterial() != Material.AIR)
{
return false;
}
else if (p_188518_5_.getMaterial() == Material.AIR)
{
return false;
}
else
{
return p_188518_5_.isFullCube();
}
}
}
static class AITakeBlock extends EntityAIBase
{
private final EntityEnderman enderman;
public AITakeBlock(EntityEnderman p_i45841_1_)
{
this.enderman = p_i45841_1_;
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (this.enderman.getHeldBlockState() != null)
{
return false;
}
else if (!net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.enderman.world, this.enderman))
{
return false;
}
else
{
return this.enderman.getRNG().nextInt(20) == 0;
}
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
Random random = this.enderman.getRNG();
World world = this.enderman.world;
int i = MathHelper.floor(this.enderman.posX - 2.0D + random.nextDouble() * 4.0D);
int j = MathHelper.floor(this.enderman.posY + random.nextDouble() * 3.0D);
int k = MathHelper.floor(this.enderman.posZ - 2.0D + random.nextDouble() * 4.0D);
BlockPos blockpos = new BlockPos(i, j, k);
IBlockState iblockstate = world.getBlockState(blockpos);
Block block = iblockstate.getBlock();
RayTraceResult raytraceresult = world.rayTraceBlocks(new Vec3d((double)((float)MathHelper.floor(this.enderman.posX) + 0.5F), (double)((float)j + 0.5F), (double)((float)MathHelper.floor(this.enderman.posZ) + 0.5F)), new Vec3d((double)((float)i + 0.5F), (double)((float)j + 0.5F), (double)((float)k + 0.5F)), false, true, false);
boolean flag = raytraceresult != null && raytraceresult.getBlockPos().equals(blockpos);
if (EntityEnderman.CARRIABLE_BLOCKS.contains(block) && flag)
{
this.enderman.setHeldBlockState(iblockstate);
world.setBlockToAir(blockpos);
}
}
}
}

View File

@@ -0,0 +1,222 @@
package net.minecraft.entity.monster;
import javax.annotation.Nullable;
import net.minecraft.block.Block;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EnumCreatureAttribute;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIAttackMelee;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAISwimming;
import net.minecraft.entity.ai.EntityAIWanderAvoidWater;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.SoundEvents;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootTableList;
public class EntityEndermite extends EntityMob
{
private int lifetime;
private boolean playerSpawned;
public EntityEndermite(World worldIn)
{
super(worldIn);
this.experienceValue = 3;
this.setSize(0.4F, 0.3F);
}
protected void initEntityAI()
{
this.tasks.addTask(1, new EntityAISwimming(this));
this.tasks.addTask(2, new EntityAIAttackMelee(this, 1.0D, false));
this.tasks.addTask(3, new EntityAIWanderAvoidWater(this, 1.0D));
this.tasks.addTask(7, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
this.tasks.addTask(8, new EntityAILookIdle(this));
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true, new Class[0]));
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityPlayer.class, true));
}
public float getEyeHeight()
{
return 0.1F;
}
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(8.0D);
this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.25D);
this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(2.0D);
}
/**
* returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to
* prevent them from trampling crops
*/
protected boolean canTriggerWalking()
{
return false;
}
protected SoundEvent getAmbientSound()
{
return SoundEvents.ENTITY_ENDERMITE_AMBIENT;
}
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return SoundEvents.ENTITY_ENDERMITE_HURT;
}
protected SoundEvent getDeathSound()
{
return SoundEvents.ENTITY_ENDERMITE_DEATH;
}
protected void playStepSound(BlockPos pos, Block blockIn)
{
this.playSound(SoundEvents.ENTITY_ENDERMITE_STEP, 0.15F, 1.0F);
}
@Nullable
protected ResourceLocation getLootTable()
{
return LootTableList.ENTITIES_ENDERMITE;
}
public static void registerFixesEndermite(DataFixer fixer)
{
EntityLiving.registerFixesMob(fixer, EntityEndermite.class);
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound compound)
{
super.readEntityFromNBT(compound);
this.lifetime = compound.getInteger("Lifetime");
this.playerSpawned = compound.getBoolean("PlayerSpawned");
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound compound)
{
super.writeEntityToNBT(compound);
compound.setInteger("Lifetime", this.lifetime);
compound.setBoolean("PlayerSpawned", this.playerSpawned);
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
this.renderYawOffset = this.rotationYaw;
super.onUpdate();
}
/**
* Set the render yaw offset
*/
public void setRenderYawOffset(float offset)
{
this.rotationYaw = offset;
super.setRenderYawOffset(offset);
}
/**
* Returns the Y Offset of this entity.
*/
public double getYOffset()
{
return 0.1D;
}
public boolean isSpawnedByPlayer()
{
return this.playerSpawned;
}
/**
* Sets if this mob was spawned by a player or not.
*/
public void setSpawnedByPlayer(boolean spawnedByPlayer)
{
this.playerSpawned = spawnedByPlayer;
}
/**
* 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)
{
for (int i = 0; i < 2; ++i)
{
this.world.spawnParticle(EnumParticleTypes.PORTAL, this.posX + (this.rand.nextDouble() - 0.5D) * (double)this.width, this.posY + this.rand.nextDouble() * (double)this.height, this.posZ + (this.rand.nextDouble() - 0.5D) * (double)this.width, (this.rand.nextDouble() - 0.5D) * 2.0D, -this.rand.nextDouble(), (this.rand.nextDouble() - 0.5D) * 2.0D);
}
}
else
{
if (!this.isNoDespawnRequired())
{
++this.lifetime;
}
if (this.lifetime >= 2400)
{
this.setDead();
}
}
}
/**
* Checks to make sure the light is not too bright where the mob is spawning
*/
protected boolean isValidLightLevel()
{
return true;
}
/**
* Checks if the entity's current position is a valid location to spawn this entity.
*/
public boolean getCanSpawnHere()
{
if (super.getCanSpawnHere())
{
EntityPlayer entityplayer = this.world.getClosestPlayerToEntity(this, 5.0D);
return entityplayer == null;
}
else
{
return false;
}
}
/**
* Get this Entity's EnumCreatureAttribute
*/
public EnumCreatureAttribute getCreatureAttribute()
{
return EnumCreatureAttribute.ARTHROPOD;
}
}

View File

@@ -0,0 +1,465 @@
package net.minecraft.entity.monster;
import com.google.common.base.Predicate;
import java.util.List;
import javax.annotation.Nullable;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.EnumCreatureAttribute;
import net.minecraft.entity.IEntityLivingData;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIAvoidEntity;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAISwimming;
import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.passive.EntitySheep;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.projectile.EntityEvokerFangs;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.EnumDyeColor;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.DamageSource;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.datafix.DataFixer;
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.minecraft.world.storage.loot.LootTableList;
public class EntityEvoker extends EntitySpellcasterIllager
{
private EntitySheep wololoTarget;
public EntityEvoker(World worldIn)
{
super(worldIn);
this.setSize(0.6F, 1.95F);
this.experienceValue = 10;
}
protected void initEntityAI()
{
super.initEntityAI();
this.tasks.addTask(0, new EntityAISwimming(this));
this.tasks.addTask(1, new EntityEvoker.AICastingSpell());
this.tasks.addTask(2, new EntityAIAvoidEntity(this, EntityPlayer.class, 8.0F, 0.6D, 1.0D));
this.tasks.addTask(4, new EntityEvoker.AISummonSpell());
this.tasks.addTask(5, new EntityEvoker.AIAttackSpell());
this.tasks.addTask(6, new EntityEvoker.AIWololoSpell());
this.tasks.addTask(8, new EntityAIWander(this, 0.6D));
this.tasks.addTask(9, new EntityAIWatchClosest(this, EntityPlayer.class, 3.0F, 1.0F));
this.tasks.addTask(10, new EntityAIWatchClosest(this, EntityLiving.class, 8.0F));
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true, new Class[] {EntityEvoker.class}));
this.targetTasks.addTask(2, (new EntityAINearestAttackableTarget(this, EntityPlayer.class, true)).setUnseenMemoryTicks(300));
this.targetTasks.addTask(3, (new EntityAINearestAttackableTarget(this, EntityVillager.class, false)).setUnseenMemoryTicks(300));
this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityIronGolem.class, false));
}
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.5D);
this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(12.0D);
this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(24.0D);
}
protected void entityInit()
{
super.entityInit();
}
public static void registerFixesEvoker(DataFixer fixer)
{
EntityLiving.registerFixesMob(fixer, EntityEvoker.class);
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound compound)
{
super.readEntityFromNBT(compound);
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound compound)
{
super.writeEntityToNBT(compound);
}
protected ResourceLocation getLootTable()
{
return LootTableList.ENTITIES_EVOCATION_ILLAGER;
}
protected void updateAITasks()
{
super.updateAITasks();
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
super.onUpdate();
}
/**
* Returns whether this Entity is on the same team as the given Entity.
*/
public boolean isOnSameTeam(Entity entityIn)
{
if (entityIn == null)
{
return false;
}
else if (entityIn == this)
{
return true;
}
else if (super.isOnSameTeam(entityIn))
{
return true;
}
else if (entityIn instanceof EntityVex)
{
return this.isOnSameTeam(((EntityVex)entityIn).getOwner());
}
else if (entityIn instanceof EntityLivingBase && ((EntityLivingBase)entityIn).getCreatureAttribute() == EnumCreatureAttribute.ILLAGER)
{
return this.getTeam() == null && entityIn.getTeam() == null;
}
else
{
return false;
}
}
protected SoundEvent getAmbientSound()
{
return SoundEvents.ENTITY_EVOCATION_ILLAGER_AMBIENT;
}
protected SoundEvent getDeathSound()
{
return SoundEvents.EVOCATION_ILLAGER_DEATH;
}
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return SoundEvents.ENTITY_EVOCATION_ILLAGER_HURT;
}
private void setWololoTarget(@Nullable EntitySheep wololoTargetIn)
{
this.wololoTarget = wololoTargetIn;
}
@Nullable
private EntitySheep getWololoTarget()
{
return this.wololoTarget;
}
protected SoundEvent getSpellSound()
{
return SoundEvents.EVOCATION_ILLAGER_CAST_SPELL;
}
class AIAttackSpell extends EntitySpellcasterIllager.AIUseSpell
{
private AIAttackSpell()
{
super();
}
protected int getCastingTime()
{
return 40;
}
protected int getCastingInterval()
{
return 100;
}
protected void castSpell()
{
EntityLivingBase entitylivingbase = EntityEvoker.this.getAttackTarget();
double d0 = Math.min(entitylivingbase.posY, EntityEvoker.this.posY);
double d1 = Math.max(entitylivingbase.posY, EntityEvoker.this.posY) + 1.0D;
float f = (float)MathHelper.atan2(entitylivingbase.posZ - EntityEvoker.this.posZ, entitylivingbase.posX - EntityEvoker.this.posX);
if (EntityEvoker.this.getDistanceSq(entitylivingbase) < 9.0D)
{
for (int i = 0; i < 5; ++i)
{
float f1 = f + (float)i * (float)Math.PI * 0.4F;
this.spawnFangs(EntityEvoker.this.posX + (double)MathHelper.cos(f1) * 1.5D, EntityEvoker.this.posZ + (double)MathHelper.sin(f1) * 1.5D, d0, d1, f1, 0);
}
for (int k = 0; k < 8; ++k)
{
float f2 = f + (float)k * (float)Math.PI * 2.0F / 8.0F + ((float)Math.PI * 2F / 5F);
this.spawnFangs(EntityEvoker.this.posX + (double)MathHelper.cos(f2) * 2.5D, EntityEvoker.this.posZ + (double)MathHelper.sin(f2) * 2.5D, d0, d1, f2, 3);
}
}
else
{
for (int l = 0; l < 16; ++l)
{
double d2 = 1.25D * (double)(l + 1);
int j = 1 * l;
this.spawnFangs(EntityEvoker.this.posX + (double)MathHelper.cos(f) * d2, EntityEvoker.this.posZ + (double)MathHelper.sin(f) * d2, d0, d1, f, j);
}
}
}
private void spawnFangs(double p_190876_1_, double p_190876_3_, double p_190876_5_, double p_190876_7_, float p_190876_9_, int p_190876_10_)
{
BlockPos blockpos = new BlockPos(p_190876_1_, p_190876_7_, p_190876_3_);
boolean flag = false;
double d0 = 0.0D;
while (true)
{
if (!EntityEvoker.this.world.isBlockNormalCube(blockpos, true) && EntityEvoker.this.world.isBlockNormalCube(blockpos.down(), true))
{
if (!EntityEvoker.this.world.isAirBlock(blockpos))
{
IBlockState iblockstate = EntityEvoker.this.world.getBlockState(blockpos);
AxisAlignedBB axisalignedbb = iblockstate.getCollisionBoundingBox(EntityEvoker.this.world, blockpos);
if (axisalignedbb != null)
{
d0 = axisalignedbb.maxY;
}
}
flag = true;
break;
}
blockpos = blockpos.down();
if (blockpos.getY() < MathHelper.floor(p_190876_5_) - 1)
{
break;
}
}
if (flag)
{
EntityEvokerFangs entityevokerfangs = new EntityEvokerFangs(EntityEvoker.this.world, p_190876_1_, (double)blockpos.getY() + d0, p_190876_3_, p_190876_9_, p_190876_10_, EntityEvoker.this);
EntityEvoker.this.world.spawnEntity(entityevokerfangs);
}
}
protected SoundEvent getSpellPrepareSound()
{
return SoundEvents.EVOCATION_ILLAGER_PREPARE_ATTACK;
}
protected EntitySpellcasterIllager.SpellType getSpellType()
{
return EntitySpellcasterIllager.SpellType.FANGS;
}
}
class AICastingSpell extends EntitySpellcasterIllager.AICastingApell
{
private AICastingSpell()
{
super();
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
if (EntityEvoker.this.getAttackTarget() != null)
{
EntityEvoker.this.getLookHelper().setLookPositionWithEntity(EntityEvoker.this.getAttackTarget(), (float)EntityEvoker.this.getHorizontalFaceSpeed(), (float)EntityEvoker.this.getVerticalFaceSpeed());
}
else if (EntityEvoker.this.getWololoTarget() != null)
{
EntityEvoker.this.getLookHelper().setLookPositionWithEntity(EntityEvoker.this.getWololoTarget(), (float)EntityEvoker.this.getHorizontalFaceSpeed(), (float)EntityEvoker.this.getVerticalFaceSpeed());
}
}
}
class AISummonSpell extends EntitySpellcasterIllager.AIUseSpell
{
private AISummonSpell()
{
super();
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (!super.shouldExecute())
{
return false;
}
else
{
int i = EntityEvoker.this.world.getEntitiesWithinAABB(EntityVex.class, EntityEvoker.this.getEntityBoundingBox().grow(16.0D)).size();
return EntityEvoker.this.rand.nextInt(8) + 1 > i;
}
}
protected int getCastingTime()
{
return 100;
}
protected int getCastingInterval()
{
return 340;
}
protected void castSpell()
{
for (int i = 0; i < 3; ++i)
{
BlockPos blockpos = (new BlockPos(EntityEvoker.this)).add(-2 + EntityEvoker.this.rand.nextInt(5), 1, -2 + EntityEvoker.this.rand.nextInt(5));
EntityVex entityvex = new EntityVex(EntityEvoker.this.world);
entityvex.moveToBlockPosAndAngles(blockpos, 0.0F, 0.0F);
entityvex.onInitialSpawn(EntityEvoker.this.world.getDifficultyForLocation(blockpos), (IEntityLivingData)null);
entityvex.setOwner(EntityEvoker.this);
entityvex.setBoundOrigin(blockpos);
entityvex.setLimitedLife(20 * (30 + EntityEvoker.this.rand.nextInt(90)));
EntityEvoker.this.world.spawnEntity(entityvex);
}
}
protected SoundEvent getSpellPrepareSound()
{
return SoundEvents.EVOCATION_ILLAGER_PREPARE_SUMMON;
}
protected EntitySpellcasterIllager.SpellType getSpellType()
{
return EntitySpellcasterIllager.SpellType.SUMMON_VEX;
}
}
public class AIWololoSpell extends EntitySpellcasterIllager.AIUseSpell
{
final Predicate<EntitySheep> wololoSelector = new Predicate<EntitySheep>()
{
public boolean apply(EntitySheep p_apply_1_)
{
return p_apply_1_.getFleeceColor() == EnumDyeColor.BLUE;
}
};
public AIWololoSpell()
{
super();
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (EntityEvoker.this.getAttackTarget() != null)
{
return false;
}
else if (EntityEvoker.this.isSpellcasting())
{
return false;
}
else if (EntityEvoker.this.ticksExisted < this.spellCooldown)
{
return false;
}
else if (!net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(EntityEvoker.this.world, EntityEvoker.this))
{
return false;
}
else
{
List<EntitySheep> list = EntityEvoker.this.world.<EntitySheep>getEntitiesWithinAABB(EntitySheep.class, EntityEvoker.this.getEntityBoundingBox().grow(16.0D, 4.0D, 16.0D), this.wololoSelector);
if (list.isEmpty())
{
return false;
}
else
{
EntityEvoker.this.setWololoTarget(list.get(EntityEvoker.this.rand.nextInt(list.size())));
return true;
}
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return EntityEvoker.this.getWololoTarget() != null && this.spellWarmup > 0;
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
super.resetTask();
EntityEvoker.this.setWololoTarget((EntitySheep)null);
}
protected void castSpell()
{
EntitySheep entitysheep = EntityEvoker.this.getWololoTarget();
if (entitysheep != null && entitysheep.isEntityAlive())
{
entitysheep.setFleeceColor(EnumDyeColor.RED);
}
}
protected int getCastWarmupTime()
{
return 40;
}
protected int getCastingTime()
{
return 60;
}
protected int getCastingInterval()
{
return 140;
}
protected SoundEvent getSpellPrepareSound()
{
return SoundEvents.EVOCATION_ILLAGER_PREPARE_WOLOLO;
}
protected EntitySpellcasterIllager.SpellType getSpellType()
{
return EntitySpellcasterIllager.SpellType.WOLOLO;
}
}
}

View File

@@ -0,0 +1,437 @@
package net.minecraft.entity.monster;
import java.util.Random;
import javax.annotation.Nullable;
import net.minecraft.entity.EntityFlying;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIBase;
import net.minecraft.entity.ai.EntityAIFindEntityNearestPlayer;
import net.minecraft.entity.ai.EntityMoveHelper;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.projectile.EntityLargeFireball;
import net.minecraft.init.SoundEvents;
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.DamageSource;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.EnumDifficulty;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootTableList;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class EntityGhast extends EntityFlying implements IMob
{
private static final DataParameter<Boolean> ATTACKING = EntityDataManager.<Boolean>createKey(EntityGhast.class, DataSerializers.BOOLEAN);
/** The explosion radius of spawned fireballs. */
private int explosionStrength = 1;
public EntityGhast(World worldIn)
{
super(worldIn);
this.setSize(4.0F, 4.0F);
this.isImmuneToFire = true;
this.experienceValue = 5;
this.moveHelper = new EntityGhast.GhastMoveHelper(this);
}
protected void initEntityAI()
{
this.tasks.addTask(5, new EntityGhast.AIRandomFly(this));
this.tasks.addTask(7, new EntityGhast.AILookAround(this));
this.tasks.addTask(7, new EntityGhast.AIFireballAttack(this));
this.targetTasks.addTask(1, new EntityAIFindEntityNearestPlayer(this));
}
@SideOnly(Side.CLIENT)
public boolean isAttacking()
{
return ((Boolean)this.dataManager.get(ATTACKING)).booleanValue();
}
public void setAttacking(boolean attacking)
{
this.dataManager.set(ATTACKING, Boolean.valueOf(attacking));
}
public int getFireballStrength()
{
return this.explosionStrength;
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
super.onUpdate();
if (!this.world.isRemote && this.world.getDifficulty() == EnumDifficulty.PEACEFUL)
{
this.setDead();
}
}
/**
* Called when the entity is attacked.
*/
public boolean attackEntityFrom(DamageSource source, float amount)
{
if (this.isEntityInvulnerable(source))
{
return false;
}
else if (source.getImmediateSource() instanceof EntityLargeFireball && source.getTrueSource() instanceof EntityPlayer)
{
super.attackEntityFrom(source, 1000.0F);
return true;
}
else
{
return super.attackEntityFrom(source, amount);
}
}
protected void entityInit()
{
super.entityInit();
this.dataManager.register(ATTACKING, Boolean.valueOf(false));
}
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(10.0D);
this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(100.0D);
}
public SoundCategory getSoundCategory()
{
return SoundCategory.HOSTILE;
}
protected SoundEvent getAmbientSound()
{
return SoundEvents.ENTITY_GHAST_AMBIENT;
}
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return SoundEvents.ENTITY_GHAST_HURT;
}
protected SoundEvent getDeathSound()
{
return SoundEvents.ENTITY_GHAST_DEATH;
}
@Nullable
protected ResourceLocation getLootTable()
{
return LootTableList.ENTITIES_GHAST;
}
/**
* Returns the volume for the sounds this mob makes.
*/
protected float getSoundVolume()
{
return 10.0F;
}
/**
* Checks if the entity's current position is a valid location to spawn this entity.
*/
public boolean getCanSpawnHere()
{
return this.rand.nextInt(20) == 0 && super.getCanSpawnHere() && this.world.getDifficulty() != EnumDifficulty.PEACEFUL;
}
/**
* Will return how many at most can spawn in a chunk at once.
*/
public int getMaxSpawnedInChunk()
{
return 1;
}
public static void registerFixesGhast(DataFixer fixer)
{
EntityLiving.registerFixesMob(fixer, EntityGhast.class);
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound compound)
{
super.writeEntityToNBT(compound);
compound.setInteger("ExplosionPower", this.explosionStrength);
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound compound)
{
super.readEntityFromNBT(compound);
if (compound.hasKey("ExplosionPower", 99))
{
this.explosionStrength = compound.getInteger("ExplosionPower");
}
}
public float getEyeHeight()
{
return 2.6F;
}
static class AIFireballAttack extends EntityAIBase
{
private final EntityGhast parentEntity;
public int attackTimer;
public AIFireballAttack(EntityGhast ghast)
{
this.parentEntity = ghast;
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
return this.parentEntity.getAttackTarget() != null;
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.attackTimer = 0;
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.parentEntity.setAttacking(false);
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
EntityLivingBase entitylivingbase = this.parentEntity.getAttackTarget();
double d0 = 64.0D;
if (entitylivingbase.getDistanceSq(this.parentEntity) < 4096.0D && this.parentEntity.canEntityBeSeen(entitylivingbase))
{
World world = this.parentEntity.world;
++this.attackTimer;
if (this.attackTimer == 10)
{
world.playEvent((EntityPlayer)null, 1015, new BlockPos(this.parentEntity), 0);
}
if (this.attackTimer == 20)
{
double d1 = 4.0D;
Vec3d vec3d = this.parentEntity.getLook(1.0F);
double d2 = entitylivingbase.posX - (this.parentEntity.posX + vec3d.x * 4.0D);
double d3 = entitylivingbase.getEntityBoundingBox().minY + (double)(entitylivingbase.height / 2.0F) - (0.5D + this.parentEntity.posY + (double)(this.parentEntity.height / 2.0F));
double d4 = entitylivingbase.posZ - (this.parentEntity.posZ + vec3d.z * 4.0D);
world.playEvent((EntityPlayer)null, 1016, new BlockPos(this.parentEntity), 0);
EntityLargeFireball entitylargefireball = new EntityLargeFireball(world, this.parentEntity, d2, d3, d4);
entitylargefireball.explosionPower = this.parentEntity.getFireballStrength();
entitylargefireball.posX = this.parentEntity.posX + vec3d.x * 4.0D;
entitylargefireball.posY = this.parentEntity.posY + (double)(this.parentEntity.height / 2.0F) + 0.5D;
entitylargefireball.posZ = this.parentEntity.posZ + vec3d.z * 4.0D;
world.spawnEntity(entitylargefireball);
this.attackTimer = -40;
}
}
else if (this.attackTimer > 0)
{
--this.attackTimer;
}
this.parentEntity.setAttacking(this.attackTimer > 10);
}
}
static class AILookAround extends EntityAIBase
{
private final EntityGhast parentEntity;
public AILookAround(EntityGhast ghast)
{
this.parentEntity = ghast;
this.setMutexBits(2);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
return true;
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
if (this.parentEntity.getAttackTarget() == null)
{
this.parentEntity.rotationYaw = -((float)MathHelper.atan2(this.parentEntity.motionX, this.parentEntity.motionZ)) * (180F / (float)Math.PI);
this.parentEntity.renderYawOffset = this.parentEntity.rotationYaw;
}
else
{
EntityLivingBase entitylivingbase = this.parentEntity.getAttackTarget();
double d0 = 64.0D;
if (entitylivingbase.getDistanceSq(this.parentEntity) < 4096.0D)
{
double d1 = entitylivingbase.posX - this.parentEntity.posX;
double d2 = entitylivingbase.posZ - this.parentEntity.posZ;
this.parentEntity.rotationYaw = -((float)MathHelper.atan2(d1, d2)) * (180F / (float)Math.PI);
this.parentEntity.renderYawOffset = this.parentEntity.rotationYaw;
}
}
}
}
static class AIRandomFly extends EntityAIBase
{
private final EntityGhast parentEntity;
public AIRandomFly(EntityGhast ghast)
{
this.parentEntity = ghast;
this.setMutexBits(1);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
EntityMoveHelper entitymovehelper = this.parentEntity.getMoveHelper();
if (!entitymovehelper.isUpdating())
{
return true;
}
else
{
double d0 = entitymovehelper.getX() - this.parentEntity.posX;
double d1 = entitymovehelper.getY() - this.parentEntity.posY;
double d2 = entitymovehelper.getZ() - this.parentEntity.posZ;
double d3 = d0 * d0 + d1 * d1 + d2 * d2;
return d3 < 1.0D || d3 > 3600.0D;
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return false;
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
Random random = this.parentEntity.getRNG();
double d0 = this.parentEntity.posX + (double)((random.nextFloat() * 2.0F - 1.0F) * 16.0F);
double d1 = this.parentEntity.posY + (double)((random.nextFloat() * 2.0F - 1.0F) * 16.0F);
double d2 = this.parentEntity.posZ + (double)((random.nextFloat() * 2.0F - 1.0F) * 16.0F);
this.parentEntity.getMoveHelper().setMoveTo(d0, d1, d2, 1.0D);
}
}
static class GhastMoveHelper extends EntityMoveHelper
{
private final EntityGhast parentEntity;
private int courseChangeCooldown;
public GhastMoveHelper(EntityGhast ghast)
{
super(ghast);
this.parentEntity = ghast;
}
public void onUpdateMoveHelper()
{
if (this.action == EntityMoveHelper.Action.MOVE_TO)
{
double d0 = this.posX - this.parentEntity.posX;
double d1 = this.posY - this.parentEntity.posY;
double d2 = this.posZ - this.parentEntity.posZ;
double d3 = d0 * d0 + d1 * d1 + d2 * d2;
if (this.courseChangeCooldown-- <= 0)
{
this.courseChangeCooldown += this.parentEntity.getRNG().nextInt(5) + 2;
d3 = (double)MathHelper.sqrt(d3);
if (this.isNotColliding(this.posX, this.posY, this.posZ, d3))
{
this.parentEntity.motionX += d0 / d3 * 0.1D;
this.parentEntity.motionY += d1 / d3 * 0.1D;
this.parentEntity.motionZ += d2 / d3 * 0.1D;
}
else
{
this.action = EntityMoveHelper.Action.WAIT;
}
}
}
}
/**
* Checks if entity bounding box is not colliding with terrain
*/
private boolean isNotColliding(double x, double y, double z, double p_179926_7_)
{
double d0 = (x - this.parentEntity.posX) / p_179926_7_;
double d1 = (y - this.parentEntity.posY) / p_179926_7_;
double d2 = (z - this.parentEntity.posZ) / p_179926_7_;
AxisAlignedBB axisalignedbb = this.parentEntity.getEntityBoundingBox();
for (int i = 1; (double)i < p_179926_7_; ++i)
{
axisalignedbb = axisalignedbb.offset(d0, d1, d2);
if (!this.parentEntity.world.getCollisionBoxes(this.parentEntity, axisalignedbb).isEmpty())
{
return false;
}
}
return true;
}
}
}

View File

@@ -0,0 +1,48 @@
package net.minecraft.entity.monster;
import javax.annotation.Nullable;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootTableList;
public class EntityGiantZombie extends EntityMob
{
public EntityGiantZombie(World worldIn)
{
super(worldIn);
this.setSize(this.width * 6.0F, this.height * 6.0F);
}
public static void registerFixesGiantZombie(DataFixer fixer)
{
EntityLiving.registerFixesMob(fixer, EntityGiantZombie.class);
}
public float getEyeHeight()
{
return 10.440001F;
}
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(100.0D);
this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.5D);
this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(50.0D);
}
public float getBlockPathWeight(BlockPos pos)
{
return this.world.getLightBrightness(pos) - 0.5F;
}
@Nullable
protected ResourceLocation getLootTable()
{
return LootTableList.ENTITIES_GIANT;
}
}

View File

@@ -0,0 +1,54 @@
package net.minecraft.entity.monster;
import javax.annotation.Nullable;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.passive.IAnimals;
import net.minecraft.util.DamageSource;
import net.minecraft.util.SoundEvent;
import net.minecraft.world.World;
public abstract class EntityGolem extends EntityCreature implements IAnimals
{
public EntityGolem(World worldIn)
{
super(worldIn);
}
public void fall(float distance, float damageMultiplier)
{
}
@Nullable
protected SoundEvent getAmbientSound()
{
return null;
}
@Nullable
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return null;
}
@Nullable
protected SoundEvent getDeathSound()
{
return null;
}
/**
* Get number of ticks, at least during which the living entity will be silent.
*/
public int getTalkInterval()
{
return 120;
}
/**
* Determines if an entity can be despawned, used on idle far away entities
*/
protected boolean canDespawn()
{
return false;
}
}

View File

@@ -0,0 +1,612 @@
package net.minecraft.entity.monster;
import com.google.common.base.Predicate;
import javax.annotation.Nullable;
import net.minecraft.block.material.Material;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.MoverType;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIBase;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAIMoveTowardsRestriction;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.ai.EntityLookHelper;
import net.minecraft.entity.ai.EntityMoveHelper;
import net.minecraft.entity.passive.EntitySquid;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.SoundEvents;
import net.minecraft.network.datasync.DataParameter;
import net.minecraft.network.datasync.DataSerializers;
import net.minecraft.network.datasync.EntityDataManager;
import net.minecraft.pathfinding.PathNavigate;
import net.minecraft.pathfinding.PathNavigateSwimmer;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.EnumDifficulty;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootTableList;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class EntityGuardian extends EntityMob
{
private static final DataParameter<Boolean> MOVING = EntityDataManager.<Boolean>createKey(EntityGuardian.class, DataSerializers.BOOLEAN);
private static final DataParameter<Integer> TARGET_ENTITY = EntityDataManager.<Integer>createKey(EntityGuardian.class, DataSerializers.VARINT);
protected float clientSideTailAnimation;
protected float clientSideTailAnimationO;
protected float clientSideTailAnimationSpeed;
protected float clientSideSpikesAnimation;
protected float clientSideSpikesAnimationO;
private EntityLivingBase targetedEntity;
private int clientSideAttackTime;
private boolean clientSideTouchedGround;
protected EntityAIWander wander;
public EntityGuardian(World worldIn)
{
super(worldIn);
this.experienceValue = 10;
this.setSize(0.85F, 0.85F);
this.moveHelper = new EntityGuardian.GuardianMoveHelper(this);
this.clientSideTailAnimation = this.rand.nextFloat();
this.clientSideTailAnimationO = this.clientSideTailAnimation;
}
protected void initEntityAI()
{
EntityAIMoveTowardsRestriction entityaimovetowardsrestriction = new EntityAIMoveTowardsRestriction(this, 1.0D);
this.wander = new EntityAIWander(this, 1.0D, 80);
this.tasks.addTask(4, new EntityGuardian.AIGuardianAttack(this));
this.tasks.addTask(5, entityaimovetowardsrestriction);
this.tasks.addTask(7, this.wander);
this.tasks.addTask(8, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
this.tasks.addTask(8, new EntityAIWatchClosest(this, EntityGuardian.class, 12.0F, 0.01F));
this.tasks.addTask(9, new EntityAILookIdle(this));
this.wander.setMutexBits(3);
entityaimovetowardsrestriction.setMutexBits(3);
this.targetTasks.addTask(1, new EntityAINearestAttackableTarget(this, EntityLivingBase.class, 10, true, false, new EntityGuardian.GuardianTargetSelector(this)));
}
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(6.0D);
this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.5D);
this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(16.0D);
this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(30.0D);
}
public static void registerFixesGuardian(DataFixer fixer)
{
EntityLiving.registerFixesMob(fixer, EntityGuardian.class);
}
/**
* Returns new PathNavigateGround instance
*/
protected PathNavigate createNavigator(World worldIn)
{
return new PathNavigateSwimmer(this, worldIn);
}
protected void entityInit()
{
super.entityInit();
this.dataManager.register(MOVING, Boolean.valueOf(false));
this.dataManager.register(TARGET_ENTITY, Integer.valueOf(0));
}
public boolean isMoving()
{
return ((Boolean)this.dataManager.get(MOVING)).booleanValue();
}
private void setMoving(boolean moving)
{
this.dataManager.set(MOVING, Boolean.valueOf(moving));
}
public int getAttackDuration()
{
return 80;
}
private void setTargetedEntity(int entityId)
{
this.dataManager.set(TARGET_ENTITY, Integer.valueOf(entityId));
}
public boolean hasTargetedEntity()
{
return ((Integer)this.dataManager.get(TARGET_ENTITY)).intValue() != 0;
}
@Nullable
public EntityLivingBase getTargetedEntity()
{
if (!this.hasTargetedEntity())
{
return null;
}
else if (this.world.isRemote)
{
if (this.targetedEntity != null)
{
return this.targetedEntity;
}
else
{
Entity entity = this.world.getEntityByID(((Integer)this.dataManager.get(TARGET_ENTITY)).intValue());
if (entity instanceof EntityLivingBase)
{
this.targetedEntity = (EntityLivingBase)entity;
return this.targetedEntity;
}
else
{
return null;
}
}
}
else
{
return this.getAttackTarget();
}
}
public void notifyDataManagerChange(DataParameter<?> key)
{
super.notifyDataManagerChange(key);
if (TARGET_ENTITY.equals(key))
{
this.clientSideAttackTime = 0;
this.targetedEntity = null;
}
}
/**
* Get number of ticks, at least during which the living entity will be silent.
*/
public int getTalkInterval()
{
return 160;
}
protected SoundEvent getAmbientSound()
{
return this.isInWater() ? SoundEvents.ENTITY_GUARDIAN_AMBIENT : SoundEvents.ENTITY_GUARDIAN_AMBIENT_LAND;
}
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return this.isInWater() ? SoundEvents.ENTITY_GUARDIAN_HURT : SoundEvents.ENTITY_GUARDIAN_HURT_LAND;
}
protected SoundEvent getDeathSound()
{
return this.isInWater() ? SoundEvents.ENTITY_GUARDIAN_DEATH : SoundEvents.ENTITY_GUARDIAN_DEATH_LAND;
}
/**
* returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to
* prevent them from trampling crops
*/
protected boolean canTriggerWalking()
{
return false;
}
public float getEyeHeight()
{
return this.height * 0.5F;
}
public float getBlockPathWeight(BlockPos pos)
{
return this.world.getBlockState(pos).getMaterial() == Material.WATER ? 10.0F + this.world.getLightBrightness(pos) - 0.5F : super.getBlockPathWeight(pos);
}
/**
* 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()
{
if (this.world.isRemote)
{
this.clientSideTailAnimationO = this.clientSideTailAnimation;
if (!this.isInWater())
{
this.clientSideTailAnimationSpeed = 2.0F;
if (this.motionY > 0.0D && this.clientSideTouchedGround && !this.isSilent())
{
this.world.playSound(this.posX, this.posY, this.posZ, this.getFlopSound(), this.getSoundCategory(), 1.0F, 1.0F, false);
}
this.clientSideTouchedGround = this.motionY < 0.0D && this.world.isBlockNormalCube((new BlockPos(this)).down(), false);
}
else if (this.isMoving())
{
if (this.clientSideTailAnimationSpeed < 0.5F)
{
this.clientSideTailAnimationSpeed = 4.0F;
}
else
{
this.clientSideTailAnimationSpeed += (0.5F - this.clientSideTailAnimationSpeed) * 0.1F;
}
}
else
{
this.clientSideTailAnimationSpeed += (0.125F - this.clientSideTailAnimationSpeed) * 0.2F;
}
this.clientSideTailAnimation += this.clientSideTailAnimationSpeed;
this.clientSideSpikesAnimationO = this.clientSideSpikesAnimation;
if (!this.isInWater())
{
this.clientSideSpikesAnimation = this.rand.nextFloat();
}
else if (this.isMoving())
{
this.clientSideSpikesAnimation += (0.0F - this.clientSideSpikesAnimation) * 0.25F;
}
else
{
this.clientSideSpikesAnimation += (1.0F - this.clientSideSpikesAnimation) * 0.06F;
}
if (this.isMoving() && this.isInWater())
{
Vec3d vec3d = this.getLook(0.0F);
for (int i = 0; i < 2; ++i)
{
this.world.spawnParticle(EnumParticleTypes.WATER_BUBBLE, this.posX + (this.rand.nextDouble() - 0.5D) * (double)this.width - vec3d.x * 1.5D, this.posY + this.rand.nextDouble() * (double)this.height - vec3d.y * 1.5D, this.posZ + (this.rand.nextDouble() - 0.5D) * (double)this.width - vec3d.z * 1.5D, 0.0D, 0.0D, 0.0D);
}
}
if (this.hasTargetedEntity())
{
if (this.clientSideAttackTime < this.getAttackDuration())
{
++this.clientSideAttackTime;
}
EntityLivingBase entitylivingbase = this.getTargetedEntity();
if (entitylivingbase != null)
{
this.getLookHelper().setLookPositionWithEntity(entitylivingbase, 90.0F, 90.0F);
this.getLookHelper().onUpdateLook();
double d5 = (double)this.getAttackAnimationScale(0.0F);
double d0 = entitylivingbase.posX - this.posX;
double d1 = entitylivingbase.posY + (double)(entitylivingbase.height * 0.5F) - (this.posY + (double)this.getEyeHeight());
double d2 = entitylivingbase.posZ - this.posZ;
double d3 = Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2);
d0 = d0 / d3;
d1 = d1 / d3;
d2 = d2 / d3;
double d4 = this.rand.nextDouble();
while (d4 < d3)
{
d4 += 1.8D - d5 + this.rand.nextDouble() * (1.7D - d5);
this.world.spawnParticle(EnumParticleTypes.WATER_BUBBLE, this.posX + d0 * d4, this.posY + d1 * d4 + (double)this.getEyeHeight(), this.posZ + d2 * d4, 0.0D, 0.0D, 0.0D);
}
}
}
}
if (this.inWater)
{
this.setAir(300);
}
else if (this.onGround)
{
this.motionY += 0.5D;
this.motionX += (double)((this.rand.nextFloat() * 2.0F - 1.0F) * 0.4F);
this.motionZ += (double)((this.rand.nextFloat() * 2.0F - 1.0F) * 0.4F);
this.rotationYaw = this.rand.nextFloat() * 360.0F;
this.onGround = false;
this.isAirBorne = true;
}
if (this.hasTargetedEntity())
{
this.rotationYaw = this.rotationYawHead;
}
super.onLivingUpdate();
}
protected SoundEvent getFlopSound()
{
return SoundEvents.ENTITY_GUARDIAN_FLOP;
}
@SideOnly(Side.CLIENT)
public float getTailAnimation(float p_175471_1_)
{
return this.clientSideTailAnimationO + (this.clientSideTailAnimation - this.clientSideTailAnimationO) * p_175471_1_;
}
@SideOnly(Side.CLIENT)
public float getSpikesAnimation(float p_175469_1_)
{
return this.clientSideSpikesAnimationO + (this.clientSideSpikesAnimation - this.clientSideSpikesAnimationO) * p_175469_1_;
}
public float getAttackAnimationScale(float p_175477_1_)
{
return ((float)this.clientSideAttackTime + p_175477_1_) / (float)this.getAttackDuration();
}
@Nullable
protected ResourceLocation getLootTable()
{
return LootTableList.ENTITIES_GUARDIAN;
}
/**
* Checks to make sure the light is not too bright where the mob is spawning
*/
protected boolean isValidLightLevel()
{
return true;
}
/**
* Checks that the entity is not colliding with any blocks / liquids
*/
public boolean isNotColliding()
{
return this.world.checkNoEntityCollision(this.getEntityBoundingBox(), this) && this.world.getCollisionBoxes(this, this.getEntityBoundingBox()).isEmpty();
}
/**
* Checks if the entity's current position is a valid location to spawn this entity.
*/
public boolean getCanSpawnHere()
{
return (this.rand.nextInt(20) == 0 || !this.world.canBlockSeeSky(new BlockPos(this))) && super.getCanSpawnHere();
}
/**
* Called when the entity is attacked.
*/
public boolean attackEntityFrom(DamageSource source, float amount)
{
if (!this.isMoving() && !source.isMagicDamage() && source.getImmediateSource() instanceof EntityLivingBase)
{
EntityLivingBase entitylivingbase = (EntityLivingBase)source.getImmediateSource();
if (!source.isExplosion())
{
entitylivingbase.attackEntityFrom(DamageSource.causeThornsDamage(this), 2.0F);
}
}
if (this.wander != null)
{
this.wander.makeUpdate();
}
return super.attackEntityFrom(source, amount);
}
/**
* The speed it takes to move the entityliving's rotationPitch through the faceEntity method. This is only currently
* use in wolves.
*/
public int getVerticalFaceSpeed()
{
return 180;
}
public void travel(float strafe, float vertical, float forward)
{
if (this.isServerWorld() && this.isInWater())
{
this.moveRelative(strafe, vertical, forward, 0.1F);
this.move(MoverType.SELF, this.motionX, this.motionY, this.motionZ);
this.motionX *= 0.8999999761581421D;
this.motionY *= 0.8999999761581421D;
this.motionZ *= 0.8999999761581421D;
if (!this.isMoving() && this.getAttackTarget() == null)
{
this.motionY -= 0.005D;
}
}
else
{
super.travel(strafe, vertical, forward);
}
}
static class AIGuardianAttack extends EntityAIBase
{
private final EntityGuardian guardian;
private int tickCounter;
private final boolean isElder;
public AIGuardianAttack(EntityGuardian guardian)
{
this.guardian = guardian;
this.isElder = guardian instanceof EntityElderGuardian;
this.setMutexBits(3);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
EntityLivingBase entitylivingbase = this.guardian.getAttackTarget();
return entitylivingbase != null && entitylivingbase.isEntityAlive();
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return super.shouldContinueExecuting() && (this.isElder || this.guardian.getDistanceSq(this.guardian.getAttackTarget()) > 9.0D);
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.tickCounter = -10;
this.guardian.getNavigator().clearPath();
this.guardian.getLookHelper().setLookPositionWithEntity(this.guardian.getAttackTarget(), 90.0F, 90.0F);
this.guardian.isAirBorne = true;
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
this.guardian.setTargetedEntity(0);
this.guardian.setAttackTarget((EntityLivingBase)null);
this.guardian.wander.makeUpdate();
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
EntityLivingBase entitylivingbase = this.guardian.getAttackTarget();
this.guardian.getNavigator().clearPath();
this.guardian.getLookHelper().setLookPositionWithEntity(entitylivingbase, 90.0F, 90.0F);
if (!this.guardian.canEntityBeSeen(entitylivingbase))
{
this.guardian.setAttackTarget((EntityLivingBase)null);
}
else
{
++this.tickCounter;
if (this.tickCounter == 0)
{
this.guardian.setTargetedEntity(this.guardian.getAttackTarget().getEntityId());
this.guardian.world.setEntityState(this.guardian, (byte)21);
}
else if (this.tickCounter >= this.guardian.getAttackDuration())
{
float f = 1.0F;
if (this.guardian.world.getDifficulty() == EnumDifficulty.HARD)
{
f += 2.0F;
}
if (this.isElder)
{
f += 2.0F;
}
entitylivingbase.attackEntityFrom(DamageSource.causeIndirectMagicDamage(this.guardian, this.guardian), f);
entitylivingbase.attackEntityFrom(DamageSource.causeMobDamage(this.guardian), (float)this.guardian.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).getAttributeValue());
this.guardian.setAttackTarget((EntityLivingBase)null);
}
super.updateTask();
}
}
}
static class GuardianMoveHelper extends EntityMoveHelper
{
private final EntityGuardian entityGuardian;
public GuardianMoveHelper(EntityGuardian guardian)
{
super(guardian);
this.entityGuardian = guardian;
}
public void onUpdateMoveHelper()
{
if (this.action == EntityMoveHelper.Action.MOVE_TO && !this.entityGuardian.getNavigator().noPath())
{
double d0 = this.posX - this.entityGuardian.posX;
double d1 = this.posY - this.entityGuardian.posY;
double d2 = this.posZ - this.entityGuardian.posZ;
double d3 = (double)MathHelper.sqrt(d0 * d0 + d1 * d1 + d2 * d2);
d1 = d1 / d3;
float f = (float)(MathHelper.atan2(d2, d0) * (180D / Math.PI)) - 90.0F;
this.entityGuardian.rotationYaw = this.limitAngle(this.entityGuardian.rotationYaw, f, 90.0F);
this.entityGuardian.renderYawOffset = this.entityGuardian.rotationYaw;
float f1 = (float)(this.speed * this.entityGuardian.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).getAttributeValue());
this.entityGuardian.setAIMoveSpeed(this.entityGuardian.getAIMoveSpeed() + (f1 - this.entityGuardian.getAIMoveSpeed()) * 0.125F);
double d4 = Math.sin((double)(this.entityGuardian.ticksExisted + this.entityGuardian.getEntityId()) * 0.5D) * 0.05D;
double d5 = Math.cos((double)(this.entityGuardian.rotationYaw * 0.017453292F));
double d6 = Math.sin((double)(this.entityGuardian.rotationYaw * 0.017453292F));
this.entityGuardian.motionX += d4 * d5;
this.entityGuardian.motionZ += d4 * d6;
d4 = Math.sin((double)(this.entityGuardian.ticksExisted + this.entityGuardian.getEntityId()) * 0.75D) * 0.05D;
this.entityGuardian.motionY += d4 * (d6 + d5) * 0.25D;
this.entityGuardian.motionY += (double)this.entityGuardian.getAIMoveSpeed() * d1 * 0.1D;
EntityLookHelper entitylookhelper = this.entityGuardian.getLookHelper();
double d7 = this.entityGuardian.posX + d0 / d3 * 2.0D;
double d8 = (double)this.entityGuardian.getEyeHeight() + this.entityGuardian.posY + d1 / d3;
double d9 = this.entityGuardian.posZ + d2 / d3 * 2.0D;
double d10 = entitylookhelper.getLookPosX();
double d11 = entitylookhelper.getLookPosY();
double d12 = entitylookhelper.getLookPosZ();
if (!entitylookhelper.getIsLooking())
{
d10 = d7;
d11 = d8;
d12 = d9;
}
this.entityGuardian.getLookHelper().setLookPosition(d10 + (d7 - d10) * 0.125D, d11 + (d8 - d11) * 0.125D, d12 + (d9 - d12) * 0.125D, 10.0F, 40.0F);
this.entityGuardian.setMoving(true);
}
else
{
this.entityGuardian.setAIMoveSpeed(0.0F);
this.entityGuardian.setMoving(false);
}
}
}
static class GuardianTargetSelector implements Predicate<EntityLivingBase>
{
private final EntityGuardian parentEntity;
public GuardianTargetSelector(EntityGuardian guardian)
{
this.parentEntity = guardian;
}
public boolean apply(@Nullable EntityLivingBase p_apply_1_)
{
return (p_apply_1_ instanceof EntityPlayer || p_apply_1_ instanceof EntitySquid) && p_apply_1_.getDistanceSq(this.parentEntity) > 9.0D;
}
}
}

View File

@@ -0,0 +1,87 @@
package net.minecraft.entity.monster;
import javax.annotation.Nullable;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.init.MobEffects;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.ItemStack;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.DamageSource;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootTableList;
public class EntityHusk extends EntityZombie
{
public EntityHusk(World worldIn)
{
super(worldIn);
}
public static void registerFixesHusk(DataFixer fixer)
{
EntityLiving.registerFixesMob(fixer, EntityHusk.class);
}
/**
* Checks if the entity's current position is a valid location to spawn this entity.
*/
public boolean getCanSpawnHere()
{
return super.getCanSpawnHere() && this.world.canSeeSky(new BlockPos(this));
}
protected boolean shouldBurnInDay()
{
return false;
}
protected SoundEvent getAmbientSound()
{
return SoundEvents.ENTITY_HUSK_AMBIENT;
}
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return SoundEvents.ENTITY_HUSK_HURT;
}
protected SoundEvent getDeathSound()
{
return SoundEvents.ENTITY_HUSK_DEATH;
}
protected SoundEvent getStepSound()
{
return SoundEvents.ENTITY_HUSK_STEP;
}
@Nullable
protected ResourceLocation getLootTable()
{
return LootTableList.ENTITIES_HUSK;
}
public boolean attackEntityAsMob(Entity entityIn)
{
boolean flag = super.attackEntityAsMob(entityIn);
if (flag && this.getHeldItemMainhand().isEmpty() && entityIn instanceof EntityLivingBase)
{
float f = this.world.getDifficultyForLocation(new BlockPos(this)).getAdditionalDifficulty();
((EntityLivingBase)entityIn).addPotionEffect(new PotionEffect(MobEffects.HUNGER, 140 * (int)f));
}
return flag;
}
protected ItemStack getSkullDrop()
{
return ItemStack.EMPTY;
}
}

View File

@@ -0,0 +1,390 @@
package net.minecraft.entity.monster;
import javax.annotation.Nullable;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.EnumCreatureAttribute;
import net.minecraft.entity.IEntityLivingData;
import net.minecraft.entity.IRangedAttackMob;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIAttackRangedBow;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAISwimming;
import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.projectile.EntityArrow;
import net.minecraft.entity.projectile.EntityTippedArrow;
import net.minecraft.init.Items;
import net.minecraft.init.MobEffects;
import net.minecraft.init.SoundEvents;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.ItemStack;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.EnumDifficulty;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootTableList;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class EntityIllusionIllager extends EntitySpellcasterIllager implements IRangedAttackMob
{
private int ghostTime;
private final Vec3d[][] renderLocations;
public EntityIllusionIllager(World worldIn)
{
super(worldIn);
this.setSize(0.6F, 1.95F);
this.experienceValue = 5;
this.renderLocations = new Vec3d[2][4];
for (int i = 0; i < 4; ++i)
{
this.renderLocations[0][i] = new Vec3d(0.0D, 0.0D, 0.0D);
this.renderLocations[1][i] = new Vec3d(0.0D, 0.0D, 0.0D);
}
}
protected void initEntityAI()
{
super.initEntityAI();
this.tasks.addTask(0, new EntityAISwimming(this));
this.tasks.addTask(1, new EntitySpellcasterIllager.AICastingApell());
this.tasks.addTask(4, new EntityIllusionIllager.AIMirriorSpell());
this.tasks.addTask(5, new EntityIllusionIllager.AIBlindnessSpell());
this.tasks.addTask(6, new EntityAIAttackRangedBow(this, 0.5D, 20, 15.0F));
this.tasks.addTask(8, new EntityAIWander(this, 0.6D));
this.tasks.addTask(9, new EntityAIWatchClosest(this, EntityPlayer.class, 3.0F, 1.0F));
this.tasks.addTask(10, new EntityAIWatchClosest(this, EntityLiving.class, 8.0F));
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true, new Class[] {EntityIllusionIllager.class}));
this.targetTasks.addTask(2, (new EntityAINearestAttackableTarget(this, EntityPlayer.class, true)).setUnseenMemoryTicks(300));
this.targetTasks.addTask(3, (new EntityAINearestAttackableTarget(this, EntityVillager.class, false)).setUnseenMemoryTicks(300));
this.targetTasks.addTask(3, (new EntityAINearestAttackableTarget(this, EntityIronGolem.class, false)).setUnseenMemoryTicks(300));
}
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.5D);
this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(18.0D);
this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(32.0D);
}
/**
* Called only once on an entity when first time spawned, via egg, mob spawner, natural spawning etc, but not called
* when entity is reloaded from nbt. Mainly used for initializing attributes and inventory
*/
public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, IEntityLivingData livingdata)
{
this.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(Items.BOW));
return super.onInitialSpawn(difficulty, livingdata);
}
protected void entityInit()
{
super.entityInit();
}
protected ResourceLocation getLootTable()
{
return LootTableList.EMPTY;
}
/**
* Gets the bounding box of this Entity, adjusted to take auxiliary entities into account (e.g. the tile contained
* by a minecart, such as a command block).
*/
@SideOnly(Side.CLIENT)
public AxisAlignedBB getRenderBoundingBox()
{
return this.getEntityBoundingBox().grow(3.0D, 0.0D, 3.0D);
}
/**
* 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 && this.isInvisible())
{
--this.ghostTime;
if (this.ghostTime < 0)
{
this.ghostTime = 0;
}
if (this.hurtTime != 1 && this.ticksExisted % 1200 != 0)
{
if (this.hurtTime == this.maxHurtTime - 1)
{
this.ghostTime = 3;
for (int k = 0; k < 4; ++k)
{
this.renderLocations[0][k] = this.renderLocations[1][k];
this.renderLocations[1][k] = new Vec3d(0.0D, 0.0D, 0.0D);
}
}
}
else
{
this.ghostTime = 3;
float f = -6.0F;
int i = 13;
for (int j = 0; j < 4; ++j)
{
this.renderLocations[0][j] = this.renderLocations[1][j];
this.renderLocations[1][j] = new Vec3d((double)(-6.0F + (float)this.rand.nextInt(13)) * 0.5D, (double)Math.max(0, this.rand.nextInt(6) - 4), (double)(-6.0F + (float)this.rand.nextInt(13)) * 0.5D);
}
for (int l = 0; l < 16; ++l)
{
this.world.spawnParticle(EnumParticleTypes.CLOUD, this.posX + (this.rand.nextDouble() - 0.5D) * (double)this.width, this.posY + this.rand.nextDouble() * (double)this.height, this.posZ + (this.rand.nextDouble() - 0.5D) * (double)this.width, 0.0D, 0.0D, 0.0D);
}
this.world.playSound(this.posX, this.posY, this.posZ, SoundEvents.ENTITY_ILLAGER_MIRROR_MOVE, this.getSoundCategory(), 1.0F, 1.0F, false);
}
}
}
@SideOnly(Side.CLIENT)
public Vec3d[] getRenderLocations(float p_193098_1_)
{
if (this.ghostTime <= 0)
{
return this.renderLocations[1];
}
else
{
double d0 = (double)(((float)this.ghostTime - p_193098_1_) / 3.0F);
d0 = Math.pow(d0, 0.25D);
Vec3d[] avec3d = new Vec3d[4];
for (int i = 0; i < 4; ++i)
{
avec3d[i] = this.renderLocations[1][i].scale(1.0D - d0).add(this.renderLocations[0][i].scale(d0));
}
return avec3d;
}
}
/**
* Returns whether this Entity is on the same team as the given Entity.
*/
public boolean isOnSameTeam(Entity entityIn)
{
if (super.isOnSameTeam(entityIn))
{
return true;
}
else if (entityIn instanceof EntityLivingBase && ((EntityLivingBase)entityIn).getCreatureAttribute() == EnumCreatureAttribute.ILLAGER)
{
return this.getTeam() == null && entityIn.getTeam() == null;
}
else
{
return false;
}
}
protected SoundEvent getAmbientSound()
{
return SoundEvents.ENTITY_ILLUSION_ILLAGER_AMBIENT;
}
protected SoundEvent getDeathSound()
{
return SoundEvents.ENTITY_ILLAGER_DEATH;
}
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return SoundEvents.ENTITY_ILLUSION_ILLAGER_HURT;
}
protected SoundEvent getSpellSound()
{
return SoundEvents.ENTITY_ILLAGER_CAST_SPELL;
}
/**
* Attack the specified entity using a ranged attack.
*/
public void attackEntityWithRangedAttack(EntityLivingBase target, float distanceFactor)
{
EntityArrow entityarrow = this.createArrowEntity(distanceFactor);
double d0 = target.posX - this.posX;
double d1 = target.getEntityBoundingBox().minY + (double)(target.height / 3.0F) - entityarrow.posY;
double d2 = target.posZ - this.posZ;
double d3 = (double)MathHelper.sqrt(d0 * d0 + d2 * d2);
entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float)(14 - this.world.getDifficulty().getDifficultyId() * 4));
this.playSound(SoundEvents.ENTITY_SKELETON_SHOOT, 1.0F, 1.0F / (this.getRNG().nextFloat() * 0.4F + 0.8F));
this.world.spawnEntity(entityarrow);
}
protected EntityArrow createArrowEntity(float p_193097_1_)
{
EntityTippedArrow entitytippedarrow = new EntityTippedArrow(this.world, this);
entitytippedarrow.setEnchantmentEffectsFromEntity(this, p_193097_1_);
return entitytippedarrow;
}
@SideOnly(Side.CLIENT)
public boolean isAggressive()
{
return this.isAggressive(1);
}
public void setSwingingArms(boolean swingingArms)
{
this.setAggressive(1, swingingArms);
}
@SideOnly(Side.CLIENT)
public AbstractIllager.IllagerArmPose getArmPose()
{
if (this.isSpellcasting())
{
return AbstractIllager.IllagerArmPose.SPELLCASTING;
}
else
{
return this.isAggressive() ? AbstractIllager.IllagerArmPose.BOW_AND_ARROW : AbstractIllager.IllagerArmPose.CROSSED;
}
}
class AIBlindnessSpell extends EntitySpellcasterIllager.AIUseSpell
{
private int lastTargetId;
private AIBlindnessSpell()
{
super();
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (!super.shouldExecute())
{
return false;
}
else if (EntityIllusionIllager.this.getAttackTarget() == null)
{
return false;
}
else if (EntityIllusionIllager.this.getAttackTarget().getEntityId() == this.lastTargetId)
{
return false;
}
else
{
return EntityIllusionIllager.this.world.getDifficultyForLocation(new BlockPos(EntityIllusionIllager.this)).isHarderThan((float)EnumDifficulty.NORMAL.ordinal());
}
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
super.startExecuting();
this.lastTargetId = EntityIllusionIllager.this.getAttackTarget().getEntityId();
}
protected int getCastingTime()
{
return 20;
}
protected int getCastingInterval()
{
return 180;
}
protected void castSpell()
{
EntityIllusionIllager.this.getAttackTarget().addPotionEffect(new PotionEffect(MobEffects.BLINDNESS, 400));
}
protected SoundEvent getSpellPrepareSound()
{
return SoundEvents.ENTITY_ILLAGER_PREPARE_BLINDNESS;
}
protected EntitySpellcasterIllager.SpellType getSpellType()
{
return EntitySpellcasterIllager.SpellType.BLINDNESS;
}
}
class AIMirriorSpell extends EntitySpellcasterIllager.AIUseSpell
{
private AIMirriorSpell()
{
super();
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (!super.shouldExecute())
{
return false;
}
else
{
return !EntityIllusionIllager.this.isPotionActive(MobEffects.INVISIBILITY);
}
}
protected int getCastingTime()
{
return 20;
}
protected int getCastingInterval()
{
return 340;
}
protected void castSpell()
{
EntityIllusionIllager.this.addPotionEffect(new PotionEffect(MobEffects.INVISIBILITY, 1200));
}
@Nullable
protected SoundEvent getSpellPrepareSound()
{
return SoundEvents.ENTITY_ILLAGER_PREPARE_MIRROR;
}
protected EntitySpellcasterIllager.SpellType getSpellType()
{
return EntitySpellcasterIllager.SpellType.DISAPPEAR;
}
}
}

View File

@@ -0,0 +1,325 @@
package net.minecraft.entity.monster;
import com.google.common.base.Predicate;
import javax.annotation.Nullable;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIAttackMelee;
import net.minecraft.entity.ai.EntityAIDefendVillage;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAILookAtVillager;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAIMoveThroughVillage;
import net.minecraft.entity.ai.EntityAIMoveTowardsRestriction;
import net.minecraft.entity.ai.EntityAIMoveTowardsTarget;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAIWanderAvoidWater;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.SoundEvents;
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.DamageSource;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.village.Village;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootTableList;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class EntityIronGolem extends EntityGolem
{
protected static final DataParameter<Byte> PLAYER_CREATED = EntityDataManager.<Byte>createKey(EntityIronGolem.class, DataSerializers.BYTE);
/** deincrements, and a distance-to-home check is done at 0 */
private int homeCheckTimer;
@Nullable
Village village;
private int attackTimer;
private int holdRoseTick;
public EntityIronGolem(World worldIn)
{
super(worldIn);
this.setSize(1.4F, 2.7F);
}
protected void initEntityAI()
{
this.tasks.addTask(1, new EntityAIAttackMelee(this, 1.0D, true));
this.tasks.addTask(2, new EntityAIMoveTowardsTarget(this, 0.9D, 32.0F));
this.tasks.addTask(3, new EntityAIMoveThroughVillage(this, 0.6D, true));
this.tasks.addTask(4, new EntityAIMoveTowardsRestriction(this, 1.0D));
this.tasks.addTask(5, new EntityAILookAtVillager(this));
this.tasks.addTask(6, new EntityAIWanderAvoidWater(this, 0.6D));
this.tasks.addTask(7, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F));
this.tasks.addTask(8, new EntityAILookIdle(this));
this.targetTasks.addTask(1, new EntityAIDefendVillage(this));
this.targetTasks.addTask(2, new EntityAIHurtByTarget(this, false, new Class[0]));
this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityLiving.class, 10, false, true, new Predicate<EntityLiving>()
{
public boolean apply(@Nullable EntityLiving p_apply_1_)
{
return p_apply_1_ != null && IMob.VISIBLE_MOB_SELECTOR.apply(p_apply_1_) && !(p_apply_1_ instanceof EntityCreeper);
}
}));
}
protected void entityInit()
{
super.entityInit();
this.dataManager.register(PLAYER_CREATED, Byte.valueOf((byte)0));
}
protected void updateAITasks()
{
if (--this.homeCheckTimer <= 0)
{
this.homeCheckTimer = 70 + this.rand.nextInt(50);
this.village = this.world.getVillageCollection().getNearestVillage(new BlockPos(this), 32);
if (this.village == null)
{
this.detachHome();
}
else
{
BlockPos blockpos = this.village.getCenter();
this.setHomePosAndDistance(blockpos, (int)((float)this.village.getVillageRadius() * 0.6F));
}
}
super.updateAITasks();
}
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(100.0D);
this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.25D);
this.getEntityAttribute(SharedMonsterAttributes.KNOCKBACK_RESISTANCE).setBaseValue(1.0D);
}
/**
* Decrements the entity's air supply when underwater
*/
protected int decreaseAirSupply(int air)
{
return air;
}
protected void collideWithEntity(Entity entityIn)
{
if (entityIn instanceof IMob && !(entityIn instanceof EntityCreeper) && this.getRNG().nextInt(20) == 0)
{
this.setAttackTarget((EntityLivingBase)entityIn);
}
super.collideWithEntity(entityIn);
}
/**
* 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.attackTimer > 0)
{
--this.attackTimer;
}
if (this.holdRoseTick > 0)
{
--this.holdRoseTick;
}
if (this.motionX * this.motionX + this.motionZ * this.motionZ > 2.500000277905201E-7D && this.rand.nextInt(5) == 0)
{
int i = MathHelper.floor(this.posX);
int j = MathHelper.floor(this.posY - 0.20000000298023224D);
int k = MathHelper.floor(this.posZ);
IBlockState iblockstate = this.world.getBlockState(new BlockPos(i, j, k));
if (iblockstate.getMaterial() != Material.AIR)
{
this.world.spawnParticle(EnumParticleTypes.BLOCK_CRACK, this.posX + ((double)this.rand.nextFloat() - 0.5D) * (double)this.width, this.getEntityBoundingBox().minY + 0.1D, this.posZ + ((double)this.rand.nextFloat() - 0.5D) * (double)this.width, 4.0D * ((double)this.rand.nextFloat() - 0.5D), 0.5D, ((double)this.rand.nextFloat() - 0.5D) * 4.0D, Block.getStateId(iblockstate));
}
}
}
/**
* Returns true if this entity can attack entities of the specified class.
*/
public boolean canAttackClass(Class <? extends EntityLivingBase > cls)
{
if (this.isPlayerCreated() && EntityPlayer.class.isAssignableFrom(cls))
{
return false;
}
else
{
return cls == EntityCreeper.class ? false : super.canAttackClass(cls);
}
}
public static void registerFixesIronGolem(DataFixer fixer)
{
EntityLiving.registerFixesMob(fixer, EntityIronGolem.class);
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound compound)
{
super.writeEntityToNBT(compound);
compound.setBoolean("PlayerCreated", this.isPlayerCreated());
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound compound)
{
super.readEntityFromNBT(compound);
this.setPlayerCreated(compound.getBoolean("PlayerCreated"));
}
public boolean attackEntityAsMob(Entity entityIn)
{
this.attackTimer = 10;
this.world.setEntityState(this, (byte)4);
boolean flag = entityIn.attackEntityFrom(DamageSource.causeMobDamage(this), (float)(7 + this.rand.nextInt(15)));
if (flag)
{
entityIn.motionY += 0.4000000059604645D;
this.applyEnchantments(this, entityIn);
}
this.playSound(SoundEvents.ENTITY_IRONGOLEM_ATTACK, 1.0F, 1.0F);
return flag;
}
/**
* Handler for {@link World#setEntityState}
*/
@SideOnly(Side.CLIENT)
public void handleStatusUpdate(byte id)
{
if (id == 4)
{
this.attackTimer = 10;
this.playSound(SoundEvents.ENTITY_IRONGOLEM_ATTACK, 1.0F, 1.0F);
}
else if (id == 11)
{
this.holdRoseTick = 400;
}
else if (id == 34)
{
this.holdRoseTick = 0;
}
else
{
super.handleStatusUpdate(id);
}
}
public Village getVillage()
{
return this.village;
}
@SideOnly(Side.CLIENT)
public int getAttackTimer()
{
return this.attackTimer;
}
public void setHoldingRose(boolean p_70851_1_)
{
if (p_70851_1_)
{
this.holdRoseTick = 400;
this.world.setEntityState(this, (byte)11);
}
else
{
this.holdRoseTick = 0;
this.world.setEntityState(this, (byte)34);
}
}
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return SoundEvents.ENTITY_IRONGOLEM_HURT;
}
protected SoundEvent getDeathSound()
{
return SoundEvents.ENTITY_IRONGOLEM_DEATH;
}
protected void playStepSound(BlockPos pos, Block blockIn)
{
this.playSound(SoundEvents.ENTITY_IRONGOLEM_STEP, 1.0F, 1.0F);
}
@Nullable
protected ResourceLocation getLootTable()
{
return LootTableList.ENTITIES_IRON_GOLEM;
}
public int getHoldRoseTick()
{
return this.holdRoseTick;
}
public boolean isPlayerCreated()
{
return (((Byte)this.dataManager.get(PLAYER_CREATED)).byteValue() & 1) != 0;
}
public void setPlayerCreated(boolean playerCreated)
{
byte b0 = ((Byte)this.dataManager.get(PLAYER_CREATED)).byteValue();
if (playerCreated)
{
this.dataManager.set(PLAYER_CREATED, Byte.valueOf((byte)(b0 | 1)));
}
else
{
this.dataManager.set(PLAYER_CREATED, Byte.valueOf((byte)(b0 & -2)));
}
}
/**
* Called when the mob's health reaches 0.
*/
public void onDeath(DamageSource cause)
{
if (!this.isPlayerCreated() && this.attackingPlayer != null && this.village != null)
{
this.village.modifyPlayerReputation(this.attackingPlayer.getUniqueID(), -5);
}
super.onDeath(cause);
}
}

View File

@@ -0,0 +1,165 @@
package net.minecraft.entity.monster;
import javax.annotation.Nullable;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.init.SoundEvents;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.world.EnumDifficulty;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootTableList;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class EntityMagmaCube extends EntitySlime
{
public EntityMagmaCube(World worldIn)
{
super(worldIn);
this.isImmuneToFire = true;
}
public static void registerFixesMagmaCube(DataFixer fixer)
{
EntityLiving.registerFixesMob(fixer, EntityMagmaCube.class);
}
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.20000000298023224D);
}
/**
* Checks if the entity's current position is a valid location to spawn this entity.
*/
public boolean getCanSpawnHere()
{
return this.world.getDifficulty() != EnumDifficulty.PEACEFUL;
}
/**
* Checks that the entity is not colliding with any blocks / liquids
*/
public boolean isNotColliding()
{
return this.world.checkNoEntityCollision(this.getEntityBoundingBox(), this) && this.world.getCollisionBoxes(this, this.getEntityBoundingBox()).isEmpty() && !this.world.containsAnyLiquid(this.getEntityBoundingBox());
}
protected void setSlimeSize(int size, boolean resetHealth)
{
super.setSlimeSize(size, resetHealth);
this.getEntityAttribute(SharedMonsterAttributes.ARMOR).setBaseValue((double)(size * 3));
}
@SideOnly(Side.CLIENT)
public int getBrightnessForRender()
{
return 15728880;
}
/**
* Gets how bright this entity is.
*/
public float getBrightness()
{
return 1.0F;
}
protected EnumParticleTypes getParticleType()
{
return EnumParticleTypes.FLAME;
}
protected EntitySlime createInstance()
{
return new EntityMagmaCube(this.world);
}
@Nullable
protected ResourceLocation getLootTable()
{
return this.isSmallSlime() ? LootTableList.EMPTY : LootTableList.ENTITIES_MAGMA_CUBE;
}
/**
* Returns true if the entity is on fire. Used by render to add the fire effect on rendering.
*/
public boolean isBurning()
{
return false;
}
/**
* Gets the amount of time the slime needs to wait between jumps.
*/
protected int getJumpDelay()
{
return super.getJumpDelay() * 4;
}
protected void alterSquishAmount()
{
this.squishAmount *= 0.9F;
}
/**
* Causes this entity to do an upwards motion (jumping).
*/
protected void jump()
{
this.motionY = (double)(0.42F + (float)this.getSlimeSize() * 0.1F);
this.isAirBorne = true;
net.minecraftforge.common.ForgeHooks.onLivingJump(this);
}
protected void handleJumpLava()
{
this.motionY = (double)(0.22F + (float)this.getSlimeSize() * 0.05F);
this.isAirBorne = true;
}
public void fall(float distance, float damageMultiplier)
{
}
/**
* Indicates weather the slime is able to damage the player (based upon the slime's size)
*/
protected boolean canDamagePlayer()
{
return true;
}
/**
* Gets the amount of damage dealt to the player when "attacked" by the slime.
*/
protected int getAttackStrength()
{
return super.getAttackStrength() + 2;
}
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return this.isSmallSlime() ? SoundEvents.ENTITY_SMALL_MAGMACUBE_HURT : SoundEvents.ENTITY_MAGMACUBE_HURT;
}
protected SoundEvent getDeathSound()
{
return this.isSmallSlime() ? SoundEvents.ENTITY_SMALL_MAGMACUBE_DEATH : SoundEvents.ENTITY_MAGMACUBE_DEATH;
}
protected SoundEvent getSquishSound()
{
return this.isSmallSlime() ? SoundEvents.ENTITY_SMALL_MAGMACUBE_SQUISH : SoundEvents.ENTITY_MAGMACUBE_SQUISH;
}
protected SoundEvent getJumpSound()
{
return SoundEvents.ENTITY_MAGMACUBE_JUMP;
}
}

View File

@@ -0,0 +1,209 @@
package net.minecraft.entity.monster;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Items;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.ItemAxe;
import net.minecraft.item.ItemStack;
import net.minecraft.util.DamageSource;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.EnumDifficulty;
import net.minecraft.world.EnumSkyBlock;
import net.minecraft.world.World;
public abstract class EntityMob extends EntityCreature implements IMob
{
public EntityMob(World worldIn)
{
super(worldIn);
this.experienceValue = 5;
}
public SoundCategory getSoundCategory()
{
return SoundCategory.HOSTILE;
}
/**
* 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()
{
this.updateArmSwingProgress();
float f = this.getBrightness();
if (f > 0.5F)
{
this.idleTime += 2;
}
super.onLivingUpdate();
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
super.onUpdate();
if (!this.world.isRemote && this.world.getDifficulty() == EnumDifficulty.PEACEFUL)
{
this.setDead();
}
}
protected SoundEvent getSwimSound()
{
return SoundEvents.ENTITY_HOSTILE_SWIM;
}
protected SoundEvent getSplashSound()
{
return SoundEvents.ENTITY_HOSTILE_SPLASH;
}
/**
* Called when the entity is attacked.
*/
public boolean attackEntityFrom(DamageSource source, float amount)
{
return this.isEntityInvulnerable(source) ? false : super.attackEntityFrom(source, amount);
}
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return SoundEvents.ENTITY_HOSTILE_HURT;
}
protected SoundEvent getDeathSound()
{
return SoundEvents.ENTITY_HOSTILE_DEATH;
}
protected SoundEvent getFallSound(int heightIn)
{
return heightIn > 4 ? SoundEvents.ENTITY_HOSTILE_BIG_FALL : SoundEvents.ENTITY_HOSTILE_SMALL_FALL;
}
public boolean attackEntityAsMob(Entity entityIn)
{
float f = (float)this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).getAttributeValue();
int i = 0;
if (entityIn instanceof EntityLivingBase)
{
f += EnchantmentHelper.getModifierForCreature(this.getHeldItemMainhand(), ((EntityLivingBase)entityIn).getCreatureAttribute());
i += EnchantmentHelper.getKnockbackModifier(this);
}
boolean flag = entityIn.attackEntityFrom(DamageSource.causeMobDamage(this), f);
if (flag)
{
if (i > 0 && entityIn instanceof EntityLivingBase)
{
((EntityLivingBase)entityIn).knockBack(this, (float)i * 0.5F, (double)MathHelper.sin(this.rotationYaw * 0.017453292F), (double)(-MathHelper.cos(this.rotationYaw * 0.017453292F)));
this.motionX *= 0.6D;
this.motionZ *= 0.6D;
}
int j = EnchantmentHelper.getFireAspectModifier(this);
if (j > 0)
{
entityIn.setFire(j * 4);
}
if (entityIn instanceof EntityPlayer)
{
EntityPlayer entityplayer = (EntityPlayer)entityIn;
ItemStack itemstack = this.getHeldItemMainhand();
ItemStack itemstack1 = entityplayer.isHandActive() ? entityplayer.getActiveItemStack() : ItemStack.EMPTY;
if (!itemstack.isEmpty() && !itemstack1.isEmpty() && itemstack.getItem().canDisableShield(itemstack, itemstack1, entityplayer, this) && itemstack1.getItem().isShield(itemstack1, entityplayer))
{
float f1 = 0.25F + (float)EnchantmentHelper.getEfficiencyModifier(this) * 0.05F;
if (this.rand.nextFloat() < f1)
{
entityplayer.getCooldownTracker().setCooldown(itemstack1.getItem(), 100);
this.world.setEntityState(entityplayer, (byte)30);
}
}
}
this.applyEnchantments(this, entityIn);
}
return flag;
}
public float getBlockPathWeight(BlockPos pos)
{
return 0.5F - this.world.getLightBrightness(pos);
}
/**
* Checks to make sure the light is not too bright where the mob is spawning
*/
protected boolean isValidLightLevel()
{
BlockPos blockpos = new BlockPos(this.posX, this.getEntityBoundingBox().minY, this.posZ);
if (this.world.getLightFor(EnumSkyBlock.SKY, blockpos) > this.rand.nextInt(32))
{
return false;
}
else
{
int i = this.world.getLightFromNeighbors(blockpos);
if (this.world.isThundering())
{
int j = this.world.getSkylightSubtracted();
this.world.setSkylightSubtracted(10);
i = this.world.getLightFromNeighbors(blockpos);
this.world.setSkylightSubtracted(j);
}
return i <= this.rand.nextInt(8);
}
}
/**
* Checks if the entity's current position is a valid location to spawn this entity.
*/
public boolean getCanSpawnHere()
{
return this.world.getDifficulty() != EnumDifficulty.PEACEFUL && this.isValidLightLevel() && super.getCanSpawnHere();
}
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getAttributeMap().registerAttribute(SharedMonsterAttributes.ATTACK_DAMAGE);
}
/**
* Entity won't drop items or experience points if this returns false
*/
protected boolean canDropLoot()
{
return true;
}
public boolean isPreventingPlayerRest(EntityPlayer playerIn)
{
return true;
}
}

View File

@@ -0,0 +1,288 @@
package net.minecraft.entity.monster;
import java.util.UUID;
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.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.entity.ai.attributes.IAttributeInstance;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Items;
import net.minecraft.init.SoundEvents;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.EnumDifficulty;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootTableList;
public class EntityPigZombie extends EntityZombie
{
private static final UUID ATTACK_SPEED_BOOST_MODIFIER_UUID = UUID.fromString("49455A49-7EC5-45BA-B886-3B90B23A1718");
private static final AttributeModifier ATTACK_SPEED_BOOST_MODIFIER = (new AttributeModifier(ATTACK_SPEED_BOOST_MODIFIER_UUID, "Attacking speed boost", 0.05D, 0)).setSaved(false);
/** Above zero if this PigZombie is Angry. */
private int angerLevel;
/** A random delay until this PigZombie next makes a sound. */
private int randomSoundDelay;
private UUID angerTargetUUID;
public EntityPigZombie(World worldIn)
{
super(worldIn);
this.isImmuneToFire = true;
}
/**
* Hint to AI tasks that we were attacked by the passed EntityLivingBase and should retaliate. Is not guaranteed to
* change our actual active target (for example if we are currently busy attacking someone else)
*/
public void setRevengeTarget(@Nullable EntityLivingBase livingBase)
{
super.setRevengeTarget(livingBase);
if (livingBase != null)
{
this.angerTargetUUID = livingBase.getUniqueID();
}
}
protected void applyEntityAI()
{
this.targetTasks.addTask(1, new EntityPigZombie.AIHurtByAggressor(this));
this.targetTasks.addTask(2, new EntityPigZombie.AITargetAggressor(this));
}
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SPAWN_REINFORCEMENTS_CHANCE).setBaseValue(0.0D);
this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.23000000417232513D);
this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(5.0D);
}
protected void updateAITasks()
{
IAttributeInstance iattributeinstance = this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED);
if (this.isAngry())
{
if (!this.isChild() && !iattributeinstance.hasModifier(ATTACK_SPEED_BOOST_MODIFIER))
{
iattributeinstance.applyModifier(ATTACK_SPEED_BOOST_MODIFIER);
}
--this.angerLevel;
}
else if (iattributeinstance.hasModifier(ATTACK_SPEED_BOOST_MODIFIER))
{
iattributeinstance.removeModifier(ATTACK_SPEED_BOOST_MODIFIER);
}
if (this.randomSoundDelay > 0 && --this.randomSoundDelay == 0)
{
this.playSound(SoundEvents.ENTITY_ZOMBIE_PIG_ANGRY, this.getSoundVolume() * 2.0F, ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F) * 1.8F);
}
if (this.angerLevel > 0 && this.angerTargetUUID != null && this.getRevengeTarget() == null)
{
EntityPlayer entityplayer = this.world.getPlayerEntityByUUID(this.angerTargetUUID);
this.setRevengeTarget(entityplayer);
this.attackingPlayer = entityplayer;
this.recentlyHit = this.getRevengeTimer();
}
super.updateAITasks();
}
/**
* Checks if the entity's current position is a valid location to spawn this entity.
*/
public boolean getCanSpawnHere()
{
return this.world.getDifficulty() != EnumDifficulty.PEACEFUL;
}
/**
* Checks that the entity is not colliding with any blocks / liquids
*/
public boolean isNotColliding()
{
return this.world.checkNoEntityCollision(this.getEntityBoundingBox(), this) && this.world.getCollisionBoxes(this, this.getEntityBoundingBox()).isEmpty() && !this.world.containsAnyLiquid(this.getEntityBoundingBox());
}
public static void registerFixesPigZombie(DataFixer fixer)
{
EntityLiving.registerFixesMob(fixer, EntityPigZombie.class);
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound compound)
{
super.writeEntityToNBT(compound);
compound.setShort("Anger", (short)this.angerLevel);
if (this.angerTargetUUID != null)
{
compound.setString("HurtBy", this.angerTargetUUID.toString());
}
else
{
compound.setString("HurtBy", "");
}
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound compound)
{
super.readEntityFromNBT(compound);
this.angerLevel = compound.getShort("Anger");
String s = compound.getString("HurtBy");
if (!s.isEmpty())
{
this.angerTargetUUID = UUID.fromString(s);
EntityPlayer entityplayer = this.world.getPlayerEntityByUUID(this.angerTargetUUID);
this.setRevengeTarget(entityplayer);
if (entityplayer != null)
{
this.attackingPlayer = entityplayer;
this.recentlyHit = this.getRevengeTimer();
}
}
}
/**
* Called when the entity is attacked.
*/
public boolean attackEntityFrom(DamageSource source, float amount)
{
if (this.isEntityInvulnerable(source))
{
return false;
}
else
{
Entity entity = source.getTrueSource();
if (entity instanceof EntityPlayer)
{
this.becomeAngryAt(entity);
}
return super.attackEntityFrom(source, amount);
}
}
/**
* Causes this PigZombie to become angry at the supplied Entity (which will be a player).
*/
private void becomeAngryAt(Entity p_70835_1_)
{
this.angerLevel = 400 + this.rand.nextInt(400);
this.randomSoundDelay = this.rand.nextInt(40);
if (p_70835_1_ instanceof EntityLivingBase)
{
this.setRevengeTarget((EntityLivingBase)p_70835_1_);
}
}
public boolean isAngry()
{
return this.angerLevel > 0;
}
protected SoundEvent getAmbientSound()
{
return SoundEvents.ENTITY_ZOMBIE_PIG_AMBIENT;
}
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return SoundEvents.ENTITY_ZOMBIE_PIG_HURT;
}
protected SoundEvent getDeathSound()
{
return SoundEvents.ENTITY_ZOMBIE_PIG_DEATH;
}
@Nullable
protected ResourceLocation getLootTable()
{
return LootTableList.ENTITIES_ZOMBIE_PIGMAN;
}
public boolean processInteract(EntityPlayer player, EnumHand hand)
{
return false;
}
/**
* Gives armor or weapon for entity based on given DifficultyInstance
*/
protected void setEquipmentBasedOnDifficulty(DifficultyInstance difficulty)
{
this.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(Items.GOLDEN_SWORD));
}
protected ItemStack getSkullDrop()
{
return ItemStack.EMPTY;
}
public boolean isPreventingPlayerRest(EntityPlayer playerIn)
{
return this.isAngry();
}
static class AIHurtByAggressor extends EntityAIHurtByTarget
{
public AIHurtByAggressor(EntityPigZombie p_i45828_1_)
{
super(p_i45828_1_, true);
}
protected void setEntityAttackTarget(EntityCreature creatureIn, EntityLivingBase entityLivingBaseIn)
{
super.setEntityAttackTarget(creatureIn, entityLivingBaseIn);
if (creatureIn instanceof EntityPigZombie)
{
((EntityPigZombie)creatureIn).becomeAngryAt(entityLivingBaseIn);
}
}
}
static class AITargetAggressor extends EntityAINearestAttackableTarget<EntityPlayer>
{
public AITargetAggressor(EntityPigZombie p_i45829_1_)
{
super(p_i45829_1_, EntityPlayer.class, true);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
return ((EntityPigZombie)this.taskOwner).isAngry() && super.shouldExecute();
}
}
}

View File

@@ -0,0 +1,361 @@
package net.minecraft.entity.monster;
import com.google.common.base.Predicate;
import javax.annotation.Nullable;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityAgeable;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.IEntityLivingData;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIAttackMelee;
import net.minecraft.entity.ai.EntityAIFollowParent;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAIPanic;
import net.minecraft.entity.ai.EntityAISwimming;
import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.passive.EntityAnimal;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.ItemStack;
import net.minecraft.network.datasync.DataParameter;
import net.minecraft.network.datasync.DataSerializers;
import net.minecraft.network.datasync.EntityDataManager;
import net.minecraft.util.DamageSource;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootTableList;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class EntityPolarBear extends EntityAnimal
{
private static final DataParameter<Boolean> IS_STANDING = EntityDataManager.<Boolean>createKey(EntityPolarBear.class, DataSerializers.BOOLEAN);
private float clientSideStandAnimation0;
private float clientSideStandAnimation;
private int warningSoundTicks;
public EntityPolarBear(World worldIn)
{
super(worldIn);
this.setSize(1.3F, 1.4F);
}
public EntityAgeable createChild(EntityAgeable ageable)
{
return new EntityPolarBear(this.world);
}
/**
* Checks if the parameter is an item which this animal can be fed to breed it (wheat, carrots or seeds depending on
* the animal type)
*/
public boolean isBreedingItem(ItemStack stack)
{
return false;
}
protected void initEntityAI()
{
super.initEntityAI();
this.tasks.addTask(0, new EntityAISwimming(this));
this.tasks.addTask(1, new EntityPolarBear.AIMeleeAttack());
this.tasks.addTask(1, new EntityPolarBear.AIPanic());
this.tasks.addTask(4, new EntityAIFollowParent(this, 1.25D));
this.tasks.addTask(5, new EntityAIWander(this, 1.0D));
this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F));
this.tasks.addTask(7, new EntityAILookIdle(this));
this.targetTasks.addTask(1, new EntityPolarBear.AIHurtByTarget());
this.targetTasks.addTask(2, new EntityPolarBear.AIAttackPlayer());
}
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(30.0D);
this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(20.0D);
this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.25D);
this.getAttributeMap().registerAttribute(SharedMonsterAttributes.ATTACK_DAMAGE);
this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(6.0D);
}
protected SoundEvent getAmbientSound()
{
return this.isChild() ? SoundEvents.ENTITY_POLAR_BEAR_BABY_AMBIENT : SoundEvents.ENTITY_POLAR_BEAR_AMBIENT;
}
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return SoundEvents.ENTITY_POLAR_BEAR_HURT;
}
protected SoundEvent getDeathSound()
{
return SoundEvents.ENTITY_POLAR_BEAR_DEATH;
}
protected void playStepSound(BlockPos pos, Block blockIn)
{
this.playSound(SoundEvents.ENTITY_POLAR_BEAR_STEP, 0.15F, 1.0F);
}
protected void playWarningSound()
{
if (this.warningSoundTicks <= 0)
{
this.playSound(SoundEvents.ENTITY_POLAR_BEAR_WARNING, 1.0F, 1.0F);
this.warningSoundTicks = 40;
}
}
@Nullable
protected ResourceLocation getLootTable()
{
return LootTableList.ENTITIES_POLAR_BEAR;
}
protected void entityInit()
{
super.entityInit();
this.dataManager.register(IS_STANDING, Boolean.valueOf(false));
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
super.onUpdate();
if (this.world.isRemote)
{
this.clientSideStandAnimation0 = this.clientSideStandAnimation;
if (this.isStanding())
{
this.clientSideStandAnimation = MathHelper.clamp(this.clientSideStandAnimation + 1.0F, 0.0F, 6.0F);
}
else
{
this.clientSideStandAnimation = MathHelper.clamp(this.clientSideStandAnimation - 1.0F, 0.0F, 6.0F);
}
}
if (this.warningSoundTicks > 0)
{
--this.warningSoundTicks;
}
}
public boolean attackEntityAsMob(Entity entityIn)
{
boolean flag = entityIn.attackEntityFrom(DamageSource.causeMobDamage(this), (float)((int)this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).getAttributeValue()));
if (flag)
{
this.applyEnchantments(this, entityIn);
}
return flag;
}
public boolean isStanding()
{
return ((Boolean)this.dataManager.get(IS_STANDING)).booleanValue();
}
public void setStanding(boolean standing)
{
this.dataManager.set(IS_STANDING, Boolean.valueOf(standing));
}
@SideOnly(Side.CLIENT)
public float getStandingAnimationScale(float p_189795_1_)
{
return (this.clientSideStandAnimation0 + (this.clientSideStandAnimation - this.clientSideStandAnimation0) * p_189795_1_) / 6.0F;
}
protected float getWaterSlowDown()
{
return 0.98F;
}
/**
* Called only once on an entity when first time spawned, via egg, mob spawner, natural spawning etc, but not called
* when entity is reloaded from nbt. Mainly used for initializing attributes and inventory
*/
public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, IEntityLivingData livingdata)
{
if (livingdata instanceof EntityPolarBear.GroupData)
{
if (((EntityPolarBear.GroupData)livingdata).madeParent)
{
this.setGrowingAge(-24000);
}
}
else
{
EntityPolarBear.GroupData entitypolarbear$groupdata = new EntityPolarBear.GroupData();
entitypolarbear$groupdata.madeParent = true;
livingdata = entitypolarbear$groupdata;
}
return livingdata;
}
class AIAttackPlayer extends EntityAINearestAttackableTarget<EntityPlayer>
{
public AIAttackPlayer()
{
super(EntityPolarBear.this, EntityPlayer.class, 20, true, true, (Predicate)null);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (EntityPolarBear.this.isChild())
{
return false;
}
else
{
if (super.shouldExecute())
{
for (EntityPolarBear entitypolarbear : EntityPolarBear.this.world.getEntitiesWithinAABB(EntityPolarBear.class, EntityPolarBear.this.getEntityBoundingBox().grow(8.0D, 4.0D, 8.0D)))
{
if (entitypolarbear.isChild())
{
return true;
}
}
}
EntityPolarBear.this.setAttackTarget((EntityLivingBase)null);
return false;
}
}
protected double getTargetDistance()
{
return super.getTargetDistance() * 0.5D;
}
}
class AIHurtByTarget extends EntityAIHurtByTarget
{
public AIHurtByTarget()
{
super(EntityPolarBear.this, false);
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
super.startExecuting();
if (EntityPolarBear.this.isChild())
{
this.alertOthers();
this.resetTask();
}
}
protected void setEntityAttackTarget(EntityCreature creatureIn, EntityLivingBase entityLivingBaseIn)
{
if (creatureIn instanceof EntityPolarBear && !creatureIn.isChild())
{
super.setEntityAttackTarget(creatureIn, entityLivingBaseIn);
}
}
}
class AIMeleeAttack extends EntityAIAttackMelee
{
public AIMeleeAttack()
{
super(EntityPolarBear.this, 1.25D, true);
}
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.attackEntityAsMob(p_190102_1_);
EntityPolarBear.this.setStanding(false);
}
else if (p_190102_2_ <= d0 * 2.0D)
{
if (this.attackTick <= 0)
{
EntityPolarBear.this.setStanding(false);
this.attackTick = 20;
}
if (this.attackTick <= 10)
{
EntityPolarBear.this.setStanding(true);
EntityPolarBear.this.playWarningSound();
}
}
else
{
this.attackTick = 20;
EntityPolarBear.this.setStanding(false);
}
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
EntityPolarBear.this.setStanding(false);
super.resetTask();
}
protected double getAttackReachSqr(EntityLivingBase attackTarget)
{
return (double)(4.0F + attackTarget.width);
}
}
class AIPanic extends EntityAIPanic
{
public AIPanic()
{
super(EntityPolarBear.this, 2.0D);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
return !EntityPolarBear.this.isChild() && !EntityPolarBear.this.isBurning() ? false : super.shouldExecute();
}
}
static class GroupData implements IEntityLivingData
{
public boolean madeParent;
private GroupData()
{
}
}
}

View File

@@ -0,0 +1,903 @@
package net.minecraft.entity.monster;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import java.util.List;
import java.util.UUID;
import javax.annotation.Nullable;
import net.minecraft.block.BlockPistonBase;
import net.minecraft.block.BlockPistonExtension;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityBodyHelper;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.IEntityLivingData;
import net.minecraft.entity.MoverType;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIBase;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.projectile.EntityArrow;
import net.minecraft.entity.projectile.EntityShulkerBullet;
import net.minecraft.init.Blocks;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.EnumDyeColor;
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.DamageSource;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.EnumDifficulty;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootTableList;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class EntityShulker extends EntityGolem implements IMob
{
private static final UUID COVERED_ARMOR_BONUS_ID = UUID.fromString("7E0292F2-9434-48D5-A29F-9583AF7DF27F");
private static final AttributeModifier COVERED_ARMOR_BONUS_MODIFIER = (new AttributeModifier(COVERED_ARMOR_BONUS_ID, "Covered armor bonus", 20.0D, 0)).setSaved(false);
protected static final DataParameter<EnumFacing> ATTACHED_FACE = EntityDataManager.<EnumFacing>createKey(EntityShulker.class, DataSerializers.FACING);
protected static final DataParameter<Optional<BlockPos>> ATTACHED_BLOCK_POS = EntityDataManager.<Optional<BlockPos>>createKey(EntityShulker.class, DataSerializers.OPTIONAL_BLOCK_POS);
protected static final DataParameter<Byte> PEEK_TICK = EntityDataManager.<Byte>createKey(EntityShulker.class, DataSerializers.BYTE);
protected static final DataParameter<Byte> COLOR = EntityDataManager.<Byte>createKey(EntityShulker.class, DataSerializers.BYTE);
public static final EnumDyeColor DEFAULT_COLOR = EnumDyeColor.PURPLE;
private float prevPeekAmount;
private float peekAmount;
private BlockPos currentAttachmentPosition;
private int clientSideTeleportInterpolation;
public EntityShulker(World worldIn)
{
super(worldIn);
this.setSize(1.0F, 1.0F);
this.prevRenderYawOffset = 180.0F;
this.renderYawOffset = 180.0F;
this.isImmuneToFire = true;
this.currentAttachmentPosition = null;
this.experienceValue = 5;
}
/**
* Called only once on an entity when first time spawned, via egg, mob spawner, natural spawning etc, but not called
* when entity is reloaded from nbt. Mainly used for initializing attributes and inventory
*/
@Nullable
public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, @Nullable IEntityLivingData livingdata)
{
this.renderYawOffset = 180.0F;
this.prevRenderYawOffset = 180.0F;
this.rotationYaw = 180.0F;
this.prevRotationYaw = 180.0F;
this.rotationYawHead = 180.0F;
this.prevRotationYawHead = 180.0F;
return super.onInitialSpawn(difficulty, livingdata);
}
protected void initEntityAI()
{
this.tasks.addTask(1, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
this.tasks.addTask(4, new EntityShulker.AIAttack());
this.tasks.addTask(7, new EntityShulker.AIPeek());
this.tasks.addTask(8, new EntityAILookIdle(this));
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true, new Class[0]));
this.targetTasks.addTask(2, new EntityShulker.AIAttackNearest(this));
this.targetTasks.addTask(3, new EntityShulker.AIDefenseAttack(this));
}
/**
* returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to
* prevent them from trampling crops
*/
protected boolean canTriggerWalking()
{
return false;
}
public SoundCategory getSoundCategory()
{
return SoundCategory.HOSTILE;
}
protected SoundEvent getAmbientSound()
{
return SoundEvents.ENTITY_SHULKER_AMBIENT;
}
/**
* Plays living's sound at its position
*/
public void playLivingSound()
{
if (!this.isClosed())
{
super.playLivingSound();
}
}
protected SoundEvent getDeathSound()
{
return SoundEvents.ENTITY_SHULKER_DEATH;
}
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return this.isClosed() ? SoundEvents.ENTITY_SHULKER_HURT_CLOSED : SoundEvents.ENTITY_SHULKER_HURT;
}
protected void entityInit()
{
super.entityInit();
this.dataManager.register(ATTACHED_FACE, EnumFacing.DOWN);
this.dataManager.register(ATTACHED_BLOCK_POS, Optional.absent());
this.dataManager.register(PEEK_TICK, Byte.valueOf((byte)0));
this.dataManager.register(COLOR, Byte.valueOf((byte)DEFAULT_COLOR.getMetadata()));
}
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(30.0D);
}
protected EntityBodyHelper createBodyHelper()
{
return new EntityShulker.BodyHelper(this);
}
public static void registerFixesShulker(DataFixer fixer)
{
EntityLiving.registerFixesMob(fixer, EntityShulker.class);
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound compound)
{
super.readEntityFromNBT(compound);
this.dataManager.set(ATTACHED_FACE, EnumFacing.getFront(compound.getByte("AttachFace")));
this.dataManager.set(PEEK_TICK, Byte.valueOf(compound.getByte("Peek")));
this.dataManager.set(COLOR, Byte.valueOf(compound.getByte("Color")));
if (compound.hasKey("APX"))
{
int i = compound.getInteger("APX");
int j = compound.getInteger("APY");
int k = compound.getInteger("APZ");
this.dataManager.set(ATTACHED_BLOCK_POS, Optional.of(new BlockPos(i, j, k)));
}
else
{
this.dataManager.set(ATTACHED_BLOCK_POS, Optional.absent());
}
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound compound)
{
super.writeEntityToNBT(compound);
compound.setByte("AttachFace", (byte)((EnumFacing)this.dataManager.get(ATTACHED_FACE)).getIndex());
compound.setByte("Peek", ((Byte)this.dataManager.get(PEEK_TICK)).byteValue());
compound.setByte("Color", ((Byte)this.dataManager.get(COLOR)).byteValue());
BlockPos blockpos = this.getAttachmentPos();
if (blockpos != null)
{
compound.setInteger("APX", blockpos.getX());
compound.setInteger("APY", blockpos.getY());
compound.setInteger("APZ", blockpos.getZ());
}
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
super.onUpdate();
BlockPos blockpos = (BlockPos)((Optional)this.dataManager.get(ATTACHED_BLOCK_POS)).orNull();
if (blockpos == null && !this.world.isRemote)
{
blockpos = new BlockPos(this);
this.dataManager.set(ATTACHED_BLOCK_POS, Optional.of(blockpos));
}
if (this.isRiding())
{
blockpos = null;
float f = this.getRidingEntity().rotationYaw;
this.rotationYaw = f;
this.renderYawOffset = f;
this.prevRenderYawOffset = f;
this.clientSideTeleportInterpolation = 0;
}
else if (!this.world.isRemote)
{
IBlockState iblockstate = this.world.getBlockState(blockpos);
if (iblockstate.getMaterial() != Material.AIR)
{
if (iblockstate.getBlock() == Blocks.PISTON_EXTENSION)
{
EnumFacing enumfacing = (EnumFacing)iblockstate.getValue(BlockPistonBase.FACING);
if (this.world.isAirBlock(blockpos.offset(enumfacing)))
{
blockpos = blockpos.offset(enumfacing);
this.dataManager.set(ATTACHED_BLOCK_POS, Optional.of(blockpos));
}
else
{
this.tryTeleportToNewPosition();
}
}
else if (iblockstate.getBlock() == Blocks.PISTON_HEAD)
{
EnumFacing enumfacing3 = (EnumFacing)iblockstate.getValue(BlockPistonExtension.FACING);
if (this.world.isAirBlock(blockpos.offset(enumfacing3)))
{
blockpos = blockpos.offset(enumfacing3);
this.dataManager.set(ATTACHED_BLOCK_POS, Optional.of(blockpos));
}
else
{
this.tryTeleportToNewPosition();
}
}
else
{
this.tryTeleportToNewPosition();
}
}
BlockPos blockpos1 = blockpos.offset(this.getAttachmentFacing());
if (!this.world.isBlockNormalCube(blockpos1, false))
{
boolean flag = false;
for (EnumFacing enumfacing1 : EnumFacing.values())
{
blockpos1 = blockpos.offset(enumfacing1);
if (this.world.isBlockNormalCube(blockpos1, false))
{
this.dataManager.set(ATTACHED_FACE, enumfacing1);
flag = true;
break;
}
}
if (!flag)
{
this.tryTeleportToNewPosition();
}
}
BlockPos blockpos2 = blockpos.offset(this.getAttachmentFacing().getOpposite());
if (this.world.isBlockNormalCube(blockpos2, false))
{
this.tryTeleportToNewPosition();
}
}
float f1 = (float)this.getPeekTick() * 0.01F;
this.prevPeekAmount = this.peekAmount;
if (this.peekAmount > f1)
{
this.peekAmount = MathHelper.clamp(this.peekAmount - 0.05F, f1, 1.0F);
}
else if (this.peekAmount < f1)
{
this.peekAmount = MathHelper.clamp(this.peekAmount + 0.05F, 0.0F, f1);
}
if (blockpos != null)
{
if (this.world.isRemote)
{
if (this.clientSideTeleportInterpolation > 0 && this.currentAttachmentPosition != null)
{
--this.clientSideTeleportInterpolation;
}
else
{
this.currentAttachmentPosition = blockpos;
}
}
this.posX = (double)blockpos.getX() + 0.5D;
this.posY = (double)blockpos.getY();
this.posZ = (double)blockpos.getZ() + 0.5D;
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
this.lastTickPosX = this.posX;
this.lastTickPosY = this.posY;
this.lastTickPosZ = this.posZ;
double d3 = 0.5D - (double)MathHelper.sin((0.5F + this.peekAmount) * (float)Math.PI) * 0.5D;
double d4 = 0.5D - (double)MathHelper.sin((0.5F + this.prevPeekAmount) * (float)Math.PI) * 0.5D;
double d5 = d3 - d4;
double d0 = 0.0D;
double d1 = 0.0D;
double d2 = 0.0D;
EnumFacing enumfacing2 = this.getAttachmentFacing();
switch (enumfacing2)
{
case DOWN:
this.setEntityBoundingBox(new AxisAlignedBB(this.posX - 0.5D, this.posY, this.posZ - 0.5D, this.posX + 0.5D, this.posY + 1.0D + d3, this.posZ + 0.5D));
d1 = d5;
break;
case UP:
this.setEntityBoundingBox(new AxisAlignedBB(this.posX - 0.5D, this.posY - d3, this.posZ - 0.5D, this.posX + 0.5D, this.posY + 1.0D, this.posZ + 0.5D));
d1 = -d5;
break;
case NORTH:
this.setEntityBoundingBox(new AxisAlignedBB(this.posX - 0.5D, this.posY, this.posZ - 0.5D, this.posX + 0.5D, this.posY + 1.0D, this.posZ + 0.5D + d3));
d2 = d5;
break;
case SOUTH:
this.setEntityBoundingBox(new AxisAlignedBB(this.posX - 0.5D, this.posY, this.posZ - 0.5D - d3, this.posX + 0.5D, this.posY + 1.0D, this.posZ + 0.5D));
d2 = -d5;
break;
case WEST:
this.setEntityBoundingBox(new AxisAlignedBB(this.posX - 0.5D, this.posY, this.posZ - 0.5D, this.posX + 0.5D + d3, this.posY + 1.0D, this.posZ + 0.5D));
d0 = d5;
break;
case EAST:
this.setEntityBoundingBox(new AxisAlignedBB(this.posX - 0.5D - d3, this.posY, this.posZ - 0.5D, this.posX + 0.5D, this.posY + 1.0D, this.posZ + 0.5D));
d0 = -d5;
}
if (d5 > 0.0D)
{
List<Entity> list = this.world.getEntitiesWithinAABBExcludingEntity(this, this.getEntityBoundingBox());
if (!list.isEmpty())
{
for (Entity entity : list)
{
if (!(entity instanceof EntityShulker) && !entity.noClip)
{
entity.move(MoverType.SHULKER, d0, d1, d2);
}
}
}
}
}
}
/**
* Tries to move the entity towards the specified location.
*/
public void move(MoverType type, double x, double y, double z)
{
if (type == MoverType.SHULKER_BOX)
{
this.tryTeleportToNewPosition();
}
else
{
super.move(type, x, y, z);
}
}
/**
* 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(x, y, z);
if (this.dataManager != null && this.ticksExisted != 0)
{
Optional<BlockPos> optional = (Optional)this.dataManager.get(ATTACHED_BLOCK_POS);
Optional<BlockPos> optional1 = Optional.<BlockPos>of(new BlockPos(x, y, z));
if (!optional1.equals(optional))
{
this.dataManager.set(ATTACHED_BLOCK_POS, optional1);
this.dataManager.set(PEEK_TICK, Byte.valueOf((byte)0));
this.isAirBorne = true;
}
}
}
protected boolean tryTeleportToNewPosition()
{
if (!this.isAIDisabled() && this.isEntityAlive())
{
BlockPos blockpos = new BlockPos(this);
for (int i = 0; i < 5; ++i)
{
BlockPos blockpos1 = blockpos.add(8 - this.rand.nextInt(17), 8 - this.rand.nextInt(17), 8 - this.rand.nextInt(17));
if (blockpos1.getY() > 0 && this.world.isAirBlock(blockpos1) && this.world.isInsideWorldBorder(this) && this.world.getCollisionBoxes(this, new AxisAlignedBB(blockpos1)).isEmpty())
{
boolean flag = false;
for (EnumFacing enumfacing : EnumFacing.values())
{
if (this.world.isBlockNormalCube(blockpos1.offset(enumfacing), false))
{
this.dataManager.set(ATTACHED_FACE, enumfacing);
flag = true;
break;
}
}
if (flag)
{
net.minecraftforge.event.entity.living.EnderTeleportEvent event = new net.minecraftforge.event.entity.living.EnderTeleportEvent(this, blockpos1.getX(), blockpos1.getY(), blockpos1.getZ(), 0);
if (net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(event)) flag = false;
blockpos1 = new BlockPos(event.getTargetX(), event.getTargetY(), event.getTargetZ());
}
if (flag)
{
this.playSound(SoundEvents.ENTITY_SHULKER_TELEPORT, 1.0F, 1.0F);
this.dataManager.set(ATTACHED_BLOCK_POS, Optional.of(blockpos1));
this.dataManager.set(PEEK_TICK, Byte.valueOf((byte)0));
this.setAttackTarget((EntityLivingBase)null);
return true;
}
}
}
return false;
}
else
{
return true;
}
}
/**
* 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();
this.motionX = 0.0D;
this.motionY = 0.0D;
this.motionZ = 0.0D;
this.prevRenderYawOffset = 180.0F;
this.renderYawOffset = 180.0F;
this.rotationYaw = 180.0F;
}
public void notifyDataManagerChange(DataParameter<?> key)
{
if (ATTACHED_BLOCK_POS.equals(key) && this.world.isRemote && !this.isRiding())
{
BlockPos blockpos = this.getAttachmentPos();
if (blockpos != null)
{
if (this.currentAttachmentPosition == null)
{
this.currentAttachmentPosition = blockpos;
}
else
{
this.clientSideTeleportInterpolation = 6;
}
this.posX = (double)blockpos.getX() + 0.5D;
this.posY = (double)blockpos.getY();
this.posZ = (double)blockpos.getZ() + 0.5D;
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
this.lastTickPosX = this.posX;
this.lastTickPosY = this.posY;
this.lastTickPosZ = this.posZ;
}
}
super.notifyDataManagerChange(key);
}
/**
* Set the position and rotation values directly without any clamping.
*/
@SideOnly(Side.CLIENT)
public void setPositionAndRotationDirect(double x, double y, double z, float yaw, float pitch, int posRotationIncrements, boolean teleport)
{
this.newPosRotationIncrements = 0;
}
/**
* Called when the entity is attacked.
*/
public boolean attackEntityFrom(DamageSource source, float amount)
{
if (this.isClosed())
{
Entity entity = source.getImmediateSource();
if (entity instanceof EntityArrow)
{
return false;
}
}
if (super.attackEntityFrom(source, amount))
{
if ((double)this.getHealth() < (double)this.getMaxHealth() * 0.5D && this.rand.nextInt(4) == 0)
{
this.tryTeleportToNewPosition();
}
return true;
}
else
{
return false;
}
}
private boolean isClosed()
{
return this.getPeekTick() == 0;
}
/**
* Returns the <b>solid</b> collision bounding box for this entity. Used to make (e.g.) boats solid. Return null if
* this entity is not solid.
*
* For general purposes, use {@link #width} and {@link #height}.
*
* @see getEntityBoundingBox
*/
@Nullable
public AxisAlignedBB getCollisionBoundingBox()
{
return this.isEntityAlive() ? this.getEntityBoundingBox() : null;
}
public EnumFacing getAttachmentFacing()
{
return (EnumFacing)this.dataManager.get(ATTACHED_FACE);
}
@Nullable
public BlockPos getAttachmentPos()
{
return (BlockPos)((Optional)this.dataManager.get(ATTACHED_BLOCK_POS)).orNull();
}
public void setAttachmentPos(@Nullable BlockPos pos)
{
this.dataManager.set(ATTACHED_BLOCK_POS, Optional.fromNullable(pos));
}
public int getPeekTick()
{
return ((Byte)this.dataManager.get(PEEK_TICK)).byteValue();
}
/**
* Applies or removes armor modifier
*/
public void updateArmorModifier(int p_184691_1_)
{
if (!this.world.isRemote)
{
this.getEntityAttribute(SharedMonsterAttributes.ARMOR).removeModifier(COVERED_ARMOR_BONUS_MODIFIER);
if (p_184691_1_ == 0)
{
this.getEntityAttribute(SharedMonsterAttributes.ARMOR).applyModifier(COVERED_ARMOR_BONUS_MODIFIER);
this.playSound(SoundEvents.ENTITY_SHULKER_CLOSE, 1.0F, 1.0F);
}
else
{
this.playSound(SoundEvents.ENTITY_SHULKER_OPEN, 1.0F, 1.0F);
}
}
this.dataManager.set(PEEK_TICK, Byte.valueOf((byte)p_184691_1_));
}
@SideOnly(Side.CLIENT)
public float getClientPeekAmount(float p_184688_1_)
{
return this.prevPeekAmount + (this.peekAmount - this.prevPeekAmount) * p_184688_1_;
}
@SideOnly(Side.CLIENT)
public int getClientTeleportInterp()
{
return this.clientSideTeleportInterpolation;
}
@SideOnly(Side.CLIENT)
public BlockPos getOldAttachPos()
{
return this.currentAttachmentPosition;
}
public float getEyeHeight()
{
return 0.5F;
}
/**
* The speed it takes to move the entityliving's rotationPitch through the faceEntity method. This is only currently
* use in wolves.
*/
public int getVerticalFaceSpeed()
{
return 180;
}
public int getHorizontalFaceSpeed()
{
return 180;
}
/**
* Applies a velocity to the entities, to push them away from eachother.
*/
public void applyEntityCollision(Entity entityIn)
{
}
public float getCollisionBorderSize()
{
return 0.0F;
}
@SideOnly(Side.CLIENT)
public boolean isAttachedToBlock()
{
return this.currentAttachmentPosition != null && this.getAttachmentPos() != null;
}
@Nullable
protected ResourceLocation getLootTable()
{
return LootTableList.ENTITIES_SHULKER;
}
@SideOnly(Side.CLIENT)
public EnumDyeColor getColor()
{
return EnumDyeColor.byMetadata(((Byte)this.dataManager.get(COLOR)).byteValue());
}
class AIAttack extends EntityAIBase
{
private int attackTime;
public AIAttack()
{
this.setMutexBits(3);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
EntityLivingBase entitylivingbase = EntityShulker.this.getAttackTarget();
if (entitylivingbase != null && entitylivingbase.isEntityAlive())
{
return EntityShulker.this.world.getDifficulty() != EnumDifficulty.PEACEFUL;
}
else
{
return false;
}
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.attackTime = 20;
EntityShulker.this.updateArmorModifier(100);
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
EntityShulker.this.updateArmorModifier(0);
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
if (EntityShulker.this.world.getDifficulty() != EnumDifficulty.PEACEFUL)
{
--this.attackTime;
EntityLivingBase entitylivingbase = EntityShulker.this.getAttackTarget();
EntityShulker.this.getLookHelper().setLookPositionWithEntity(entitylivingbase, 180.0F, 180.0F);
double d0 = EntityShulker.this.getDistanceSq(entitylivingbase);
if (d0 < 400.0D)
{
if (this.attackTime <= 0)
{
this.attackTime = 20 + EntityShulker.this.rand.nextInt(10) * 20 / 2;
EntityShulkerBullet entityshulkerbullet = new EntityShulkerBullet(EntityShulker.this.world, EntityShulker.this, entitylivingbase, EntityShulker.this.getAttachmentFacing().getAxis());
EntityShulker.this.world.spawnEntity(entityshulkerbullet);
EntityShulker.this.playSound(SoundEvents.ENTITY_SHULKER_SHOOT, 2.0F, (EntityShulker.this.rand.nextFloat() - EntityShulker.this.rand.nextFloat()) * 0.2F + 1.0F);
}
}
else
{
EntityShulker.this.setAttackTarget((EntityLivingBase)null);
}
super.updateTask();
}
}
}
class AIAttackNearest extends EntityAINearestAttackableTarget<EntityPlayer>
{
public AIAttackNearest(EntityShulker shulker)
{
super(shulker, EntityPlayer.class, true);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
return EntityShulker.this.world.getDifficulty() == EnumDifficulty.PEACEFUL ? false : super.shouldExecute();
}
protected AxisAlignedBB getTargetableArea(double targetDistance)
{
EnumFacing enumfacing = ((EntityShulker)this.taskOwner).getAttachmentFacing();
if (enumfacing.getAxis() == EnumFacing.Axis.X)
{
return this.taskOwner.getEntityBoundingBox().grow(4.0D, targetDistance, targetDistance);
}
else
{
return enumfacing.getAxis() == EnumFacing.Axis.Z ? this.taskOwner.getEntityBoundingBox().grow(targetDistance, targetDistance, 4.0D) : this.taskOwner.getEntityBoundingBox().grow(targetDistance, 4.0D, targetDistance);
}
}
}
static class AIDefenseAttack extends EntityAINearestAttackableTarget<EntityLivingBase>
{
public AIDefenseAttack(EntityShulker shulker)
{
super(shulker, EntityLivingBase.class, 10, true, false, new Predicate<EntityLivingBase>()
{
public boolean apply(@Nullable EntityLivingBase p_apply_1_)
{
return p_apply_1_ instanceof IMob;
}
});
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
return this.taskOwner.getTeam() == null ? false : super.shouldExecute();
}
protected AxisAlignedBB getTargetableArea(double targetDistance)
{
EnumFacing enumfacing = ((EntityShulker)this.taskOwner).getAttachmentFacing();
if (enumfacing.getAxis() == EnumFacing.Axis.X)
{
return this.taskOwner.getEntityBoundingBox().grow(4.0D, targetDistance, targetDistance);
}
else
{
return enumfacing.getAxis() == EnumFacing.Axis.Z ? this.taskOwner.getEntityBoundingBox().grow(targetDistance, targetDistance, 4.0D) : this.taskOwner.getEntityBoundingBox().grow(targetDistance, 4.0D, targetDistance);
}
}
}
class AIPeek extends EntityAIBase
{
private int peekTime;
private AIPeek()
{
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
return EntityShulker.this.getAttackTarget() == null && EntityShulker.this.rand.nextInt(40) == 0;
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return EntityShulker.this.getAttackTarget() == null && this.peekTime > 0;
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.peekTime = 20 * (1 + EntityShulker.this.rand.nextInt(3));
EntityShulker.this.updateArmorModifier(30);
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
if (EntityShulker.this.getAttackTarget() == null)
{
EntityShulker.this.updateArmorModifier(0);
}
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
--this.peekTime;
}
}
class BodyHelper extends EntityBodyHelper
{
public BodyHelper(EntityLivingBase theEntity)
{
super(theEntity);
}
/**
* Update the Head and Body rendenring angles
*/
public void updateRenderAngles()
{
}
}
}

View File

@@ -0,0 +1,336 @@
package net.minecraft.entity.monster;
import java.util.Random;
import javax.annotation.Nullable;
import net.minecraft.block.Block;
import net.minecraft.block.BlockSilverfish;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EnumCreatureAttribute;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIAttackMelee;
import net.minecraft.entity.ai.EntityAIBase;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAISwimming;
import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.init.SoundEvents;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EntityDamageSource;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootTableList;
public class EntitySilverfish extends EntityMob
{
private EntitySilverfish.AISummonSilverfish summonSilverfish;
public EntitySilverfish(World worldIn)
{
super(worldIn);
this.setSize(0.4F, 0.3F);
}
public static void registerFixesSilverfish(DataFixer fixer)
{
EntityLiving.registerFixesMob(fixer, EntitySilverfish.class);
}
protected void initEntityAI()
{
this.summonSilverfish = new EntitySilverfish.AISummonSilverfish(this);
this.tasks.addTask(1, new EntityAISwimming(this));
this.tasks.addTask(3, this.summonSilverfish);
this.tasks.addTask(4, new EntityAIAttackMelee(this, 1.0D, false));
this.tasks.addTask(5, new EntitySilverfish.AIHideInStone(this));
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true, new Class[0]));
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityPlayer.class, true));
}
/**
* Returns the Y Offset of this entity.
*/
public double getYOffset()
{
return 0.1D;
}
public float getEyeHeight()
{
return 0.1F;
}
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(8.0D);
this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.25D);
this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(1.0D);
}
/**
* returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to
* prevent them from trampling crops
*/
protected boolean canTriggerWalking()
{
return false;
}
protected SoundEvent getAmbientSound()
{
return SoundEvents.ENTITY_SILVERFISH_AMBIENT;
}
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return SoundEvents.ENTITY_SILVERFISH_HURT;
}
protected SoundEvent getDeathSound()
{
return SoundEvents.ENTITY_SILVERFISH_DEATH;
}
protected void playStepSound(BlockPos pos, Block blockIn)
{
this.playSound(SoundEvents.ENTITY_SILVERFISH_STEP, 0.15F, 1.0F);
}
/**
* Called when the entity is attacked.
*/
public boolean attackEntityFrom(DamageSource source, float amount)
{
if (this.isEntityInvulnerable(source))
{
return false;
}
else
{
if ((source instanceof EntityDamageSource || source == DamageSource.MAGIC) && this.summonSilverfish != null)
{
this.summonSilverfish.notifyHurt();
}
return super.attackEntityFrom(source, amount);
}
}
@Nullable
protected ResourceLocation getLootTable()
{
return LootTableList.ENTITIES_SILVERFISH;
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
this.renderYawOffset = this.rotationYaw;
super.onUpdate();
}
/**
* Set the render yaw offset
*/
public void setRenderYawOffset(float offset)
{
this.rotationYaw = offset;
super.setRenderYawOffset(offset);
}
public float getBlockPathWeight(BlockPos pos)
{
return this.world.getBlockState(pos.down()).getBlock() == Blocks.STONE ? 10.0F : super.getBlockPathWeight(pos);
}
/**
* Checks to make sure the light is not too bright where the mob is spawning
*/
protected boolean isValidLightLevel()
{
return true;
}
/**
* Checks if the entity's current position is a valid location to spawn this entity.
*/
public boolean getCanSpawnHere()
{
if (super.getCanSpawnHere())
{
EntityPlayer entityplayer = this.world.getNearestPlayerNotCreative(this, 5.0D);
return entityplayer == null;
}
else
{
return false;
}
}
/**
* Get this Entity's EnumCreatureAttribute
*/
public EnumCreatureAttribute getCreatureAttribute()
{
return EnumCreatureAttribute.ARTHROPOD;
}
static class AIHideInStone extends EntityAIWander
{
private EnumFacing facing;
private boolean doMerge;
public AIHideInStone(EntitySilverfish silverfishIn)
{
super(silverfishIn, 1.0D, 10);
this.setMutexBits(1);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (this.entity.getAttackTarget() != null)
{
return false;
}
else if (!this.entity.getNavigator().noPath())
{
return false;
}
else
{
Random random = this.entity.getRNG();
if (net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.entity.world, this.entity) && random.nextInt(10) == 0)
{
this.facing = EnumFacing.random(random);
BlockPos blockpos = (new BlockPos(this.entity.posX, this.entity.posY + 0.5D, this.entity.posZ)).offset(this.facing);
IBlockState iblockstate = this.entity.world.getBlockState(blockpos);
if (BlockSilverfish.canContainSilverfish(iblockstate))
{
this.doMerge = true;
return true;
}
}
this.doMerge = false;
return super.shouldExecute();
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return this.doMerge ? false : super.shouldContinueExecuting();
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
if (!this.doMerge)
{
super.startExecuting();
}
else
{
World world = this.entity.world;
BlockPos blockpos = (new BlockPos(this.entity.posX, this.entity.posY + 0.5D, this.entity.posZ)).offset(this.facing);
IBlockState iblockstate = world.getBlockState(blockpos);
if (BlockSilverfish.canContainSilverfish(iblockstate))
{
world.setBlockState(blockpos, Blocks.MONSTER_EGG.getDefaultState().withProperty(BlockSilverfish.VARIANT, BlockSilverfish.EnumType.forModelBlock(iblockstate)), 3);
this.entity.spawnExplosionParticle();
this.entity.setDead();
}
}
}
}
static class AISummonSilverfish extends EntityAIBase
{
private final EntitySilverfish silverfish;
private int lookForFriends;
public AISummonSilverfish(EntitySilverfish silverfishIn)
{
this.silverfish = silverfishIn;
}
public void notifyHurt()
{
if (this.lookForFriends == 0)
{
this.lookForFriends = 20;
}
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
return this.lookForFriends > 0;
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
--this.lookForFriends;
if (this.lookForFriends <= 0)
{
World world = this.silverfish.world;
Random random = this.silverfish.getRNG();
BlockPos blockpos = new BlockPos(this.silverfish);
for (int i = 0; i <= 5 && i >= -5; i = (i <= 0 ? 1 : 0) - i)
{
for (int j = 0; j <= 10 && j >= -10; j = (j <= 0 ? 1 : 0) - j)
{
for (int k = 0; k <= 10 && k >= -10; k = (k <= 0 ? 1 : 0) - k)
{
BlockPos blockpos1 = blockpos.add(j, i, k);
IBlockState iblockstate = world.getBlockState(blockpos1);
if (iblockstate.getBlock() == Blocks.MONSTER_EGG)
{
if (net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(world, this.silverfish))
{
world.destroyBlock(blockpos1, true);
}
else
{
world.setBlockState(blockpos1, ((BlockSilverfish.EnumType)iblockstate.getValue(BlockSilverfish.VARIANT)).getModelBlock(), 3);
}
if (random.nextBoolean())
{
return;
}
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,98 @@
package net.minecraft.entity.monster;
import javax.annotation.Nullable;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.projectile.EntityArrow;
import net.minecraft.entity.projectile.EntitySpectralArrow;
import net.minecraft.entity.projectile.EntityTippedArrow;
import net.minecraft.init.Items;
import net.minecraft.init.SoundEvents;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.ItemStack;
import net.minecraft.util.DamageSource;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootTableList;
public class EntitySkeleton extends AbstractSkeleton
{
public EntitySkeleton(World worldIn)
{
super(worldIn);
}
public static void registerFixesSkeleton(DataFixer fixer)
{
EntityLiving.registerFixesMob(fixer, EntitySkeleton.class);
}
@Nullable
protected ResourceLocation getLootTable()
{
return LootTableList.ENTITIES_SKELETON;
}
protected SoundEvent getAmbientSound()
{
return SoundEvents.ENTITY_SKELETON_AMBIENT;
}
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return SoundEvents.ENTITY_SKELETON_HURT;
}
protected SoundEvent getDeathSound()
{
return SoundEvents.ENTITY_SKELETON_DEATH;
}
protected SoundEvent getStepSound()
{
return SoundEvents.ENTITY_SKELETON_STEP;
}
/**
* Called when the mob's health reaches 0.
*/
public void onDeath(DamageSource cause)
{
super.onDeath(cause);
if (cause.getTrueSource() instanceof EntityCreeper)
{
EntityCreeper entitycreeper = (EntityCreeper)cause.getTrueSource();
if (entitycreeper.getPowered() && entitycreeper.ableToCauseSkullDrop())
{
entitycreeper.incrementDroppedSkulls();
this.entityDropItem(new ItemStack(Items.SKULL, 1, 0), 0.0F);
}
}
}
protected EntityArrow getArrow(float p_190726_1_)
{
ItemStack itemstack = this.getItemStackFromSlot(EntityEquipmentSlot.OFFHAND);
if (itemstack.getItem() == Items.SPECTRAL_ARROW)
{
EntitySpectralArrow entityspectralarrow = new EntitySpectralArrow(this.world, this);
entityspectralarrow.setEnchantmentEffectsFromEntity(this, p_190726_1_);
return entityspectralarrow;
}
else
{
EntityArrow entityarrow = super.getArrow(p_190726_1_);
if (itemstack.getItem() == Items.TIPPED_ARROW && entityarrow instanceof EntityTippedArrow)
{
((EntityTippedArrow)entityarrow).setPotionEffect(itemstack);
}
return entityarrow;
}
}
}

View File

@@ -0,0 +1,676 @@
package net.minecraft.entity.monster;
import javax.annotation.Nullable;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.IEntityLivingData;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIBase;
import net.minecraft.entity.ai.EntityAIFindEntityNearest;
import net.minecraft.entity.ai.EntityAIFindEntityNearestPlayer;
import net.minecraft.entity.ai.EntityMoveHelper;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Biomes;
import net.minecraft.init.Items;
import net.minecraft.init.MobEffects;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.Item;
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.pathfinding.PathNavigateGround;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.EnumDifficulty;
import net.minecraft.world.World;
import net.minecraft.world.WorldType;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.storage.loot.LootTableList;
public class EntitySlime extends EntityLiving implements IMob
{
private static final DataParameter<Integer> SLIME_SIZE = EntityDataManager.<Integer>createKey(EntitySlime.class, DataSerializers.VARINT);
public float squishAmount;
public float squishFactor;
public float prevSquishFactor;
private boolean wasOnGround;
public EntitySlime(World worldIn)
{
super(worldIn);
this.moveHelper = new EntitySlime.SlimeMoveHelper(this);
}
protected void initEntityAI()
{
this.tasks.addTask(1, new EntitySlime.AISlimeFloat(this));
this.tasks.addTask(2, new EntitySlime.AISlimeAttack(this));
this.tasks.addTask(3, new EntitySlime.AISlimeFaceRandom(this));
this.tasks.addTask(5, new EntitySlime.AISlimeHop(this));
this.targetTasks.addTask(1, new EntityAIFindEntityNearestPlayer(this));
this.targetTasks.addTask(3, new EntityAIFindEntityNearest(this, EntityIronGolem.class));
}
protected void entityInit()
{
super.entityInit();
this.dataManager.register(SLIME_SIZE, Integer.valueOf(1));
}
protected void setSlimeSize(int size, boolean resetHealth)
{
this.dataManager.set(SLIME_SIZE, Integer.valueOf(size));
this.setSize(0.51000005F * (float)size, 0.51000005F * (float)size);
this.setPosition(this.posX, this.posY, this.posZ);
this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue((double)(size * size));
this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue((double)(0.2F + 0.1F * (float)size));
if (resetHealth)
{
this.setHealth(this.getMaxHealth());
}
this.experienceValue = size;
}
/**
* Returns the size of the slime.
*/
public int getSlimeSize()
{
return ((Integer)this.dataManager.get(SLIME_SIZE)).intValue();
}
public static void registerFixesSlime(DataFixer fixer)
{
EntityLiving.registerFixesMob(fixer, EntitySlime.class);
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound compound)
{
super.writeEntityToNBT(compound);
compound.setInteger("Size", this.getSlimeSize() - 1);
compound.setBoolean("wasOnGround", this.wasOnGround);
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound compound)
{
super.readEntityFromNBT(compound);
int i = compound.getInteger("Size");
if (i < 0)
{
i = 0;
}
this.setSlimeSize(i + 1, false);
this.wasOnGround = compound.getBoolean("wasOnGround");
}
public boolean isSmallSlime()
{
return this.getSlimeSize() <= 1;
}
protected EnumParticleTypes getParticleType()
{
return EnumParticleTypes.SLIME;
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
if (!this.world.isRemote && this.world.getDifficulty() == EnumDifficulty.PEACEFUL && this.getSlimeSize() > 0)
{
this.isDead = true;
}
this.squishFactor += (this.squishAmount - this.squishFactor) * 0.5F;
this.prevSquishFactor = this.squishFactor;
super.onUpdate();
if (this.onGround && !this.wasOnGround)
{
int i = this.getSlimeSize();
if (spawnCustomParticles()) { i = 0; } // don't spawn particles if it's handled by the implementation itself
for (int j = 0; j < i * 8; ++j)
{
float f = this.rand.nextFloat() * ((float)Math.PI * 2F);
float f1 = this.rand.nextFloat() * 0.5F + 0.5F;
float f2 = MathHelper.sin(f) * (float)i * 0.5F * f1;
float f3 = MathHelper.cos(f) * (float)i * 0.5F * f1;
World world = this.world;
EnumParticleTypes enumparticletypes = this.getParticleType();
double d0 = this.posX + (double)f2;
double d1 = this.posZ + (double)f3;
world.spawnParticle(enumparticletypes, d0, this.getEntityBoundingBox().minY, d1, 0.0D, 0.0D, 0.0D);
}
this.playSound(this.getSquishSound(), this.getSoundVolume(), ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F) / 0.8F);
this.squishAmount = -0.5F;
}
else if (!this.onGround && this.wasOnGround)
{
this.squishAmount = 1.0F;
}
this.wasOnGround = this.onGround;
this.alterSquishAmount();
}
protected void alterSquishAmount()
{
this.squishAmount *= 0.6F;
}
/**
* Gets the amount of time the slime needs to wait between jumps.
*/
protected int getJumpDelay()
{
return this.rand.nextInt(20) + 10;
}
protected EntitySlime createInstance()
{
return new EntitySlime(this.world);
}
public void notifyDataManagerChange(DataParameter<?> key)
{
if (SLIME_SIZE.equals(key))
{
int i = this.getSlimeSize();
this.setSize(0.51000005F * (float)i, 0.51000005F * (float)i);
this.rotationYaw = this.rotationYawHead;
this.renderYawOffset = this.rotationYawHead;
if (this.isInWater() && this.rand.nextInt(20) == 0)
{
this.doWaterSplashEffect();
}
}
super.notifyDataManagerChange(key);
}
/**
* Will get destroyed next tick.
*/
public void setDead()
{
int i = this.getSlimeSize();
if (!this.world.isRemote && i > 1 && this.getHealth() <= 0.0F)
{
int j = 2 + this.rand.nextInt(3);
for (int k = 0; k < j; ++k)
{
float f = ((float)(k % 2) - 0.5F) * (float)i / 4.0F;
float f1 = ((float)(k / 2) - 0.5F) * (float)i / 4.0F;
EntitySlime entityslime = this.createInstance();
if (this.hasCustomName())
{
entityslime.setCustomNameTag(this.getCustomNameTag());
}
if (this.isNoDespawnRequired())
{
entityslime.enablePersistence();
}
entityslime.setSlimeSize(i / 2, true);
entityslime.setLocationAndAngles(this.posX + (double)f, this.posY + 0.5D, this.posZ + (double)f1, this.rand.nextFloat() * 360.0F, 0.0F);
this.world.spawnEntity(entityslime);
}
}
super.setDead();
}
/**
* Applies a velocity to the entities, to push them away from eachother.
*/
public void applyEntityCollision(Entity entityIn)
{
super.applyEntityCollision(entityIn);
if (entityIn instanceof EntityIronGolem && this.canDamagePlayer())
{
this.dealDamage((EntityLivingBase)entityIn);
}
}
/**
* Called by a player entity when they collide with an entity
*/
public void onCollideWithPlayer(EntityPlayer entityIn)
{
if (this.canDamagePlayer())
{
this.dealDamage(entityIn);
}
}
protected void dealDamage(EntityLivingBase entityIn)
{
int i = this.getSlimeSize();
if (this.canEntityBeSeen(entityIn) && this.getDistanceSq(entityIn) < 0.6D * (double)i * 0.6D * (double)i && entityIn.attackEntityFrom(DamageSource.causeMobDamage(this), (float)this.getAttackStrength()))
{
this.playSound(SoundEvents.ENTITY_SLIME_ATTACK, 1.0F, (this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F);
this.applyEnchantments(this, entityIn);
}
}
public float getEyeHeight()
{
return 0.625F * this.height;
}
/**
* Indicates weather the slime is able to damage the player (based upon the slime's size)
*/
protected boolean canDamagePlayer()
{
return !this.isSmallSlime();
}
/**
* Gets the amount of damage dealt to the player when "attacked" by the slime.
*/
protected int getAttackStrength()
{
return this.getSlimeSize();
}
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return this.isSmallSlime() ? SoundEvents.ENTITY_SMALL_SLIME_HURT : SoundEvents.ENTITY_SLIME_HURT;
}
protected SoundEvent getDeathSound()
{
return this.isSmallSlime() ? SoundEvents.ENTITY_SMALL_SLIME_DEATH : SoundEvents.ENTITY_SLIME_DEATH;
}
protected SoundEvent getSquishSound()
{
return this.isSmallSlime() ? SoundEvents.ENTITY_SMALL_SLIME_SQUISH : SoundEvents.ENTITY_SLIME_SQUISH;
}
protected Item getDropItem()
{
return this.getSlimeSize() == 1 ? Items.SLIME_BALL : null;
}
@Nullable
protected ResourceLocation getLootTable()
{
return this.getSlimeSize() == 1 ? LootTableList.ENTITIES_SLIME : LootTableList.EMPTY;
}
/**
* Checks if the entity's current position is a valid location to spawn this entity.
*/
public boolean getCanSpawnHere()
{
BlockPos blockpos = new BlockPos(MathHelper.floor(this.posX), 0, MathHelper.floor(this.posZ));
Chunk chunk = this.world.getChunkFromBlockCoords(blockpos);
if (this.world.getWorldInfo().getTerrainType().handleSlimeSpawnReduction(rand, world))
{
return false;
}
else
{
if (this.world.getDifficulty() != EnumDifficulty.PEACEFUL)
{
Biome biome = this.world.getBiome(blockpos);
if (biome == Biomes.SWAMPLAND && this.posY > 50.0D && this.posY < 70.0D && this.rand.nextFloat() < 0.5F && this.rand.nextFloat() < this.world.getCurrentMoonPhaseFactor() && this.world.getLightFromNeighbors(new BlockPos(this)) <= this.rand.nextInt(8))
{
return super.getCanSpawnHere();
}
if (this.rand.nextInt(10) == 0 && chunk.getRandomWithSeed(987234911L).nextInt(10) == 0 && this.posY < 40.0D)
{
return super.getCanSpawnHere();
}
}
return false;
}
}
/**
* Returns the volume for the sounds this mob makes.
*/
protected float getSoundVolume()
{
return 0.4F * (float)this.getSlimeSize();
}
/**
* The speed it takes to move the entityliving's rotationPitch through the faceEntity method. This is only currently
* use in wolves.
*/
public int getVerticalFaceSpeed()
{
return 0;
}
/**
* Returns true if the slime makes a sound when it jumps (based upon the slime's size)
*/
protected boolean makesSoundOnJump()
{
return this.getSlimeSize() > 0;
}
/**
* Causes this entity to do an upwards motion (jumping).
*/
protected void jump()
{
this.motionY = 0.41999998688697815D;
this.isAirBorne = true;
}
/**
* Called only once on an entity when first time spawned, via egg, mob spawner, natural spawning etc, but not called
* when entity is reloaded from nbt. Mainly used for initializing attributes and inventory
*/
@Nullable
public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, @Nullable IEntityLivingData livingdata)
{
int i = this.rand.nextInt(3);
if (i < 2 && this.rand.nextFloat() < 0.5F * difficulty.getClampedAdditionalDifficulty())
{
++i;
}
int j = 1 << i;
this.setSlimeSize(j, true);
return super.onInitialSpawn(difficulty, livingdata);
}
protected SoundEvent getJumpSound()
{
return this.isSmallSlime() ? SoundEvents.ENTITY_SMALL_SLIME_JUMP : SoundEvents.ENTITY_SLIME_JUMP;
}
/* ======================================== FORGE START =====================================*/
/**
* Called when the slime spawns particles on landing, see onUpdate.
* Return true to prevent the spawning of the default particles.
*/
protected boolean spawnCustomParticles() { return false; }
/* ======================================== FORGE END =====================================*/
static class AISlimeAttack extends EntityAIBase
{
private final EntitySlime slime;
private int growTieredTimer;
public AISlimeAttack(EntitySlime slimeIn)
{
this.slime = slimeIn;
this.setMutexBits(2);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
EntityLivingBase entitylivingbase = this.slime.getAttackTarget();
if (entitylivingbase == null)
{
return false;
}
else if (!entitylivingbase.isEntityAlive())
{
return false;
}
else
{
return !(entitylivingbase instanceof EntityPlayer) || !((EntityPlayer)entitylivingbase).capabilities.disableDamage;
}
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.growTieredTimer = 300;
super.startExecuting();
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
EntityLivingBase entitylivingbase = this.slime.getAttackTarget();
if (entitylivingbase == null)
{
return false;
}
else if (!entitylivingbase.isEntityAlive())
{
return false;
}
else if (entitylivingbase instanceof EntityPlayer && ((EntityPlayer)entitylivingbase).capabilities.disableDamage)
{
return false;
}
else
{
return --this.growTieredTimer > 0;
}
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
this.slime.faceEntity(this.slime.getAttackTarget(), 10.0F, 10.0F);
((EntitySlime.SlimeMoveHelper)this.slime.getMoveHelper()).setDirection(this.slime.rotationYaw, this.slime.canDamagePlayer());
}
}
static class AISlimeFaceRandom extends EntityAIBase
{
private final EntitySlime slime;
private float chosenDegrees;
private int nextRandomizeTime;
public AISlimeFaceRandom(EntitySlime slimeIn)
{
this.slime = slimeIn;
this.setMutexBits(2);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
return this.slime.getAttackTarget() == null && (this.slime.onGround || this.slime.isInWater() || this.slime.isInLava() || this.slime.isPotionActive(MobEffects.LEVITATION));
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
if (--this.nextRandomizeTime <= 0)
{
this.nextRandomizeTime = 40 + this.slime.getRNG().nextInt(60);
this.chosenDegrees = (float)this.slime.getRNG().nextInt(360);
}
((EntitySlime.SlimeMoveHelper)this.slime.getMoveHelper()).setDirection(this.chosenDegrees, false);
}
}
static class AISlimeFloat extends EntityAIBase
{
private final EntitySlime slime;
public AISlimeFloat(EntitySlime slimeIn)
{
this.slime = slimeIn;
this.setMutexBits(5);
((PathNavigateGround)slimeIn.getNavigator()).setCanSwim(true);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
return this.slime.isInWater() || this.slime.isInLava();
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
if (this.slime.getRNG().nextFloat() < 0.8F)
{
this.slime.getJumpHelper().setJumping();
}
((EntitySlime.SlimeMoveHelper)this.slime.getMoveHelper()).setSpeed(1.2D);
}
}
static class AISlimeHop extends EntityAIBase
{
private final EntitySlime slime;
public AISlimeHop(EntitySlime slimeIn)
{
this.slime = slimeIn;
this.setMutexBits(5);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
return true;
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
((EntitySlime.SlimeMoveHelper)this.slime.getMoveHelper()).setSpeed(1.0D);
}
}
static class SlimeMoveHelper extends EntityMoveHelper
{
private float yRot;
private int jumpDelay;
private final EntitySlime slime;
private boolean isAggressive;
public SlimeMoveHelper(EntitySlime slimeIn)
{
super(slimeIn);
this.slime = slimeIn;
this.yRot = 180.0F * slimeIn.rotationYaw / (float)Math.PI;
}
public void setDirection(float p_179920_1_, boolean p_179920_2_)
{
this.yRot = p_179920_1_;
this.isAggressive = p_179920_2_;
}
public void setSpeed(double speedIn)
{
this.speed = speedIn;
this.action = EntityMoveHelper.Action.MOVE_TO;
}
public void onUpdateMoveHelper()
{
this.entity.rotationYaw = this.limitAngle(this.entity.rotationYaw, this.yRot, 90.0F);
this.entity.rotationYawHead = this.entity.rotationYaw;
this.entity.renderYawOffset = this.entity.rotationYaw;
if (this.action != EntityMoveHelper.Action.MOVE_TO)
{
this.entity.setMoveForward(0.0F);
}
else
{
this.action = EntityMoveHelper.Action.WAIT;
if (this.entity.onGround)
{
this.entity.setAIMoveSpeed((float)(this.speed * this.entity.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).getAttributeValue()));
if (this.jumpDelay-- <= 0)
{
this.jumpDelay = this.slime.getJumpDelay();
if (this.isAggressive)
{
this.jumpDelay /= 3;
}
this.slime.getJumpHelper().setJumping();
if (this.slime.makesSoundOnJump())
{
this.slime.playSound(this.slime.getJumpSound(), this.slime.getSoundVolume(), ((this.slime.getRNG().nextFloat() - this.slime.getRNG().nextFloat()) * 0.2F + 1.0F) * 0.8F);
}
}
else
{
this.slime.moveStrafing = 0.0F;
this.slime.moveForward = 0.0F;
this.entity.setAIMoveSpeed(0.0F);
}
}
else
{
this.entity.setAIMoveSpeed((float)(this.speed * this.entity.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).getAttributeValue()));
}
}
}
}
}

View File

@@ -0,0 +1,225 @@
package net.minecraft.entity.monster;
import javax.annotation.Nullable;
import net.minecraft.block.material.Material;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.IRangedAttackMob;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIAttackRanged;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAIWanderAvoidWater;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.projectile.EntitySnowball;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.init.SoundEvents;
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.DamageSource;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootTableList;
public class EntitySnowman extends EntityGolem implements IRangedAttackMob, net.minecraftforge.common.IShearable
{
private static final DataParameter<Byte> PUMPKIN_EQUIPPED = EntityDataManager.<Byte>createKey(EntitySnowman.class, DataSerializers.BYTE);
public EntitySnowman(World worldIn)
{
super(worldIn);
this.setSize(0.7F, 1.9F);
}
public static void registerFixesSnowman(DataFixer fixer)
{
EntityLiving.registerFixesMob(fixer, EntitySnowman.class);
}
protected void initEntityAI()
{
this.tasks.addTask(1, new EntityAIAttackRanged(this, 1.25D, 20, 10.0F));
this.tasks.addTask(2, new EntityAIWanderAvoidWater(this, 1.0D, 1.0000001E-5F));
this.tasks.addTask(3, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F));
this.tasks.addTask(4, new EntityAILookIdle(this));
this.targetTasks.addTask(1, new EntityAINearestAttackableTarget(this, EntityLiving.class, 10, true, false, IMob.MOB_SELECTOR));
}
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(4.0D);
this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.20000000298023224D);
}
protected void entityInit()
{
super.entityInit();
this.dataManager.register(PUMPKIN_EQUIPPED, Byte.valueOf((byte)16));
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound compound)
{
super.writeEntityToNBT(compound);
compound.setBoolean("Pumpkin", this.isPumpkinEquipped());
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound compound)
{
super.readEntityFromNBT(compound);
if (compound.hasKey("Pumpkin"))
{
this.setPumpkinEquipped(compound.getBoolean("Pumpkin"));
}
}
/**
* 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)
{
int i = MathHelper.floor(this.posX);
int j = MathHelper.floor(this.posY);
int k = MathHelper.floor(this.posZ);
if (this.isWet())
{
this.attackEntityFrom(DamageSource.DROWN, 1.0F);
}
if (this.world.getBiome(new BlockPos(i, 0, k)).getTemperature(new BlockPos(i, j, k)) > 1.0F)
{
this.attackEntityFrom(DamageSource.ON_FIRE, 1.0F);
}
if (!net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.world, this))
{
return;
}
for (int l = 0; l < 4; ++l)
{
i = MathHelper.floor(this.posX + (double)((float)(l % 2 * 2 - 1) * 0.25F));
j = MathHelper.floor(this.posY);
k = MathHelper.floor(this.posZ + (double)((float)(l / 2 % 2 * 2 - 1) * 0.25F));
BlockPos blockpos = new BlockPos(i, j, k);
if (this.world.getBlockState(blockpos).getMaterial() == Material.AIR && this.world.getBiome(blockpos).getTemperature(blockpos) < 0.8F && Blocks.SNOW_LAYER.canPlaceBlockAt(this.world, blockpos))
{
this.world.setBlockState(blockpos, Blocks.SNOW_LAYER.getDefaultState());
}
}
}
}
@Nullable
protected ResourceLocation getLootTable()
{
return LootTableList.ENTITIES_SNOWMAN;
}
/**
* Attack the specified entity using a ranged attack.
*/
public void attackEntityWithRangedAttack(EntityLivingBase target, float distanceFactor)
{
EntitySnowball entitysnowball = new EntitySnowball(this.world, this);
double d0 = target.posY + (double)target.getEyeHeight() - 1.100000023841858D;
double d1 = target.posX - this.posX;
double d2 = d0 - entitysnowball.posY;
double d3 = target.posZ - this.posZ;
float f = MathHelper.sqrt(d1 * d1 + d3 * d3) * 0.2F;
entitysnowball.shoot(d1, d2 + (double)f, d3, 1.6F, 12.0F);
this.playSound(SoundEvents.ENTITY_SNOWMAN_SHOOT, 1.0F, 1.0F / (this.getRNG().nextFloat() * 0.4F + 0.8F));
this.world.spawnEntity(entitysnowball);
}
public float getEyeHeight()
{
return 1.7F;
}
protected boolean processInteract(EntityPlayer player, EnumHand hand)
{
ItemStack itemstack = player.getHeldItem(hand);
if (false && itemstack.getItem() == Items.SHEARS && this.isPumpkinEquipped() && !this.world.isRemote) //Forge: Moved to onSheared
{
this.setPumpkinEquipped(false);
itemstack.damageItem(1, player);
}
return super.processInteract(player, hand);
}
public boolean isPumpkinEquipped()
{
return (((Byte)this.dataManager.get(PUMPKIN_EQUIPPED)).byteValue() & 16) != 0;
}
public void setPumpkinEquipped(boolean pumpkinEquipped)
{
byte b0 = ((Byte)this.dataManager.get(PUMPKIN_EQUIPPED)).byteValue();
if (pumpkinEquipped)
{
this.dataManager.set(PUMPKIN_EQUIPPED, Byte.valueOf((byte)(b0 | 16)));
}
else
{
this.dataManager.set(PUMPKIN_EQUIPPED, Byte.valueOf((byte)(b0 & -17)));
}
}
@Nullable
protected SoundEvent getAmbientSound()
{
return SoundEvents.ENTITY_SNOWMAN_AMBIENT;
}
@Nullable
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return SoundEvents.ENTITY_SNOWMAN_HURT;
}
@Nullable
protected SoundEvent getDeathSound()
{
return SoundEvents.ENTITY_SNOWMAN_DEATH;
}
@Override public boolean isShearable(ItemStack item, net.minecraft.world.IBlockAccess world, BlockPos pos) { return this.isPumpkinEquipped(); }
@Override
public java.util.List<ItemStack> onSheared(ItemStack item, net.minecraft.world.IBlockAccess world, BlockPos pos, int fortune)
{
this.setPumpkinEquipped(false);
return com.google.common.collect.Lists.newArrayList();
}
public void setSwingingArms(boolean swingingArms)
{
}
}

View File

@@ -0,0 +1,276 @@
package net.minecraft.entity.monster;
import javax.annotation.Nullable;
import net.minecraft.entity.ai.EntityAIBase;
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.EnumParticleTypes;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public abstract class EntitySpellcasterIllager extends AbstractIllager
{
private static final DataParameter<Byte> SPELL = EntityDataManager.<Byte>createKey(EntitySpellcasterIllager.class, DataSerializers.BYTE);
protected int spellTicks;
private EntitySpellcasterIllager.SpellType activeSpell = EntitySpellcasterIllager.SpellType.NONE;
public EntitySpellcasterIllager(World p_i47506_1_)
{
super(p_i47506_1_);
}
protected void entityInit()
{
super.entityInit();
this.dataManager.register(SPELL, Byte.valueOf((byte)0));
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound compound)
{
super.readEntityFromNBT(compound);
this.spellTicks = compound.getInteger("SpellTicks");
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound compound)
{
super.writeEntityToNBT(compound);
compound.setInteger("SpellTicks", this.spellTicks);
}
@SideOnly(Side.CLIENT)
public AbstractIllager.IllagerArmPose getArmPose()
{
return this.isSpellcasting() ? AbstractIllager.IllagerArmPose.SPELLCASTING : AbstractIllager.IllagerArmPose.CROSSED;
}
public boolean isSpellcasting()
{
if (this.world.isRemote)
{
return ((Byte)this.dataManager.get(SPELL)).byteValue() > 0;
}
else
{
return this.spellTicks > 0;
}
}
public void setSpellType(EntitySpellcasterIllager.SpellType spellType)
{
this.activeSpell = spellType;
this.dataManager.set(SPELL, Byte.valueOf((byte)spellType.id));
}
protected EntitySpellcasterIllager.SpellType getSpellType()
{
return !this.world.isRemote ? this.activeSpell : EntitySpellcasterIllager.SpellType.getFromId(((Byte)this.dataManager.get(SPELL)).byteValue());
}
protected void updateAITasks()
{
super.updateAITasks();
if (this.spellTicks > 0)
{
--this.spellTicks;
}
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
super.onUpdate();
if (this.world.isRemote && this.isSpellcasting())
{
EntitySpellcasterIllager.SpellType entityspellcasterillager$spelltype = this.getSpellType();
double d0 = entityspellcasterillager$spelltype.particleSpeed[0];
double d1 = entityspellcasterillager$spelltype.particleSpeed[1];
double d2 = entityspellcasterillager$spelltype.particleSpeed[2];
float f = this.renderYawOffset * 0.017453292F + MathHelper.cos((float)this.ticksExisted * 0.6662F) * 0.25F;
float f1 = MathHelper.cos(f);
float f2 = MathHelper.sin(f);
this.world.spawnParticle(EnumParticleTypes.SPELL_MOB, this.posX + (double)f1 * 0.6D, this.posY + 1.8D, this.posZ + (double)f2 * 0.6D, d0, d1, d2);
this.world.spawnParticle(EnumParticleTypes.SPELL_MOB, this.posX - (double)f1 * 0.6D, this.posY + 1.8D, this.posZ - (double)f2 * 0.6D, d0, d1, d2);
}
}
protected int getSpellTicks()
{
return this.spellTicks;
}
protected abstract SoundEvent getSpellSound();
public class AICastingApell extends EntityAIBase
{
public AICastingApell()
{
this.setMutexBits(3);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
return EntitySpellcasterIllager.this.getSpellTicks() > 0;
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
super.startExecuting();
EntitySpellcasterIllager.this.navigator.clearPath();
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
super.resetTask();
EntitySpellcasterIllager.this.setSpellType(EntitySpellcasterIllager.SpellType.NONE);
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
if (EntitySpellcasterIllager.this.getAttackTarget() != null)
{
EntitySpellcasterIllager.this.getLookHelper().setLookPositionWithEntity(EntitySpellcasterIllager.this.getAttackTarget(), (float)EntitySpellcasterIllager.this.getHorizontalFaceSpeed(), (float)EntitySpellcasterIllager.this.getVerticalFaceSpeed());
}
}
}
public abstract class AIUseSpell extends EntityAIBase
{
protected int spellWarmup;
protected int spellCooldown;
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (EntitySpellcasterIllager.this.getAttackTarget() == null)
{
return false;
}
else if (EntitySpellcasterIllager.this.isSpellcasting())
{
return false;
}
else
{
return EntitySpellcasterIllager.this.ticksExisted >= this.spellCooldown;
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return EntitySpellcasterIllager.this.getAttackTarget() != null && this.spellWarmup > 0;
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
this.spellWarmup = this.getCastWarmupTime();
EntitySpellcasterIllager.this.spellTicks = this.getCastingTime();
this.spellCooldown = EntitySpellcasterIllager.this.ticksExisted + this.getCastingInterval();
SoundEvent soundevent = this.getSpellPrepareSound();
if (soundevent != null)
{
EntitySpellcasterIllager.this.playSound(soundevent, 1.0F, 1.0F);
}
EntitySpellcasterIllager.this.setSpellType(this.getSpellType());
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
--this.spellWarmup;
if (this.spellWarmup == 0)
{
this.castSpell();
EntitySpellcasterIllager.this.playSound(EntitySpellcasterIllager.this.getSpellSound(), 1.0F, 1.0F);
}
}
protected abstract void castSpell();
protected int getCastWarmupTime()
{
return 20;
}
protected abstract int getCastingTime();
protected abstract int getCastingInterval();
@Nullable
protected abstract SoundEvent getSpellPrepareSound();
protected abstract EntitySpellcasterIllager.SpellType getSpellType();
}
public static enum SpellType
{
NONE(0, 0.0D, 0.0D, 0.0D),
SUMMON_VEX(1, 0.7D, 0.7D, 0.8D),
FANGS(2, 0.4D, 0.3D, 0.35D),
WOLOLO(3, 0.7D, 0.5D, 0.2D),
DISAPPEAR(4, 0.3D, 0.3D, 0.8D),
BLINDNESS(5, 0.1D, 0.1D, 0.2D);
private final int id;
/** Particle motion speed. An array with 3 values: x, y, and z. */
private final double[] particleSpeed;
private SpellType(int idIn, double xParticleSpeed, double yParticleSpeed, double zParticleSpeed)
{
this.id = idIn;
this.particleSpeed = new double[] {xParticleSpeed, yParticleSpeed, zParticleSpeed};
}
public static EntitySpellcasterIllager.SpellType getFromId(int idIn)
{
for (EntitySpellcasterIllager.SpellType entityspellcasterillager$spelltype : values())
{
if (idIn == entityspellcasterillager$spelltype.id)
{
return entityspellcasterillager$spelltype;
}
}
return NONE;
}
}
}

View File

@@ -0,0 +1,313 @@
package net.minecraft.entity.monster;
import java.util.Random;
import javax.annotation.Nullable;
import net.minecraft.block.Block;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.EnumCreatureAttribute;
import net.minecraft.entity.IEntityLivingData;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIAttackMelee;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAILeapAtTarget;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAISwimming;
import net.minecraft.entity.ai.EntityAIWanderAvoidWater;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.MobEffects;
import net.minecraft.init.SoundEvents;
import net.minecraft.network.datasync.DataParameter;
import net.minecraft.network.datasync.DataSerializers;
import net.minecraft.network.datasync.EntityDataManager;
import net.minecraft.pathfinding.PathNavigate;
import net.minecraft.pathfinding.PathNavigateClimber;
import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.DamageSource;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.EnumDifficulty;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootTableList;
public class EntitySpider extends EntityMob
{
private static final DataParameter<Byte> CLIMBING = EntityDataManager.<Byte>createKey(EntitySpider.class, DataSerializers.BYTE);
public EntitySpider(World worldIn)
{
super(worldIn);
this.setSize(1.4F, 0.9F);
}
public static void registerFixesSpider(DataFixer fixer)
{
EntityLiving.registerFixesMob(fixer, EntitySpider.class);
}
protected void initEntityAI()
{
this.tasks.addTask(1, new EntityAISwimming(this));
this.tasks.addTask(3, new EntityAILeapAtTarget(this, 0.4F));
this.tasks.addTask(4, new EntitySpider.AISpiderAttack(this));
this.tasks.addTask(5, new EntityAIWanderAvoidWater(this, 0.8D));
this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
this.tasks.addTask(6, new EntityAILookIdle(this));
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false, new Class[0]));
this.targetTasks.addTask(2, new EntitySpider.AISpiderTarget(this, EntityPlayer.class));
this.targetTasks.addTask(3, new EntitySpider.AISpiderTarget(this, EntityIronGolem.class));
}
/**
* Returns the Y offset from the entity's position for any entity riding this one.
*/
public double getMountedYOffset()
{
return (double)(this.height * 0.5F);
}
/**
* Returns new PathNavigateGround instance
*/
protected PathNavigate createNavigator(World worldIn)
{
return new PathNavigateClimber(this, worldIn);
}
protected void entityInit()
{
super.entityInit();
this.dataManager.register(CLIMBING, Byte.valueOf((byte)0));
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
super.onUpdate();
if (!this.world.isRemote)
{
this.setBesideClimbableBlock(this.collidedHorizontally);
}
}
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(16.0D);
this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.30000001192092896D);
}
protected SoundEvent getAmbientSound()
{
return SoundEvents.ENTITY_SPIDER_AMBIENT;
}
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return SoundEvents.ENTITY_SPIDER_HURT;
}
protected SoundEvent getDeathSound()
{
return SoundEvents.ENTITY_SPIDER_DEATH;
}
protected void playStepSound(BlockPos pos, Block blockIn)
{
this.playSound(SoundEvents.ENTITY_SPIDER_STEP, 0.15F, 1.0F);
}
@Nullable
protected ResourceLocation getLootTable()
{
return LootTableList.ENTITIES_SPIDER;
}
/**
* 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 this.isBesideClimbableBlock();
}
/**
* Sets the Entity inside a web block.
*/
public void setInWeb()
{
}
/**
* Get this Entity's EnumCreatureAttribute
*/
public EnumCreatureAttribute getCreatureAttribute()
{
return EnumCreatureAttribute.ARTHROPOD;
}
public boolean isPotionApplicable(PotionEffect potioneffectIn)
{
return potioneffectIn.getPotion() == MobEffects.POISON ? false : super.isPotionApplicable(potioneffectIn);
}
/**
* Returns true if the WatchableObject (Byte) is 0x01 otherwise returns false. The WatchableObject is updated using
* setBesideClimableBlock.
*/
public boolean isBesideClimbableBlock()
{
return (((Byte)this.dataManager.get(CLIMBING)).byteValue() & 1) != 0;
}
/**
* Updates the WatchableObject (Byte) created in entityInit(), setting it to 0x01 if par1 is true or 0x00 if it is
* false.
*/
public void setBesideClimbableBlock(boolean climbing)
{
byte b0 = ((Byte)this.dataManager.get(CLIMBING)).byteValue();
if (climbing)
{
b0 = (byte)(b0 | 1);
}
else
{
b0 = (byte)(b0 & -2);
}
this.dataManager.set(CLIMBING, Byte.valueOf(b0));
}
/**
* Called only once on an entity when first time spawned, via egg, mob spawner, natural spawning etc, but not called
* when entity is reloaded from nbt. Mainly used for initializing attributes and inventory
*/
@Nullable
public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, @Nullable IEntityLivingData livingdata)
{
livingdata = super.onInitialSpawn(difficulty, livingdata);
if (this.world.rand.nextInt(100) == 0)
{
EntitySkeleton entityskeleton = new EntitySkeleton(this.world);
entityskeleton.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotationYaw, 0.0F);
entityskeleton.onInitialSpawn(difficulty, (IEntityLivingData)null);
this.world.spawnEntity(entityskeleton);
entityskeleton.startRiding(this);
}
if (livingdata == null)
{
livingdata = new EntitySpider.GroupData();
if (this.world.getDifficulty() == EnumDifficulty.HARD && this.world.rand.nextFloat() < 0.1F * difficulty.getClampedAdditionalDifficulty())
{
((EntitySpider.GroupData)livingdata).setRandomEffect(this.world.rand);
}
}
if (livingdata instanceof EntitySpider.GroupData)
{
Potion potion = ((EntitySpider.GroupData)livingdata).effect;
if (potion != null)
{
this.addPotionEffect(new PotionEffect(potion, Integer.MAX_VALUE));
}
}
return livingdata;
}
public float getEyeHeight()
{
return 0.65F;
}
static class AISpiderAttack extends EntityAIAttackMelee
{
public AISpiderAttack(EntitySpider spider)
{
super(spider, 1.0D, true);
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
float f = this.attacker.getBrightness();
if (f >= 0.5F && this.attacker.getRNG().nextInt(100) == 0)
{
this.attacker.setAttackTarget((EntityLivingBase)null);
return false;
}
else
{
return super.shouldContinueExecuting();
}
}
protected double getAttackReachSqr(EntityLivingBase attackTarget)
{
return (double)(4.0F + attackTarget.width);
}
}
static class AISpiderTarget<T extends EntityLivingBase> extends EntityAINearestAttackableTarget<T>
{
public AISpiderTarget(EntitySpider spider, Class<T> classTarget)
{
super(spider, classTarget, true);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
float f = this.taskOwner.getBrightness();
return f >= 0.5F ? false : super.shouldExecute();
}
}
public static class GroupData implements IEntityLivingData
{
public Potion effect;
public void setRandomEffect(Random rand)
{
int i = rand.nextInt(5);
if (i <= 1)
{
this.effect = MobEffects.SPEED;
}
else if (i <= 2)
{
this.effect = MobEffects.STRENGTH;
}
else if (i <= 3)
{
this.effect = MobEffects.REGENERATION;
}
else if (i <= 4)
{
this.effect = MobEffects.INVISIBILITY;
}
}
}
}

View File

@@ -0,0 +1,75 @@
package net.minecraft.entity.monster;
import javax.annotation.Nullable;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.projectile.EntityArrow;
import net.minecraft.entity.projectile.EntityTippedArrow;
import net.minecraft.init.MobEffects;
import net.minecraft.init.SoundEvents;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.DamageSource;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootTableList;
public class EntityStray extends AbstractSkeleton
{
public EntityStray(World worldIn)
{
super(worldIn);
}
public static void registerFixesStray(DataFixer fixer)
{
EntityLiving.registerFixesMob(fixer, EntityStray.class);
}
/**
* Checks if the entity's current position is a valid location to spawn this entity.
*/
public boolean getCanSpawnHere()
{
return super.getCanSpawnHere() && this.world.canSeeSky(new BlockPos(this));
}
@Nullable
protected ResourceLocation getLootTable()
{
return LootTableList.ENTITIES_STRAY;
}
protected SoundEvent getAmbientSound()
{
return SoundEvents.ENTITY_STRAY_AMBIENT;
}
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return SoundEvents.ENTITY_STRAY_HURT;
}
protected SoundEvent getDeathSound()
{
return SoundEvents.ENTITY_STRAY_DEATH;
}
protected SoundEvent getStepSound()
{
return SoundEvents.ENTITY_STRAY_STEP;
}
protected EntityArrow getArrow(float p_190726_1_)
{
EntityArrow entityarrow = super.getArrow(p_190726_1_);
if (entityarrow instanceof EntityTippedArrow)
{
((EntityTippedArrow)entityarrow).addEffect(new PotionEffect(MobEffects.SLOWNESS, 600));
}
return entityarrow;
}
}

View File

@@ -0,0 +1,467 @@
package net.minecraft.entity.monster;
import javax.annotation.Nullable;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.IEntityLivingData;
import net.minecraft.entity.MoverType;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIBase;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAISwimming;
import net.minecraft.entity.ai.EntityAITarget;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.ai.EntityMoveHelper;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Items;
import net.minecraft.init.SoundEvents;
import net.minecraft.inventory.EntityEquipmentSlot;
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.DamageSource;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootTableList;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class EntityVex extends EntityMob
{
protected static final DataParameter<Byte> VEX_FLAGS = EntityDataManager.<Byte>createKey(EntityVex.class, DataSerializers.BYTE);
private EntityLiving owner;
@Nullable
private BlockPos boundOrigin;
private boolean limitedLifespan;
private int limitedLifeTicks;
public EntityVex(World worldIn)
{
super(worldIn);
this.isImmuneToFire = true;
this.moveHelper = new EntityVex.AIMoveControl(this);
this.setSize(0.4F, 0.8F);
this.experienceValue = 3;
}
/**
* Tries to move the entity towards the specified location.
*/
public void move(MoverType type, double x, double y, double z)
{
super.move(type, x, y, z);
this.doBlockCollisions();
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
this.noClip = true;
super.onUpdate();
this.noClip = false;
this.setNoGravity(true);
if (this.limitedLifespan && --this.limitedLifeTicks <= 0)
{
this.limitedLifeTicks = 20;
this.attackEntityFrom(DamageSource.STARVE, 1.0F);
}
}
protected void initEntityAI()
{
super.initEntityAI();
this.tasks.addTask(0, new EntityAISwimming(this));
this.tasks.addTask(4, new EntityVex.AIChargeAttack());
this.tasks.addTask(8, new EntityVex.AIMoveRandom());
this.tasks.addTask(9, new EntityAIWatchClosest(this, EntityPlayer.class, 3.0F, 1.0F));
this.tasks.addTask(10, new EntityAIWatchClosest(this, EntityLiving.class, 8.0F));
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true, new Class[] {EntityVex.class}));
this.targetTasks.addTask(2, new EntityVex.AICopyOwnerTarget(this));
this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityPlayer.class, true));
}
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(14.0D);
this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(4.0D);
}
protected void entityInit()
{
super.entityInit();
this.dataManager.register(VEX_FLAGS, Byte.valueOf((byte)0));
}
public static void registerFixesVex(DataFixer fixer)
{
EntityLiving.registerFixesMob(fixer, EntityVex.class);
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound compound)
{
super.readEntityFromNBT(compound);
if (compound.hasKey("BoundX"))
{
this.boundOrigin = new BlockPos(compound.getInteger("BoundX"), compound.getInteger("BoundY"), compound.getInteger("BoundZ"));
}
if (compound.hasKey("LifeTicks"))
{
this.setLimitedLife(compound.getInteger("LifeTicks"));
}
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound compound)
{
super.writeEntityToNBT(compound);
if (this.boundOrigin != null)
{
compound.setInteger("BoundX", this.boundOrigin.getX());
compound.setInteger("BoundY", this.boundOrigin.getY());
compound.setInteger("BoundZ", this.boundOrigin.getZ());
}
if (this.limitedLifespan)
{
compound.setInteger("LifeTicks", this.limitedLifeTicks);
}
}
public EntityLiving getOwner()
{
return this.owner;
}
@Nullable
public BlockPos getBoundOrigin()
{
return this.boundOrigin;
}
public void setBoundOrigin(@Nullable BlockPos boundOriginIn)
{
this.boundOrigin = boundOriginIn;
}
private boolean getVexFlag(int mask)
{
int i = ((Byte)this.dataManager.get(VEX_FLAGS)).byteValue();
return (i & mask) != 0;
}
private void setVexFlag(int mask, boolean value)
{
int i = ((Byte)this.dataManager.get(VEX_FLAGS)).byteValue();
if (value)
{
i = i | mask;
}
else
{
i = i & ~mask;
}
this.dataManager.set(VEX_FLAGS, Byte.valueOf((byte)(i & 255)));
}
public boolean isCharging()
{
return this.getVexFlag(1);
}
public void setCharging(boolean charging)
{
this.setVexFlag(1, charging);
}
public void setOwner(EntityLiving ownerIn)
{
this.owner = ownerIn;
}
public void setLimitedLife(int limitedLifeTicksIn)
{
this.limitedLifespan = true;
this.limitedLifeTicks = limitedLifeTicksIn;
}
protected SoundEvent getAmbientSound()
{
return SoundEvents.ENTITY_VEX_AMBIENT;
}
protected SoundEvent getDeathSound()
{
return SoundEvents.ENTITY_VEX_DEATH;
}
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return SoundEvents.ENTITY_VEX_HURT;
}
@Nullable
protected ResourceLocation getLootTable()
{
return LootTableList.ENTITIES_VEX;
}
@SideOnly(Side.CLIENT)
public int getBrightnessForRender()
{
return 15728880;
}
/**
* Gets how bright this entity is.
*/
public float getBrightness()
{
return 1.0F;
}
/**
* Called only once on an entity when first time spawned, via egg, mob spawner, natural spawning etc, but not called
* when entity is reloaded from nbt. Mainly used for initializing attributes and inventory
*/
@Nullable
public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, @Nullable IEntityLivingData livingdata)
{
this.setEquipmentBasedOnDifficulty(difficulty);
this.setEnchantmentBasedOnDifficulty(difficulty);
return super.onInitialSpawn(difficulty, livingdata);
}
/**
* Gives armor or weapon for entity based on given DifficultyInstance
*/
protected void setEquipmentBasedOnDifficulty(DifficultyInstance difficulty)
{
this.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(Items.IRON_SWORD));
this.setDropChance(EntityEquipmentSlot.MAINHAND, 0.0F);
}
class AIChargeAttack extends EntityAIBase
{
public AIChargeAttack()
{
this.setMutexBits(1);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
if (EntityVex.this.getAttackTarget() != null && !EntityVex.this.getMoveHelper().isUpdating() && EntityVex.this.rand.nextInt(7) == 0)
{
return EntityVex.this.getDistanceSq(EntityVex.this.getAttackTarget()) > 4.0D;
}
else
{
return false;
}
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return EntityVex.this.getMoveHelper().isUpdating() && EntityVex.this.isCharging() && EntityVex.this.getAttackTarget() != null && EntityVex.this.getAttackTarget().isEntityAlive();
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
EntityLivingBase entitylivingbase = EntityVex.this.getAttackTarget();
Vec3d vec3d = entitylivingbase.getPositionEyes(1.0F);
EntityVex.this.moveHelper.setMoveTo(vec3d.x, vec3d.y, vec3d.z, 1.0D);
EntityVex.this.setCharging(true);
EntityVex.this.playSound(SoundEvents.ENTITY_VEX_CHARGE, 1.0F, 1.0F);
}
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
public void resetTask()
{
EntityVex.this.setCharging(false);
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
EntityLivingBase entitylivingbase = EntityVex.this.getAttackTarget();
if (EntityVex.this.getEntityBoundingBox().intersects(entitylivingbase.getEntityBoundingBox()))
{
EntityVex.this.attackEntityAsMob(entitylivingbase);
EntityVex.this.setCharging(false);
}
else
{
double d0 = EntityVex.this.getDistanceSq(entitylivingbase);
if (d0 < 9.0D)
{
Vec3d vec3d = entitylivingbase.getPositionEyes(1.0F);
EntityVex.this.moveHelper.setMoveTo(vec3d.x, vec3d.y, vec3d.z, 1.0D);
}
}
}
}
class AICopyOwnerTarget extends EntityAITarget
{
public AICopyOwnerTarget(EntityCreature creature)
{
super(creature, false);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
return EntityVex.this.owner != null && EntityVex.this.owner.getAttackTarget() != null && this.isSuitableTarget(EntityVex.this.owner.getAttackTarget(), false);
}
/**
* Execute a one shot task or start executing a continuous task
*/
public void startExecuting()
{
EntityVex.this.setAttackTarget(EntityVex.this.owner.getAttackTarget());
super.startExecuting();
}
}
class AIMoveControl extends EntityMoveHelper
{
public AIMoveControl(EntityVex vex)
{
super(vex);
}
public void onUpdateMoveHelper()
{
if (this.action == EntityMoveHelper.Action.MOVE_TO)
{
double d0 = this.posX - EntityVex.this.posX;
double d1 = this.posY - EntityVex.this.posY;
double d2 = this.posZ - EntityVex.this.posZ;
double d3 = d0 * d0 + d1 * d1 + d2 * d2;
d3 = (double)MathHelper.sqrt(d3);
if (d3 < EntityVex.this.getEntityBoundingBox().getAverageEdgeLength())
{
this.action = EntityMoveHelper.Action.WAIT;
EntityVex.this.motionX *= 0.5D;
EntityVex.this.motionY *= 0.5D;
EntityVex.this.motionZ *= 0.5D;
}
else
{
EntityVex.this.motionX += d0 / d3 * 0.05D * this.speed;
EntityVex.this.motionY += d1 / d3 * 0.05D * this.speed;
EntityVex.this.motionZ += d2 / d3 * 0.05D * this.speed;
if (EntityVex.this.getAttackTarget() == null)
{
EntityVex.this.rotationYaw = -((float)MathHelper.atan2(EntityVex.this.motionX, EntityVex.this.motionZ)) * (180F / (float)Math.PI);
EntityVex.this.renderYawOffset = EntityVex.this.rotationYaw;
}
else
{
double d4 = EntityVex.this.getAttackTarget().posX - EntityVex.this.posX;
double d5 = EntityVex.this.getAttackTarget().posZ - EntityVex.this.posZ;
EntityVex.this.rotationYaw = -((float)MathHelper.atan2(d4, d5)) * (180F / (float)Math.PI);
EntityVex.this.renderYawOffset = EntityVex.this.rotationYaw;
}
}
}
}
}
class AIMoveRandom extends EntityAIBase
{
public AIMoveRandom()
{
this.setMutexBits(1);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
return !EntityVex.this.getMoveHelper().isUpdating() && EntityVex.this.rand.nextInt(7) == 0;
}
/**
* Returns whether an in-progress EntityAIBase should continue executing
*/
public boolean shouldContinueExecuting()
{
return false;
}
/**
* Keep ticking a continuous task that has already been started
*/
public void updateTask()
{
BlockPos blockpos = EntityVex.this.getBoundOrigin();
if (blockpos == null)
{
blockpos = new BlockPos(EntityVex.this);
}
for (int i = 0; i < 3; ++i)
{
BlockPos blockpos1 = blockpos.add(EntityVex.this.rand.nextInt(15) - 7, EntityVex.this.rand.nextInt(11) - 5, EntityVex.this.rand.nextInt(15) - 7);
if (EntityVex.this.world.isAirBlock(blockpos1))
{
EntityVex.this.moveHelper.setMoveTo((double)blockpos1.getX() + 0.5D, (double)blockpos1.getY() + 0.5D, (double)blockpos1.getZ() + 0.5D, 0.25D);
if (EntityVex.this.getAttackTarget() == null)
{
EntityVex.this.getLookHelper().setLookPosition((double)blockpos1.getX() + 0.5D, (double)blockpos1.getY() + 0.5D, (double)blockpos1.getZ() + 0.5D, 180.0F, 20.0F);
}
break;
}
}
}
}
}

View File

@@ -0,0 +1,222 @@
package net.minecraft.entity.monster;
import com.google.common.base.Predicate;
import javax.annotation.Nullable;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.EnumCreatureAttribute;
import net.minecraft.entity.IEntityLivingData;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIAttackMelee;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAISwimming;
import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Items;
import net.minecraft.init.SoundEvents;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.DamageSource;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootTableList;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class EntityVindicator extends AbstractIllager
{
private boolean johnny;
private static final Predicate<Entity> JOHNNY_SELECTOR = new Predicate<Entity>()
{
public boolean apply(@Nullable Entity p_apply_1_)
{
return p_apply_1_ instanceof EntityLivingBase && ((EntityLivingBase)p_apply_1_).attackable();
}
};
public EntityVindicator(World worldIn)
{
super(worldIn);
this.setSize(0.6F, 1.95F);
}
public static void registerFixesVindicator(DataFixer fixer)
{
EntityLiving.registerFixesMob(fixer, EntityVindicator.class);
}
protected void initEntityAI()
{
super.initEntityAI();
this.tasks.addTask(0, new EntityAISwimming(this));
this.tasks.addTask(4, new EntityAIAttackMelee(this, 1.0D, false));
this.tasks.addTask(8, new EntityAIWander(this, 0.6D));
this.tasks.addTask(9, new EntityAIWatchClosest(this, EntityPlayer.class, 3.0F, 1.0F));
this.tasks.addTask(10, new EntityAIWatchClosest(this, EntityLiving.class, 8.0F));
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true, new Class[] {EntityVindicator.class}));
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityPlayer.class, true));
this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityVillager.class, true));
this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityIronGolem.class, true));
this.targetTasks.addTask(4, new EntityVindicator.AIJohnnyAttack(this));
}
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.3499999940395355D);
this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(12.0D);
this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(24.0D);
this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(5.0D);
}
protected void entityInit()
{
super.entityInit();
}
protected ResourceLocation getLootTable()
{
return LootTableList.ENTITIES_VINDICATION_ILLAGER;
}
@SideOnly(Side.CLIENT)
public boolean isAggressive()
{
return this.isAggressive(1);
}
public void setAggressive(boolean p_190636_1_)
{
this.setAggressive(1, p_190636_1_);
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound compound)
{
super.writeEntityToNBT(compound);
if (this.johnny)
{
compound.setBoolean("Johnny", true);
}
}
@SideOnly(Side.CLIENT)
public AbstractIllager.IllagerArmPose getArmPose()
{
return this.isAggressive() ? AbstractIllager.IllagerArmPose.ATTACKING : AbstractIllager.IllagerArmPose.CROSSED;
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound compound)
{
super.readEntityFromNBT(compound);
if (compound.hasKey("Johnny", 99))
{
this.johnny = compound.getBoolean("Johnny");
}
}
/**
* Called only once on an entity when first time spawned, via egg, mob spawner, natural spawning etc, but not called
* when entity is reloaded from nbt. Mainly used for initializing attributes and inventory
*/
@Nullable
public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, @Nullable IEntityLivingData livingdata)
{
IEntityLivingData ientitylivingdata = super.onInitialSpawn(difficulty, livingdata);
this.setEquipmentBasedOnDifficulty(difficulty);
this.setEnchantmentBasedOnDifficulty(difficulty);
return ientitylivingdata;
}
/**
* Gives armor or weapon for entity based on given DifficultyInstance
*/
protected void setEquipmentBasedOnDifficulty(DifficultyInstance difficulty)
{
this.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(Items.IRON_AXE));
}
protected void updateAITasks()
{
super.updateAITasks();
this.setAggressive(this.getAttackTarget() != null);
}
/**
* Returns whether this Entity is on the same team as the given Entity.
*/
public boolean isOnSameTeam(Entity entityIn)
{
if (super.isOnSameTeam(entityIn))
{
return true;
}
else if (entityIn instanceof EntityLivingBase && ((EntityLivingBase)entityIn).getCreatureAttribute() == EnumCreatureAttribute.ILLAGER)
{
return this.getTeam() == null && entityIn.getTeam() == null;
}
else
{
return false;
}
}
/**
* Sets the custom name tag for this entity
*/
public void setCustomNameTag(String name)
{
super.setCustomNameTag(name);
if (!this.johnny && "Johnny".equals(name))
{
this.johnny = true;
}
}
protected SoundEvent getAmbientSound()
{
return SoundEvents.VINDICATION_ILLAGER_AMBIENT;
}
protected SoundEvent getDeathSound()
{
return SoundEvents.VINDICATION_ILLAGER_DEATH;
}
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return SoundEvents.ENTITY_VINDICATION_ILLAGER_HURT;
}
static class AIJohnnyAttack extends EntityAINearestAttackableTarget<EntityLivingBase>
{
public AIJohnnyAttack(EntityVindicator vindicator)
{
super(vindicator, EntityLivingBase.class, 0, true, true, EntityVindicator.JOHNNY_SELECTOR);
}
/**
* Returns whether the EntityAIBase should begin execution.
*/
public boolean shouldExecute()
{
return ((EntityVindicator)this.taskOwner).johnny && super.shouldExecute();
}
}
}

View File

@@ -0,0 +1,281 @@
package net.minecraft.entity.monster;
import java.util.List;
import java.util.UUID;
import javax.annotation.Nullable;
import net.minecraft.block.material.Material;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.IRangedAttackMob;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIAttackRanged;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAISwimming;
import net.minecraft.entity.ai.EntityAIWanderAvoidWater;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.entity.ai.attributes.IAttributeInstance;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.projectile.EntityPotion;
import net.minecraft.init.Items;
import net.minecraft.init.MobEffects;
import net.minecraft.init.PotionTypes;
import net.minecraft.init.SoundEvents;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.ItemStack;
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.DamageSource;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootTableList;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class EntityWitch extends EntityMob implements IRangedAttackMob
{
private static final UUID MODIFIER_UUID = UUID.fromString("5CD17E52-A79A-43D3-A529-90FDE04B181E");
private static final AttributeModifier MODIFIER = (new AttributeModifier(MODIFIER_UUID, "Drinking speed penalty", -0.25D, 0)).setSaved(false);
private static final DataParameter<Boolean> IS_DRINKING = EntityDataManager.<Boolean>createKey(EntityWitch.class, DataSerializers.BOOLEAN);
/**
* A timer that counts down until a witch finishes drinking a potion, at which time the held item (if it is a
* potion) will have its effects applied. Set to {@link ItemStack#getMaxItemUseDuration()}.
*/
private int potionUseTimer;
public EntityWitch(World worldIn)
{
super(worldIn);
this.setSize(0.6F, 1.95F);
}
public static void registerFixesWitch(DataFixer fixer)
{
EntityLiving.registerFixesMob(fixer, EntityWitch.class);
}
protected void initEntityAI()
{
this.tasks.addTask(1, new EntityAISwimming(this));
this.tasks.addTask(2, new EntityAIAttackRanged(this, 1.0D, 60, 10.0F));
this.tasks.addTask(2, new EntityAIWanderAvoidWater(this, 1.0D));
this.tasks.addTask(3, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
this.tasks.addTask(3, new EntityAILookIdle(this));
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false, new Class[0]));
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityPlayer.class, true));
}
protected void entityInit()
{
super.entityInit();
this.getDataManager().register(IS_DRINKING, Boolean.valueOf(false));
}
protected SoundEvent getAmbientSound()
{
return SoundEvents.ENTITY_WITCH_AMBIENT;
}
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return SoundEvents.ENTITY_WITCH_HURT;
}
protected SoundEvent getDeathSound()
{
return SoundEvents.ENTITY_WITCH_DEATH;
}
/**
* Set whether this witch is aggressive at an entity.
*/
public void setDrinkingPotion(boolean drinkingPotion)
{
this.getDataManager().set(IS_DRINKING, Boolean.valueOf(drinkingPotion));
}
public boolean isDrinkingPotion()
{
return ((Boolean)this.getDataManager().get(IS_DRINKING)).booleanValue();
}
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(26.0D);
this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.25D);
}
/**
* 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()
{
if (!this.world.isRemote)
{
if (this.isDrinkingPotion())
{
if (this.potionUseTimer-- <= 0)
{
this.setDrinkingPotion(false);
ItemStack itemstack = this.getHeldItemMainhand();
this.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, ItemStack.EMPTY);
if (itemstack.getItem() == Items.POTIONITEM)
{
List<PotionEffect> list = PotionUtils.getEffectsFromStack(itemstack);
if (list != null)
{
for (PotionEffect potioneffect : list)
{
this.addPotionEffect(new PotionEffect(potioneffect));
}
}
}
this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).removeModifier(MODIFIER);
}
}
else
{
PotionType potiontype = null;
if (this.rand.nextFloat() < 0.15F && this.isInsideOfMaterial(Material.WATER) && !this.isPotionActive(MobEffects.WATER_BREATHING))
{
potiontype = PotionTypes.WATER_BREATHING;
}
else if (this.rand.nextFloat() < 0.15F && (this.isBurning() || this.getLastDamageSource() != null && this.getLastDamageSource().isFireDamage()) && !this.isPotionActive(MobEffects.FIRE_RESISTANCE))
{
potiontype = PotionTypes.FIRE_RESISTANCE;
}
else if (this.rand.nextFloat() < 0.05F && this.getHealth() < this.getMaxHealth())
{
potiontype = PotionTypes.HEALING;
}
else if (this.rand.nextFloat() < 0.5F && this.getAttackTarget() != null && !this.isPotionActive(MobEffects.SPEED) && this.getAttackTarget().getDistanceSq(this) > 121.0D)
{
potiontype = PotionTypes.SWIFTNESS;
}
if (potiontype != null)
{
this.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, PotionUtils.addPotionToItemStack(new ItemStack(Items.POTIONITEM), potiontype));
this.potionUseTimer = this.getHeldItemMainhand().getMaxItemUseDuration();
this.setDrinkingPotion(true);
this.world.playSound((EntityPlayer)null, this.posX, this.posY, this.posZ, SoundEvents.ENTITY_WITCH_DRINK, this.getSoundCategory(), 1.0F, 0.8F + this.rand.nextFloat() * 0.4F);
IAttributeInstance iattributeinstance = this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED);
iattributeinstance.removeModifier(MODIFIER);
iattributeinstance.applyModifier(MODIFIER);
}
}
if (this.rand.nextFloat() < 7.5E-4F)
{
this.world.setEntityState(this, (byte)15);
}
}
super.onLivingUpdate();
}
/**
* Handler for {@link World#setEntityState}
*/
@SideOnly(Side.CLIENT)
public void handleStatusUpdate(byte id)
{
if (id == 15)
{
for (int i = 0; i < this.rand.nextInt(35) + 10; ++i)
{
this.world.spawnParticle(EnumParticleTypes.SPELL_WITCH, this.posX + this.rand.nextGaussian() * 0.12999999523162842D, this.getEntityBoundingBox().maxY + 0.5D + this.rand.nextGaussian() * 0.12999999523162842D, this.posZ + this.rand.nextGaussian() * 0.12999999523162842D, 0.0D, 0.0D, 0.0D);
}
}
else
{
super.handleStatusUpdate(id);
}
}
/**
* Reduces damage, depending on potions
*/
protected float applyPotionDamageCalculations(DamageSource source, float damage)
{
damage = super.applyPotionDamageCalculations(source, damage);
if (source.getTrueSource() == this)
{
damage = 0.0F;
}
if (source.isMagicDamage())
{
damage = (float)((double)damage * 0.15D);
}
return damage;
}
@Nullable
protected ResourceLocation getLootTable()
{
return LootTableList.ENTITIES_WITCH;
}
/**
* Attack the specified entity using a ranged attack.
*/
public void attackEntityWithRangedAttack(EntityLivingBase target, float distanceFactor)
{
if (!this.isDrinkingPotion())
{
double d0 = target.posY + (double)target.getEyeHeight() - 1.100000023841858D;
double d1 = target.posX + target.motionX - this.posX;
double d2 = d0 - this.posY;
double d3 = target.posZ + target.motionZ - this.posZ;
float f = MathHelper.sqrt(d1 * d1 + d3 * d3);
PotionType potiontype = PotionTypes.HARMING;
if (f >= 8.0F && !target.isPotionActive(MobEffects.SLOWNESS))
{
potiontype = PotionTypes.SLOWNESS;
}
else if (target.getHealth() >= 8.0F && !target.isPotionActive(MobEffects.POISON))
{
potiontype = PotionTypes.POISON;
}
else if (f <= 3.0F && !target.isPotionActive(MobEffects.WEAKNESS) && this.rand.nextFloat() < 0.25F)
{
potiontype = PotionTypes.WEAKNESS;
}
EntityPotion entitypotion = new EntityPotion(this.world, this, PotionUtils.addPotionToItemStack(new ItemStack(Items.SPLASH_POTION), potiontype));
entitypotion.rotationPitch -= -20.0F;
entitypotion.shoot(d1, d2 + (double)(f * 0.2F), d3, 0.75F, 8.0F);
this.world.playSound((EntityPlayer)null, this.posX, this.posY, this.posZ, SoundEvents.ENTITY_WITCH_THROW, this.getSoundCategory(), 1.0F, 0.8F + this.rand.nextFloat() * 0.4F);
this.world.spawnEntity(entitypotion);
}
}
public float getEyeHeight()
{
return 1.62F;
}
public void setSwingingArms(boolean swingingArms)
{
}
}

View File

@@ -0,0 +1,139 @@
package net.minecraft.entity.monster;
import javax.annotation.Nullable;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.IEntityLivingData;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.projectile.EntityArrow;
import net.minecraft.init.Items;
import net.minecraft.init.MobEffects;
import net.minecraft.init.SoundEvents;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.ItemStack;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.DamageSource;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootTableList;
public class EntityWitherSkeleton extends AbstractSkeleton
{
public EntityWitherSkeleton(World worldIn)
{
super(worldIn);
this.setSize(0.7F, 2.4F);
this.isImmuneToFire = true;
}
public static void registerFixesWitherSkeleton(DataFixer fixer)
{
EntityLiving.registerFixesMob(fixer, EntityWitherSkeleton.class);
}
@Nullable
protected ResourceLocation getLootTable()
{
return LootTableList.ENTITIES_WITHER_SKELETON;
}
protected SoundEvent getAmbientSound()
{
return SoundEvents.ENTITY_WITHER_SKELETON_AMBIENT;
}
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return SoundEvents.ENTITY_WITHER_SKELETON_HURT;
}
protected SoundEvent getDeathSound()
{
return SoundEvents.ENTITY_WITHER_SKELETON_DEATH;
}
protected SoundEvent getStepSound()
{
return SoundEvents.ENTITY_WITHER_SKELETON_STEP;
}
/**
* Called when the mob's health reaches 0.
*/
public void onDeath(DamageSource cause)
{
super.onDeath(cause);
if (cause.getTrueSource() instanceof EntityCreeper)
{
EntityCreeper entitycreeper = (EntityCreeper)cause.getTrueSource();
if (entitycreeper.getPowered() && entitycreeper.ableToCauseSkullDrop())
{
entitycreeper.incrementDroppedSkulls();
this.entityDropItem(new ItemStack(Items.SKULL, 1, 1), 0.0F);
}
}
}
/**
* Gives armor or weapon for entity based on given DifficultyInstance
*/
protected void setEquipmentBasedOnDifficulty(DifficultyInstance difficulty)
{
this.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(Items.STONE_SWORD));
}
/**
* Enchants Entity's current equipments based on given DifficultyInstance
*/
protected void setEnchantmentBasedOnDifficulty(DifficultyInstance difficulty)
{
}
/**
* Called only once on an entity when first time spawned, via egg, mob spawner, natural spawning etc, but not called
* when entity is reloaded from nbt. Mainly used for initializing attributes and inventory
*/
@Nullable
public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, @Nullable IEntityLivingData livingdata)
{
IEntityLivingData ientitylivingdata = super.onInitialSpawn(difficulty, livingdata);
this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(4.0D);
this.setCombatTask();
return ientitylivingdata;
}
public float getEyeHeight()
{
return 2.1F;
}
public boolean attackEntityAsMob(Entity entityIn)
{
if (!super.attackEntityAsMob(entityIn))
{
return false;
}
else
{
if (entityIn instanceof EntityLivingBase)
{
((EntityLivingBase)entityIn).addPotionEffect(new PotionEffect(MobEffects.WITHER, 200));
}
return true;
}
}
protected EntityArrow getArrow(float p_190726_1_)
{
EntityArrow entityarrow = super.getArrow(p_190726_1_);
entityarrow.setFire(100);
return entityarrow;
}
}

View File

@@ -0,0 +1,639 @@
package net.minecraft.entity.monster;
import java.util.Calendar;
import java.util.List;
import java.util.UUID;
import javax.annotation.Nullable;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.EnumCreatureAttribute;
import net.minecraft.entity.IEntityLivingData;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIBreakDoor;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAIMoveThroughVillage;
import net.minecraft.entity.ai.EntityAIMoveTowardsRestriction;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAISwimming;
import net.minecraft.entity.ai.EntityAIWanderAvoidWater;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.ai.EntityAIZombieAttack;
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.entity.passive.EntityChicken;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.init.SoundEvents;
import net.minecraft.inventory.EntityEquipmentSlot;
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.pathfinding.PathNavigateGround;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EntitySelectors;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.EnumDifficulty;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootTableList;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class EntityZombie extends EntityMob
{
/** The attribute which determines the chance that this mob will spawn reinforcements */
protected static final IAttribute SPAWN_REINFORCEMENTS_CHANCE = (new RangedAttribute((IAttribute)null, "zombie.spawnReinforcements", 0.0D, 0.0D, 1.0D)).setDescription("Spawn Reinforcements Chance");
private static final UUID BABY_SPEED_BOOST_ID = UUID.fromString("B9766B59-9566-4402-BC1F-2EE2A276D836");
private static final AttributeModifier BABY_SPEED_BOOST = new AttributeModifier(BABY_SPEED_BOOST_ID, "Baby speed boost", 0.5D, 1);
private static final DataParameter<Boolean> IS_CHILD = EntityDataManager.<Boolean>createKey(EntityZombie.class, DataSerializers.BOOLEAN);
/**
* Was the type of villager for zombie villagers prior to 1.11. Now unused. Use {@link
* EntityZombieVillager#PROFESSION} instead.
*/
private static final DataParameter<Integer> VILLAGER_TYPE = EntityDataManager.<Integer>createKey(EntityZombie.class, DataSerializers.VARINT);
private static final DataParameter<Boolean> ARMS_RAISED = EntityDataManager.<Boolean>createKey(EntityZombie.class, DataSerializers.BOOLEAN);
private final EntityAIBreakDoor breakDoor = new EntityAIBreakDoor(this);
private boolean isBreakDoorsTaskSet;
/** The width of the entity */
private float zombieWidth = -1.0F;
/** The height of the the entity. */
private float zombieHeight;
public EntityZombie(World worldIn)
{
super(worldIn);
this.setSize(0.6F, 1.95F);
}
protected void initEntityAI()
{
this.tasks.addTask(0, new EntityAISwimming(this));
this.tasks.addTask(2, new EntityAIZombieAttack(this, 1.0D, false));
this.tasks.addTask(5, new EntityAIMoveTowardsRestriction(this, 1.0D));
this.tasks.addTask(7, new EntityAIWanderAvoidWater(this, 1.0D));
this.tasks.addTask(8, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
this.tasks.addTask(8, new EntityAILookIdle(this));
this.applyEntityAI();
}
protected void applyEntityAI()
{
this.tasks.addTask(6, new EntityAIMoveThroughVillage(this, 1.0D, false));
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true, new Class[] {EntityPigZombie.class}));
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityPlayer.class, true));
this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityVillager.class, false));
this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityIronGolem.class, true));
}
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(35.0D);
this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.23000000417232513D);
this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(3.0D);
this.getEntityAttribute(SharedMonsterAttributes.ARMOR).setBaseValue(2.0D);
this.getAttributeMap().registerAttribute(SPAWN_REINFORCEMENTS_CHANCE).setBaseValue(this.rand.nextDouble() * net.minecraftforge.common.ForgeModContainer.zombieSummonBaseChance);
}
protected void entityInit()
{
super.entityInit();
this.getDataManager().register(IS_CHILD, Boolean.valueOf(false));
this.getDataManager().register(VILLAGER_TYPE, Integer.valueOf(0));
this.getDataManager().register(ARMS_RAISED, Boolean.valueOf(false));
}
public void setArmsRaised(boolean armsRaised)
{
this.getDataManager().set(ARMS_RAISED, Boolean.valueOf(armsRaised));
}
@SideOnly(Side.CLIENT)
public boolean isArmsRaised()
{
return ((Boolean)this.getDataManager().get(ARMS_RAISED)).booleanValue();
}
public boolean isBreakDoorsTaskSet()
{
return this.isBreakDoorsTaskSet;
}
/**
* Sets or removes EntityAIBreakDoor task
*/
public void setBreakDoorsAItask(boolean enabled)
{
if (this.isBreakDoorsTaskSet != enabled)
{
this.isBreakDoorsTaskSet = enabled;
((PathNavigateGround)this.getNavigator()).setBreakDoors(enabled);
if (enabled)
{
this.tasks.addTask(1, this.breakDoor);
}
else
{
this.tasks.removeTask(this.breakDoor);
}
}
}
/**
* If Animal, checks if the age timer is negative
*/
public boolean isChild()
{
return ((Boolean)this.getDataManager().get(IS_CHILD)).booleanValue();
}
/**
* Get the experience points the entity currently has.
*/
protected int getExperiencePoints(EntityPlayer player)
{
if (this.isChild())
{
this.experienceValue = (int)((float)this.experienceValue * 2.5F);
}
return super.getExperiencePoints(player);
}
/**
* Set whether this zombie is a child.
*/
public void setChild(boolean childZombie)
{
this.getDataManager().set(IS_CHILD, Boolean.valueOf(childZombie));
if (this.world != null && !this.world.isRemote)
{
IAttributeInstance iattributeinstance = this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED);
iattributeinstance.removeModifier(BABY_SPEED_BOOST);
if (childZombie)
{
iattributeinstance.applyModifier(BABY_SPEED_BOOST);
}
}
this.setChildSize(childZombie);
}
public void notifyDataManagerChange(DataParameter<?> key)
{
if (IS_CHILD.equals(key))
{
this.setChildSize(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()
{
if (this.world.isDaytime() && !this.world.isRemote && !this.isChild() && this.shouldBurnInDay())
{
float f = this.getBrightness();
if (f > 0.5F && this.rand.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.world.canSeeSky(new BlockPos(this.posX, this.posY + (double)this.getEyeHeight(), this.posZ)))
{
boolean flag = true;
ItemStack itemstack = this.getItemStackFromSlot(EntityEquipmentSlot.HEAD);
if (!itemstack.isEmpty())
{
if (itemstack.isItemStackDamageable())
{
itemstack.setItemDamage(itemstack.getItemDamage() + this.rand.nextInt(2));
if (itemstack.getItemDamage() >= itemstack.getMaxDamage())
{
this.renderBrokenItemStack(itemstack);
this.setItemStackToSlot(EntityEquipmentSlot.HEAD, ItemStack.EMPTY);
}
}
flag = false;
}
if (flag)
{
this.setFire(8);
}
}
}
super.onLivingUpdate();
}
protected boolean shouldBurnInDay()
{
return true;
}
/**
* Called when the entity is attacked.
*/
public boolean attackEntityFrom(DamageSource source, float amount)
{
if (super.attackEntityFrom(source, amount))
{
EntityLivingBase entitylivingbase = this.getAttackTarget();
if (entitylivingbase == null && source.getTrueSource() instanceof EntityLivingBase)
{
entitylivingbase = (EntityLivingBase)source.getTrueSource();
}
int i = MathHelper.floor(this.posX);
int j = MathHelper.floor(this.posY);
int k = MathHelper.floor(this.posZ);
net.minecraftforge.event.entity.living.ZombieEvent.SummonAidEvent summonAid = net.minecraftforge.event.ForgeEventFactory.fireZombieSummonAid(this, world, i, j, k, entitylivingbase, this.getEntityAttribute(SPAWN_REINFORCEMENTS_CHANCE).getAttributeValue());
if (summonAid.getResult() == net.minecraftforge.fml.common.eventhandler.Event.Result.DENY) return true;
if (summonAid.getResult() == net.minecraftforge.fml.common.eventhandler.Event.Result.ALLOW ||
entitylivingbase != null && this.world.getDifficulty() == EnumDifficulty.HARD && (double)this.rand.nextFloat() < this.getEntityAttribute(SPAWN_REINFORCEMENTS_CHANCE).getAttributeValue() && this.world.getGameRules().getBoolean("doMobSpawning"))
{
EntityZombie entityzombie;
if (summonAid.getCustomSummonedAid() != null && summonAid.getResult() == net.minecraftforge.fml.common.eventhandler.Event.Result.ALLOW)
{
entityzombie = summonAid.getCustomSummonedAid();
}
else
{
entityzombie = new EntityZombie(this.world);
}
for (int l = 0; l < 50; ++l)
{
int i1 = i + MathHelper.getInt(this.rand, 7, 40) * MathHelper.getInt(this.rand, -1, 1);
int j1 = j + MathHelper.getInt(this.rand, 7, 40) * MathHelper.getInt(this.rand, -1, 1);
int k1 = k + MathHelper.getInt(this.rand, 7, 40) * MathHelper.getInt(this.rand, -1, 1);
if (this.world.getBlockState(new BlockPos(i1, j1 - 1, k1)).isSideSolid(this.world, new BlockPos(i1, j1 - 1, k1), net.minecraft.util.EnumFacing.UP) && this.world.getLightFromNeighbors(new BlockPos(i1, j1, k1)) < 10)
{
entityzombie.setPosition((double)i1, (double)j1, (double)k1);
if (!this.world.isAnyPlayerWithinRangeAt((double)i1, (double)j1, (double)k1, 7.0D) && this.world.checkNoEntityCollision(entityzombie.getEntityBoundingBox(), entityzombie) && this.world.getCollisionBoxes(entityzombie, entityzombie.getEntityBoundingBox()).isEmpty() && !this.world.containsAnyLiquid(entityzombie.getEntityBoundingBox()))
{
this.world.spawnEntity(entityzombie);
if (entitylivingbase != null) entityzombie.setAttackTarget(entitylivingbase);
entityzombie.onInitialSpawn(this.world.getDifficultyForLocation(new BlockPos(entityzombie)), (IEntityLivingData)null);
this.getEntityAttribute(SPAWN_REINFORCEMENTS_CHANCE).applyModifier(new AttributeModifier("Zombie reinforcement caller charge", -0.05000000074505806D, 0));
entityzombie.getEntityAttribute(SPAWN_REINFORCEMENTS_CHANCE).applyModifier(new AttributeModifier("Zombie reinforcement callee charge", -0.05000000074505806D, 0));
break;
}
}
}
}
return true;
}
else
{
return false;
}
}
public boolean attackEntityAsMob(Entity entityIn)
{
boolean flag = super.attackEntityAsMob(entityIn);
if (flag)
{
float f = this.world.getDifficultyForLocation(new BlockPos(this)).getAdditionalDifficulty();
if (this.getHeldItemMainhand().isEmpty() && this.isBurning() && this.rand.nextFloat() < f * 0.3F)
{
entityIn.setFire(2 * (int)f);
}
}
return flag;
}
protected SoundEvent getAmbientSound()
{
return SoundEvents.ENTITY_ZOMBIE_AMBIENT;
}
protected SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return SoundEvents.ENTITY_ZOMBIE_HURT;
}
protected SoundEvent getDeathSound()
{
return SoundEvents.ENTITY_ZOMBIE_DEATH;
}
protected SoundEvent getStepSound()
{
return SoundEvents.ENTITY_ZOMBIE_STEP;
}
protected void playStepSound(BlockPos pos, Block blockIn)
{
this.playSound(this.getStepSound(), 0.15F, 1.0F);
}
/**
* Get this Entity's EnumCreatureAttribute
*/
public EnumCreatureAttribute getCreatureAttribute()
{
return EnumCreatureAttribute.UNDEAD;
}
@Nullable
protected ResourceLocation getLootTable()
{
return LootTableList.ENTITIES_ZOMBIE;
}
/**
* Gives armor or weapon for entity based on given DifficultyInstance
*/
protected void setEquipmentBasedOnDifficulty(DifficultyInstance difficulty)
{
super.setEquipmentBasedOnDifficulty(difficulty);
if (this.rand.nextFloat() < (this.world.getDifficulty() == EnumDifficulty.HARD ? 0.05F : 0.01F))
{
int i = this.rand.nextInt(3);
if (i == 0)
{
this.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(Items.IRON_SWORD));
}
else
{
this.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(Items.IRON_SHOVEL));
}
}
}
public static void registerFixesZombie(DataFixer fixer)
{
EntityLiving.registerFixesMob(fixer, EntityZombie.class);
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound compound)
{
super.writeEntityToNBT(compound);
if (this.isChild())
{
compound.setBoolean("IsBaby", true);
}
compound.setBoolean("CanBreakDoors", this.isBreakDoorsTaskSet());
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound compound)
{
super.readEntityFromNBT(compound);
if (compound.getBoolean("IsBaby"))
{
this.setChild(true);
}
this.setBreakDoorsAItask(compound.getBoolean("CanBreakDoors"));
}
/**
* This method gets called when the entity kills another one.
*/
public void onKillEntity(EntityLivingBase entityLivingIn)
{
super.onKillEntity(entityLivingIn);
if ((this.world.getDifficulty() == EnumDifficulty.NORMAL || this.world.getDifficulty() == EnumDifficulty.HARD) && entityLivingIn instanceof EntityVillager)
{
if (this.world.getDifficulty() != EnumDifficulty.HARD && this.rand.nextBoolean())
{
return;
}
EntityVillager entityvillager = (EntityVillager)entityLivingIn;
EntityZombieVillager entityzombievillager = new EntityZombieVillager(this.world);
entityzombievillager.copyLocationAndAnglesFrom(entityvillager);
this.world.removeEntity(entityvillager);
entityzombievillager.onInitialSpawn(this.world.getDifficultyForLocation(new BlockPos(entityzombievillager)), new EntityZombie.GroupData(false));
entityzombievillager.setProfession(entityvillager.getProfession());
entityzombievillager.setChild(entityvillager.isChild());
entityzombievillager.setNoAI(entityvillager.isAIDisabled());
if (entityvillager.hasCustomName())
{
entityzombievillager.setCustomNameTag(entityvillager.getCustomNameTag());
entityzombievillager.setAlwaysRenderNameTag(entityvillager.getAlwaysRenderNameTag());
}
this.world.spawnEntity(entityzombievillager);
this.world.playEvent((EntityPlayer)null, 1026, new BlockPos(this), 0);
}
}
public float getEyeHeight()
{
float f = 1.74F;
if (this.isChild())
{
f = (float)((double)f - 0.81D);
}
return f;
}
protected boolean canEquipItem(ItemStack stack)
{
return stack.getItem() == Items.EGG && this.isChild() && this.isRiding() ? false : super.canEquipItem(stack);
}
/**
* Called only once on an entity when first time spawned, via egg, mob spawner, natural spawning etc, but not called
* when entity is reloaded from nbt. Mainly used for initializing attributes and inventory
*/
@Nullable
public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, @Nullable IEntityLivingData livingdata)
{
livingdata = super.onInitialSpawn(difficulty, livingdata);
float f = difficulty.getClampedAdditionalDifficulty();
this.setCanPickUpLoot(this.rand.nextFloat() < 0.55F * f);
if (livingdata == null)
{
livingdata = new EntityZombie.GroupData(this.world.rand.nextFloat() < net.minecraftforge.common.ForgeModContainer.zombieBabyChance);
}
if (livingdata instanceof EntityZombie.GroupData)
{
EntityZombie.GroupData entityzombie$groupdata = (EntityZombie.GroupData)livingdata;
if (entityzombie$groupdata.isChild)
{
this.setChild(true);
if ((double)this.world.rand.nextFloat() < 0.05D)
{
List<EntityChicken> list = this.world.<EntityChicken>getEntitiesWithinAABB(EntityChicken.class, this.getEntityBoundingBox().grow(5.0D, 3.0D, 5.0D), EntitySelectors.IS_STANDALONE);
if (!list.isEmpty())
{
EntityChicken entitychicken = list.get(0);
entitychicken.setChickenJockey(true);
this.startRiding(entitychicken);
}
}
else if ((double)this.world.rand.nextFloat() < 0.05D)
{
EntityChicken entitychicken1 = new EntityChicken(this.world);
entitychicken1.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotationYaw, 0.0F);
entitychicken1.onInitialSpawn(difficulty, (IEntityLivingData)null);
entitychicken1.setChickenJockey(true);
this.world.spawnEntity(entitychicken1);
this.startRiding(entitychicken1);
}
}
}
this.setBreakDoorsAItask(this.rand.nextFloat() < f * 0.1F);
this.setEquipmentBasedOnDifficulty(difficulty);
this.setEnchantmentBasedOnDifficulty(difficulty);
if (this.getItemStackFromSlot(EntityEquipmentSlot.HEAD).isEmpty())
{
Calendar calendar = this.world.getCurrentDate();
if (calendar.get(2) + 1 == 10 && calendar.get(5) == 31 && this.rand.nextFloat() < 0.25F)
{
this.setItemStackToSlot(EntityEquipmentSlot.HEAD, new ItemStack(this.rand.nextFloat() < 0.1F ? Blocks.LIT_PUMPKIN : Blocks.PUMPKIN));
this.inventoryArmorDropChances[EntityEquipmentSlot.HEAD.getIndex()] = 0.0F;
}
}
this.getEntityAttribute(SharedMonsterAttributes.KNOCKBACK_RESISTANCE).applyModifier(new AttributeModifier("Random spawn bonus", this.rand.nextDouble() * 0.05000000074505806D, 0));
double d0 = this.rand.nextDouble() * 1.5D * (double)f;
if (d0 > 1.0D)
{
this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).applyModifier(new AttributeModifier("Random zombie-spawn bonus", d0, 2));
}
if (this.rand.nextFloat() < f * 0.05F)
{
this.getEntityAttribute(SPAWN_REINFORCEMENTS_CHANCE).applyModifier(new AttributeModifier("Leader zombie bonus", this.rand.nextDouble() * 0.25D + 0.5D, 0));
this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).applyModifier(new AttributeModifier("Leader zombie bonus", this.rand.nextDouble() * 3.0D + 1.0D, 2));
this.setBreakDoorsAItask(true);
}
return livingdata;
}
/**
* sets the size of the entity to be half of its current size if true.
*/
public void setChildSize(boolean isChild)
{
this.multiplySize(isChild ? 0.5F : 1.0F);
}
/**
* Sets the width and height of the entity.
*/
protected final void setSize(float width, float height)
{
boolean flag = this.zombieWidth > 0.0F && this.zombieHeight > 0.0F;
this.zombieWidth = width;
this.zombieHeight = height;
if (!flag)
{
this.multiplySize(1.0F);
}
}
/**
* Multiplies the height and width by the provided float.
*/
protected final void multiplySize(float size)
{
super.setSize(this.zombieWidth * size, this.zombieHeight * size);
}
/**
* Returns the Y Offset of this entity.
*/
public double getYOffset()
{
return this.isChild() ? 0.0D : -0.45D;
}
/**
* Called when the mob's health reaches 0.
*/
public void onDeath(DamageSource cause)
{
super.onDeath(cause);
if (cause.getTrueSource() instanceof EntityCreeper)
{
EntityCreeper entitycreeper = (EntityCreeper)cause.getTrueSource();
if (entitycreeper.getPowered() && entitycreeper.ableToCauseSkullDrop())
{
entitycreeper.incrementDroppedSkulls();
ItemStack itemstack = this.getSkullDrop();
if (!itemstack.isEmpty())
{
this.entityDropItem(itemstack, 0.0F);
}
}
}
}
protected ItemStack getSkullDrop()
{
return new ItemStack(Items.SKULL, 1, 2);
}
class GroupData implements IEntityLivingData
{
public boolean isChild;
private GroupData(boolean p_i47328_2_)
{
this.isChild = p_i47328_2_;
}
}
}

View File

@@ -0,0 +1,360 @@
package net.minecraft.entity.monster;
import java.util.UUID;
import javax.annotation.Nullable;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.block.Block;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.IEntityLivingData;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.init.MobEffects;
import net.minecraft.init.SoundEvents;
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.potion.PotionEffect;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootTableList;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class EntityZombieVillager extends EntityZombie
{
private static final DataParameter<Boolean> CONVERTING = EntityDataManager.<Boolean>createKey(EntityZombieVillager.class, DataSerializers.BOOLEAN);
private static final DataParameter<Integer> PROFESSION = EntityDataManager.<Integer>createKey(EntityZombieVillager.class, DataSerializers.VARINT);
/** Ticker used to determine the time remaining for this zombie to convert into a villager when cured. */
private int conversionTime;
/**
* The entity that started the conversion, used for the {@link CriteriaTriggers#CURED_ZOMBIE_VILLAGER} advancement
* criteria
*/
private UUID converstionStarter;
public EntityZombieVillager(World worldIn)
{
super(worldIn);
}
protected void entityInit()
{
super.entityInit();
this.dataManager.register(CONVERTING, Boolean.valueOf(false));
this.dataManager.register(PROFESSION, Integer.valueOf(0));
}
public void setProfession(int profession)
{
this.dataManager.set(PROFESSION, Integer.valueOf(profession));
net.minecraftforge.fml.common.registry.VillagerRegistry.onSetProfession(this, profession);
}
//Use Forge Variant below
@Deprecated
public int getProfession()
{
return Math.max(((Integer)this.dataManager.get(PROFESSION)).intValue(), 0);
}
public static void registerFixesZombieVillager(DataFixer fixer)
{
EntityLiving.registerFixesMob(fixer, EntityZombieVillager.class);
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound compound)
{
super.writeEntityToNBT(compound);
compound.setInteger("Profession", this.getProfession());
compound.setString("ProfessionName", this.getForgeProfession().getRegistryName().toString());
compound.setInteger("ConversionTime", this.isConverting() ? this.conversionTime : -1);
if (this.converstionStarter != null)
{
compound.setUniqueId("ConversionPlayer", this.converstionStarter);
}
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound compound)
{
super.readEntityFromNBT(compound);
this.setProfession(compound.getInteger("Profession"));
if (compound.hasKey("ProfessionName"))
{
net.minecraftforge.fml.common.registry.VillagerRegistry.VillagerProfession p = net.minecraftforge.fml.common.registry.ForgeRegistries.VILLAGER_PROFESSIONS.getValue(new net.minecraft.util.ResourceLocation(compound.getString("ProfessionName")));
if (p == null) p = net.minecraftforge.fml.common.registry.VillagerRegistry.FARMER;
this.setForgeProfession(p);
}
if (compound.hasKey("ConversionTime", 99) && compound.getInteger("ConversionTime") > -1)
{
this.startConverting(compound.hasUniqueId("ConversionPlayer") ? compound.getUniqueId("ConversionPlayer") : null, compound.getInteger("ConversionTime"));
}
}
/**
* Called only once on an entity when first time spawned, via egg, mob spawner, natural spawning etc, but not called
* when entity is reloaded from nbt. Mainly used for initializing attributes and inventory
*/
@Nullable
public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, @Nullable IEntityLivingData livingdata)
{
this.setProfession(this.world.rand.nextInt(6));
return super.onInitialSpawn(difficulty, livingdata);
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
if (!this.world.isRemote && this.isConverting())
{
int i = this.getConversionProgress();
this.conversionTime -= i;
if (this.conversionTime <= 0)
{
this.finishConversion();
}
}
super.onUpdate();
}
public boolean processInteract(EntityPlayer player, EnumHand hand)
{
ItemStack itemstack = player.getHeldItem(hand);
if (itemstack.getItem() == Items.GOLDEN_APPLE && itemstack.getMetadata() == 0 && this.isPotionActive(MobEffects.WEAKNESS))
{
if (!player.capabilities.isCreativeMode)
{
itemstack.shrink(1);
}
if (!this.world.isRemote)
{
this.startConverting(player.getUniqueID(), this.rand.nextInt(2401) + 3600);
}
return true;
}
else
{
return false;
}
}
/**
* Determines if an entity can be despawned, used on idle far away entities
*/
protected boolean canDespawn()
{
return !this.isConverting();
}
/**
* Returns whether this zombie is in the process of converting to a villager
*/
public boolean isConverting()
{
return ((Boolean)this.getDataManager().get(CONVERTING)).booleanValue();
}
/**
* Starts conversion of this zombie villager to a villager
*
* @param conversionStarterIn The entity that started the conversion's UUID
* @param conversionTimeIn The time that it will take to finish conversion
*/
protected void startConverting(@Nullable UUID conversionStarterIn, int conversionTimeIn)
{
this.converstionStarter = conversionStarterIn;
this.conversionTime = conversionTimeIn;
this.getDataManager().set(CONVERTING, Boolean.valueOf(true));
this.removePotionEffect(MobEffects.WEAKNESS);
this.addPotionEffect(new PotionEffect(MobEffects.STRENGTH, conversionTimeIn, Math.min(this.world.getDifficulty().getDifficultyId() - 1, 0)));
this.world.setEntityState(this, (byte)16);
}
/**
* Handler for {@link World#setEntityState}
*/
@SideOnly(Side.CLIENT)
public void handleStatusUpdate(byte id)
{
if (id == 16)
{
if (!this.isSilent())
{
this.world.playSound(this.posX + 0.5D, this.posY + 0.5D, this.posZ + 0.5D, SoundEvents.ENTITY_ZOMBIE_VILLAGER_CURE, this.getSoundCategory(), 1.0F + this.rand.nextFloat(), this.rand.nextFloat() * 0.7F + 0.3F, false);
}
}
else
{
super.handleStatusUpdate(id);
}
}
protected void finishConversion()
{
EntityVillager entityvillager = new EntityVillager(this.world);
entityvillager.copyLocationAndAnglesFrom(this);
entityvillager.setProfession(this.getForgeProfession());
entityvillager.finalizeMobSpawn(this.world.getDifficultyForLocation(new BlockPos(entityvillager)), (IEntityLivingData)null, false);
entityvillager.setLookingForHome();
if (this.isChild())
{
entityvillager.setGrowingAge(-24000);
}
this.world.removeEntity(this);
entityvillager.setNoAI(this.isAIDisabled());
if (this.hasCustomName())
{
entityvillager.setCustomNameTag(this.getCustomNameTag());
entityvillager.setAlwaysRenderNameTag(this.getAlwaysRenderNameTag());
}
this.world.spawnEntity(entityvillager);
if (this.converstionStarter != null)
{
EntityPlayer entityplayer = this.world.getPlayerEntityByUUID(this.converstionStarter);
if (entityplayer instanceof EntityPlayerMP)
{
CriteriaTriggers.CURED_ZOMBIE_VILLAGER.trigger((EntityPlayerMP)entityplayer, this, entityvillager);
}
}
entityvillager.addPotionEffect(new PotionEffect(MobEffects.NAUSEA, 200, 0));
this.world.playEvent((EntityPlayer)null, 1027, new BlockPos((int)this.posX, (int)this.posY, (int)this.posZ), 0);
}
protected int getConversionProgress()
{
int i = 1;
if (this.rand.nextFloat() < 0.01F)
{
int j = 0;
BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos();
for (int k = (int)this.posX - 4; k < (int)this.posX + 4 && j < 14; ++k)
{
for (int l = (int)this.posY - 4; l < (int)this.posY + 4 && j < 14; ++l)
{
for (int i1 = (int)this.posZ - 4; i1 < (int)this.posZ + 4 && j < 14; ++i1)
{
Block block = this.world.getBlockState(blockpos$mutableblockpos.setPos(k, l, i1)).getBlock();
if (block == Blocks.IRON_BARS || block == Blocks.BED)
{
if (this.rand.nextFloat() < 0.3F)
{
++i;
}
++j;
}
}
}
}
}
return i;
}
/**
* Gets the pitch of living sounds in living entities.
*/
protected float getSoundPitch()
{
return this.isChild() ? (this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 2.0F : (this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F;
}
public SoundEvent getAmbientSound()
{
return SoundEvents.ENTITY_ZOMBIE_VILLAGER_AMBIENT;
}
public SoundEvent getHurtSound(DamageSource damageSourceIn)
{
return SoundEvents.ENTITY_ZOMBIE_VILLAGER_HURT;
}
public SoundEvent getDeathSound()
{
return SoundEvents.ENTITY_ZOMBIE_VILLAGER_DEATH;
}
public SoundEvent getStepSound()
{
return SoundEvents.ENTITY_ZOMBIE_VILLAGER_STEP;
}
@Nullable
protected ResourceLocation getLootTable()
{
return LootTableList.ENTITIES_ZOMBIE_VILLAGER;
}
protected ItemStack getSkullDrop()
{
return ItemStack.EMPTY;
}
/* ======================================== FORGE START =====================================*/
@Nullable
private net.minecraftforge.fml.common.registry.VillagerRegistry.VillagerProfession prof;
public void setForgeProfession(net.minecraftforge.fml.common.registry.VillagerRegistry.VillagerProfession prof)
{
this.prof = prof;
this.setProfession(net.minecraftforge.fml.common.registry.VillagerRegistry.getId(prof));
}
public net.minecraftforge.fml.common.registry.VillagerRegistry.VillagerProfession getForgeProfession()
{
if (this.prof == null)
{
this.prof = net.minecraftforge.fml.common.registry.VillagerRegistry.getById(this.getProfession());
if (this.prof == null)
return net.minecraftforge.fml.common.registry.VillagerRegistry.FARMER;
}
return this.prof;
}
@Override
public void notifyDataManagerChange(DataParameter<?> key)
{
super.notifyDataManagerChange(key);
if (key.equals(PROFESSION))
{
net.minecraftforge.fml.common.registry.VillagerRegistry.onSetProfession(this, this.dataManager.get(PROFESSION));
}
}
/* ======================================== FORGE END =====================================*/
}

View File

@@ -0,0 +1,26 @@
package net.minecraft.entity.monster;
import com.google.common.base.Predicate;
import javax.annotation.Nullable;
import net.minecraft.entity.Entity;
import net.minecraft.entity.passive.IAnimals;
public interface IMob extends IAnimals
{
/** Entity selector for IMob types. */
Predicate<Entity> MOB_SELECTOR = new Predicate<Entity>()
{
public boolean apply(@Nullable Entity p_apply_1_)
{
return p_apply_1_ instanceof IMob;
}
};
/** Entity selector for IMob types that are not invisible */
Predicate<Entity> VISIBLE_MOB_SELECTOR = new Predicate<Entity>()
{
public boolean apply(@Nullable Entity p_apply_1_)
{
return p_apply_1_ instanceof IMob && !p_apply_1_.isInvisible();
}
};
}

View File

@@ -0,0 +1,7 @@
// Auto generated package-info by MCP
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
package net.minecraft.entity.monster;
import mcp.MethodsReturnNonnullByDefault;
import javax.annotation.ParametersAreNonnullByDefault;