package net.minecraft.server;
import com.google.common.collect.Lists;
import java.util.Iterator;
import java.util.List;
import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit
public class EntityFallingBlock extends Entity {
private IBlockData block;
public int ticksLived;
public boolean dropItem;
private boolean g;
public boolean hurtEntities;
private int fallHurtMax;
private float fallHurtAmount;
public NBTTagCompound tileEntityData;
protected static final DataWatcherObject<BlockPosition> e = DataWatcher.a(EntityFallingBlock.class, DataWatcherRegistry.l);
public EntityFallingBlock(EntityTypes<? extends EntityFallingBlock> entitytypes, World world) {
super(entitytypes, world);
this.block = Blocks.SAND.getBlockData();
this.dropItem = true;
this.fallHurtMax = 40;
this.fallHurtAmount = 2.0F;
}
public EntityFallingBlock(World world, double d0, double d1, double d2, IBlockData iblockdata) {
this(EntityTypes.FALLING_BLOCK, world);
this.block = iblockdata;
this.i = true;
this.setPosition(d0, d1 + (double) ((1.0F - this.getHeight()) / 2.0F), d2);
this.setMot(Vec3D.a);
this.lastX = d0;
this.lastY = d1;
this.lastZ = d2;
this.a(new BlockPosition(this));
}
@Override
public boolean bA() {
return false;
}
public void a(BlockPosition blockposition) {
this.datawatcher.set(EntityFallingBlock.e, blockposition);
}
@Override
protected boolean playStepSound() {
return false;
}
@Override
protected void initDatawatcher() {
this.datawatcher.register(EntityFallingBlock.e, BlockPosition.ZERO);
}
@Override
public boolean isInteractable() {
return !this.dead;
}
@Override
public void tick() {
if (this.block.isAir()) {
this.die();
} else {
Block block = this.block.getBlock();
BlockPosition blockposition;
if (this.ticksLived++ == 0) {
blockposition = new BlockPosition(this);
if (this.world.getType(blockposition).getBlock() == block && !CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.getBlockData()).isCancelled()) {
this.world.a(blockposition, false);
} else if (!this.world.isClientSide) {
this.die();
return;
}
}
if (!this.isNoGravity()) {
this.setMot(this.getMot().add(0.0D, -0.04D, 0.0D));
}
this.move(EnumMoveType.SELF, this.getMot());
if (!this.world.isClientSide) {
blockposition = new BlockPosition(this);
boolean flag = this.block.getBlock() instanceof BlockConcretePowder;
boolean flag1 = flag && this.world.getFluid(blockposition).a(TagsFluid.WATER);
double d0 = this.getMot().g();
if (flag && d0 > 1.0D) {
MovingObjectPositionBlock movingobjectpositionblock = this.world.rayTrace(new RayTrace(new Vec3D(this.lastX, this.lastY, this.lastZ), this.getPositionVector(), RayTrace.BlockCollisionOption.COLLIDER, RayTrace.FluidCollisionOption.SOURCE_ONLY, this));
if (movingobjectpositionblock.getType() != MovingObjectPosition.EnumMovingObjectType.MISS && this.world.getFluid(movingobjectpositionblock.getBlockPosition()).a(TagsFluid.WATER)) {
blockposition = movingobjectpositionblock.getBlockPosition();
flag1 = true;
}
}
if (!this.onGround && !flag1) {
if (!this.world.isClientSide && (this.ticksLived > 100 && (blockposition.getY() < 1 || blockposition.getY() > 256) || this.ticksLived > 600)) {
if (this.dropItem && this.world.getGameRules().getBoolean(GameRules.DO_ENTITY_DROPS)) {
this.a((IMaterial) block);
}
this.die();
}
} else {
IBlockData iblockdata = this.world.getType(blockposition);
this.setMot(this.getMot().d(0.7D, -0.5D, 0.7D));
if (iblockdata.getBlock() != Blocks.MOVING_PISTON) {
this.die();
if (!this.g) {
boolean flag2 = iblockdata.a((BlockActionContext) (new BlockActionContextDirectional(this.world, blockposition, EnumDirection.DOWN, ItemStack.a, EnumDirection.UP)));
boolean flag3 = BlockFalling.canFallThrough(this.world.getType(blockposition.down())) && (!flag || !flag1);
boolean flag4 = this.block.canPlace(this.world, blockposition) && !flag3;
if (flag2 && flag4) {
if (this.block.b((IBlockState) BlockProperties.C) && this.world.getFluid(blockposition).getType() == FluidTypes.WATER) {
this.block = (IBlockData) this.block.set(BlockProperties.C, true);
}
// CraftBukkit start
if (CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, this.block).isCancelled()) {
return;
}
// CraftBukkit end
if (this.world.setTypeAndData(blockposition, this.block, 3)) {
if (block instanceof BlockFalling) {
((BlockFalling) block).a(this.world, blockposition, this.block, iblockdata);
}
if (this.tileEntityData != null && block instanceof ITileEntity) {
TileEntity tileentity = this.world.getTileEntity(blockposition);
if (tileentity != null) {
NBTTagCompound nbttagcompound = tileentity.save(new NBTTagCompound());
Iterator iterator = this.tileEntityData.getKeys().iterator();
while (iterator.hasNext()) {
String s = (String) iterator.next();
NBTBase nbtbase = this.tileEntityData.get(s);
if (!"x".equals(s) && !"y".equals(s) && !"z".equals(s)) {
nbttagcompound.set(s, nbtbase.clone());
}
}
tileentity.load(nbttagcompound);
tileentity.update();
}
}
} else if (this.dropItem && this.world.getGameRules().getBoolean(GameRules.DO_ENTITY_DROPS)) {
this.a((IMaterial) block);
}
} else if (this.dropItem && this.world.getGameRules().getBoolean(GameRules.DO_ENTITY_DROPS)) {
this.a((IMaterial) block);
}
} else if (block instanceof BlockFalling) {
((BlockFalling) block).a(this.world, blockposition);
}
}
}
}
this.setMot(this.getMot().a(0.98D));
}
}
@Override
public boolean b(float f, float f1) {
if (this.hurtEntities) {
int i = MathHelper.f(f - 1.0F);
if (i > 0) {
List<Entity> list = Lists.newArrayList(this.world.getEntities(this, this.getBoundingBox()));
boolean flag = this.block.a(TagsBlock.ANVIL);
DamageSource damagesource = flag ? DamageSource.ANVIL : DamageSource.FALLING_BLOCK;
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
Entity entity = (Entity) iterator.next();
CraftEventFactory.entityDamage = this; // CraftBukkit
entity.damageEntity(damagesource, (float) Math.min(MathHelper.d((float) i * this.fallHurtAmount), this.fallHurtMax));
CraftEventFactory.entityDamage = null; // CraftBukkit
}
if (flag && (double) this.random.nextFloat() < 0.05000000074505806D + (double) i * 0.05D) {
IBlockData iblockdata = BlockAnvil.e(this.block);
if (iblockdata == null) {
this.g = true;
} else {
this.block = iblockdata;
}
}
}
}
return false;
}
@Override
protected void b(NBTTagCompound nbttagcompound) {
nbttagcompound.set("BlockState", GameProfileSerializer.a(this.block));
nbttagcompound.setInt("Time", this.ticksLived);
nbttagcompound.setBoolean("DropItem", this.dropItem);
nbttagcompound.setBoolean("HurtEntities", this.hurtEntities);
nbttagcompound.setFloat("FallHurtAmount", this.fallHurtAmount);
nbttagcompound.setInt("FallHurtMax", this.fallHurtMax);
if (this.tileEntityData != null) {
nbttagcompound.set("TileEntityData", this.tileEntityData);
}
}
@Override
protected void a(NBTTagCompound nbttagcompound) {
this.block = GameProfileSerializer.d(nbttagcompound.getCompound("BlockState"));
this.ticksLived = nbttagcompound.getInt("Time");
if (nbttagcompound.hasKeyOfType("HurtEntities", 99)) {
this.hurtEntities = nbttagcompound.getBoolean("HurtEntities");
this.fallHurtAmount = nbttagcompound.getFloat("FallHurtAmount");
this.fallHurtMax = nbttagcompound.getInt("FallHurtMax");
} else if (this.block.a(TagsBlock.ANVIL)) {
this.hurtEntities = true;
}
if (nbttagcompound.hasKeyOfType("DropItem", 99)) {
this.dropItem = nbttagcompound.getBoolean("DropItem");
}
if (nbttagcompound.hasKeyOfType("TileEntityData", 10)) {
this.tileEntityData = nbttagcompound.getCompound("TileEntityData");
}
if (this.block.isAir()) {
this.block = Blocks.SAND.getBlockData();
}
}
public void a(boolean flag) {
this.hurtEntities = flag;
}
@Override
public void appendEntityCrashDetails(CrashReportSystemDetails crashreportsystemdetails) {
super.appendEntityCrashDetails(crashreportsystemdetails);
crashreportsystemdetails.a("Immitating BlockState", (Object) this.block.toString());
}
public IBlockData getBlock() {
return this.block;
}
@Override
public boolean cb() {
return true;
}
@Override
public Packet<?> L() {
return new PacketPlayOutSpawnEntity(this, Block.getCombinedId(this.getBlock()));
}
}