/FileExtraction/Java_unseen/Wind-Development_WindSpigot/WindSpigot-Server/src/main/java/net/minecraft/server/EntityFallingBlock.java
package net.minecraft.server;

import java.util.ArrayList;
import java.util.Iterator;

import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit

import com.google.common.collect.Lists;

public class EntityFallingBlock extends Entity {

	private IBlockData block;
	public int ticksLived;
	public boolean dropItem = true;
	private boolean e;
	public boolean hurtEntities; // PAIL: private -> public
	private int fallHurtMax = 40;
	private float fallHurtAmount = 2.0F;
	public NBTTagCompound tileEntityData;
	public org.bukkit.Location sourceLoc; // PaperSpigot

	// PaperSpigot start - Add FallingBlock source location API
	public EntityFallingBlock(World world) {
		this(null, world);
	}

	public EntityFallingBlock(org.bukkit.Location loc, World world) {
		super(world);
		sourceLoc = loc;
		this.loadChunks = world.paperSpigotConfig.loadUnloadedFallingBlocks; // PaperSpigot
	}

	public EntityFallingBlock(World world, double d0, double d1, double d2, IBlockData iblockdata) {
		this(null, world, d0, d1, d2, iblockdata);
	}

	public EntityFallingBlock(org.bukkit.Location loc, World world, double d0, double d1, double d2,
			IBlockData iblockdata) {
		super(world);
		sourceLoc = loc;
		// PaperSpigot end
		this.block = iblockdata;
		this.k = true;
		this.setSize(0.98F, 0.98F);
		this.setPosition(d0, d1, d2);
		this.motX = 0.0D;
		this.motY = 0.0D;
		this.motZ = 0.0D;
		this.lastX = d0;
		this.lastY = d1;
		this.lastZ = d2;
		this.loadChunks = world.paperSpigotConfig.loadUnloadedFallingBlocks; // PaperSpigot
	}

	@Override
	protected boolean s_() {
		return false;
	}

	@Override
	protected void h() {
	}

	@Override
	public boolean ad() {
		return !this.dead;
	}

