base mod created
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,201 @@
|
||||
package net.minecraft.entity.item;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.boss.EntityDragon;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTUtil;
|
||||
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.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldProviderEnd;
|
||||
import net.minecraft.world.end.DragonFightManager;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class EntityEnderCrystal extends Entity
|
||||
{
|
||||
private static final DataParameter<Optional<BlockPos>> BEAM_TARGET = EntityDataManager.<Optional<BlockPos>>createKey(EntityEnderCrystal.class, DataSerializers.OPTIONAL_BLOCK_POS);
|
||||
private static final DataParameter<Boolean> SHOW_BOTTOM = EntityDataManager.<Boolean>createKey(EntityEnderCrystal.class, DataSerializers.BOOLEAN);
|
||||
/** Used to create the rotation animation when rendering the crystal. */
|
||||
public int innerRotation;
|
||||
|
||||
public EntityEnderCrystal(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
this.preventEntitySpawning = true;
|
||||
this.setSize(2.0F, 2.0F);
|
||||
this.innerRotation = this.rand.nextInt(100000);
|
||||
}
|
||||
|
||||
public EntityEnderCrystal(World worldIn, double x, double y, double z)
|
||||
{
|
||||
this(worldIn);
|
||||
this.setPosition(x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 void entityInit()
|
||||
{
|
||||
this.getDataManager().register(BEAM_TARGET, Optional.absent());
|
||||
this.getDataManager().register(SHOW_BOTTOM, Boolean.valueOf(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to update the entity's position/logic.
|
||||
*/
|
||||
public void onUpdate()
|
||||
{
|
||||
this.prevPosX = this.posX;
|
||||
this.prevPosY = this.posY;
|
||||
this.prevPosZ = this.posZ;
|
||||
++this.innerRotation;
|
||||
|
||||
if (!this.world.isRemote)
|
||||
{
|
||||
BlockPos blockpos = new BlockPos(this);
|
||||
|
||||
if (this.world.provider instanceof WorldProviderEnd && this.world.getBlockState(blockpos).getBlock() != Blocks.FIRE)
|
||||
{
|
||||
this.world.setBlockState(blockpos, Blocks.FIRE.getDefaultState());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to write subclass entity data to NBT.
|
||||
*/
|
||||
protected void writeEntityToNBT(NBTTagCompound compound)
|
||||
{
|
||||
if (this.getBeamTarget() != null)
|
||||
{
|
||||
compound.setTag("BeamTarget", NBTUtil.createPosTag(this.getBeamTarget()));
|
||||
}
|
||||
|
||||
compound.setBoolean("ShowBottom", this.shouldShowBottom());
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to read subclass entity data from NBT.
|
||||
*/
|
||||
protected void readEntityFromNBT(NBTTagCompound compound)
|
||||
{
|
||||
if (compound.hasKey("BeamTarget", 10))
|
||||
{
|
||||
this.setBeamTarget(NBTUtil.getPosFromTag(compound.getCompoundTag("BeamTarget")));
|
||||
}
|
||||
|
||||
if (compound.hasKey("ShowBottom", 1))
|
||||
{
|
||||
this.setShowBottom(compound.getBoolean("ShowBottom"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if other Entities should be prevented from moving through this Entity.
|
||||
*/
|
||||
public boolean canBeCollidedWith()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the entity is attacked.
|
||||
*/
|
||||
public boolean attackEntityFrom(DamageSource source, float amount)
|
||||
{
|
||||
if (this.isEntityInvulnerable(source))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (source.getTrueSource() instanceof EntityDragon)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!this.isDead && !this.world.isRemote)
|
||||
{
|
||||
this.setDead();
|
||||
|
||||
if (!this.world.isRemote)
|
||||
{
|
||||
if (!source.isExplosion())
|
||||
{
|
||||
this.world.createExplosion((Entity)null, this.posX, this.posY, this.posZ, 6.0F, true);
|
||||
}
|
||||
|
||||
this.onCrystalDestroyed(source);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the /kill command.
|
||||
*/
|
||||
public void onKillCommand()
|
||||
{
|
||||
this.onCrystalDestroyed(DamageSource.GENERIC);
|
||||
super.onKillCommand();
|
||||
}
|
||||
|
||||
private void onCrystalDestroyed(DamageSource source)
|
||||
{
|
||||
if (this.world.provider instanceof WorldProviderEnd)
|
||||
{
|
||||
WorldProviderEnd worldproviderend = (WorldProviderEnd)this.world.provider;
|
||||
DragonFightManager dragonfightmanager = worldproviderend.getDragonFightManager();
|
||||
|
||||
if (dragonfightmanager != null)
|
||||
{
|
||||
dragonfightmanager.onCrystalDestroyed(this, source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setBeamTarget(@Nullable BlockPos beamTarget)
|
||||
{
|
||||
this.getDataManager().set(BEAM_TARGET, Optional.fromNullable(beamTarget));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public BlockPos getBeamTarget()
|
||||
{
|
||||
return (BlockPos)((Optional)this.getDataManager().get(BEAM_TARGET)).orNull();
|
||||
}
|
||||
|
||||
public void setShowBottom(boolean showBottom)
|
||||
{
|
||||
this.getDataManager().set(SHOW_BOTTOM, Boolean.valueOf(showBottom));
|
||||
}
|
||||
|
||||
public boolean shouldShowBottom()
|
||||
{
|
||||
return ((Boolean)this.getDataManager().get(SHOW_BOTTOM)).booleanValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the entity is in range to render.
|
||||
*/
|
||||
@SideOnly(Side.CLIENT)
|
||||
public boolean isInRangeToRenderDist(double distance)
|
||||
{
|
||||
return super.isInRangeToRenderDist(distance) || this.getBeamTarget() != null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,243 @@
|
||||
package net.minecraft.entity.item;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.init.SoundEvents;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.EnumParticleTypes;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class EntityEnderEye extends Entity
|
||||
{
|
||||
/** 'x' location the eye should float towards. */
|
||||
private double targetX;
|
||||
/** 'y' location the eye should float towards. */
|
||||
private double targetY;
|
||||
/** 'z' location the eye should float towards. */
|
||||
private double targetZ;
|
||||
private int despawnTimer;
|
||||
private boolean shatterOrDrop;
|
||||
|
||||
public EntityEnderEye(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
this.setSize(0.25F, 0.25F);
|
||||
}
|
||||
|
||||
protected void entityInit()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the entity is in range to render.
|
||||
*/
|
||||
@SideOnly(Side.CLIENT)
|
||||
public boolean isInRangeToRenderDist(double distance)
|
||||
{
|
||||
double d0 = this.getEntityBoundingBox().getAverageEdgeLength() * 4.0D;
|
||||
|
||||
if (Double.isNaN(d0))
|
||||
{
|
||||
d0 = 4.0D;
|
||||
}
|
||||
|
||||
d0 = d0 * 64.0D;
|
||||
return distance < d0 * d0;
|
||||
}
|
||||
|
||||
public EntityEnderEye(World worldIn, double x, double y, double z)
|
||||
{
|
||||
super(worldIn);
|
||||
this.despawnTimer = 0;
|
||||
this.setSize(0.25F, 0.25F);
|
||||
this.setPosition(x, y, z);
|
||||
}
|
||||
|
||||
public void moveTowards(BlockPos pos)
|
||||
{
|
||||
double d0 = (double)pos.getX();
|
||||
int i = pos.getY();
|
||||
double d1 = (double)pos.getZ();
|
||||
double d2 = d0 - this.posX;
|
||||
double d3 = d1 - this.posZ;
|
||||
float f = MathHelper.sqrt(d2 * d2 + d3 * d3);
|
||||
|
||||
if (f > 12.0F)
|
||||
{
|
||||
this.targetX = this.posX + d2 / (double)f * 12.0D;
|
||||
this.targetZ = this.posZ + d3 / (double)f * 12.0D;
|
||||
this.targetY = this.posY + 8.0D;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.targetX = d0;
|
||||
this.targetY = (double)i;
|
||||
this.targetZ = d1;
|
||||
}
|
||||
|
||||
this.despawnTimer = 0;
|
||||
this.shatterOrDrop = this.rand.nextInt(5) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the entity motion clientside, called by packets from the server
|
||||
*/
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void setVelocity(double x, double y, double z)
|
||||
{
|
||||
this.motionX = x;
|
||||
this.motionY = y;
|
||||
this.motionZ = z;
|
||||
|
||||
if (this.prevRotationPitch == 0.0F && this.prevRotationYaw == 0.0F)
|
||||
{
|
||||
float f = MathHelper.sqrt(x * x + z * z);
|
||||
this.rotationYaw = (float)(MathHelper.atan2(x, z) * (180D / Math.PI));
|
||||
this.rotationPitch = (float)(MathHelper.atan2(y, (double)f) * (180D / Math.PI));
|
||||
this.prevRotationYaw = this.rotationYaw;
|
||||
this.prevRotationPitch = this.rotationPitch;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to update the entity's position/logic.
|
||||
*/
|
||||
public void onUpdate()
|
||||
{
|
||||
this.lastTickPosX = this.posX;
|
||||
this.lastTickPosY = this.posY;
|
||||
this.lastTickPosZ = this.posZ;
|
||||
super.onUpdate();
|
||||
this.posX += this.motionX;
|
||||
this.posY += this.motionY;
|
||||
this.posZ += this.motionZ;
|
||||
float f = MathHelper.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ);
|
||||
this.rotationYaw = (float)(MathHelper.atan2(this.motionX, this.motionZ) * (180D / Math.PI));
|
||||
|
||||
for (this.rotationPitch = (float)(MathHelper.atan2(this.motionY, (double)f) * (180D / Math.PI)); this.rotationPitch - this.prevRotationPitch < -180.0F; this.prevRotationPitch -= 360.0F)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
while (this.rotationPitch - this.prevRotationPitch >= 180.0F)
|
||||
{
|
||||
this.prevRotationPitch += 360.0F;
|
||||
}
|
||||
|
||||
while (this.rotationYaw - this.prevRotationYaw < -180.0F)
|
||||
{
|
||||
this.prevRotationYaw -= 360.0F;
|
||||
}
|
||||
|
||||
while (this.rotationYaw - this.prevRotationYaw >= 180.0F)
|
||||
{
|
||||
this.prevRotationYaw += 360.0F;
|
||||
}
|
||||
|
||||
this.rotationPitch = this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch) * 0.2F;
|
||||
this.rotationYaw = this.prevRotationYaw + (this.rotationYaw - this.prevRotationYaw) * 0.2F;
|
||||
|
||||
if (!this.world.isRemote)
|
||||
{
|
||||
double d0 = this.targetX - this.posX;
|
||||
double d1 = this.targetZ - this.posZ;
|
||||
float f1 = (float)Math.sqrt(d0 * d0 + d1 * d1);
|
||||
float f2 = (float)MathHelper.atan2(d1, d0);
|
||||
double d2 = (double)f + (double)(f1 - f) * 0.0025D;
|
||||
|
||||
if (f1 < 1.0F)
|
||||
{
|
||||
d2 *= 0.8D;
|
||||
this.motionY *= 0.8D;
|
||||
}
|
||||
|
||||
this.motionX = Math.cos((double)f2) * d2;
|
||||
this.motionZ = Math.sin((double)f2) * d2;
|
||||
|
||||
if (this.posY < this.targetY)
|
||||
{
|
||||
this.motionY += (1.0D - this.motionY) * 0.014999999664723873D;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.motionY += (-1.0D - this.motionY) * 0.014999999664723873D;
|
||||
}
|
||||
}
|
||||
|
||||
float f3 = 0.25F;
|
||||
|
||||
if (this.isInWater())
|
||||
{
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
this.world.spawnParticle(EnumParticleTypes.WATER_BUBBLE, this.posX - this.motionX * 0.25D, this.posY - this.motionY * 0.25D, this.posZ - this.motionZ * 0.25D, this.motionX, this.motionY, this.motionZ);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.world.spawnParticle(EnumParticleTypes.PORTAL, this.posX - this.motionX * 0.25D + this.rand.nextDouble() * 0.6D - 0.3D, this.posY - this.motionY * 0.25D - 0.5D, this.posZ - this.motionZ * 0.25D + this.rand.nextDouble() * 0.6D - 0.3D, this.motionX, this.motionY, this.motionZ);
|
||||
}
|
||||
|
||||
if (!this.world.isRemote)
|
||||
{
|
||||
this.setPosition(this.posX, this.posY, this.posZ);
|
||||
++this.despawnTimer;
|
||||
|
||||
if (this.despawnTimer > 80 && !this.world.isRemote)
|
||||
{
|
||||
this.playSound(SoundEvents.ENTITY_ENDEREYE_DEATH, 1.0F, 1.0F);
|
||||
this.setDead();
|
||||
|
||||
if (this.shatterOrDrop)
|
||||
{
|
||||
this.world.spawnEntity(new EntityItem(this.world, this.posX, this.posY, this.posZ, new ItemStack(Items.ENDER_EYE)));
|
||||
}
|
||||
else
|
||||
{
|
||||
this.world.playEvent(2003, new BlockPos(this), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to write subclass entity data to NBT.
|
||||
*/
|
||||
public void writeEntityToNBT(NBTTagCompound compound)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to read subclass entity data from NBT.
|
||||
*/
|
||||
public void readEntityFromNBT(NBTTagCompound compound)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets how bright this entity is.
|
||||
*/
|
||||
public float getBrightness()
|
||||
{
|
||||
return 1.0F;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public int getBrightnessForRender()
|
||||
{
|
||||
return 15728880;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if it's possible to attack this entity with an item.
|
||||
*/
|
||||
public boolean canBeAttackedWithItem()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
package net.minecraft.entity.item;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.advancements.CriteriaTriggers;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.monster.EntityEndermite;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.entity.projectile.EntityThrowable;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityEndGateway;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.EnumParticleTypes;
|
||||
import net.minecraft.util.datafix.DataFixer;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class EntityEnderPearl extends EntityThrowable
|
||||
{
|
||||
private EntityLivingBase perlThrower;
|
||||
|
||||
public EntityEnderPearl(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
}
|
||||
|
||||
public EntityEnderPearl(World worldIn, EntityLivingBase throwerIn)
|
||||
{
|
||||
super(worldIn, throwerIn);
|
||||
this.perlThrower = throwerIn;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public EntityEnderPearl(World worldIn, double x, double y, double z)
|
||||
{
|
||||
super(worldIn, x, y, z);
|
||||
}
|
||||
|
||||
public static void registerFixesEnderPearl(DataFixer fixer)
|
||||
{
|
||||
EntityThrowable.registerFixesThrowable(fixer, "ThrownEnderpearl");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this EntityThrowable hits a block or entity.
|
||||
*/
|
||||
protected void onImpact(RayTraceResult result)
|
||||
{
|
||||
EntityLivingBase entitylivingbase = this.getThrower();
|
||||
|
||||
if (result.entityHit != null)
|
||||
{
|
||||
if (result.entityHit == this.perlThrower)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
result.entityHit.attackEntityFrom(DamageSource.causeThrownDamage(this, entitylivingbase), 0.0F);
|
||||
}
|
||||
|
||||
if (result.typeOfHit == RayTraceResult.Type.BLOCK)
|
||||
{
|
||||
BlockPos blockpos = result.getBlockPos();
|
||||
TileEntity tileentity = this.world.getTileEntity(blockpos);
|
||||
|
||||
if (tileentity instanceof TileEntityEndGateway)
|
||||
{
|
||||
TileEntityEndGateway tileentityendgateway = (TileEntityEndGateway)tileentity;
|
||||
|
||||
if (entitylivingbase != null)
|
||||
{
|
||||
if (entitylivingbase instanceof EntityPlayerMP)
|
||||
{
|
||||
CriteriaTriggers.ENTER_BLOCK.trigger((EntityPlayerMP)entitylivingbase, this.world.getBlockState(blockpos));
|
||||
}
|
||||
|
||||
tileentityendgateway.teleportEntity(entitylivingbase);
|
||||
this.setDead();
|
||||
return;
|
||||
}
|
||||
|
||||
tileentityendgateway.teleportEntity(this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 32; ++i)
|
||||
{
|
||||
this.world.spawnParticle(EnumParticleTypes.PORTAL, this.posX, this.posY + this.rand.nextDouble() * 2.0D, this.posZ, this.rand.nextGaussian(), 0.0D, this.rand.nextGaussian());
|
||||
}
|
||||
|
||||
if (!this.world.isRemote)
|
||||
{
|
||||
if (entitylivingbase instanceof EntityPlayerMP)
|
||||
{
|
||||
EntityPlayerMP entityplayermp = (EntityPlayerMP)entitylivingbase;
|
||||
|
||||
if (entityplayermp.connection.getNetworkManager().isChannelOpen() && entityplayermp.world == this.world && !entityplayermp.isPlayerSleeping())
|
||||
{
|
||||
net.minecraftforge.event.entity.living.EnderTeleportEvent event = new net.minecraftforge.event.entity.living.EnderTeleportEvent(entityplayermp, this.posX, this.posY, this.posZ, 5.0F);
|
||||
if (!net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(event))
|
||||
{ // Don't indent to lower patch size
|
||||
if (this.rand.nextFloat() < 0.05F && this.world.getGameRules().getBoolean("doMobSpawning"))
|
||||
{
|
||||
EntityEndermite entityendermite = new EntityEndermite(this.world);
|
||||
entityendermite.setSpawnedByPlayer(true);
|
||||
entityendermite.setLocationAndAngles(entitylivingbase.posX, entitylivingbase.posY, entitylivingbase.posZ, entitylivingbase.rotationYaw, entitylivingbase.rotationPitch);
|
||||
this.world.spawnEntity(entityendermite);
|
||||
}
|
||||
|
||||
if (entitylivingbase.isRiding())
|
||||
{
|
||||
entitylivingbase.dismountRidingEntity();
|
||||
}
|
||||
|
||||
entitylivingbase.setPositionAndUpdate(event.getTargetX(), event.getTargetY(), event.getTargetZ());
|
||||
entitylivingbase.fallDistance = 0.0F;
|
||||
entitylivingbase.attackEntityFrom(DamageSource.FALL, event.getAttackDamage());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (entitylivingbase != null)
|
||||
{
|
||||
entitylivingbase.setPositionAndUpdate(this.posX, this.posY, this.posZ);
|
||||
entitylivingbase.fallDistance = 0.0F;
|
||||
}
|
||||
|
||||
this.setDead();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to update the entity's position/logic.
|
||||
*/
|
||||
public void onUpdate()
|
||||
{
|
||||
EntityLivingBase entitylivingbase = this.getThrower();
|
||||
|
||||
if (entitylivingbase != null && entitylivingbase instanceof EntityPlayer && !entitylivingbase.isEntityAlive())
|
||||
{
|
||||
this.setDead();
|
||||
}
|
||||
else
|
||||
{
|
||||
super.onUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Entity changeDimension(int dimensionIn, net.minecraftforge.common.util.ITeleporter teleporter)
|
||||
{
|
||||
if (this.thrower.dimension != dimensionIn)
|
||||
{
|
||||
this.thrower = null;
|
||||
}
|
||||
|
||||
return super.changeDimension(dimensionIn, teleporter);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package net.minecraft.entity.item;
|
||||
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.projectile.EntityThrowable;
|
||||
import net.minecraft.init.PotionTypes;
|
||||
import net.minecraft.potion.PotionUtils;
|
||||
import net.minecraft.util.datafix.DataFixer;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class EntityExpBottle extends EntityThrowable
|
||||
{
|
||||
public EntityExpBottle(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
}
|
||||
|
||||
public EntityExpBottle(World worldIn, EntityLivingBase throwerIn)
|
||||
{
|
||||
super(worldIn, throwerIn);
|
||||
}
|
||||
|
||||
public EntityExpBottle(World worldIn, double x, double y, double z)
|
||||
{
|
||||
super(worldIn, x, y, z);
|
||||
}
|
||||
|
||||
public static void registerFixesExpBottle(DataFixer fixer)
|
||||
{
|
||||
EntityThrowable.registerFixesThrowable(fixer, "ThrowableExpBottle");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount of gravity to apply to the thrown entity with each tick.
|
||||
*/
|
||||
protected float getGravityVelocity()
|
||||
{
|
||||
return 0.07F;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this EntityThrowable hits a block or entity.
|
||||
*/
|
||||
protected void onImpact(RayTraceResult result)
|
||||
{
|
||||
if (!this.world.isRemote)
|
||||
{
|
||||
this.world.playEvent(2002, new BlockPos(this), PotionUtils.getPotionColor(PotionTypes.WATER));
|
||||
int i = 3 + this.world.rand.nextInt(5) + this.world.rand.nextInt(5);
|
||||
|
||||
while (i > 0)
|
||||
{
|
||||
int j = EntityXPOrb.getXPSplit(i);
|
||||
i -= j;
|
||||
this.world.spawnEntity(new EntityXPOrb(this.world, this.posX, this.posY, this.posZ, j));
|
||||
}
|
||||
|
||||
this.setDead();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,402 @@
|
||||
package net.minecraft.entity.item;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockAnvil;
|
||||
import net.minecraft.block.BlockFalling;
|
||||
import net.minecraft.block.ITileEntityProvider;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.crash.CrashReportCategory;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.MoverType;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTBase;
|
||||
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.tileentity.TileEntity;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
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.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class EntityFallingBlock extends Entity
|
||||
{
|
||||
private IBlockState fallTile;
|
||||
public int fallTime;
|
||||
public boolean shouldDropItem = true;
|
||||
private boolean dontSetBlock;
|
||||
private boolean hurtEntities;
|
||||
private int fallHurtMax = 40;
|
||||
private float fallHurtAmount = 2.0F;
|
||||
public NBTTagCompound tileEntityData;
|
||||
protected static final DataParameter<BlockPos> ORIGIN = EntityDataManager.<BlockPos>createKey(EntityFallingBlock.class, DataSerializers.BLOCK_POS);
|
||||
|
||||
public EntityFallingBlock(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
}
|
||||
|
||||
public EntityFallingBlock(World worldIn, double x, double y, double z, IBlockState fallingBlockState)
|
||||
{
|
||||
super(worldIn);
|
||||
this.fallTile = fallingBlockState;
|
||||
this.preventEntitySpawning = true;
|
||||
this.setSize(0.98F, 0.98F);
|
||||
this.setPosition(x, y + (double)((1.0F - this.height) / 2.0F), z);
|
||||
this.motionX = 0.0D;
|
||||
this.motionY = 0.0D;
|
||||
this.motionZ = 0.0D;
|
||||
this.prevPosX = x;
|
||||
this.prevPosY = y;
|
||||
this.prevPosZ = z;
|
||||
this.setOrigin(new BlockPos(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if it's possible to attack this entity with an item.
|
||||
*/
|
||||
public boolean canBeAttackedWithItem()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setOrigin(BlockPos p_184530_1_)
|
||||
{
|
||||
this.dataManager.set(ORIGIN, p_184530_1_);
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public BlockPos getOrigin()
|
||||
{
|
||||
return (BlockPos)this.dataManager.get(ORIGIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 void entityInit()
|
||||
{
|
||||
this.dataManager.register(ORIGIN, BlockPos.ORIGIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if other Entities should be prevented from moving through this Entity.
|
||||
*/
|
||||
public boolean canBeCollidedWith()
|
||||
{
|
||||
return !this.isDead;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to update the entity's position/logic.
|
||||
*/
|
||||
public void onUpdate()
|
||||
{
|
||||
Block block = this.fallTile.getBlock();
|
||||
|
||||
if (this.fallTile.getMaterial() == Material.AIR)
|
||||
{
|
||||
this.setDead();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.prevPosX = this.posX;
|
||||
this.prevPosY = this.posY;
|
||||
this.prevPosZ = this.posZ;
|
||||
|
||||
if (this.fallTime++ == 0)
|
||||
{
|
||||
BlockPos blockpos = new BlockPos(this);
|
||||
|
||||
if (this.world.getBlockState(blockpos).getBlock() == block)
|
||||
{
|
||||
this.world.setBlockToAir(blockpos);
|
||||
}
|
||||
else if (!this.world.isRemote)
|
||||
{
|
||||
this.setDead();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.hasNoGravity())
|
||||
{
|
||||
this.motionY -= 0.03999999910593033D;
|
||||
}
|
||||
|
||||
this.move(MoverType.SELF, this.motionX, this.motionY, this.motionZ);
|
||||
|
||||
if (!this.world.isRemote)
|
||||
{
|
||||
BlockPos blockpos1 = new BlockPos(this);
|
||||
boolean flag = this.fallTile.getBlock() == Blocks.CONCRETE_POWDER;
|
||||
boolean flag1 = flag && this.world.getBlockState(blockpos1).getMaterial() == Material.WATER;
|
||||
double d0 = this.motionX * this.motionX + this.motionY * this.motionY + this.motionZ * this.motionZ;
|
||||
|
||||
if (flag && d0 > 1.0D)
|
||||
{
|
||||
RayTraceResult raytraceresult = this.world.rayTraceBlocks(new Vec3d(this.prevPosX, this.prevPosY, this.prevPosZ), new Vec3d(this.posX, this.posY, this.posZ), true);
|
||||
|
||||
if (raytraceresult != null && this.world.getBlockState(raytraceresult.getBlockPos()).getMaterial() == Material.WATER)
|
||||
{
|
||||
blockpos1 = raytraceresult.getBlockPos();
|
||||
flag1 = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.onGround && !flag1)
|
||||
{
|
||||
if (this.fallTime > 100 && !this.world.isRemote && (blockpos1.getY() < 1 || blockpos1.getY() > 256) || this.fallTime > 600)
|
||||
{
|
||||
if (this.shouldDropItem && this.world.getGameRules().getBoolean("doEntityDrops"))
|
||||
{
|
||||
this.entityDropItem(new ItemStack(block, 1, block.damageDropped(this.fallTile)), 0.0F);
|
||||
}
|
||||
|
||||
this.setDead();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IBlockState iblockstate = this.world.getBlockState(blockpos1);
|
||||
|
||||
if (this.world.isAirBlock(new BlockPos(this.posX, this.posY - 0.009999999776482582D, this.posZ))) //Forge: Don't indent below.
|
||||
if (!flag1 && BlockFalling.canFallThrough(this.world.getBlockState(new BlockPos(this.posX, this.posY - 0.009999999776482582D, this.posZ))))
|
||||
{
|
||||
this.onGround = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.motionX *= 0.699999988079071D;
|
||||
this.motionZ *= 0.699999988079071D;
|
||||
this.motionY *= -0.5D;
|
||||
|
||||
if (iblockstate.getBlock() != Blocks.PISTON_EXTENSION)
|
||||
{
|
||||
this.setDead();
|
||||
|
||||
if (!this.dontSetBlock)
|
||||
{
|
||||
if (this.world.mayPlace(block, blockpos1, true, EnumFacing.UP, (Entity)null) && (flag1 || !BlockFalling.canFallThrough(this.world.getBlockState(blockpos1.down()))) && this.world.setBlockState(blockpos1, this.fallTile, 3))
|
||||
{
|
||||
if (block instanceof BlockFalling)
|
||||
{
|
||||
((BlockFalling)block).onEndFalling(this.world, blockpos1, this.fallTile, iblockstate);
|
||||
}
|
||||
|
||||
if (this.tileEntityData != null && block.hasTileEntity(this.fallTile))
|
||||
{
|
||||
TileEntity tileentity = this.world.getTileEntity(blockpos1);
|
||||
|
||||
if (tileentity != null)
|
||||
{
|
||||
NBTTagCompound nbttagcompound = tileentity.writeToNBT(new NBTTagCompound());
|
||||
|
||||
for (String s : this.tileEntityData.getKeySet())
|
||||
{
|
||||
NBTBase nbtbase = this.tileEntityData.getTag(s);
|
||||
|
||||
if (!"x".equals(s) && !"y".equals(s) && !"z".equals(s))
|
||||
{
|
||||
nbttagcompound.setTag(s, nbtbase.copy());
|
||||
}
|
||||
}
|
||||
|
||||
tileentity.readFromNBT(nbttagcompound);
|
||||
tileentity.markDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (this.shouldDropItem && this.world.getGameRules().getBoolean("doEntityDrops"))
|
||||
{
|
||||
this.entityDropItem(new ItemStack(block, 1, block.damageDropped(this.fallTile)), 0.0F);
|
||||
}
|
||||
}
|
||||
else if (block instanceof BlockFalling)
|
||||
{
|
||||
((BlockFalling)block).onBroken(this.world, blockpos1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.motionX *= 0.9800000190734863D;
|
||||
this.motionY *= 0.9800000190734863D;
|
||||
this.motionZ *= 0.9800000190734863D;
|
||||
}
|
||||
}
|
||||
|
||||
public void fall(float distance, float damageMultiplier)
|
||||
{
|
||||
Block block = this.fallTile.getBlock();
|
||||
|
||||
if (this.hurtEntities)
|
||||
{
|
||||
int i = MathHelper.ceil(distance - 1.0F);
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
List<Entity> list = Lists.newArrayList(this.world.getEntitiesWithinAABBExcludingEntity(this, this.getEntityBoundingBox()));
|
||||
boolean flag = block == Blocks.ANVIL;
|
||||
DamageSource damagesource = flag ? DamageSource.ANVIL : DamageSource.FALLING_BLOCK;
|
||||
|
||||
for (Entity entity : list)
|
||||
{
|
||||
entity.attackEntityFrom(damagesource, (float)Math.min(MathHelper.floor((float)i * this.fallHurtAmount), this.fallHurtMax));
|
||||
}
|
||||
|
||||
if (flag && (double)this.rand.nextFloat() < 0.05000000074505806D + (double)i * 0.05D)
|
||||
{
|
||||
int j = ((Integer)this.fallTile.getValue(BlockAnvil.DAMAGE)).intValue();
|
||||
++j;
|
||||
|
||||
if (j > 2)
|
||||
{
|
||||
this.dontSetBlock = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.fallTile = this.fallTile.withProperty(BlockAnvil.DAMAGE, Integer.valueOf(j));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void registerFixesFallingBlock(DataFixer fixer)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to write subclass entity data to NBT.
|
||||
*/
|
||||
protected void writeEntityToNBT(NBTTagCompound compound)
|
||||
{
|
||||
Block block = this.fallTile != null ? this.fallTile.getBlock() : Blocks.AIR;
|
||||
ResourceLocation resourcelocation = Block.REGISTRY.getNameForObject(block);
|
||||
compound.setString("Block", resourcelocation == null ? "" : resourcelocation.toString());
|
||||
compound.setByte("Data", (byte)block.getMetaFromState(this.fallTile));
|
||||
compound.setInteger("Time", this.fallTime);
|
||||
compound.setBoolean("DropItem", this.shouldDropItem);
|
||||
compound.setBoolean("HurtEntities", this.hurtEntities);
|
||||
compound.setFloat("FallHurtAmount", this.fallHurtAmount);
|
||||
compound.setInteger("FallHurtMax", this.fallHurtMax);
|
||||
|
||||
if (this.tileEntityData != null)
|
||||
{
|
||||
compound.setTag("TileEntityData", this.tileEntityData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to read subclass entity data from NBT.
|
||||
*/
|
||||
protected void readEntityFromNBT(NBTTagCompound compound)
|
||||
{
|
||||
int i = compound.getByte("Data") & 255;
|
||||
|
||||
if (compound.hasKey("Block", 8))
|
||||
{
|
||||
this.fallTile = Block.getBlockFromName(compound.getString("Block")).getStateFromMeta(i);
|
||||
}
|
||||
else if (compound.hasKey("TileID", 99))
|
||||
{
|
||||
this.fallTile = Block.getBlockById(compound.getInteger("TileID")).getStateFromMeta(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.fallTile = Block.getBlockById(compound.getByte("Tile") & 255).getStateFromMeta(i);
|
||||
}
|
||||
|
||||
this.fallTime = compound.getInteger("Time");
|
||||
Block block = this.fallTile.getBlock();
|
||||
|
||||
if (compound.hasKey("HurtEntities", 99))
|
||||
{
|
||||
this.hurtEntities = compound.getBoolean("HurtEntities");
|
||||
this.fallHurtAmount = compound.getFloat("FallHurtAmount");
|
||||
this.fallHurtMax = compound.getInteger("FallHurtMax");
|
||||
}
|
||||
else if (block == Blocks.ANVIL)
|
||||
{
|
||||
this.hurtEntities = true;
|
||||
}
|
||||
|
||||
if (compound.hasKey("DropItem", 99))
|
||||
{
|
||||
this.shouldDropItem = compound.getBoolean("DropItem");
|
||||
}
|
||||
|
||||
if (compound.hasKey("TileEntityData", 10))
|
||||
{
|
||||
this.tileEntityData = compound.getCompoundTag("TileEntityData");
|
||||
}
|
||||
|
||||
if (block == null || block.getDefaultState().getMaterial() == Material.AIR)
|
||||
{
|
||||
this.fallTile = Blocks.SAND.getDefaultState();
|
||||
}
|
||||
}
|
||||
|
||||
public void setHurtEntities(boolean p_145806_1_)
|
||||
{
|
||||
this.hurtEntities = p_145806_1_;
|
||||
}
|
||||
|
||||
public void addEntityCrashInfo(CrashReportCategory category)
|
||||
{
|
||||
super.addEntityCrashInfo(category);
|
||||
|
||||
if (this.fallTile != null)
|
||||
{
|
||||
Block block = this.fallTile.getBlock();
|
||||
category.addCrashSection("Immitating block ID", Integer.valueOf(Block.getIdFromBlock(block)));
|
||||
category.addCrashSection("Immitating block data", Integer.valueOf(block.getMetaFromState(this.fallTile)));
|
||||
}
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public World getWorldObj()
|
||||
{
|
||||
return this.world;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this entity should be rendered as on fire.
|
||||
*/
|
||||
@SideOnly(Side.CLIENT)
|
||||
public boolean canRenderOnFire()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public IBlockState getBlock()
|
||||
{
|
||||
return this.fallTile;
|
||||
}
|
||||
|
||||
public boolean ignoreItemEntityData()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,324 @@
|
||||
package net.minecraft.entity.item;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.MoverType;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.SoundEvents;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.network.datasync.DataParameter;
|
||||
import net.minecraft.network.datasync.DataSerializers;
|
||||
import net.minecraft.network.datasync.EntityDataManager;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.EnumParticleTypes;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.datafix.DataFixer;
|
||||
import net.minecraft.util.datafix.FixTypes;
|
||||
import net.minecraft.util.datafix.walkers.ItemStackData;
|
||||
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.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class EntityFireworkRocket extends Entity
|
||||
{
|
||||
private static final DataParameter<ItemStack> FIREWORK_ITEM = EntityDataManager.<ItemStack>createKey(EntityFireworkRocket.class, DataSerializers.ITEM_STACK);
|
||||
private static final DataParameter<Integer> BOOSTED_ENTITY_ID = EntityDataManager.<Integer>createKey(EntityFireworkRocket.class, DataSerializers.VARINT);
|
||||
/** The age of the firework in ticks. */
|
||||
private int fireworkAge;
|
||||
/** The lifetime of the firework in ticks. When the age reaches the lifetime the firework explodes. */
|
||||
private int lifetime;
|
||||
private EntityLivingBase boostedEntity;
|
||||
|
||||
public EntityFireworkRocket(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
this.setSize(0.25F, 0.25F);
|
||||
}
|
||||
|
||||
protected void entityInit()
|
||||
{
|
||||
this.dataManager.register(FIREWORK_ITEM, ItemStack.EMPTY);
|
||||
this.dataManager.register(BOOSTED_ENTITY_ID, Integer.valueOf(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the entity is in range to render.
|
||||
*/
|
||||
@SideOnly(Side.CLIENT)
|
||||
public boolean isInRangeToRenderDist(double distance)
|
||||
{
|
||||
return distance < 4096.0D && !this.isAttachedToEntity();
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public boolean isInRangeToRender3d(double x, double y, double z)
|
||||
{
|
||||
return super.isInRangeToRender3d(x, y, z) && !this.isAttachedToEntity();
|
||||
}
|
||||
|
||||
public EntityFireworkRocket(World worldIn, double x, double y, double z, ItemStack givenItem)
|
||||
{
|
||||
super(worldIn);
|
||||
this.fireworkAge = 0;
|
||||
this.setSize(0.25F, 0.25F);
|
||||
this.setPosition(x, y, z);
|
||||
int i = 1;
|
||||
|
||||
if (!givenItem.isEmpty() && givenItem.hasTagCompound())
|
||||
{
|
||||
this.dataManager.set(FIREWORK_ITEM, givenItem.copy());
|
||||
NBTTagCompound nbttagcompound = givenItem.getTagCompound();
|
||||
NBTTagCompound nbttagcompound1 = nbttagcompound.getCompoundTag("Fireworks");
|
||||
i += nbttagcompound1.getByte("Flight");
|
||||
}
|
||||
|
||||
this.motionX = this.rand.nextGaussian() * 0.001D;
|
||||
this.motionZ = this.rand.nextGaussian() * 0.001D;
|
||||
this.motionY = 0.05D;
|
||||
this.lifetime = 10 * i + this.rand.nextInt(6) + this.rand.nextInt(7);
|
||||
}
|
||||
|
||||
public EntityFireworkRocket(World p_i47367_1_, ItemStack p_i47367_2_, EntityLivingBase p_i47367_3_)
|
||||
{
|
||||
this(p_i47367_1_, p_i47367_3_.posX, p_i47367_3_.posY, p_i47367_3_.posZ, p_i47367_2_);
|
||||
this.dataManager.set(BOOSTED_ENTITY_ID, Integer.valueOf(p_i47367_3_.getEntityId()));
|
||||
this.boostedEntity = p_i47367_3_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the entity motion clientside, called by packets from the server
|
||||
*/
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void setVelocity(double x, double y, double z)
|
||||
{
|
||||
this.motionX = x;
|
||||
this.motionY = y;
|
||||
this.motionZ = z;
|
||||
|
||||
if (this.prevRotationPitch == 0.0F && this.prevRotationYaw == 0.0F)
|
||||
{
|
||||
float f = MathHelper.sqrt(x * x + z * z);
|
||||
this.rotationYaw = (float)(MathHelper.atan2(x, z) * (180D / Math.PI));
|
||||
this.rotationPitch = (float)(MathHelper.atan2(y, (double)f) * (180D / Math.PI));
|
||||
this.prevRotationYaw = this.rotationYaw;
|
||||
this.prevRotationPitch = this.rotationPitch;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to update the entity's position/logic.
|
||||
*/
|
||||
public void onUpdate()
|
||||
{
|
||||
this.lastTickPosX = this.posX;
|
||||
this.lastTickPosY = this.posY;
|
||||
this.lastTickPosZ = this.posZ;
|
||||
super.onUpdate();
|
||||
|
||||
if (this.isAttachedToEntity())
|
||||
{
|
||||
if (this.boostedEntity == null)
|
||||
{
|
||||
Entity entity = this.world.getEntityByID(((Integer)this.dataManager.get(BOOSTED_ENTITY_ID)).intValue());
|
||||
|
||||
if (entity instanceof EntityLivingBase)
|
||||
{
|
||||
this.boostedEntity = (EntityLivingBase)entity;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.boostedEntity != null)
|
||||
{
|
||||
if (this.boostedEntity.isElytraFlying())
|
||||
{
|
||||
Vec3d vec3d = this.boostedEntity.getLookVec();
|
||||
double d0 = 1.5D;
|
||||
double d1 = 0.1D;
|
||||
this.boostedEntity.motionX += vec3d.x * 0.1D + (vec3d.x * 1.5D - this.boostedEntity.motionX) * 0.5D;
|
||||
this.boostedEntity.motionY += vec3d.y * 0.1D + (vec3d.y * 1.5D - this.boostedEntity.motionY) * 0.5D;
|
||||
this.boostedEntity.motionZ += vec3d.z * 0.1D + (vec3d.z * 1.5D - this.boostedEntity.motionZ) * 0.5D;
|
||||
}
|
||||
|
||||
this.setPosition(this.boostedEntity.posX, this.boostedEntity.posY, this.boostedEntity.posZ);
|
||||
this.motionX = this.boostedEntity.motionX;
|
||||
this.motionY = this.boostedEntity.motionY;
|
||||
this.motionZ = this.boostedEntity.motionZ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.motionX *= 1.15D;
|
||||
this.motionZ *= 1.15D;
|
||||
this.motionY += 0.04D;
|
||||
this.move(MoverType.SELF, this.motionX, this.motionY, this.motionZ);
|
||||
}
|
||||
|
||||
float f = MathHelper.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ);
|
||||
this.rotationYaw = (float)(MathHelper.atan2(this.motionX, this.motionZ) * (180D / Math.PI));
|
||||
|
||||
for (this.rotationPitch = (float)(MathHelper.atan2(this.motionY, (double)f) * (180D / Math.PI)); this.rotationPitch - this.prevRotationPitch < -180.0F; this.prevRotationPitch -= 360.0F)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
while (this.rotationPitch - this.prevRotationPitch >= 180.0F)
|
||||
{
|
||||
this.prevRotationPitch += 360.0F;
|
||||
}
|
||||
|
||||
while (this.rotationYaw - this.prevRotationYaw < -180.0F)
|
||||
{
|
||||
this.prevRotationYaw -= 360.0F;
|
||||
}
|
||||
|
||||
while (this.rotationYaw - this.prevRotationYaw >= 180.0F)
|
||||
{
|
||||
this.prevRotationYaw += 360.0F;
|
||||
}
|
||||
|
||||
this.rotationPitch = this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch) * 0.2F;
|
||||
this.rotationYaw = this.prevRotationYaw + (this.rotationYaw - this.prevRotationYaw) * 0.2F;
|
||||
|
||||
if (this.fireworkAge == 0 && !this.isSilent())
|
||||
{
|
||||
this.world.playSound((EntityPlayer)null, this.posX, this.posY, this.posZ, SoundEvents.ENTITY_FIREWORK_LAUNCH, SoundCategory.AMBIENT, 3.0F, 1.0F);
|
||||
}
|
||||
|
||||
++this.fireworkAge;
|
||||
|
||||
if (this.world.isRemote && this.fireworkAge % 2 < 2)
|
||||
{
|
||||
this.world.spawnParticle(EnumParticleTypes.FIREWORKS_SPARK, this.posX, this.posY - 0.3D, this.posZ, this.rand.nextGaussian() * 0.05D, -this.motionY * 0.5D, this.rand.nextGaussian() * 0.05D);
|
||||
}
|
||||
|
||||
if (!this.world.isRemote && this.fireworkAge > this.lifetime)
|
||||
{
|
||||
this.world.setEntityState(this, (byte)17);
|
||||
this.dealExplosionDamage();
|
||||
this.setDead();
|
||||
}
|
||||
}
|
||||
|
||||
private void dealExplosionDamage()
|
||||
{
|
||||
float f = 0.0F;
|
||||
ItemStack itemstack = (ItemStack)this.dataManager.get(FIREWORK_ITEM);
|
||||
NBTTagCompound nbttagcompound = itemstack.isEmpty() ? null : itemstack.getSubCompound("Fireworks");
|
||||
NBTTagList nbttaglist = nbttagcompound != null ? nbttagcompound.getTagList("Explosions", 10) : null;
|
||||
|
||||
if (nbttaglist != null && !nbttaglist.hasNoTags())
|
||||
{
|
||||
f = (float)(5 + nbttaglist.tagCount() * 2);
|
||||
}
|
||||
|
||||
if (f > 0.0F)
|
||||
{
|
||||
if (this.boostedEntity != null)
|
||||
{
|
||||
this.boostedEntity.attackEntityFrom(DamageSource.FIREWORKS, (float)(5 + nbttaglist.tagCount() * 2));
|
||||
}
|
||||
|
||||
double d0 = 5.0D;
|
||||
Vec3d vec3d = new Vec3d(this.posX, this.posY, this.posZ);
|
||||
|
||||
for (EntityLivingBase entitylivingbase : this.world.getEntitiesWithinAABB(EntityLivingBase.class, this.getEntityBoundingBox().grow(5.0D)))
|
||||
{
|
||||
if (entitylivingbase != this.boostedEntity && this.getDistanceSq(entitylivingbase) <= 25.0D)
|
||||
{
|
||||
boolean flag = false;
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
RayTraceResult raytraceresult = this.world.rayTraceBlocks(vec3d, new Vec3d(entitylivingbase.posX, entitylivingbase.posY + (double)entitylivingbase.height * 0.5D * (double)i, entitylivingbase.posZ), false, true, false);
|
||||
|
||||
if (raytraceresult == null || raytraceresult.typeOfHit == RayTraceResult.Type.MISS)
|
||||
{
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag)
|
||||
{
|
||||
float f1 = f * (float)Math.sqrt((5.0D - (double)this.getDistance(entitylivingbase)) / 5.0D);
|
||||
entitylivingbase.attackEntityFrom(DamageSource.FIREWORKS, f1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAttachedToEntity()
|
||||
{
|
||||
return ((Integer)this.dataManager.get(BOOSTED_ENTITY_ID)).intValue() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for {@link World#setEntityState}
|
||||
*/
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void handleStatusUpdate(byte id)
|
||||
{
|
||||
if (id == 17 && this.world.isRemote)
|
||||
{
|
||||
ItemStack itemstack = (ItemStack)this.dataManager.get(FIREWORK_ITEM);
|
||||
NBTTagCompound nbttagcompound = itemstack.isEmpty() ? null : itemstack.getSubCompound("Fireworks");
|
||||
this.world.makeFireworks(this.posX, this.posY, this.posZ, this.motionX, this.motionY, this.motionZ, nbttagcompound);
|
||||
}
|
||||
|
||||
super.handleStatusUpdate(id);
|
||||
}
|
||||
|
||||
public static void registerFixesFireworkRocket(DataFixer fixer)
|
||||
{
|
||||
fixer.registerWalker(FixTypes.ENTITY, new ItemStackData(EntityFireworkRocket.class, new String[] {"FireworksItem"}));
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to write subclass entity data to NBT.
|
||||
*/
|
||||
public void writeEntityToNBT(NBTTagCompound compound)
|
||||
{
|
||||
compound.setInteger("Life", this.fireworkAge);
|
||||
compound.setInteger("LifeTime", this.lifetime);
|
||||
ItemStack itemstack = (ItemStack)this.dataManager.get(FIREWORK_ITEM);
|
||||
|
||||
if (!itemstack.isEmpty())
|
||||
{
|
||||
compound.setTag("FireworksItem", itemstack.writeToNBT(new NBTTagCompound()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to read subclass entity data from NBT.
|
||||
*/
|
||||
public void readEntityFromNBT(NBTTagCompound compound)
|
||||
{
|
||||
this.fireworkAge = compound.getInteger("Life");
|
||||
this.lifetime = compound.getInteger("LifeTime");
|
||||
NBTTagCompound nbttagcompound = compound.getCompoundTag("FireworksItem");
|
||||
|
||||
if (nbttagcompound != null)
|
||||
{
|
||||
ItemStack itemstack = new ItemStack(nbttagcompound);
|
||||
|
||||
if (!itemstack.isEmpty())
|
||||
{
|
||||
this.dataManager.set(FIREWORK_ITEM, itemstack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if it's possible to attack this entity with an item.
|
||||
*/
|
||||
public boolean canBeAttackedWithItem()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,563 @@
|
||||
package net.minecraft.entity.item;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.MoverType;
|
||||
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.stats.StatList;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.datafix.DataFixer;
|
||||
import net.minecraft.util.datafix.FixTypes;
|
||||
import net.minecraft.util.datafix.walkers.ItemStackData;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.text.translation.I18n;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class EntityItem extends Entity
|
||||
{
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private static final DataParameter<ItemStack> ITEM = EntityDataManager.<ItemStack>createKey(EntityItem.class, DataSerializers.ITEM_STACK);
|
||||
/** The age of this EntityItem (used to animate it up and down as well as expire it) */
|
||||
private int age;
|
||||
private int pickupDelay;
|
||||
/** The health of this EntityItem. (For example, damage for tools) */
|
||||
private int health;
|
||||
private String thrower;
|
||||
private String owner;
|
||||
/** The EntityItem's random initial float height. */
|
||||
public float hoverStart;
|
||||
|
||||
/**
|
||||
* The maximum age of this EntityItem. The item is expired once this is reached.
|
||||
*/
|
||||
public int lifespan = 6000;
|
||||
|
||||
public EntityItem(World worldIn, double x, double y, double z)
|
||||
{
|
||||
super(worldIn);
|
||||
this.health = 5;
|
||||
this.hoverStart = (float)(Math.random() * Math.PI * 2.0D);
|
||||
this.setSize(0.25F, 0.25F);
|
||||
this.setPosition(x, y, z);
|
||||
this.rotationYaw = (float)(Math.random() * 360.0D);
|
||||
this.motionX = (double)((float)(Math.random() * 0.20000000298023224D - 0.10000000149011612D));
|
||||
this.motionY = 0.20000000298023224D;
|
||||
this.motionZ = (double)((float)(Math.random() * 0.20000000298023224D - 0.10000000149011612D));
|
||||
}
|
||||
|
||||
public EntityItem(World worldIn, double x, double y, double z, ItemStack stack)
|
||||
{
|
||||
this(worldIn, x, y, z);
|
||||
this.setItem(stack);
|
||||
this.lifespan = (stack.getItem() == null ? 6000 : stack.getItem().getEntityLifespan(stack, worldIn));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 EntityItem(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
this.health = 5;
|
||||
this.hoverStart = (float)(Math.random() * Math.PI * 2.0D);
|
||||
this.setSize(0.25F, 0.25F);
|
||||
this.setItem(ItemStack.EMPTY);
|
||||
}
|
||||
|
||||
protected void entityInit()
|
||||
{
|
||||
this.getDataManager().register(ITEM, ItemStack.EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to update the entity's position/logic.
|
||||
*/
|
||||
public void onUpdate()
|
||||
{
|
||||
if (getItem().getItem().onEntityItemUpdate(this)) return;
|
||||
if (this.getItem().isEmpty())
|
||||
{
|
||||
this.setDead();
|
||||
}
|
||||
else
|
||||
{
|
||||
super.onUpdate();
|
||||
|
||||
if (this.pickupDelay > 0 && this.pickupDelay != 32767)
|
||||
{
|
||||
--this.pickupDelay;
|
||||
}
|
||||
|
||||
this.prevPosX = this.posX;
|
||||
this.prevPosY = this.posY;
|
||||
this.prevPosZ = this.posZ;
|
||||
double d0 = this.motionX;
|
||||
double d1 = this.motionY;
|
||||
double d2 = this.motionZ;
|
||||
|
||||
if (!this.hasNoGravity())
|
||||
{
|
||||
this.motionY -= 0.03999999910593033D;
|
||||
}
|
||||
|
||||
if (this.world.isRemote)
|
||||
{
|
||||
this.noClip = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.noClip = this.pushOutOfBlocks(this.posX, (this.getEntityBoundingBox().minY + this.getEntityBoundingBox().maxY) / 2.0D, this.posZ);
|
||||
}
|
||||
|
||||
this.move(MoverType.SELF, this.motionX, this.motionY, this.motionZ);
|
||||
boolean flag = (int)this.prevPosX != (int)this.posX || (int)this.prevPosY != (int)this.posY || (int)this.prevPosZ != (int)this.posZ;
|
||||
|
||||
if (flag || this.ticksExisted % 25 == 0)
|
||||
{
|
||||
if (this.world.getBlockState(new BlockPos(this)).getMaterial() == Material.LAVA)
|
||||
{
|
||||
this.motionY = 0.20000000298023224D;
|
||||
this.motionX = (double)((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F);
|
||||
this.motionZ = (double)((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F);
|
||||
this.playSound(SoundEvents.ENTITY_GENERIC_BURN, 0.4F, 2.0F + this.rand.nextFloat() * 0.4F);
|
||||
}
|
||||
|
||||
if (!this.world.isRemote)
|
||||
{
|
||||
this.searchForOtherItemsNearby();
|
||||
}
|
||||
}
|
||||
|
||||
float f = 0.98F;
|
||||
|
||||
if (this.onGround)
|
||||
{
|
||||
BlockPos underPos = new BlockPos(MathHelper.floor(this.posX), MathHelper.floor(this.getEntityBoundingBox().minY) - 1, MathHelper.floor(this.posZ));
|
||||
net.minecraft.block.state.IBlockState underState = this.world.getBlockState(underPos);
|
||||
f = underState.getBlock().getSlipperiness(underState, this.world, underPos, this) * 0.98F;
|
||||
}
|
||||
|
||||
this.motionX *= (double)f;
|
||||
this.motionY *= 0.9800000190734863D;
|
||||
this.motionZ *= (double)f;
|
||||
|
||||
if (this.onGround)
|
||||
{
|
||||
this.motionY *= -0.5D;
|
||||
}
|
||||
|
||||
if (this.age != -32768)
|
||||
{
|
||||
++this.age;
|
||||
}
|
||||
|
||||
this.handleWaterMovement();
|
||||
|
||||
if (!this.world.isRemote)
|
||||
{
|
||||
double d3 = this.motionX - d0;
|
||||
double d4 = this.motionY - d1;
|
||||
double d5 = this.motionZ - d2;
|
||||
double d6 = d3 * d3 + d4 * d4 + d5 * d5;
|
||||
|
||||
if (d6 > 0.01D)
|
||||
{
|
||||
this.isAirBorne = true;
|
||||
}
|
||||
}
|
||||
|
||||
ItemStack item = this.getItem();
|
||||
|
||||
if (!this.world.isRemote && this.age >= lifespan)
|
||||
{
|
||||
int hook = net.minecraftforge.event.ForgeEventFactory.onItemExpire(this, item);
|
||||
if (hook < 0) this.setDead();
|
||||
else this.lifespan += hook;
|
||||
}
|
||||
if (item.isEmpty())
|
||||
{
|
||||
this.setDead();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks for other itemstacks nearby and tries to stack them together
|
||||
*/
|
||||
private void searchForOtherItemsNearby()
|
||||
{
|
||||
for (EntityItem entityitem : this.world.getEntitiesWithinAABB(EntityItem.class, this.getEntityBoundingBox().grow(0.5D, 0.0D, 0.5D)))
|
||||
{
|
||||
this.combineItems(entityitem);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to merge this item with the item passed as the parameter. Returns true if successful. Either this item or
|
||||
* the other item will be removed from the world.
|
||||
*/
|
||||
private boolean combineItems(EntityItem other)
|
||||
{
|
||||
if (other == this)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (other.isEntityAlive() && this.isEntityAlive())
|
||||
{
|
||||
ItemStack itemstack = this.getItem();
|
||||
ItemStack itemstack1 = other.getItem();
|
||||
|
||||
if (this.pickupDelay != 32767 && other.pickupDelay != 32767)
|
||||
{
|
||||
if (this.age != -32768 && other.age != -32768)
|
||||
{
|
||||
if (itemstack1.getItem() != itemstack.getItem())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (itemstack1.hasTagCompound() ^ itemstack.hasTagCompound())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (itemstack1.hasTagCompound() && !itemstack1.getTagCompound().equals(itemstack.getTagCompound()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (itemstack1.getItem() == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (itemstack1.getItem().getHasSubtypes() && itemstack1.getMetadata() != itemstack.getMetadata())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (itemstack1.getCount() < itemstack.getCount())
|
||||
{
|
||||
return other.combineItems(this);
|
||||
}
|
||||
else if (itemstack1.getCount() + itemstack.getCount() > itemstack1.getMaxStackSize())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!itemstack.areCapsCompatible(itemstack1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
itemstack1.grow(itemstack.getCount());
|
||||
other.pickupDelay = Math.max(other.pickupDelay, this.pickupDelay);
|
||||
other.age = Math.min(other.age, this.age);
|
||||
other.setItem(itemstack1);
|
||||
this.setDead();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the age of the item so that it'll despawn one minute after it has been dropped (instead of five). Used when
|
||||
* items are dropped from players in creative mode
|
||||
*/
|
||||
public void setAgeToCreativeDespawnTime()
|
||||
{
|
||||
this.age = 4800;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if this entity is in water and will end up adding the waters velocity to the entity
|
||||
*/
|
||||
public boolean handleWaterMovement()
|
||||
{
|
||||
if (this.world.handleMaterialAcceleration(this.getEntityBoundingBox(), Material.WATER, this))
|
||||
{
|
||||
if (!this.inWater && !this.firstUpdate)
|
||||
{
|
||||
this.doWaterSplashEffect();
|
||||
}
|
||||
|
||||
this.inWater = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.inWater = false;
|
||||
}
|
||||
|
||||
return this.inWater;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will deal the specified amount of fire damage to the entity if the entity isn't immune to fire damage.
|
||||
*/
|
||||
protected void dealFireDamage(int amount)
|
||||
{
|
||||
this.attackEntityFrom(DamageSource.IN_FIRE, (float)amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the entity is attacked.
|
||||
*/
|
||||
public boolean attackEntityFrom(DamageSource source, float amount)
|
||||
{
|
||||
if (this.world.isRemote || this.isDead) return false; //Forge: Fixes MC-53850
|
||||
if (this.isEntityInvulnerable(source))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!this.getItem().isEmpty() && this.getItem().getItem() == Items.NETHER_STAR && source.isExplosion())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.markVelocityChanged();
|
||||
this.health = (int)((float)this.health - amount);
|
||||
|
||||
if (this.health <= 0)
|
||||
{
|
||||
this.setDead();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void registerFixesItem(DataFixer fixer)
|
||||
{
|
||||
fixer.registerWalker(FixTypes.ENTITY, new ItemStackData(EntityItem.class, new String[] {"Item"}));
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to write subclass entity data to NBT.
|
||||
*/
|
||||
public void writeEntityToNBT(NBTTagCompound compound)
|
||||
{
|
||||
compound.setShort("Health", (short)this.health);
|
||||
compound.setShort("Age", (short)this.age);
|
||||
compound.setShort("PickupDelay", (short)this.pickupDelay);
|
||||
compound.setInteger("Lifespan", lifespan);
|
||||
|
||||
if (this.getThrower() != null)
|
||||
{
|
||||
compound.setString("Thrower", this.thrower);
|
||||
}
|
||||
|
||||
if (this.getOwner() != null)
|
||||
{
|
||||
compound.setString("Owner", this.owner);
|
||||
}
|
||||
|
||||
if (!this.getItem().isEmpty())
|
||||
{
|
||||
compound.setTag("Item", this.getItem().writeToNBT(new NBTTagCompound()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to read subclass entity data from NBT.
|
||||
*/
|
||||
public void readEntityFromNBT(NBTTagCompound compound)
|
||||
{
|
||||
this.health = compound.getShort("Health");
|
||||
this.age = compound.getShort("Age");
|
||||
|
||||
if (compound.hasKey("PickupDelay"))
|
||||
{
|
||||
this.pickupDelay = compound.getShort("PickupDelay");
|
||||
}
|
||||
|
||||
if (compound.hasKey("Owner"))
|
||||
{
|
||||
this.owner = compound.getString("Owner");
|
||||
}
|
||||
|
||||
if (compound.hasKey("Thrower"))
|
||||
{
|
||||
this.thrower = compound.getString("Thrower");
|
||||
}
|
||||
|
||||
NBTTagCompound nbttagcompound = compound.getCompoundTag("Item");
|
||||
this.setItem(new ItemStack(nbttagcompound));
|
||||
|
||||
if (this.getItem().isEmpty())
|
||||
{
|
||||
this.setDead();
|
||||
}
|
||||
if (compound.hasKey("Lifespan")) lifespan = compound.getInteger("Lifespan");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by a player entity when they collide with an entity
|
||||
*/
|
||||
public void onCollideWithPlayer(EntityPlayer entityIn)
|
||||
{
|
||||
if (!this.world.isRemote)
|
||||
{
|
||||
if (this.pickupDelay > 0) return;
|
||||
ItemStack itemstack = this.getItem();
|
||||
Item item = itemstack.getItem();
|
||||
int i = itemstack.getCount();
|
||||
|
||||
int hook = net.minecraftforge.event.ForgeEventFactory.onItemPickup(this, entityIn);
|
||||
if (hook < 0) return;
|
||||
ItemStack clone = itemstack.copy();
|
||||
|
||||
if (this.pickupDelay <= 0 && (this.owner == null || lifespan - this.age <= 200 || this.owner.equals(entityIn.getName())) && (hook == 1 || i <= 0 || entityIn.inventory.addItemStackToInventory(itemstack) || clone.getCount() > this.getItem().getCount()))
|
||||
{
|
||||
clone.setCount(clone.getCount() - this.getItem().getCount());
|
||||
net.minecraftforge.fml.common.FMLCommonHandler.instance().firePlayerItemPickupEvent(entityIn, this, clone);
|
||||
|
||||
if (itemstack.isEmpty())
|
||||
{
|
||||
entityIn.onItemPickup(this, i);
|
||||
this.setDead();
|
||||
itemstack.setCount(i);
|
||||
}
|
||||
|
||||
entityIn.addStat(StatList.getObjectsPickedUpStats(item), i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of this object. For players this returns their username
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
return this.hasCustomName() ? this.getCustomNameTag() : I18n.translateToLocal("item." + this.getItem().getUnlocalizedName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if it's possible to attack this entity with an item.
|
||||
*/
|
||||
public boolean canBeAttackedWithItem()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Entity changeDimension(int dimensionIn, net.minecraftforge.common.util.ITeleporter teleporter)
|
||||
{
|
||||
Entity entity = super.changeDimension(dimensionIn, teleporter);
|
||||
|
||||
if (!this.world.isRemote && entity instanceof EntityItem)
|
||||
{
|
||||
((EntityItem)entity).searchForOtherItemsNearby();
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item that this entity represents.
|
||||
*/
|
||||
public ItemStack getItem()
|
||||
{
|
||||
return (ItemStack)this.getDataManager().get(ITEM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the item that this entity represents.
|
||||
*/
|
||||
public void setItem(ItemStack stack)
|
||||
{
|
||||
this.getDataManager().set(ITEM, stack);
|
||||
this.getDataManager().setDirty(ITEM);
|
||||
}
|
||||
|
||||
public String getOwner()
|
||||
{
|
||||
return this.owner;
|
||||
}
|
||||
|
||||
public void setOwner(String owner)
|
||||
{
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public String getThrower()
|
||||
{
|
||||
return this.thrower;
|
||||
}
|
||||
|
||||
public void setThrower(String thrower)
|
||||
{
|
||||
this.thrower = thrower;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public int getAge()
|
||||
{
|
||||
return this.age;
|
||||
}
|
||||
|
||||
public void setDefaultPickupDelay()
|
||||
{
|
||||
this.pickupDelay = 10;
|
||||
}
|
||||
|
||||
public void setNoPickupDelay()
|
||||
{
|
||||
this.pickupDelay = 0;
|
||||
}
|
||||
|
||||
public void setInfinitePickupDelay()
|
||||
{
|
||||
this.pickupDelay = 32767;
|
||||
}
|
||||
|
||||
public void setPickupDelay(int ticks)
|
||||
{
|
||||
this.pickupDelay = ticks;
|
||||
}
|
||||
|
||||
public boolean cannotPickup()
|
||||
{
|
||||
return this.pickupDelay > 0;
|
||||
}
|
||||
|
||||
public void setNoDespawn()
|
||||
{
|
||||
this.age = -6000;
|
||||
}
|
||||
|
||||
public void makeFakeItem()
|
||||
{
|
||||
this.setInfinitePickupDelay();
|
||||
this.age = getItem().getItem().getEntityLifespan(getItem(), world) - 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,309 @@
|
||||
package net.minecraft.entity.item;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityHanging;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.init.SoundEvents;
|
||||
import net.minecraft.item.ItemMap;
|
||||
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.EnumFacing;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.datafix.DataFixer;
|
||||
import net.minecraft.util.datafix.FixTypes;
|
||||
import net.minecraft.util.datafix.walkers.ItemStackData;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.storage.MapData;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class EntityItemFrame extends EntityHanging
|
||||
{
|
||||
private static final DataParameter<ItemStack> ITEM = EntityDataManager.<ItemStack>createKey(EntityItemFrame.class, DataSerializers.ITEM_STACK);
|
||||
private static final DataParameter<Integer> ROTATION = EntityDataManager.<Integer>createKey(EntityItemFrame.class, DataSerializers.VARINT);
|
||||
/** Chance for this item frame's item to drop from the frame. */
|
||||
private float itemDropChance = 1.0F;
|
||||
|
||||
public EntityItemFrame(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
}
|
||||
|
||||
public EntityItemFrame(World worldIn, BlockPos p_i45852_2_, EnumFacing p_i45852_3_)
|
||||
{
|
||||
super(worldIn, p_i45852_2_);
|
||||
this.updateFacingWithBoundingBox(p_i45852_3_);
|
||||
}
|
||||
|
||||
protected void entityInit()
|
||||
{
|
||||
this.getDataManager().register(ITEM, ItemStack.EMPTY);
|
||||
this.getDataManager().register(ROTATION, Integer.valueOf(0));
|
||||
}
|
||||
|
||||
public float getCollisionBorderSize()
|
||||
{
|
||||
return 0.0F;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the entity is attacked.
|
||||
*/
|
||||
public boolean attackEntityFrom(DamageSource source, float amount)
|
||||
{
|
||||
if (this.isEntityInvulnerable(source))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!source.isExplosion() && !this.getDisplayedItem().isEmpty())
|
||||
{
|
||||
if (!this.world.isRemote)
|
||||
{
|
||||
this.dropItemOrSelf(source.getTrueSource(), false);
|
||||
this.playSound(SoundEvents.ENTITY_ITEMFRAME_REMOVE_ITEM, 1.0F, 1.0F);
|
||||
this.setDisplayedItem(ItemStack.EMPTY);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return super.attackEntityFrom(source, amount);
|
||||
}
|
||||
}
|
||||
|
||||
public int getWidthPixels()
|
||||
{
|
||||
return 12;
|
||||
}
|
||||
|
||||
public int getHeightPixels()
|
||||
{
|
||||
return 12;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the entity is in range to render.
|
||||
*/
|
||||
@SideOnly(Side.CLIENT)
|
||||
public boolean isInRangeToRenderDist(double distance)
|
||||
{
|
||||
double d0 = 16.0D;
|
||||
d0 = d0 * 64.0D * getRenderDistanceWeight();
|
||||
return distance < d0 * d0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this entity is broken. Entity parameter may be null.
|
||||
*/
|
||||
public void onBroken(@Nullable Entity brokenEntity)
|
||||
{
|
||||
this.playSound(SoundEvents.ENTITY_ITEMFRAME_BREAK, 1.0F, 1.0F);
|
||||
this.dropItemOrSelf(brokenEntity, true);
|
||||
}
|
||||
|
||||
public void playPlaceSound()
|
||||
{
|
||||
this.playSound(SoundEvents.ENTITY_ITEMFRAME_PLACE, 1.0F, 1.0F);
|
||||
}
|
||||
|
||||
public void dropItemOrSelf(@Nullable Entity entityIn, boolean p_146065_2_)
|
||||
{
|
||||
if (this.world.getGameRules().getBoolean("doEntityDrops"))
|
||||
{
|
||||
ItemStack itemstack = this.getDisplayedItem();
|
||||
|
||||
if (entityIn instanceof EntityPlayer)
|
||||
{
|
||||
EntityPlayer entityplayer = (EntityPlayer)entityIn;
|
||||
|
||||
if (entityplayer.capabilities.isCreativeMode)
|
||||
{
|
||||
this.removeFrameFromMap(itemstack);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (p_146065_2_)
|
||||
{
|
||||
this.entityDropItem(new ItemStack(Items.ITEM_FRAME), 0.0F);
|
||||
}
|
||||
|
||||
if (!itemstack.isEmpty() && this.rand.nextFloat() < this.itemDropChance)
|
||||
{
|
||||
itemstack = itemstack.copy();
|
||||
this.removeFrameFromMap(itemstack);
|
||||
this.entityDropItem(itemstack, 0.0F);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the dot representing this frame's position from the map when the item frame is broken.
|
||||
*/
|
||||
private void removeFrameFromMap(ItemStack stack)
|
||||
{
|
||||
if (!stack.isEmpty())
|
||||
{
|
||||
if (stack.getItem() instanceof net.minecraft.item.ItemMap)
|
||||
{
|
||||
MapData mapdata = ((ItemMap)stack.getItem()).getMapData(stack, this.world);
|
||||
mapdata.mapDecorations.remove("frame-" + this.getEntityId());
|
||||
}
|
||||
|
||||
stack.setItemFrame((EntityItemFrame)null);
|
||||
this.setDisplayedItem(ItemStack.EMPTY); //Forge: Fix MC-124833 Pistons duplicating Items.
|
||||
}
|
||||
}
|
||||
|
||||
public ItemStack getDisplayedItem()
|
||||
{
|
||||
return (ItemStack)this.getDataManager().get(ITEM);
|
||||
}
|
||||
|
||||
public void setDisplayedItem(ItemStack stack)
|
||||
{
|
||||
this.setDisplayedItemWithUpdate(stack, true);
|
||||
}
|
||||
|
||||
private void setDisplayedItemWithUpdate(ItemStack stack, boolean p_174864_2_)
|
||||
{
|
||||
if (!stack.isEmpty())
|
||||
{
|
||||
stack = stack.copy();
|
||||
stack.setCount(1);
|
||||
stack.setItemFrame(this);
|
||||
}
|
||||
|
||||
this.getDataManager().set(ITEM, stack);
|
||||
this.getDataManager().setDirty(ITEM);
|
||||
|
||||
if (!stack.isEmpty())
|
||||
{
|
||||
this.playSound(SoundEvents.ENTITY_ITEMFRAME_ADD_ITEM, 1.0F, 1.0F);
|
||||
}
|
||||
|
||||
if (p_174864_2_ && this.hangingPosition != null)
|
||||
{
|
||||
this.world.updateComparatorOutputLevel(this.hangingPosition, Blocks.AIR);
|
||||
}
|
||||
}
|
||||
|
||||
public void notifyDataManagerChange(DataParameter<?> key)
|
||||
{
|
||||
if (key.equals(ITEM))
|
||||
{
|
||||
ItemStack itemstack = this.getDisplayedItem();
|
||||
|
||||
if (!itemstack.isEmpty() && itemstack.getItemFrame() != this)
|
||||
{
|
||||
itemstack.setItemFrame(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the rotation of the item currently on this frame.
|
||||
*/
|
||||
public int getRotation()
|
||||
{
|
||||
return ((Integer)this.getDataManager().get(ROTATION)).intValue();
|
||||
}
|
||||
|
||||
public void setItemRotation(int rotationIn)
|
||||
{
|
||||
this.setRotation(rotationIn, true);
|
||||
}
|
||||
|
||||
private void setRotation(int rotationIn, boolean p_174865_2_)
|
||||
{
|
||||
this.getDataManager().set(ROTATION, Integer.valueOf(rotationIn % 8));
|
||||
|
||||
if (p_174865_2_ && this.hangingPosition != null)
|
||||
{
|
||||
this.world.updateComparatorOutputLevel(this.hangingPosition, Blocks.AIR);
|
||||
}
|
||||
}
|
||||
|
||||
public static void registerFixesItemFrame(DataFixer fixer)
|
||||
{
|
||||
fixer.registerWalker(FixTypes.ENTITY, new ItemStackData(EntityItemFrame.class, new String[] {"Item"}));
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to write subclass entity data to NBT.
|
||||
*/
|
||||
public void writeEntityToNBT(NBTTagCompound compound)
|
||||
{
|
||||
if (!this.getDisplayedItem().isEmpty())
|
||||
{
|
||||
compound.setTag("Item", this.getDisplayedItem().writeToNBT(new NBTTagCompound()));
|
||||
compound.setByte("ItemRotation", (byte)this.getRotation());
|
||||
compound.setFloat("ItemDropChance", this.itemDropChance);
|
||||
}
|
||||
|
||||
super.writeEntityToNBT(compound);
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to read subclass entity data from NBT.
|
||||
*/
|
||||
public void readEntityFromNBT(NBTTagCompound compound)
|
||||
{
|
||||
NBTTagCompound nbttagcompound = compound.getCompoundTag("Item");
|
||||
|
||||
if (nbttagcompound != null && !nbttagcompound.hasNoTags())
|
||||
{
|
||||
this.setDisplayedItemWithUpdate(new ItemStack(nbttagcompound), false);
|
||||
this.setRotation(compound.getByte("ItemRotation"), false);
|
||||
|
||||
if (compound.hasKey("ItemDropChance", 99))
|
||||
{
|
||||
this.itemDropChance = compound.getFloat("ItemDropChance");
|
||||
}
|
||||
}
|
||||
|
||||
super.readEntityFromNBT(compound);
|
||||
}
|
||||
|
||||
public boolean processInitialInteract(EntityPlayer player, EnumHand hand)
|
||||
{
|
||||
ItemStack itemstack = player.getHeldItem(hand);
|
||||
|
||||
if (!this.world.isRemote)
|
||||
{
|
||||
if (this.getDisplayedItem().isEmpty())
|
||||
{
|
||||
if (!itemstack.isEmpty())
|
||||
{
|
||||
this.setDisplayedItem(itemstack);
|
||||
|
||||
if (!player.capabilities.isCreativeMode)
|
||||
{
|
||||
itemstack.shrink(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.playSound(SoundEvents.ENTITY_ITEMFRAME_ROTATE_ITEM, 1.0F, 1.0F);
|
||||
this.setItemRotation(this.getRotation() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getAnalogOutput()
|
||||
{
|
||||
return this.getDisplayedItem().isEmpty() ? 0 : this.getRotation() % 8 + 1;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,76 @@
|
||||
package net.minecraft.entity.item;
|
||||
|
||||
import net.minecraft.block.BlockChest;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.inventory.Container;
|
||||
import net.minecraft.inventory.ContainerChest;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.datafix.DataFixer;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class EntityMinecartChest extends EntityMinecartContainer
|
||||
{
|
||||
public EntityMinecartChest(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
}
|
||||
|
||||
public EntityMinecartChest(World worldIn, double x, double y, double z)
|
||||
{
|
||||
super(worldIn, x, y, z);
|
||||
}
|
||||
|
||||
public static void registerFixesMinecartChest(DataFixer fixer)
|
||||
{
|
||||
EntityMinecartContainer.addDataFixers(fixer, EntityMinecartChest.class);
|
||||
}
|
||||
|
||||
public void killMinecart(DamageSource source)
|
||||
{
|
||||
super.killMinecart(source);
|
||||
|
||||
if (this.world.getGameRules().getBoolean("doEntityDrops"))
|
||||
{
|
||||
this.dropItemWithOffset(Item.getItemFromBlock(Blocks.CHEST), 1, 0.0F);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of slots in the inventory.
|
||||
*/
|
||||
public int getSizeInventory()
|
||||
{
|
||||
return 27;
|
||||
}
|
||||
|
||||
public EntityMinecart.Type getType()
|
||||
{
|
||||
return EntityMinecart.Type.CHEST;
|
||||
}
|
||||
|
||||
public IBlockState getDefaultDisplayTile()
|
||||
{
|
||||
return Blocks.CHEST.getDefaultState().withProperty(BlockChest.FACING, EnumFacing.NORTH);
|
||||
}
|
||||
|
||||
public int getDefaultDisplayTileOffset()
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
public String getGuiID()
|
||||
{
|
||||
return "minecraft:chest";
|
||||
}
|
||||
|
||||
public Container createContainer(InventoryPlayer playerInventory, EntityPlayer playerIn)
|
||||
{
|
||||
this.addLoot(playerIn);
|
||||
return new ContainerChest(playerInventory, this, playerIn);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
package net.minecraft.entity.item;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Blocks;
|
||||
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.server.MinecraftServer;
|
||||
import net.minecraft.tileentity.CommandBlockBaseLogic;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityCommandBlock;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.datafix.DataFixer;
|
||||
import net.minecraft.util.datafix.FixTypes;
|
||||
import net.minecraft.util.datafix.IDataFixer;
|
||||
import net.minecraft.util.datafix.IDataWalker;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class EntityMinecartCommandBlock extends EntityMinecart
|
||||
{
|
||||
private static final DataParameter<String> COMMAND = EntityDataManager.<String>createKey(EntityMinecartCommandBlock.class, DataSerializers.STRING);
|
||||
private static final DataParameter<ITextComponent> LAST_OUTPUT = EntityDataManager.<ITextComponent>createKey(EntityMinecartCommandBlock.class, DataSerializers.TEXT_COMPONENT);
|
||||
private final CommandBlockBaseLogic commandBlockLogic = new CommandBlockBaseLogic()
|
||||
{
|
||||
public void updateCommand()
|
||||
{
|
||||
EntityMinecartCommandBlock.this.getDataManager().set(EntityMinecartCommandBlock.COMMAND, this.getCommand());
|
||||
EntityMinecartCommandBlock.this.getDataManager().set(EntityMinecartCommandBlock.LAST_OUTPUT, this.getLastOutput());
|
||||
}
|
||||
/**
|
||||
* Currently this returns 0 for the traditional command block, and 1 for the minecart command block
|
||||
*/
|
||||
@SideOnly(Side.CLIENT)
|
||||
public int getCommandBlockType()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
/**
|
||||
* Fills in information about the command block for the packet. entityId for the minecart version, and X/Y/Z for
|
||||
* the traditional version
|
||||
*/
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void fillInInfo(ByteBuf buf)
|
||||
{
|
||||
buf.writeInt(EntityMinecartCommandBlock.this.getEntityId());
|
||||
}
|
||||
/**
|
||||
* Get the position in the world. <b>{@code null} is not allowed!</b> If you are not an entity in the world,
|
||||
* return the coordinates 0, 0, 0
|
||||
*/
|
||||
public BlockPos getPosition()
|
||||
{
|
||||
return new BlockPos(EntityMinecartCommandBlock.this.posX, EntityMinecartCommandBlock.this.posY + 0.5D, EntityMinecartCommandBlock.this.posZ);
|
||||
}
|
||||
/**
|
||||
* Get the position vector. <b>{@code null} is not allowed!</b> If you are not an entity in the world, return
|
||||
* 0.0D, 0.0D, 0.0D
|
||||
*/
|
||||
public Vec3d getPositionVector()
|
||||
{
|
||||
return new Vec3d(EntityMinecartCommandBlock.this.posX, EntityMinecartCommandBlock.this.posY, EntityMinecartCommandBlock.this.posZ);
|
||||
}
|
||||
/**
|
||||
* Get the world, if available. <b>{@code null} is not allowed!</b> If you are not an entity in the world,
|
||||
* return the overworld
|
||||
*/
|
||||
public World getEntityWorld()
|
||||
{
|
||||
return EntityMinecartCommandBlock.this.world;
|
||||
}
|
||||
/**
|
||||
* Returns the entity associated with the command sender. MAY BE NULL!
|
||||
*/
|
||||
public Entity getCommandSenderEntity()
|
||||
{
|
||||
return EntityMinecartCommandBlock.this;
|
||||
}
|
||||
/**
|
||||
* Get the Minecraft server instance
|
||||
*/
|
||||
public MinecraftServer getServer()
|
||||
{
|
||||
return EntityMinecartCommandBlock.this.world.getMinecraftServer();
|
||||
}
|
||||
};
|
||||
/** Cooldown before command block logic runs again in ticks */
|
||||
private int activatorRailCooldown;
|
||||
|
||||
public EntityMinecartCommandBlock(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
}
|
||||
|
||||
public EntityMinecartCommandBlock(World worldIn, double x, double y, double z)
|
||||
{
|
||||
super(worldIn, x, y, z);
|
||||
}
|
||||
|
||||
public static void registerFixesMinecartCommand(DataFixer fixer)
|
||||
{
|
||||
EntityMinecart.registerFixesMinecart(fixer, EntityMinecartCommandBlock.class);
|
||||
fixer.registerWalker(FixTypes.ENTITY, new IDataWalker()
|
||||
{
|
||||
public NBTTagCompound process(IDataFixer fixer, NBTTagCompound compound, int versionIn)
|
||||
{
|
||||
if (TileEntity.getKey(TileEntityCommandBlock.class).equals(new ResourceLocation(compound.getString("id"))))
|
||||
{
|
||||
compound.setString("id", "Control");
|
||||
fixer.process(FixTypes.BLOCK_ENTITY, compound, versionIn);
|
||||
compound.setString("id", "MinecartCommandBlock");
|
||||
}
|
||||
|
||||
return compound;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void entityInit()
|
||||
{
|
||||
super.entityInit();
|
||||
this.getDataManager().register(COMMAND, "");
|
||||
this.getDataManager().register(LAST_OUTPUT, new TextComponentString(""));
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to read subclass entity data from NBT.
|
||||
*/
|
||||
protected void readEntityFromNBT(NBTTagCompound compound)
|
||||
{
|
||||
super.readEntityFromNBT(compound);
|
||||
this.commandBlockLogic.readDataFromNBT(compound);
|
||||
this.getDataManager().set(COMMAND, this.getCommandBlockLogic().getCommand());
|
||||
this.getDataManager().set(LAST_OUTPUT, this.getCommandBlockLogic().getLastOutput());
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to write subclass entity data to NBT.
|
||||
*/
|
||||
protected void writeEntityToNBT(NBTTagCompound compound)
|
||||
{
|
||||
super.writeEntityToNBT(compound);
|
||||
this.commandBlockLogic.writeToNBT(compound);
|
||||
}
|
||||
|
||||
public EntityMinecart.Type getType()
|
||||
{
|
||||
return EntityMinecart.Type.COMMAND_BLOCK;
|
||||
}
|
||||
|
||||
public IBlockState getDefaultDisplayTile()
|
||||
{
|
||||
return Blocks.COMMAND_BLOCK.getDefaultState();
|
||||
}
|
||||
|
||||
public CommandBlockBaseLogic getCommandBlockLogic()
|
||||
{
|
||||
return this.commandBlockLogic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called every tick the minecart is on an activator rail.
|
||||
*/
|
||||
public void onActivatorRailPass(int x, int y, int z, boolean receivingPower)
|
||||
{
|
||||
if (receivingPower && this.ticksExisted - this.activatorRailCooldown >= 4)
|
||||
{
|
||||
this.getCommandBlockLogic().trigger(this.world);
|
||||
this.activatorRailCooldown = this.ticksExisted;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean processInitialInteract(EntityPlayer player, EnumHand hand)
|
||||
{
|
||||
if (super.processInitialInteract(player, hand)) return true;
|
||||
this.commandBlockLogic.tryOpenEditCommandBlock(player);
|
||||
return false;
|
||||
}
|
||||
|
||||
public void notifyDataManagerChange(DataParameter<?> key)
|
||||
{
|
||||
super.notifyDataManagerChange(key);
|
||||
|
||||
if (LAST_OUTPUT.equals(key))
|
||||
{
|
||||
try
|
||||
{
|
||||
this.commandBlockLogic.setLastOutput((ITextComponent)this.getDataManager().get(LAST_OUTPUT));
|
||||
}
|
||||
catch (Throwable var3)
|
||||
{
|
||||
;
|
||||
}
|
||||
}
|
||||
else if (COMMAND.equals(key))
|
||||
{
|
||||
this.commandBlockLogic.setCommand((String)this.getDataManager().get(COMMAND));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean ignoreItemEntityData()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,366 @@
|
||||
package net.minecraft.entity.item;
|
||||
|
||||
import java.util.Random;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.inventory.Container;
|
||||
import net.minecraft.inventory.InventoryHelper;
|
||||
import net.minecraft.inventory.ItemStackHelper;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.datafix.DataFixer;
|
||||
import net.minecraft.util.datafix.FixTypes;
|
||||
import net.minecraft.util.datafix.walkers.ItemStackDataLists;
|
||||
import net.minecraft.world.ILockableContainer;
|
||||
import net.minecraft.world.LockCode;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraft.world.storage.loot.ILootContainer;
|
||||
import net.minecraft.world.storage.loot.LootContext;
|
||||
import net.minecraft.world.storage.loot.LootTable;
|
||||
|
||||
public abstract class EntityMinecartContainer extends EntityMinecart implements ILockableContainer, ILootContainer
|
||||
{
|
||||
private NonNullList<ItemStack> minecartContainerItems = NonNullList.<ItemStack>withSize(36, ItemStack.EMPTY);
|
||||
/**
|
||||
* When set to true, the minecart will drop all items when setDead() is called. When false (such as when travelling
|
||||
* dimensions) it preserves its contents.
|
||||
*/
|
||||
public boolean dropContentsWhenDead = true;
|
||||
private ResourceLocation lootTable;
|
||||
private long lootTableSeed;
|
||||
|
||||
public EntityMinecartContainer(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
}
|
||||
|
||||
public EntityMinecartContainer(World worldIn, double x, double y, double z)
|
||||
{
|
||||
super(worldIn, x, y, z);
|
||||
}
|
||||
|
||||
public void killMinecart(DamageSource source)
|
||||
{
|
||||
super.killMinecart(source);
|
||||
|
||||
if (this.world.getGameRules().getBoolean("doEntityDrops"))
|
||||
{
|
||||
InventoryHelper.dropInventoryItems(this.world, this, this);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
for (ItemStack itemstack : this.minecartContainerItems)
|
||||
{
|
||||
if (!itemstack.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the stack in the given slot.
|
||||
*/
|
||||
public ItemStack getStackInSlot(int index)
|
||||
{
|
||||
this.addLoot((EntityPlayer)null);
|
||||
return this.minecartContainerItems.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes up to a specified number of items from an inventory slot and returns them in a new stack.
|
||||
*/
|
||||
public ItemStack decrStackSize(int index, int count)
|
||||
{
|
||||
this.addLoot((EntityPlayer)null);
|
||||
return ItemStackHelper.getAndSplit(this.minecartContainerItems, index, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a stack from the given slot and returns it.
|
||||
*/
|
||||
public ItemStack removeStackFromSlot(int index)
|
||||
{
|
||||
this.addLoot((EntityPlayer)null);
|
||||
ItemStack itemstack = this.minecartContainerItems.get(index);
|
||||
|
||||
if (itemstack.isEmpty())
|
||||
{
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.minecartContainerItems.set(index, ItemStack.EMPTY);
|
||||
return itemstack;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given item stack to the specified slot in the inventory (can be crafting or armor sections).
|
||||
*/
|
||||
public void setInventorySlotContents(int index, ItemStack stack)
|
||||
{
|
||||
this.addLoot((EntityPlayer)null);
|
||||
this.minecartContainerItems.set(index, stack);
|
||||
|
||||
if (!stack.isEmpty() && stack.getCount() > this.getInventoryStackLimit())
|
||||
{
|
||||
stack.setCount(this.getInventoryStackLimit());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For tile entities, ensures the chunk containing the tile entity is saved to disk later - the game won't think it
|
||||
* hasn't changed and skip it.
|
||||
*/
|
||||
public void markDirty()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't rename this method to canInteractWith due to conflicts with Container
|
||||
*/
|
||||
public boolean isUsableByPlayer(EntityPlayer player)
|
||||
{
|
||||
if (this.isDead)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return player.getDistanceSq(this) <= 64.0D;
|
||||
}
|
||||
}
|
||||
|
||||
public void openInventory(EntityPlayer player)
|
||||
{
|
||||
}
|
||||
|
||||
public void closeInventory(EntityPlayer player)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if automation is allowed to insert the given stack (ignoring stack size) into the given slot. For
|
||||
* guis use Slot.isItemValid
|
||||
*/
|
||||
public boolean isItemValidForSlot(int index, ItemStack stack)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum stack size for a inventory slot. Seems to always be 64, possibly will be extended.
|
||||
*/
|
||||
public int getInventoryStackLimit()
|
||||
{
|
||||
return 64;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Entity changeDimension(int dimensionIn, net.minecraftforge.common.util.ITeleporter teleporter)
|
||||
{
|
||||
this.dropContentsWhenDead = false;
|
||||
return super.changeDimension(dimensionIn, teleporter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Will get destroyed next tick.
|
||||
*/
|
||||
public void setDead()
|
||||
{
|
||||
if (this.dropContentsWhenDead)
|
||||
{
|
||||
InventoryHelper.dropInventoryItems(this.world, this, this);
|
||||
}
|
||||
|
||||
super.setDead();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this entity should drop its items when setDead() is called. This applies to container minecarts.
|
||||
*/
|
||||
public void setDropItemsWhenDead(boolean dropWhenDead)
|
||||
{
|
||||
this.dropContentsWhenDead = dropWhenDead;
|
||||
}
|
||||
|
||||
public static void addDataFixers(DataFixer p_190574_0_, Class<?> p_190574_1_)
|
||||
{
|
||||
EntityMinecart.registerFixesMinecart(p_190574_0_, p_190574_1_);
|
||||
p_190574_0_.registerWalker(FixTypes.ENTITY, new ItemStackDataLists(p_190574_1_, new String[] {"Items"}));
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to write subclass entity data to NBT.
|
||||
*/
|
||||
protected void writeEntityToNBT(NBTTagCompound compound)
|
||||
{
|
||||
super.writeEntityToNBT(compound);
|
||||
|
||||
if (this.lootTable != null)
|
||||
{
|
||||
compound.setString("LootTable", this.lootTable.toString());
|
||||
|
||||
if (this.lootTableSeed != 0L)
|
||||
{
|
||||
compound.setLong("LootTableSeed", this.lootTableSeed);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ItemStackHelper.saveAllItems(compound, this.minecartContainerItems);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to read subclass entity data from NBT.
|
||||
*/
|
||||
protected void readEntityFromNBT(NBTTagCompound compound)
|
||||
{
|
||||
super.readEntityFromNBT(compound);
|
||||
this.minecartContainerItems = NonNullList.<ItemStack>withSize(this.getSizeInventory(), ItemStack.EMPTY);
|
||||
|
||||
if (compound.hasKey("LootTable", 8))
|
||||
{
|
||||
this.lootTable = new ResourceLocation(compound.getString("LootTable"));
|
||||
this.lootTableSeed = compound.getLong("LootTableSeed");
|
||||
}
|
||||
else
|
||||
{
|
||||
ItemStackHelper.loadAllItems(compound, this.minecartContainerItems);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean processInitialInteract(EntityPlayer player, EnumHand hand)
|
||||
{
|
||||
if (super.processInitialInteract(player, hand)) return true;
|
||||
if (!this.world.isRemote)
|
||||
{
|
||||
player.displayGUIChest(this);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void applyDrag()
|
||||
{
|
||||
float f = 0.98F;
|
||||
|
||||
if (this.lootTable == null)
|
||||
{
|
||||
int i = 15 - Container.calcRedstoneFromInventory(this);
|
||||
f += (float)i * 0.001F;
|
||||
}
|
||||
|
||||
this.motionX *= (double)f;
|
||||
this.motionY *= 0.0D;
|
||||
this.motionZ *= (double)f;
|
||||
}
|
||||
|
||||
public int getField(int id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void setField(int id, int value)
|
||||
{
|
||||
}
|
||||
|
||||
public int getFieldCount()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean isLocked()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setLockCode(LockCode code)
|
||||
{
|
||||
}
|
||||
|
||||
public LockCode getLockCode()
|
||||
{
|
||||
return LockCode.EMPTY_CODE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds loot to the minecart's contents.
|
||||
*/
|
||||
public void addLoot(@Nullable EntityPlayer player)
|
||||
{
|
||||
if (this.lootTable != null)
|
||||
{
|
||||
LootTable loottable = this.world.getLootTableManager().getLootTableFromLocation(this.lootTable);
|
||||
this.lootTable = null;
|
||||
Random random;
|
||||
|
||||
if (this.lootTableSeed == 0L)
|
||||
{
|
||||
random = new Random();
|
||||
}
|
||||
else
|
||||
{
|
||||
random = new Random(this.lootTableSeed);
|
||||
}
|
||||
|
||||
LootContext.Builder lootcontext$builder = new LootContext.Builder((WorldServer)this.world).withLootedEntity(this); // Forge: add looted entity to LootContext
|
||||
|
||||
if (player != null)
|
||||
{
|
||||
lootcontext$builder.withLuck(player.getLuck()).withPlayer(player); // Forge: add player to LootContext
|
||||
}
|
||||
|
||||
loottable.fillInventory(this, random, lootcontext$builder.build());
|
||||
}
|
||||
}
|
||||
|
||||
public net.minecraftforge.items.IItemHandler itemHandler = new net.minecraftforge.items.wrapper.InvWrapper(this);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
@Nullable
|
||||
public <T> T getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, @Nullable net.minecraft.util.EnumFacing facing)
|
||||
{
|
||||
if (capability == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
|
||||
{
|
||||
return (T) itemHandler;
|
||||
}
|
||||
return super.getCapability(capability, facing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCapability(net.minecraftforge.common.capabilities.Capability<?> capability, @Nullable net.minecraft.util.EnumFacing facing)
|
||||
{
|
||||
return capability == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY || super.hasCapability(capability, facing);
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
this.addLoot((EntityPlayer)null);
|
||||
this.minecartContainerItems.clear();
|
||||
}
|
||||
|
||||
public void setLootTable(ResourceLocation lootTableIn, long lootTableSeedIn)
|
||||
{
|
||||
this.lootTable = lootTableIn;
|
||||
this.lootTableSeed = lootTableSeedIn;
|
||||
}
|
||||
|
||||
public ResourceLocation getLootTable()
|
||||
{
|
||||
return this.lootTable;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package net.minecraft.entity.item;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.datafix.DataFixer;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class EntityMinecartEmpty extends EntityMinecart
|
||||
{
|
||||
public EntityMinecartEmpty(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
}
|
||||
|
||||
public EntityMinecartEmpty(World worldIn, double x, double y, double z)
|
||||
{
|
||||
super(worldIn, x, y, z);
|
||||
}
|
||||
|
||||
public static void registerFixesMinecartEmpty(DataFixer fixer)
|
||||
{
|
||||
EntityMinecart.registerFixesMinecart(fixer, EntityMinecartEmpty.class);
|
||||
}
|
||||
|
||||
public boolean processInitialInteract(EntityPlayer player, EnumHand hand)
|
||||
{
|
||||
if (super.processInitialInteract(player, hand)) return true;
|
||||
|
||||
if (player.isSneaking())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (this.isBeingRidden())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!this.world.isRemote)
|
||||
{
|
||||
player.startRiding(this);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called every tick the minecart is on an activator rail.
|
||||
*/
|
||||
public void onActivatorRailPass(int x, int y, int z, boolean receivingPower)
|
||||
{
|
||||
if (receivingPower)
|
||||
{
|
||||
if (this.isBeingRidden())
|
||||
{
|
||||
this.removePassengers();
|
||||
}
|
||||
|
||||
if (this.getRollingAmplitude() == 0)
|
||||
{
|
||||
this.setRollingDirection(-this.getRollingDirection());
|
||||
this.setRollingAmplitude(10);
|
||||
this.setDamage(50.0F);
|
||||
this.markVelocityChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public EntityMinecart.Type getType()
|
||||
{
|
||||
return EntityMinecart.Type.RIDEABLE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
package net.minecraft.entity.item;
|
||||
|
||||
import net.minecraft.block.BlockFurnace;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.init.Items;
|
||||
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.EnumFacing;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.EnumParticleTypes;
|
||||
import net.minecraft.util.datafix.DataFixer;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class EntityMinecartFurnace extends EntityMinecart
|
||||
{
|
||||
private static final DataParameter<Boolean> POWERED = EntityDataManager.<Boolean>createKey(EntityMinecartFurnace.class, DataSerializers.BOOLEAN);
|
||||
private int fuel;
|
||||
public double pushX;
|
||||
public double pushZ;
|
||||
|
||||
public EntityMinecartFurnace(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
}
|
||||
|
||||
public EntityMinecartFurnace(World worldIn, double x, double y, double z)
|
||||
{
|
||||
super(worldIn, x, y, z);
|
||||
}
|
||||
|
||||
public static void registerFixesMinecartFurnace(DataFixer fixer)
|
||||
{
|
||||
EntityMinecart.registerFixesMinecart(fixer, EntityMinecartFurnace.class);
|
||||
}
|
||||
|
||||
public EntityMinecart.Type getType()
|
||||
{
|
||||
return EntityMinecart.Type.FURNACE;
|
||||
}
|
||||
|
||||
protected void entityInit()
|
||||
{
|
||||
super.entityInit();
|
||||
this.dataManager.register(POWERED, Boolean.valueOf(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to update the entity's position/logic.
|
||||
*/
|
||||
public void onUpdate()
|
||||
{
|
||||
super.onUpdate();
|
||||
|
||||
if (this.fuel > 0)
|
||||
{
|
||||
--this.fuel;
|
||||
}
|
||||
|
||||
if (this.fuel <= 0)
|
||||
{
|
||||
this.pushX = 0.0D;
|
||||
this.pushZ = 0.0D;
|
||||
}
|
||||
|
||||
this.setMinecartPowered(this.fuel > 0);
|
||||
|
||||
if (this.isMinecartPowered() && this.rand.nextInt(4) == 0)
|
||||
{
|
||||
this.world.spawnParticle(EnumParticleTypes.SMOKE_LARGE, this.posX, this.posY + 0.8D, this.posZ, 0.0D, 0.0D, 0.0D);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get's the maximum speed for a minecart
|
||||
*/
|
||||
protected double getMaximumSpeed()
|
||||
{
|
||||
return 0.2D;
|
||||
}
|
||||
|
||||
public void killMinecart(DamageSource source)
|
||||
{
|
||||
super.killMinecart(source);
|
||||
|
||||
if (!source.isExplosion() && this.world.getGameRules().getBoolean("doEntityDrops"))
|
||||
{
|
||||
this.entityDropItem(new ItemStack(Blocks.FURNACE, 1), 0.0F);
|
||||
}
|
||||
}
|
||||
|
||||
protected void moveAlongTrack(BlockPos pos, IBlockState state)
|
||||
{
|
||||
super.moveAlongTrack(pos, state);
|
||||
double d0 = this.pushX * this.pushX + this.pushZ * this.pushZ;
|
||||
|
||||
if (d0 > 1.0E-4D && this.motionX * this.motionX + this.motionZ * this.motionZ > 0.001D)
|
||||
{
|
||||
d0 = (double)MathHelper.sqrt(d0);
|
||||
this.pushX /= d0;
|
||||
this.pushZ /= d0;
|
||||
|
||||
if (this.pushX * this.motionX + this.pushZ * this.motionZ < 0.0D)
|
||||
{
|
||||
this.pushX = 0.0D;
|
||||
this.pushZ = 0.0D;
|
||||
}
|
||||
else
|
||||
{
|
||||
double d1 = d0 / this.getMaximumSpeed();
|
||||
this.pushX *= d1;
|
||||
this.pushZ *= d1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void applyDrag()
|
||||
{
|
||||
double d0 = this.pushX * this.pushX + this.pushZ * this.pushZ;
|
||||
|
||||
if (d0 > 1.0E-4D)
|
||||
{
|
||||
d0 = (double)MathHelper.sqrt(d0);
|
||||
this.pushX /= d0;
|
||||
this.pushZ /= d0;
|
||||
double d1 = 1.0D;
|
||||
this.motionX *= 0.800000011920929D;
|
||||
this.motionY *= 0.0D;
|
||||
this.motionZ *= 0.800000011920929D;
|
||||
this.motionX += this.pushX * 1.0D;
|
||||
this.motionZ += this.pushZ * 1.0D;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.motionX *= 0.9800000190734863D;
|
||||
this.motionY *= 0.0D;
|
||||
this.motionZ *= 0.9800000190734863D;
|
||||
}
|
||||
|
||||
super.applyDrag();
|
||||
}
|
||||
|
||||
public boolean processInitialInteract(EntityPlayer player, EnumHand hand)
|
||||
{
|
||||
ItemStack itemstack = player.getHeldItem(hand);
|
||||
|
||||
if (super.processInitialInteract(player, hand)) return true;
|
||||
|
||||
if (itemstack.getItem() == Items.COAL && this.fuel + 3600 <= 32000)
|
||||
{
|
||||
if (!player.capabilities.isCreativeMode)
|
||||
{
|
||||
itemstack.shrink(1);
|
||||
}
|
||||
|
||||
this.fuel += 3600;
|
||||
}
|
||||
|
||||
this.pushX = this.posX - player.posX;
|
||||
this.pushZ = this.posZ - player.posZ;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to write subclass entity data to NBT.
|
||||
*/
|
||||
protected void writeEntityToNBT(NBTTagCompound compound)
|
||||
{
|
||||
super.writeEntityToNBT(compound);
|
||||
compound.setDouble("PushX", this.pushX);
|
||||
compound.setDouble("PushZ", this.pushZ);
|
||||
compound.setShort("Fuel", (short)this.fuel);
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to read subclass entity data from NBT.
|
||||
*/
|
||||
protected void readEntityFromNBT(NBTTagCompound compound)
|
||||
{
|
||||
super.readEntityFromNBT(compound);
|
||||
this.pushX = compound.getDouble("PushX");
|
||||
this.pushZ = compound.getDouble("PushZ");
|
||||
this.fuel = compound.getShort("Fuel");
|
||||
}
|
||||
|
||||
protected boolean isMinecartPowered()
|
||||
{
|
||||
return ((Boolean)this.dataManager.get(POWERED)).booleanValue();
|
||||
}
|
||||
|
||||
protected void setMinecartPowered(boolean p_94107_1_)
|
||||
{
|
||||
this.dataManager.set(POWERED, Boolean.valueOf(p_94107_1_));
|
||||
}
|
||||
|
||||
public IBlockState getDefaultDisplayTile()
|
||||
{
|
||||
return (this.isMinecartPowered() ? Blocks.LIT_FURNACE : Blocks.FURNACE).getDefaultState().withProperty(BlockFurnace.FACING, EnumFacing.NORTH);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
package net.minecraft.entity.item;
|
||||
|
||||
import java.util.List;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.inventory.Container;
|
||||
import net.minecraft.inventory.ContainerHopper;
|
||||
import net.minecraft.inventory.IInventory;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.tileentity.IHopper;
|
||||
import net.minecraft.tileentity.TileEntityHopper;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.EntitySelectors;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.datafix.DataFixer;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class EntityMinecartHopper extends EntityMinecartContainer implements IHopper
|
||||
{
|
||||
/** Whether this hopper minecart is being blocked by an activator rail. */
|
||||
private boolean isBlocked = true;
|
||||
private int transferTicker = -1;
|
||||
private final BlockPos lastPosition = BlockPos.ORIGIN;
|
||||
|
||||
public EntityMinecartHopper(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
}
|
||||
|
||||
public EntityMinecartHopper(World worldIn, double x, double y, double z)
|
||||
{
|
||||
super(worldIn, x, y, z);
|
||||
}
|
||||
|
||||
public EntityMinecart.Type getType()
|
||||
{
|
||||
return EntityMinecart.Type.HOPPER;
|
||||
}
|
||||
|
||||
public IBlockState getDefaultDisplayTile()
|
||||
{
|
||||
return Blocks.HOPPER.getDefaultState();
|
||||
}
|
||||
|
||||
public int getDefaultDisplayTileOffset()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of slots in the inventory.
|
||||
*/
|
||||
public int getSizeInventory()
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
public boolean processInitialInteract(EntityPlayer player, EnumHand hand)
|
||||
{
|
||||
if (super.processInitialInteract(player, hand)) return true;
|
||||
if (!this.world.isRemote)
|
||||
{
|
||||
player.displayGUIChest(this);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called every tick the minecart is on an activator rail.
|
||||
*/
|
||||
public void onActivatorRailPass(int x, int y, int z, boolean receivingPower)
|
||||
{
|
||||
boolean flag = !receivingPower;
|
||||
|
||||
if (flag != this.getBlocked())
|
||||
{
|
||||
this.setBlocked(flag);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether this hopper minecart is being blocked by an activator rail.
|
||||
*/
|
||||
public boolean getBlocked()
|
||||
{
|
||||
return this.isBlocked;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether this hopper minecart is being blocked by an activator rail.
|
||||
*/
|
||||
public void setBlocked(boolean p_96110_1_)
|
||||
{
|
||||
this.isBlocked = p_96110_1_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the worldObj for this tileEntity.
|
||||
*/
|
||||
public World getWorld()
|
||||
{
|
||||
return this.world;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the world X position for this hopper entity.
|
||||
*/
|
||||
public double getXPos()
|
||||
{
|
||||
return this.posX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the world Y position for this hopper entity.
|
||||
*/
|
||||
public double getYPos()
|
||||
{
|
||||
return this.posY + 0.5D;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the world Z position for this hopper entity.
|
||||
*/
|
||||
public double getZPos()
|
||||
{
|
||||
return this.posZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to update the entity's position/logic.
|
||||
*/
|
||||
public void onUpdate()
|
||||
{
|
||||
super.onUpdate();
|
||||
|
||||
if (!this.world.isRemote && this.isEntityAlive() && this.getBlocked())
|
||||
{
|
||||
BlockPos blockpos = new BlockPos(this);
|
||||
|
||||
if (blockpos.equals(this.lastPosition))
|
||||
{
|
||||
--this.transferTicker;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.setTransferTicker(0);
|
||||
}
|
||||
|
||||
if (!this.canTransfer())
|
||||
{
|
||||
this.setTransferTicker(0);
|
||||
|
||||
if (this.captureDroppedItems())
|
||||
{
|
||||
this.setTransferTicker(4);
|
||||
this.markDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean captureDroppedItems()
|
||||
{
|
||||
if (TileEntityHopper.pullItems(this))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
List<EntityItem> list = this.world.<EntityItem>getEntitiesWithinAABB(EntityItem.class, this.getEntityBoundingBox().grow(0.25D, 0.0D, 0.25D), EntitySelectors.IS_ALIVE);
|
||||
|
||||
if (!list.isEmpty())
|
||||
{
|
||||
TileEntityHopper.putDropInInventoryAllSlots((IInventory)null, this, list.get(0));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void killMinecart(DamageSource source)
|
||||
{
|
||||
super.killMinecart(source);
|
||||
|
||||
if (this.world.getGameRules().getBoolean("doEntityDrops"))
|
||||
{
|
||||
this.dropItemWithOffset(Item.getItemFromBlock(Blocks.HOPPER), 1, 0.0F);
|
||||
}
|
||||
}
|
||||
|
||||
public static void registerFixesMinecartHopper(DataFixer fixer)
|
||||
{
|
||||
EntityMinecartContainer.addDataFixers(fixer, EntityMinecartHopper.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to write subclass entity data to NBT.
|
||||
*/
|
||||
protected void writeEntityToNBT(NBTTagCompound compound)
|
||||
{
|
||||
super.writeEntityToNBT(compound);
|
||||
compound.setInteger("TransferCooldown", this.transferTicker);
|
||||
compound.setBoolean("Enabled", this.isBlocked);
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to read subclass entity data from NBT.
|
||||
*/
|
||||
protected void readEntityFromNBT(NBTTagCompound compound)
|
||||
{
|
||||
super.readEntityFromNBT(compound);
|
||||
this.transferTicker = compound.getInteger("TransferCooldown");
|
||||
this.isBlocked = compound.hasKey("Enabled") ? compound.getBoolean("Enabled") : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the transfer ticker, used to determine the delay between transfers.
|
||||
*/
|
||||
public void setTransferTicker(int p_98042_1_)
|
||||
{
|
||||
this.transferTicker = p_98042_1_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the hopper cart can currently transfer an item.
|
||||
*/
|
||||
public boolean canTransfer()
|
||||
{
|
||||
return this.transferTicker > 0;
|
||||
}
|
||||
|
||||
public String getGuiID()
|
||||
{
|
||||
return "minecraft:hopper";
|
||||
}
|
||||
|
||||
public Container createContainer(InventoryPlayer playerInventory, EntityPlayer playerIn)
|
||||
{
|
||||
return new ContainerHopper(playerInventory, this, playerIn);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package net.minecraft.entity.item;
|
||||
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.EntityList;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.tileentity.MobSpawnerBaseLogic;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityMobSpawner;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.datafix.DataFixer;
|
||||
import net.minecraft.util.datafix.FixTypes;
|
||||
import net.minecraft.util.datafix.IDataFixer;
|
||||
import net.minecraft.util.datafix.IDataWalker;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class EntityMinecartMobSpawner extends EntityMinecart
|
||||
{
|
||||
/** Mob spawner logic for this spawner minecart. */
|
||||
private final MobSpawnerBaseLogic mobSpawnerLogic = new MobSpawnerBaseLogic()
|
||||
{
|
||||
public void broadcastEvent(int id)
|
||||
{
|
||||
EntityMinecartMobSpawner.this.world.setEntityState(EntityMinecartMobSpawner.this, (byte)id);
|
||||
}
|
||||
public World getSpawnerWorld()
|
||||
{
|
||||
return EntityMinecartMobSpawner.this.world;
|
||||
}
|
||||
public BlockPos getSpawnerPosition()
|
||||
{
|
||||
return new BlockPos(EntityMinecartMobSpawner.this);
|
||||
}
|
||||
public net.minecraft.entity.Entity getSpawnerEntity() {
|
||||
return EntityMinecartMobSpawner.this;
|
||||
}
|
||||
};
|
||||
|
||||
public EntityMinecartMobSpawner(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
}
|
||||
|
||||
public EntityMinecartMobSpawner(World worldIn, double x, double y, double z)
|
||||
{
|
||||
super(worldIn, x, y, z);
|
||||
}
|
||||
|
||||
public static void registerFixesMinecartMobSpawner(DataFixer fixer)
|
||||
{
|
||||
registerFixesMinecart(fixer, EntityMinecartMobSpawner.class);
|
||||
fixer.registerWalker(FixTypes.ENTITY, new IDataWalker()
|
||||
{
|
||||
public NBTTagCompound process(IDataFixer fixer, NBTTagCompound compound, int versionIn)
|
||||
{
|
||||
String s = compound.getString("id");
|
||||
|
||||
if (EntityList.getKey(EntityMinecartMobSpawner.class).equals(new ResourceLocation(s)))
|
||||
{
|
||||
compound.setString("id", TileEntity.getKey(TileEntityMobSpawner.class).toString());
|
||||
fixer.process(FixTypes.BLOCK_ENTITY, compound, versionIn);
|
||||
compound.setString("id", s);
|
||||
}
|
||||
|
||||
return compound;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public EntityMinecart.Type getType()
|
||||
{
|
||||
return EntityMinecart.Type.SPAWNER;
|
||||
}
|
||||
|
||||
public IBlockState getDefaultDisplayTile()
|
||||
{
|
||||
return Blocks.MOB_SPAWNER.getDefaultState();
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to read subclass entity data from NBT.
|
||||
*/
|
||||
protected void readEntityFromNBT(NBTTagCompound compound)
|
||||
{
|
||||
super.readEntityFromNBT(compound);
|
||||
this.mobSpawnerLogic.readFromNBT(compound);
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to write subclass entity data to NBT.
|
||||
*/
|
||||
protected void writeEntityToNBT(NBTTagCompound compound)
|
||||
{
|
||||
super.writeEntityToNBT(compound);
|
||||
this.mobSpawnerLogic.writeToNBT(compound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for {@link World#setEntityState}
|
||||
*/
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void handleStatusUpdate(byte id)
|
||||
{
|
||||
this.mobSpawnerLogic.setDelayToMin(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to update the entity's position/logic.
|
||||
*/
|
||||
public void onUpdate()
|
||||
{
|
||||
super.onUpdate();
|
||||
this.mobSpawnerLogic.updateSpawner();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
package net.minecraft.entity.item;
|
||||
|
||||
import net.minecraft.block.BlockRailBase;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.projectile.EntityArrow;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.init.SoundEvents;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.EnumParticleTypes;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.datafix.DataFixer;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.Explosion;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class EntityMinecartTNT extends EntityMinecart
|
||||
{
|
||||
private int minecartTNTFuse = -1;
|
||||
|
||||
public EntityMinecartTNT(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
}
|
||||
|
||||
public EntityMinecartTNT(World worldIn, double x, double y, double z)
|
||||
{
|
||||
super(worldIn, x, y, z);
|
||||
}
|
||||
|
||||
public static void registerFixesMinecartTNT(DataFixer fixer)
|
||||
{
|
||||
EntityMinecart.registerFixesMinecart(fixer, EntityMinecartTNT.class);
|
||||
}
|
||||
|
||||
public EntityMinecart.Type getType()
|
||||
{
|
||||
return EntityMinecart.Type.TNT;
|
||||
}
|
||||
|
||||
public IBlockState getDefaultDisplayTile()
|
||||
{
|
||||
return Blocks.TNT.getDefaultState();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to update the entity's position/logic.
|
||||
*/
|
||||
public void onUpdate()
|
||||
{
|
||||
super.onUpdate();
|
||||
|
||||
if (this.minecartTNTFuse > 0)
|
||||
{
|
||||
--this.minecartTNTFuse;
|
||||
this.world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, this.posX, this.posY + 0.5D, this.posZ, 0.0D, 0.0D, 0.0D);
|
||||
}
|
||||
else if (this.minecartTNTFuse == 0)
|
||||
{
|
||||
this.explodeCart(this.motionX * this.motionX + this.motionZ * this.motionZ);
|
||||
}
|
||||
|
||||
if (this.collidedHorizontally)
|
||||
{
|
||||
double d0 = this.motionX * this.motionX + this.motionZ * this.motionZ;
|
||||
|
||||
if (d0 >= 0.009999999776482582D)
|
||||
{
|
||||
this.explodeCart(d0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the entity is attacked.
|
||||
*/
|
||||
public boolean attackEntityFrom(DamageSource source, float amount)
|
||||
{
|
||||
Entity entity = source.getImmediateSource();
|
||||
|
||||
if (entity instanceof EntityArrow)
|
||||
{
|
||||
EntityArrow entityarrow = (EntityArrow)entity;
|
||||
|
||||
if (entityarrow.isBurning())
|
||||
{
|
||||
this.explodeCart(entityarrow.motionX * entityarrow.motionX + entityarrow.motionY * entityarrow.motionY + entityarrow.motionZ * entityarrow.motionZ);
|
||||
}
|
||||
}
|
||||
|
||||
return super.attackEntityFrom(source, amount);
|
||||
}
|
||||
|
||||
public void killMinecart(DamageSource source)
|
||||
{
|
||||
double d0 = this.motionX * this.motionX + this.motionZ * this.motionZ;
|
||||
|
||||
if (!source.isFireDamage() && !source.isExplosion() && d0 < 0.009999999776482582D)
|
||||
{
|
||||
super.killMinecart(source);
|
||||
|
||||
if (!source.isExplosion() && this.world.getGameRules().getBoolean("doEntityDrops"))
|
||||
{
|
||||
this.entityDropItem(new ItemStack(Blocks.TNT, 1), 0.0F);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.minecartTNTFuse < 0)
|
||||
{
|
||||
this.ignite();
|
||||
this.minecartTNTFuse = this.rand.nextInt(20) + this.rand.nextInt(20);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the minecart explode.
|
||||
*/
|
||||
protected void explodeCart(double p_94103_1_)
|
||||
{
|
||||
if (!this.world.isRemote)
|
||||
{
|
||||
double d0 = Math.sqrt(p_94103_1_);
|
||||
|
||||
if (d0 > 5.0D)
|
||||
{
|
||||
d0 = 5.0D;
|
||||
}
|
||||
|
||||
this.world.createExplosion(this, this.posX, this.posY, this.posZ, (float)(4.0D + this.rand.nextDouble() * 1.5D * d0), true);
|
||||
this.setDead();
|
||||
}
|
||||
}
|
||||
|
||||
public void fall(float distance, float damageMultiplier)
|
||||
{
|
||||
if (distance >= 3.0F)
|
||||
{
|
||||
float f = distance / 10.0F;
|
||||
this.explodeCart((double)(f * f));
|
||||
}
|
||||
|
||||
super.fall(distance, damageMultiplier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called every tick the minecart is on an activator rail.
|
||||
*/
|
||||
public void onActivatorRailPass(int x, int y, int z, boolean receivingPower)
|
||||
{
|
||||
if (receivingPower && this.minecartTNTFuse < 0)
|
||||
{
|
||||
this.ignite();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for {@link World#setEntityState}
|
||||
*/
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void handleStatusUpdate(byte id)
|
||||
{
|
||||
if (id == 10)
|
||||
{
|
||||
this.ignite();
|
||||
}
|
||||
else
|
||||
{
|
||||
super.handleStatusUpdate(id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ignites this TNT cart.
|
||||
*/
|
||||
public void ignite()
|
||||
{
|
||||
this.minecartTNTFuse = 80;
|
||||
|
||||
if (!this.world.isRemote)
|
||||
{
|
||||
this.world.setEntityState(this, (byte)10);
|
||||
|
||||
if (!this.isSilent())
|
||||
{
|
||||
this.world.playSound((EntityPlayer)null, this.posX, this.posY, this.posZ, SoundEvents.ENTITY_TNT_PRIMED, SoundCategory.BLOCKS, 1.0F, 1.0F);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the remaining fuse time in ticks.
|
||||
*/
|
||||
@SideOnly(Side.CLIENT)
|
||||
public int getFuseTicks()
|
||||
{
|
||||
return this.minecartTNTFuse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the TNT minecart is ignited.
|
||||
*/
|
||||
public boolean isIgnited()
|
||||
{
|
||||
return this.minecartTNTFuse > -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Explosion resistance of a block relative to this entity
|
||||
*/
|
||||
public float getExplosionResistance(Explosion explosionIn, World worldIn, BlockPos pos, IBlockState blockStateIn)
|
||||
{
|
||||
return !this.isIgnited() || !BlockRailBase.isRailBlock(blockStateIn) && !BlockRailBase.isRailBlock(worldIn, pos.up()) ? super.getExplosionResistance(explosionIn, worldIn, pos, blockStateIn) : 0.0F;
|
||||
}
|
||||
|
||||
public boolean canExplosionDestroyBlock(Explosion explosionIn, World worldIn, BlockPos pos, IBlockState blockStateIn, float p_174816_5_)
|
||||
{
|
||||
return !this.isIgnited() || !BlockRailBase.isRailBlock(blockStateIn) && !BlockRailBase.isRailBlock(worldIn, pos.up()) ? super.canExplosionDestroyBlock(explosionIn, worldIn, pos, blockStateIn, p_174816_5_) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to read subclass entity data from NBT.
|
||||
*/
|
||||
protected void readEntityFromNBT(NBTTagCompound compound)
|
||||
{
|
||||
super.readEntityFromNBT(compound);
|
||||
|
||||
if (compound.hasKey("TNTFuse", 99))
|
||||
{
|
||||
this.minecartTNTFuse = compound.getInteger("TNTFuse");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to write subclass entity data to NBT.
|
||||
*/
|
||||
protected void writeEntityToNBT(NBTTagCompound compound)
|
||||
{
|
||||
super.writeEntityToNBT(compound);
|
||||
compound.setInteger("TNTFuse", this.minecartTNTFuse);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
package net.minecraft.entity.item;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityHanging;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.init.SoundEvents;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class EntityPainting extends EntityHanging
|
||||
{
|
||||
public EntityPainting.EnumArt art;
|
||||
|
||||
public EntityPainting(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
}
|
||||
|
||||
public EntityPainting(World worldIn, BlockPos pos, EnumFacing facing)
|
||||
{
|
||||
super(worldIn, pos);
|
||||
List<EntityPainting.EnumArt> list = Lists.<EntityPainting.EnumArt>newArrayList();
|
||||
int i = 0;
|
||||
|
||||
for (EntityPainting.EnumArt entitypainting$enumart : EntityPainting.EnumArt.values())
|
||||
{
|
||||
this.art = entitypainting$enumart;
|
||||
this.updateFacingWithBoundingBox(facing);
|
||||
|
||||
if (this.onValidSurface())
|
||||
{
|
||||
list.add(entitypainting$enumart);
|
||||
int j = entitypainting$enumart.sizeX * entitypainting$enumart.sizeY;
|
||||
|
||||
if (j > i)
|
||||
{
|
||||
i = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!list.isEmpty())
|
||||
{
|
||||
Iterator<EntityPainting.EnumArt> iterator = list.iterator();
|
||||
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
EntityPainting.EnumArt entitypainting$enumart1 = iterator.next();
|
||||
|
||||
if (entitypainting$enumart1.sizeX * entitypainting$enumart1.sizeY < i)
|
||||
{
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
this.art = list.get(this.rand.nextInt(list.size()));
|
||||
}
|
||||
|
||||
this.updateFacingWithBoundingBox(facing);
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public EntityPainting(World worldIn, BlockPos pos, EnumFacing facing, String title)
|
||||
{
|
||||
this(worldIn, pos, facing);
|
||||
|
||||
for (EntityPainting.EnumArt entitypainting$enumart : EntityPainting.EnumArt.values())
|
||||
{
|
||||
if (entitypainting$enumart.title.equals(title))
|
||||
{
|
||||
this.art = entitypainting$enumart;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.updateFacingWithBoundingBox(facing);
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to write subclass entity data to NBT.
|
||||
*/
|
||||
public void writeEntityToNBT(NBTTagCompound compound)
|
||||
{
|
||||
compound.setString("Motive", this.art.title);
|
||||
super.writeEntityToNBT(compound);
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to read subclass entity data from NBT.
|
||||
*/
|
||||
public void readEntityFromNBT(NBTTagCompound compound)
|
||||
{
|
||||
String s = compound.getString("Motive");
|
||||
|
||||
for (EntityPainting.EnumArt entitypainting$enumart : EntityPainting.EnumArt.values())
|
||||
{
|
||||
if (entitypainting$enumart.title.equals(s))
|
||||
{
|
||||
this.art = entitypainting$enumart;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.art == null)
|
||||
{
|
||||
this.art = EntityPainting.EnumArt.KEBAB;
|
||||
}
|
||||
|
||||
super.readEntityFromNBT(compound);
|
||||
}
|
||||
|
||||
public int getWidthPixels()
|
||||
{
|
||||
return this.art.sizeX;
|
||||
}
|
||||
|
||||
public int getHeightPixels()
|
||||
{
|
||||
return this.art.sizeY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this entity is broken. Entity parameter may be null.
|
||||
*/
|
||||
public void onBroken(@Nullable Entity brokenEntity)
|
||||
{
|
||||
if (this.world.getGameRules().getBoolean("doEntityDrops"))
|
||||
{
|
||||
this.playSound(SoundEvents.ENTITY_PAINTING_BREAK, 1.0F, 1.0F);
|
||||
|
||||
if (brokenEntity instanceof EntityPlayer)
|
||||
{
|
||||
EntityPlayer entityplayer = (EntityPlayer)brokenEntity;
|
||||
|
||||
if (entityplayer.capabilities.isCreativeMode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.entityDropItem(new ItemStack(Items.PAINTING), 0.0F);
|
||||
}
|
||||
}
|
||||
|
||||
public void playPlaceSound()
|
||||
{
|
||||
this.playSound(SoundEvents.ENTITY_PAINTING_PLACE, 1.0F, 1.0F);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the location and Yaw/Pitch of an entity in the world
|
||||
*/
|
||||
public void setLocationAndAngles(double x, double y, double z, float yaw, float pitch)
|
||||
{
|
||||
this.setPosition(x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
BlockPos blockpos = this.hangingPosition.add(x - this.posX, y - this.posY, z - this.posZ);
|
||||
this.setPosition((double)blockpos.getX(), (double)blockpos.getY(), (double)blockpos.getZ());
|
||||
}
|
||||
|
||||
public static enum EnumArt
|
||||
{
|
||||
KEBAB("Kebab", 16, 16, 0, 0),
|
||||
AZTEC("Aztec", 16, 16, 16, 0),
|
||||
ALBAN("Alban", 16, 16, 32, 0),
|
||||
AZTEC_2("Aztec2", 16, 16, 48, 0),
|
||||
BOMB("Bomb", 16, 16, 64, 0),
|
||||
PLANT("Plant", 16, 16, 80, 0),
|
||||
WASTELAND("Wasteland", 16, 16, 96, 0),
|
||||
POOL("Pool", 32, 16, 0, 32),
|
||||
COURBET("Courbet", 32, 16, 32, 32),
|
||||
SEA("Sea", 32, 16, 64, 32),
|
||||
SUNSET("Sunset", 32, 16, 96, 32),
|
||||
CREEBET("Creebet", 32, 16, 128, 32),
|
||||
WANDERER("Wanderer", 16, 32, 0, 64),
|
||||
GRAHAM("Graham", 16, 32, 16, 64),
|
||||
MATCH("Match", 32, 32, 0, 128),
|
||||
BUST("Bust", 32, 32, 32, 128),
|
||||
STAGE("Stage", 32, 32, 64, 128),
|
||||
VOID("Void", 32, 32, 96, 128),
|
||||
SKULL_AND_ROSES("SkullAndRoses", 32, 32, 128, 128),
|
||||
WITHER("Wither", 32, 32, 160, 128),
|
||||
FIGHTERS("Fighters", 64, 32, 0, 96),
|
||||
POINTER("Pointer", 64, 64, 0, 192),
|
||||
PIGSCENE("Pigscene", 64, 64, 64, 192),
|
||||
BURNING_SKULL("BurningSkull", 64, 64, 128, 192),
|
||||
SKELETON("Skeleton", 64, 48, 192, 64),
|
||||
DONKEY_KONG("DonkeyKong", 64, 48, 192, 112);
|
||||
|
||||
public static final int MAX_NAME_LENGTH = "SkullAndRoses".length();
|
||||
/** Painting Title. */
|
||||
public final String title;
|
||||
public final int sizeX;
|
||||
public final int sizeY;
|
||||
public final int offsetX;
|
||||
public final int offsetY;
|
||||
|
||||
private EnumArt(String titleIn, int width, int height, int textureU, int textureV)
|
||||
{
|
||||
this.title = titleIn;
|
||||
this.sizeX = width;
|
||||
this.sizeY = height;
|
||||
this.offsetX = textureU;
|
||||
this.offsetY = textureV;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
package net.minecraft.entity.item;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.MoverType;
|
||||
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.world.World;
|
||||
|
||||
public class EntityTNTPrimed extends Entity
|
||||
{
|
||||
private static final DataParameter<Integer> FUSE = EntityDataManager.<Integer>createKey(EntityTNTPrimed.class, DataSerializers.VARINT);
|
||||
@Nullable
|
||||
private EntityLivingBase tntPlacedBy;
|
||||
/** How long the fuse is */
|
||||
private int fuse;
|
||||
|
||||
public EntityTNTPrimed(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
this.fuse = 80;
|
||||
this.preventEntitySpawning = true;
|
||||
this.isImmuneToFire = true;
|
||||
this.setSize(0.98F, 0.98F);
|
||||
}
|
||||
|
||||
public EntityTNTPrimed(World worldIn, double x, double y, double z, EntityLivingBase igniter)
|
||||
{
|
||||
this(worldIn);
|
||||
this.setPosition(x, y, z);
|
||||
float f = (float)(Math.random() * (Math.PI * 2D));
|
||||
this.motionX = (double)(-((float)Math.sin((double)f)) * 0.02F);
|
||||
this.motionY = 0.20000000298023224D;
|
||||
this.motionZ = (double)(-((float)Math.cos((double)f)) * 0.02F);
|
||||
this.setFuse(80);
|
||||
this.prevPosX = x;
|
||||
this.prevPosY = y;
|
||||
this.prevPosZ = z;
|
||||
this.tntPlacedBy = igniter;
|
||||
}
|
||||
|
||||
protected void entityInit()
|
||||
{
|
||||
this.dataManager.register(FUSE, Integer.valueOf(80));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if other Entities should be prevented from moving through this Entity.
|
||||
*/
|
||||
public boolean canBeCollidedWith()
|
||||
{
|
||||
return !this.isDead;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to update the entity's position/logic.
|
||||
*/
|
||||
public void onUpdate()
|
||||
{
|
||||
this.prevPosX = this.posX;
|
||||
this.prevPosY = this.posY;
|
||||
this.prevPosZ = this.posZ;
|
||||
|
||||
if (!this.hasNoGravity())
|
||||
{
|
||||
this.motionY -= 0.03999999910593033D;
|
||||
}
|
||||
|
||||
this.move(MoverType.SELF, this.motionX, this.motionY, this.motionZ);
|
||||
this.motionX *= 0.9800000190734863D;
|
||||
this.motionY *= 0.9800000190734863D;
|
||||
this.motionZ *= 0.9800000190734863D;
|
||||
|
||||
if (this.onGround)
|
||||
{
|
||||
this.motionX *= 0.699999988079071D;
|
||||
this.motionZ *= 0.699999988079071D;
|
||||
this.motionY *= -0.5D;
|
||||
}
|
||||
|
||||
--this.fuse;
|
||||
|
||||
if (this.fuse <= 0)
|
||||
{
|
||||
this.setDead();
|
||||
|
||||
if (!this.world.isRemote)
|
||||
{
|
||||
this.explode();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.handleWaterMovement();
|
||||
this.world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, this.posX, this.posY + 0.5D, this.posZ, 0.0D, 0.0D, 0.0D);
|
||||
}
|
||||
}
|
||||
|
||||
private void explode()
|
||||
{
|
||||
float f = 4.0F;
|
||||
this.world.createExplosion(this, this.posX, this.posY + (double)(this.height / 16.0F), this.posZ, 4.0F, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to write subclass entity data to NBT.
|
||||
*/
|
||||
protected void writeEntityToNBT(NBTTagCompound compound)
|
||||
{
|
||||
compound.setShort("Fuse", (short)this.getFuse());
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to read subclass entity data from NBT.
|
||||
*/
|
||||
protected void readEntityFromNBT(NBTTagCompound compound)
|
||||
{
|
||||
this.setFuse(compound.getShort("Fuse"));
|
||||
}
|
||||
|
||||
/**
|
||||
* returns null or the entityliving it was placed or ignited by
|
||||
*/
|
||||
@Nullable
|
||||
public EntityLivingBase getTntPlacedBy()
|
||||
{
|
||||
return this.tntPlacedBy;
|
||||
}
|
||||
|
||||
public float getEyeHeight()
|
||||
{
|
||||
return 0.0F;
|
||||
}
|
||||
|
||||
public void setFuse(int fuseIn)
|
||||
{
|
||||
this.dataManager.set(FUSE, Integer.valueOf(fuseIn));
|
||||
this.fuse = fuseIn;
|
||||
}
|
||||
|
||||
public void notifyDataManagerChange(DataParameter<?> key)
|
||||
{
|
||||
if (FUSE.equals(key))
|
||||
{
|
||||
this.fuse = this.getFuseDataManager();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the fuse from the data manager
|
||||
*/
|
||||
public int getFuseDataManager()
|
||||
{
|
||||
return ((Integer)this.dataManager.get(FUSE)).intValue();
|
||||
}
|
||||
|
||||
public int getFuse()
|
||||
{
|
||||
return this.fuse;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,388 @@
|
||||
package net.minecraft.entity.item;
|
||||
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.MoverType;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Enchantments;
|
||||
import net.minecraft.init.SoundEvents;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
public class EntityXPOrb extends Entity
|
||||
{
|
||||
/** A constantly increasing value that RenderXPOrb uses to control the colour shifting (Green / yellow) */
|
||||
public int xpColor;
|
||||
/** The age of the XP orb in ticks. */
|
||||
public int xpOrbAge;
|
||||
public int delayBeforeCanPickup;
|
||||
/** The health of this XP orb. */
|
||||
private int xpOrbHealth = 5;
|
||||
/** This is how much XP this orb has. */
|
||||
public int xpValue;
|
||||
/** The closest EntityPlayer to this orb. */
|
||||
private EntityPlayer closestPlayer;
|
||||
/** Threshold color for tracking players */
|
||||
private int xpTargetColor;
|
||||
|
||||
public EntityXPOrb(World worldIn, double x, double y, double z, int expValue)
|
||||
{
|
||||
super(worldIn);
|
||||
this.setSize(0.5F, 0.5F);
|
||||
this.setPosition(x, y, z);
|
||||
this.rotationYaw = (float)(Math.random() * 360.0D);
|
||||
this.motionX = (double)((float)(Math.random() * 0.20000000298023224D - 0.10000000149011612D) * 2.0F);
|
||||
this.motionY = (double)((float)(Math.random() * 0.2D) * 2.0F);
|
||||
this.motionZ = (double)((float)(Math.random() * 0.20000000298023224D - 0.10000000149011612D) * 2.0F);
|
||||
this.xpValue = expValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 EntityXPOrb(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
this.setSize(0.25F, 0.25F);
|
||||
}
|
||||
|
||||
protected void entityInit()
|
||||
{
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public int getBrightnessForRender()
|
||||
{
|
||||
float f = 0.5F;
|
||||
f = MathHelper.clamp(f, 0.0F, 1.0F);
|
||||
int i = super.getBrightnessForRender();
|
||||
int j = i & 255;
|
||||
int k = i >> 16 & 255;
|
||||
j = j + (int)(f * 15.0F * 16.0F);
|
||||
|
||||
if (j > 240)
|
||||
{
|
||||
j = 240;
|
||||
}
|
||||
|
||||
return j | k << 16;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to update the entity's position/logic.
|
||||
*/
|
||||
public void onUpdate()
|
||||
{
|
||||
super.onUpdate();
|
||||
|
||||
if (this.delayBeforeCanPickup > 0)
|
||||
{
|
||||
--this.delayBeforeCanPickup;
|
||||
}
|
||||
|
||||
this.prevPosX = this.posX;
|
||||
this.prevPosY = this.posY;
|
||||
this.prevPosZ = this.posZ;
|
||||
|
||||
if (!this.hasNoGravity())
|
||||
{
|
||||
this.motionY -= 0.029999999329447746D;
|
||||
}
|
||||
|
||||
if (this.world.getBlockState(new BlockPos(this)).getMaterial() == Material.LAVA)
|
||||
{
|
||||
this.motionY = 0.20000000298023224D;
|
||||
this.motionX = (double)((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F);
|
||||
this.motionZ = (double)((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F);
|
||||
this.playSound(SoundEvents.ENTITY_GENERIC_BURN, 0.4F, 2.0F + this.rand.nextFloat() * 0.4F);
|
||||
}
|
||||
|
||||
this.pushOutOfBlocks(this.posX, (this.getEntityBoundingBox().minY + this.getEntityBoundingBox().maxY) / 2.0D, this.posZ);
|
||||
double d0 = 8.0D;
|
||||
|
||||
if (this.xpTargetColor < this.xpColor - 20 + this.getEntityId() % 100)
|
||||
{
|
||||
if (this.closestPlayer == null || this.closestPlayer.getDistanceSq(this) > 64.0D)
|
||||
{
|
||||
this.closestPlayer = this.world.getClosestPlayerToEntity(this, 8.0D);
|
||||
}
|
||||
|
||||
this.xpTargetColor = this.xpColor;
|
||||
}
|
||||
|
||||
if (this.closestPlayer != null && this.closestPlayer.isSpectator())
|
||||
{
|
||||
this.closestPlayer = null;
|
||||
}
|
||||
|
||||
if (this.closestPlayer != null)
|
||||
{
|
||||
double d1 = (this.closestPlayer.posX - this.posX) / 8.0D;
|
||||
double d2 = (this.closestPlayer.posY + (double)this.closestPlayer.getEyeHeight() / 2.0D - this.posY) / 8.0D;
|
||||
double d3 = (this.closestPlayer.posZ - this.posZ) / 8.0D;
|
||||
double d4 = Math.sqrt(d1 * d1 + d2 * d2 + d3 * d3);
|
||||
double d5 = 1.0D - d4;
|
||||
|
||||
if (d5 > 0.0D)
|
||||
{
|
||||
d5 = d5 * d5;
|
||||
this.motionX += d1 / d4 * d5 * 0.1D;
|
||||
this.motionY += d2 / d4 * d5 * 0.1D;
|
||||
this.motionZ += d3 / d4 * d5 * 0.1D;
|
||||
}
|
||||
}
|
||||
|
||||
this.move(MoverType.SELF, this.motionX, this.motionY, this.motionZ);
|
||||
float f = 0.98F;
|
||||
|
||||
if (this.onGround)
|
||||
{
|
||||
BlockPos underPos = new BlockPos(MathHelper.floor(this.posX), MathHelper.floor(this.getEntityBoundingBox().minY) - 1, MathHelper.floor(this.posZ));
|
||||
net.minecraft.block.state.IBlockState underState = this.world.getBlockState(underPos);
|
||||
f = underState.getBlock().getSlipperiness(underState, this.world, underPos, this) * 0.98F;
|
||||
}
|
||||
|
||||
this.motionX *= (double)f;
|
||||
this.motionY *= 0.9800000190734863D;
|
||||
this.motionZ *= (double)f;
|
||||
|
||||
if (this.onGround)
|
||||
{
|
||||
this.motionY *= -0.8999999761581421D;
|
||||
}
|
||||
|
||||
++this.xpColor;
|
||||
++this.xpOrbAge;
|
||||
|
||||
if (this.xpOrbAge >= 6000)
|
||||
{
|
||||
this.setDead();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if this entity is in water and will end up adding the waters velocity to the entity
|
||||
*/
|
||||
public boolean handleWaterMovement()
|
||||
{
|
||||
return this.world.handleMaterialAcceleration(this.getEntityBoundingBox(), Material.WATER, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Will deal the specified amount of fire damage to the entity if the entity isn't immune to fire damage.
|
||||
*/
|
||||
protected void dealFireDamage(int amount)
|
||||
{
|
||||
this.attackEntityFrom(DamageSource.IN_FIRE, (float)amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the entity is attacked.
|
||||
*/
|
||||
public boolean attackEntityFrom(DamageSource source, float amount)
|
||||
{
|
||||
if (this.world.isRemote || this.isDead) return false; //Forge: Fixes MC-53850
|
||||
if (this.isEntityInvulnerable(source))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.markVelocityChanged();
|
||||
this.xpOrbHealth = (int)((float)this.xpOrbHealth - amount);
|
||||
|
||||
if (this.xpOrbHealth <= 0)
|
||||
{
|
||||
this.setDead();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to write subclass entity data to NBT.
|
||||
*/
|
||||
public void writeEntityToNBT(NBTTagCompound compound)
|
||||
{
|
||||
compound.setShort("Health", (short)this.xpOrbHealth);
|
||||
compound.setShort("Age", (short)this.xpOrbAge);
|
||||
compound.setShort("Value", (short)this.xpValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to read subclass entity data from NBT.
|
||||
*/
|
||||
public void readEntityFromNBT(NBTTagCompound compound)
|
||||
{
|
||||
this.xpOrbHealth = compound.getShort("Health");
|
||||
this.xpOrbAge = compound.getShort("Age");
|
||||
this.xpValue = compound.getShort("Value");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by a player entity when they collide with an entity
|
||||
*/
|
||||
public void onCollideWithPlayer(EntityPlayer entityIn)
|
||||
{
|
||||
if (!this.world.isRemote)
|
||||
{
|
||||
if (this.delayBeforeCanPickup == 0 && entityIn.xpCooldown == 0)
|
||||
{
|
||||
if (net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.entity.player.PlayerPickupXpEvent(entityIn, this))) return;
|
||||
entityIn.xpCooldown = 2;
|
||||
entityIn.onItemPickup(this, 1);
|
||||
ItemStack itemstack = EnchantmentHelper.getEnchantedItem(Enchantments.MENDING, entityIn);
|
||||
|
||||
if (!itemstack.isEmpty() && itemstack.isItemDamaged())
|
||||
{
|
||||
int i = Math.min(this.xpToDurability(this.xpValue), itemstack.getItemDamage());
|
||||
this.xpValue -= this.durabilityToXp(i);
|
||||
itemstack.setItemDamage(itemstack.getItemDamage() - i);
|
||||
}
|
||||
|
||||
if (this.xpValue > 0)
|
||||
{
|
||||
entityIn.addExperience(this.xpValue);
|
||||
}
|
||||
|
||||
this.setDead();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int durabilityToXp(int durability)
|
||||
{
|
||||
return durability / 2;
|
||||
}
|
||||
|
||||
private int xpToDurability(int xp)
|
||||
{
|
||||
return xp * 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the XP value of this XP orb.
|
||||
*/
|
||||
public int getXpValue()
|
||||
{
|
||||
return this.xpValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a number from 1 to 10 based on how much XP this orb is worth. This is used by RenderXPOrb to determine
|
||||
* what texture to use.
|
||||
*/
|
||||
@SideOnly(Side.CLIENT)
|
||||
public int getTextureByXP()
|
||||
{
|
||||
if (this.xpValue >= 2477)
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
else if (this.xpValue >= 1237)
|
||||
{
|
||||
return 9;
|
||||
}
|
||||
else if (this.xpValue >= 617)
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
else if (this.xpValue >= 307)
|
||||
{
|
||||
return 7;
|
||||
}
|
||||
else if (this.xpValue >= 149)
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
else if (this.xpValue >= 73)
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
else if (this.xpValue >= 37)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
else if (this.xpValue >= 17)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
else if (this.xpValue >= 7)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.xpValue >= 3 ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a fragment of the maximum experience points value for the supplied value of experience points value.
|
||||
*/
|
||||
public static int getXPSplit(int expValue)
|
||||
{
|
||||
if (expValue >= 2477)
|
||||
{
|
||||
return 2477;
|
||||
}
|
||||
else if (expValue >= 1237)
|
||||
{
|
||||
return 1237;
|
||||
}
|
||||
else if (expValue >= 617)
|
||||
{
|
||||
return 617;
|
||||
}
|
||||
else if (expValue >= 307)
|
||||
{
|
||||
return 307;
|
||||
}
|
||||
else if (expValue >= 149)
|
||||
{
|
||||
return 149;
|
||||
}
|
||||
else if (expValue >= 73)
|
||||
{
|
||||
return 73;
|
||||
}
|
||||
else if (expValue >= 37)
|
||||
{
|
||||
return 37;
|
||||
}
|
||||
else if (expValue >= 17)
|
||||
{
|
||||
return 17;
|
||||
}
|
||||
else if (expValue >= 7)
|
||||
{
|
||||
return 7;
|
||||
}
|
||||
else
|
||||
{
|
||||
return expValue >= 3 ? 3 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if it's possible to attack this entity with an item.
|
||||
*/
|
||||
public boolean canBeAttackedWithItem()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// Auto generated package-info by MCP
|
||||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
package net.minecraft.entity.item;
|
||||
|
||||
import mcp.MethodsReturnNonnullByDefault;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
Reference in New Issue
Block a user