	@Override
	public void t_() {
		Block block = this.block.getBlock();

		if (block.getMaterial() == Material.AIR) {
			this.die();
		} else {
			this.lastX = this.locX;
			this.lastY = this.locY;
			this.lastZ = this.locZ;
			BlockPosition blockposition;

			if (this.ticksLived++ == 0) {
				blockposition = new BlockPosition(this);
				if (this.world.getType(blockposition).getBlock() == block
						&& !CraftEventFactory.callEntityChangeBlockEvent(this, blockposition.getX(),
								blockposition.getY(), blockposition.getZ(), Blocks.AIR, 0).isCancelled()) {
					this.world.setAir(blockposition);
					world.spigotConfig.antiXrayInstance.updateNearbyBlocks(world, blockposition); // Spigot
				} else if (!this.world.isClientSide) {
					this.die();
					return;
				}
			}

			this.motY -= 0.03999999910593033D;
			this.move(this.motX, this.motY, this.motZ);

			// PaperSpigot start - Remove entities in unloaded chunks
			if (this.inUnloadedChunk && world.paperSpigotConfig.removeUnloadedFallingBlocks) {
				this.die();
			}
			// PaperSpigot end

			// PaperSpigot start - Drop falling blocks above the specified height
			if (this.world.paperSpigotConfig.fallingBlockHeightNerf != 0
					&& this.locY > this.world.paperSpigotConfig.fallingBlockHeightNerf) {
				if (this.dropItem) {
					this.a(new ItemStack(block, 1, block.getDropData(this.block)), 0.0F);
				}

				this.die();
			}
			// PaperSpigot end

			this.motX *= 0.9800000190734863D;
			this.motY *= 0.9800000190734863D;
			this.motZ *= 0.9800000190734863D;
			if (!this.world.isClientSide) {
				blockposition = new BlockPosition(this);
				if (this.onGround) {
					this.motX *= 0.699999988079071D;
					this.motZ *= 0.699999988079071D;
					this.motY *= -0.5D;
					if (this.world.getType(blockposition).getBlock() != Blocks.PISTON_EXTENSION) {
						this.die();
						if (!this.e) {
							if (this.world
									.a(block, blockposition, true, EnumDirection.UP, (Entity) null, (ItemStack) null)
									&& !BlockFalling.canFall(this.world, blockposition.down()) /*
																								 * mimic the false
																								 * conditions of
																								 * setTypeIdAndData
																								 */
									&& blockposition.getX() >= -30000000 && blockposition.getZ() >= -30000000
									&& blockposition.getX() < 30000000 && blockposition.getZ() < 30000000
									&& blockposition.getY() >= 0
									&& blockposition
											.getY() < (this.world.tacoSpigotConfig.disableFallingBlockStackingAt256
													? 255
													: 256)
									&& this.world.getType(blockposition) != this.block) {
								if (CraftEventFactory.callEntityChangeBlockEvent(this, blockposition.getX(),
										blockposition.getY(), blockposition.getZ(), this.block.getBlock(),
										this.block.getBlock().toLegacyData(this.block)).isCancelled()) {
									return;
								}
								this.world.setTypeAndData(blockposition, this.block, 3);
								world.spigotConfig.antiXrayInstance.updateNearbyBlocks(world, blockposition); // Spigot
								// CraftBukkit end
								if (block instanceof BlockFalling) {
									((BlockFalling) block).a_(this.world, blockposition);
								}

								if (this.tileEntityData != null && block instanceof IContainer) {
									TileEntity tileentity = this.world.getTileEntity(blockposition);

									if (tileentity != null) {
										NBTTagCompound nbttagcompound = new NBTTagCompound();

										tileentity.b(nbttagcompound);
										Iterator iterator = this.tileEntityData.c().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.a(nbttagcompound);
										tileentity.update();
									}
								}
							} else if (this.dropItem && this.world.getGameRules().getBoolean("doEntityDrops")) {
								this.a(new ItemStack(block, 1, block.getDropData(this.block)), 0.0F);
							}
						}
					}
				} else if (this.ticksLived > 100 && !this.world.isClientSide
						&& (blockposition.getY() < 1 || blockposition.getY() > 256) || this.ticksLived > 600) {
					if (this.dropItem && this.world.getGameRules().getBoolean("doEntityDrops")) {
						this.a(new ItemStack(block, 1, block.getDropData(this.block)), 0.0F);
					}

					this.die();
				}
			}

		}
	}

	@Override
	public void e(float f, float f1) {
		Block block = this.block.getBlock();

		if (this.hurtEntities) {
			int i = MathHelper.f(f - 1.0F);

			if (i > 0) {
				ArrayList arraylist = Lists.newArrayList(this.world.getEntities(this, this.getBoundingBox()));
				boolean flag = block == Blocks.ANVIL;
				DamageSource damagesource = flag ? DamageSource.ANVIL : DamageSource.FALLING_BLOCK;
				Iterator iterator = arraylist.iterator();

				while (iterator.hasNext()) {
					Entity entity = (Entity) iterator.next();

					CraftEventFactory.entityDamage = this; // CraftBukkit
					entity.damageEntity(damagesource,
							Math.min(MathHelper.d(i * this.fallHurtAmount), this.fallHurtMax));
					CraftEventFactory.entityDamage = null; // CraftBukkit
				}

				if (flag && this.random.nextFloat() < 0.05000000074505806D + i * 0.05D) {
					int j = this.block.get(BlockAnvil.DAMAGE).intValue();

					++j;
					if (j > 2) {
						this.e = true;
					} else {
						this.block = this.block.set(BlockAnvil.DAMAGE, Integer.valueOf(j));
					}
				}
			}
		}

	}

	@Override
	protected void b(NBTTagCompound nbttagcompound) {
		Block block = this.block != null ? this.block.getBlock() : Blocks.AIR;
		MinecraftKey minecraftkey = Block.REGISTRY.c(block);

		nbttagcompound.setString("Block", minecraftkey == null ? "" : minecraftkey.toString());
		nbttagcompound.setByte("Data", (byte) block.toLegacyData(this.block));
		nbttagcompound.setByte("Time", (byte) 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);
		}
		// PaperSpigot start - Add FallingBlock source location API
		if (sourceLoc != null) {
			nbttagcompound.setInt("SourceLoc_x", sourceLoc.getBlockX());
			nbttagcompound.setInt("SourceLoc_y", sourceLoc.getBlockY());
			nbttagcompound.setInt("SourceLoc_z", sourceLoc.getBlockZ());
		}
		// PaperSpigot end
	}

	@Override
	protected void a(NBTTagCompound nbttagcompound) {
		int i = nbttagcompound.getByte("Data") & 255;

		if (nbttagcompound.hasKeyOfType("Block", 8)) {
			this.block = Block.getByName(nbttagcompound.getString("Block")).fromLegacyData(i);
		} else if (nbttagcompound.hasKeyOfType("TileID", 99)) {
			this.block = Block.getById(nbttagcompound.getInt("TileID")).fromLegacyData(i);
		} else {
			this.block = Block.getById(nbttagcompound.getByte("Tile") & 255).fromLegacyData(i);
		}

		this.ticksLived = nbttagcompound.getByte("Time") & 255;
		Block block = this.block.getBlock();

		if (nbttagcompound.hasKeyOfType("HurtEntities", 99)) {
			this.hurtEntities = nbttagcompound.getBoolean("HurtEntities");
			this.fallHurtAmount = nbttagcompound.getFloat("FallHurtAmount");
			this.fallHurtMax = nbttagcompound.getInt("FallHurtMax");
		} else if (block == Blocks.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 (block == null || block.getMaterial() == Material.AIR) {
			this.block = Blocks.SAND.getBlockData();
		}
		// PaperSpigot start - Add FallingBlock source location API
		if (nbttagcompound.hasKey("SourceLoc_x")) {
			int srcX = nbttagcompound.getInt("SourceLoc_x");
			int srcY = nbttagcompound.getInt("SourceLoc_y");
			int srcZ = nbttagcompound.getInt("SourceLoc_z");
			sourceLoc = new org.bukkit.Location(world.getWorld(), srcX, srcY, srcZ);
		}
		// PaperSpigot end
	}

	public void a(boolean flag) {
		this.hurtEntities = flag;
	}

	@Override
	public void appendEntityCrashDetails(CrashReportSystemDetails crashreportsystemdetails) {
		super.appendEntityCrashDetails(crashreportsystemdetails);
		if (this.block != null) {
			Block block = this.block.getBlock();

			crashreportsystemdetails.a("Immitating block ID", Integer.valueOf(Block.getId(block)));
			crashreportsystemdetails.a("Immitating block data", Integer.valueOf(block.toLegacyData(this.block)));
		}

	}

	public IBlockData getBlock() {
		return this.block;
	}

	// PaperSpigot start - Fix cannons
	@Override
	public double f(double d0, double d1, double d2) {
		if (!world.paperSpigotConfig.fixCannons) {
			return super.f(d0, d1, d2);
		}

		double d3 = this.locX - d0;
		double d4 = this.locY + this.getHeadHeight() - d1;
		double d5 = this.locZ - d2;

		return MathHelper.sqrt(d3 * d3 + d4 * d4 + d5 * d5);
	}

	@Override
	public float getHeadHeight() {
		return world.paperSpigotConfig.fixCannons ? this.length / 2 : super.getHeadHeight();
	}
	// PaperSpigot end
}
