package net.tropicraft.entity.placeable;
import java.util.List;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.DamageSource;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
import net.tropicraft.registry.TCItemRegistry;
import net.tropicraft.util.ColorHelper;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
public class EntityChair extends Entity {
// TODO add drips after being wet
// TODO make it so monkies can sit in the chair ouo
/** Combined rgba of the chair */
private static final int DATAWATCHER_COLOR = 2;
/** Current damage to the chair (from punching it) */
private static final int DATAWATCHER_DAMAGE = 3;
/** Is come sail away mode? */
private static final int DATAWATCHER_COMESAILAWAY = 4;
/** Which direction is this chair facing? */
private static final int DATAWATCHER_FORWARD_DIRECTION = 5;
/** The time to count down from since the last time entity was hit. */
private static final int DATAWATCHER_TIME_SINCE_HIT = 6;
/** Is any entity sitting in the chair? */
public boolean isChairEmpty;
private int chairPosRotationIncrements;
private double chairX;
private double chairY;
private double chairZ;
private double chairPitch;
private double chairYaw;
@SideOnly(Side.CLIENT)
private double velocityX;
@SideOnly(Side.CLIENT)
private double velocityY;
@SideOnly(Side.CLIENT)
private double velocityZ;
/** Acceleration */
private double speedMultiplier;
public EntityChair(World world) {
super(world);
this.ignoreFrustumCheck = true;
this.isChairEmpty = true;
this.speedMultiplier = 0.10D;
this.preventEntitySpawning = true;
this.entityCollisionReduction = .95F;
this.setSize(1F, 1F);
}
public EntityChair(World world, double x, double y, double z, int color, EntityPlayer player) {
this(world);
setPosition(x, y, z);
motionX = 0.0D;
motionY = 0.0D;
motionZ = 0.0D;
prevPosX = x;
prevPosY = y;
prevPosZ = z;
setColor(color);
rotationYaw = this.getAngleToPlayer(player);
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate() {
super.onUpdate();
if (this.getTimeSinceHit() > 0) {
this.setTimeSinceHit(this.getTimeSinceHit() - 1);
}
if (this.getDamage() > 0.0F) {
this.setDamage(this.getDamage() - 1.0F);
}
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
byte b0 = 5;
double d0 = 0.0D;
if (this.getComeSailAway())
for (int i = 0; i < b0; ++i) {
double d1 = this.boundingBox.minY + (this.boundingBox.maxY - this.boundingBox.minY) * (double)(i + 0) / (double)b0 - 0.125D;
double d3 = this.boundingBox.minY + (this.boundingBox.maxY - this.boundingBox.minY) * (double)(i + 1) / (double)b0 - 0.125D;
AxisAlignedBB axisalignedbb = AxisAlignedBB.getBoundingBox(this.boundingBox.minX, d1, this.boundingBox.minZ, this.boundingBox.maxX, d3, this.boundingBox.maxZ);
if (this.worldObj.isAABBInMaterial(axisalignedbb, Material.water))
{
d0 += 1.0D / (double)b0;
}
}
double d10 = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ);
double d2;
double d4;
int j;
if (/*this.getComeSailAway() && */d10 > 0.26249999999999996D) {
d2 = Math.cos((double)this.rotationYaw * Math.PI / 180.0D);
d4 = Math.sin((double)this.rotationYaw * Math.PI / 180.0D);
if (this.getComeSailAway())
for (j = 0; (double)j < 1.0D + d10 * 60.0D; ++j) {
double d5 = (double)(this.rand.nextFloat() * 2.0F - 1.0F);
double d6 = (double)(this.rand.nextInt(2) * 2 - 1) * 0.7D;
double d8;
double d9;
if (this.rand.nextBoolean()) {
d8 = this.posX - d2 * d5 * 0.8D + d4 * d6;
d9 = this.posZ - d4 * d5 * 0.8D - d2 * d6;
this.worldObj.spawnParticle("splash", d8, this.posY - 0.125D, d9, this.motionX, this.motionY, this.motionZ);
} else {
d8 = this.posX + d2 + d4 * d5 * 0.7D;
d9 = this.posZ + d4 - d2 * d5 * 0.7D;
this.worldObj.spawnParticle("splash", d8, this.posY - 0.125D, d9, this.motionX, this.motionY, this.motionZ);
}
}
}
double d11;
double d12;
if (this.worldObj.isRemote && this.isChairEmpty) {
if (this.chairPosRotationIncrements > 0) {
d2 = this.posX + (this.chairX - this.posX) / (double)this.chairPosRotationIncrements;
d4 = this.posY + (this.chairY - this.posY) / (double)this.chairPosRotationIncrements;
d11 = this.posZ + (this.chairZ - this.posZ) / (double)this.chairPosRotationIncrements;
d12 = MathHelper.wrapAngleTo180_double(this.chairYaw - (double)this.rotationYaw);
this.rotationYaw = (float)((double)this.rotationYaw + d12 / (double)this.chairPosRotationIncrements);
this.rotationPitch = (float)((double)this.rotationPitch + (this.chairPitch - (double)this.rotationPitch) / (double)this.chairPosRotationIncrements);
--this.chairPosRotationIncrements;
this.setPosition(d2, d4, d11);
this.setRotation(this.rotationYaw, this.rotationPitch);
} else {
d2 = this.posX + this.motionX;
d4 = this.posY + this.motionY;
d11 = this.posZ + this.motionZ;
this.setPosition(d2, d4, d11);
if (this.onGround) {
this.motionX *= 0.5D;
this.motionY *= 0.5D;
this.motionZ *= 0.5D;
}
this.motionX *= 0.9900000095367432D;
this.motionY *= 0.949999988079071D;
this.motionZ *= 0.9900000095367432D;
}
} else {
if (d0 < 1.0D) {
d2 = d0 * 2.0D - 1.0D;
this.motionY += 0.03999999910593033D * d2;
} else {
if (this.motionY < 0.0D) {
this.motionY /= 2.0D;
}
this.motionY += 0.007000000216066837D;
}
if (this.getComeSailAway() && this.riddenByEntity != null && this.riddenByEntity instanceof EntityLivingBase) {
EntityLivingBase entitylivingbase = (EntityLivingBase)this.riddenByEntity;
float f = this.riddenByEntity.rotationYaw + -entitylivingbase.moveStrafing * 90.0F;
this.motionX += -Math.sin((double)(f * (float)Math.PI / 180.0F)) * this.speedMultiplier * (double)entitylivingbase.moveForward * 0.05000000074505806D;
this.motionZ += Math.cos((double)(f * (float)Math.PI / 180.0F)) * this.speedMultiplier * (double)entitylivingbase.moveForward * 0.05000000074505806D;
}
d2 = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ);
if (d2 > 0.45D) {
d4 = 0.45D / d2;
this.motionX *= d4;
this.motionZ *= d4;
d2 = 0.45D;
}
if (d2 > d10 && this.speedMultiplier < 0.45D) {
this.speedMultiplier += (0.45D - this.speedMultiplier) / 45.0D;
if (this.speedMultiplier > 0.45D) {
this.speedMultiplier = 0.45D;
}
} else {
this.speedMultiplier -= (this.speedMultiplier - 0.10D) / 45.0D;
if (this.speedMultiplier < 0.10D) {
this.speedMultiplier = 0.10D;
}
}
int l;
if (this.getComeSailAway())
for (l = 0; l < 4; ++l) {
int i1 = MathHelper.floor_double(this.posX + ((double)(l % 2) - 0.5D) * 0.8D);
j = MathHelper.floor_double(this.posZ + ((double)(l / 2) - 0.5D) * 0.8D);
for (int j1 = 0; j1 < 2; ++j1) {
int k = MathHelper.floor_double(this.posY) + j1;
Block block = this.worldObj.getBlock(i1, k, j);
if (block == Blocks.snow_layer) {
this.worldObj.setBlockToAir(i1, k, j);
this.isCollidedHorizontally = false;
} else
if (block == Blocks.waterlily) {
this.worldObj.setBlockToAir(i1, k, j);
this.worldObj.func_147480_a(i1, k, j, true);
this.isCollidedHorizontally = false;
}
}
}
if (this.getComeSailAway() && this.onGround) {
this.motionX *= 0.5D;
this.motionY *= 0.5D;
this.motionZ *= 0.5D;
} else
if (this.onGround) {
this.motionX = 0;
this.motionY = 0;
this.motionZ = 0;
}
this.moveEntity(this.motionX, this.motionY, this.motionZ);
// This will never trigger since d10 will only ever get up to 0.45 >:D *evil laugh*
// In other words, when come sail away, there is no stopping this sucker
if (this.getComeSailAway()) {
this.motionX *= 0.9900000095367432D;
this.motionY *= 0.949999988079071D;
this.motionZ *= 0.9900000095367432D;
}
this.rotationPitch = 0.0F;
d4 = (double)this.rotationYaw;
d11 = this.prevPosX - this.posX;
d12 = this.prevPosZ - this.posZ;
if (d11 * d11 + d12 * d12 > 0.001D) {
d4 = (double)((float)(Math.atan2(d12, d11) * 180.0D / Math.PI));
}
double d7 = MathHelper.wrapAngleTo180_double(d4 - (double)this.rotationYaw);
if (d7 > 20.0D) {
d7 = 20.0D;
}
if (d7 < -20.0D) {
d7 = -20.0D;
}
this.rotationYaw = (float)((double)this.rotationYaw + d7);
this.setRotation(this.rotationYaw, this.rotationPitch);
if (!this.worldObj.isRemote) {
List<?> list = this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.boundingBox.expand(0.20000000298023224D, 0.0D, 0.20000000298023224D));
if (list != null && !list.isEmpty()) {
for (int k1 = 0; k1 < list.size(); ++k1) {
Entity entity = (Entity)list.get(k1);
if (entity != this.riddenByEntity && entity.canBePushed() && entity instanceof EntityChair) {
entity.applyEntityCollision(this);
}
}
}
if (this.riddenByEntity != null && this.riddenByEntity.isDead) {
this.riddenByEntity = null;
}
}
}
}
@Override
protected void entityInit() {
this.dataWatcher.addObject(DATAWATCHER_COLOR, new Integer(ColorHelper.DEFAULT_VALUE));
this.dataWatcher.addObject(DATAWATCHER_DAMAGE, new Float(0));
this.dataWatcher.addObject(DATAWATCHER_COMESAILAWAY, new Byte((byte)0));
this.dataWatcher.addObject(DATAWATCHER_FORWARD_DIRECTION, new Integer(1));
this.dataWatcher.addObject(DATAWATCHER_TIME_SINCE_HIT, new Integer(0));
}
@Override
protected void readEntityFromNBT(NBTTagCompound nbt) {
this.setColor(Integer.valueOf(nbt.getInteger("COLOR")));
this.setComeSailAway(Boolean.valueOf(nbt.getBoolean("COME_SAIL_AWAY")));
}
@Override
protected void writeEntityToNBT(NBTTagCompound nbt) {
nbt.setInteger("COLOR", Integer.valueOf(this.getColor()));
nbt.setBoolean("COME_SAIL_AWAY", Boolean.valueOf(this.getComeSailAway()));
}
/**
* Called when the entity is attacked.
*/
@Override
public boolean attackEntityFrom(DamageSource par1DamageSource, float par2) {
if (this.isEntityInvulnerable()) {
return false;
}
else if (!this.worldObj.isRemote && !this.isDead) {
this.setForwardDirection(-this.getForwardDirection());
this.setTimeSinceHit(10);
this.setDamage(this.getDamage() + par2 * 10.0F);
this.setBeenAttacked();
boolean flag = par1DamageSource.getEntity() instanceof EntityPlayer && ((EntityPlayer)par1DamageSource.getEntity()).capabilities.isCreativeMode;
if (flag || this.getDamage() > 40.0F) {
if (this.riddenByEntity != null) {
this.riddenByEntity.mountEntity(this);
}
if (!flag) {
this.entityDropItem(new ItemStack(TCItemRegistry.chair, 1, getDamageFromColor()), 0.0F);
}
this.setDead();
}
return true;
} else {
return true;
}
}
/**
* @return Returns the damage value associated with the color of this chair
*/
public int getDamageFromColor() {
return ColorHelper.getDamageFromColor(this.getColor());
}
/**
* Setups the entity to do the hurt animation. Only used by packets in multiplayer.
*/
@SideOnly(Side.CLIENT)
@Override
public void performHurtAnimation() {
this.setForwardDirection(-this.getForwardDirection());
this.setTimeSinceHit(10);
this.setDamage(this.getDamage() * 11.0F);
}
/**
* First layer of player interaction
*/
@Override
public boolean interactFirst(EntityPlayer player) {
if (this.riddenByEntity != null && this.riddenByEntity instanceof EntityPlayer && this.riddenByEntity != player) {
return true;
} else {
if (!this.worldObj.isRemote) {
System.out.println("mount");
player.mountEntity(this);
}
return true;
}
}
/**
* Sets the position and rotation. Only difference from the other one is no bounding on the rotation. Args: posX,
* posY, posZ, yaw, pitch
*/
@SideOnly(Side.CLIENT)
@Override
public void setPositionAndRotation2(double par1, double par3, double par5, float par7, float par8, int par9)
{
if (this.isChairEmpty)
{
this.chairPosRotationIncrements = par9 + 5;
}
else
{
double d3 = par1 - this.posX;
double d4 = par3 - this.posY;
double d5 = par5 - this.posZ;
double d6 = d3 * d3 + d4 * d4 + d5 * d5;
if (d6 <= 1.0D)
{
return;
}
this.chairPosRotationIncrements = 3;
}
this.chairX = par1;
this.chairY = par3;
this.chairZ = par5;
this.chairYaw = (double)par7;
this.chairPitch = (double)par8;
this.motionX = this.velocityX;
this.motionY = this.velocityY;
this.motionZ = this.velocityZ;
}
/**
* Returns true if other Entities should be prevented from moving through this Entity.
*/
@Override
public boolean canBeCollidedWith() {
return !this.isDead;
}
/**
* Sets the velocity to the args. Args: x, y, z
*/
@SideOnly(Side.CLIENT)
@Override
public void setVelocity(double xVelocity, double yVelocity, double zVelocity) {
this.velocityX = this.motionX = xVelocity;
this.velocityY = this.motionY = yVelocity;
this.velocityZ = this.motionZ = zVelocity;
}
/**
* Update rider position with x, y, and z offsets
*/
@Override
public void updateRiderPosition() {
if (this.riddenByEntity != null) {
double xOffset = Math.cos((double)this.rotationYaw * Math.PI / 180.0D) * 0.4D;
double zOffset = Math.sin((double)this.rotationYaw * Math.PI / 180.0D) * 0.4D;
this.riddenByEntity.setPosition(this.posX + xOffset, this.posY + this.getMountedYOffset() + this.riddenByEntity.getYOffset(), this.posZ + zOffset);
}
}
@SideOnly(Side.CLIENT)
public float getShadowSize() {
return 0.5F;
}
/**
* Returns the Y offset from the entity's position for any entity riding this one.
*/
@Override
public double getMountedYOffset() {
return (double)this.height - 0.65D;
}
/**
* Given a player, get the angle that the chair should be at to face the player
* @param player
* @return The angle the chair should be at to face the players
*/
private float getAngleToPlayer(EntityPlayer player) {
float angle = MathHelper.wrapAngleTo180_float(player.rotationYaw);
return angle;
}
/**
* Returns a boundingBox used to collide the entity with other entities and blocks. This enables the entity to be
* pushable on contact, like chairs or minecarts.
*/
@Override
public AxisAlignedBB getCollisionBox(Entity par1Entity) {
return par1Entity.boundingBox;
}
/**
* returns the bounding box for this entity
*/
@Override
public AxisAlignedBB getBoundingBox() {
return this.boundingBox;
}
/**
* Returns true if this entity should push and be pushed by other entities when colliding.
*/
@Override
public boolean canBePushed() {
return false;
}
/**
* returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to
* prevent them from trampling crops
*/
@Override
protected boolean canTriggerWalking() {
return false;
}
/**
* Takes in the distance the entity has fallen this tick and whether its on the ground to update the fall distance
* and deal fall damage if landing on the ground. Args: distanceFallenThisTick, onGround
*/
@Override
protected void updateFallState(double distanceFallenThisTick, boolean onGround) {
int i = MathHelper.floor_double(this.posX);
int j = MathHelper.floor_double(this.posY);
int k = MathHelper.floor_double(this.posZ);
if (onGround) {
if (this.fallDistance > 3.0F) {
this.fall(this.fallDistance);
if (!this.worldObj.isRemote && !this.isDead) {
this.setDead();
int l;
for (l = 0; l < 3; ++l) {
this.entityDropItem(new ItemStack(Item.getItemFromBlock(Blocks.wool), 1, getDamageFromColor()), 0.0F);
}
for (l = 0; l < rand.nextInt(5) + 1; ++l) {
this.dropItem(TCItemRegistry.bambooStick, 1);
}
}
this.fallDistance = 0.0F;
}
}
else if (this.worldObj.getBlock(i, j - 1, k).getMaterial() != Material.water && distanceFallenThisTick < 0.0D)
{
this.fallDistance = (float)((double)this.fallDistance - distanceFallenThisTick);
}
}
public void setColor(int color) {
this.dataWatcher.updateObject(DATAWATCHER_COLOR, Integer.valueOf(color));
}
public void setColor(float red, float green, float blue) {
this.dataWatcher.updateObject(DATAWATCHER_COLOR, Integer.valueOf(ColorHelper.getColor(red, green, blue)));
}
public int getColor() {
return this.dataWatcher.getWatchableObjectInt(DATAWATCHER_COLOR);
}
public void setDamage(float damage) {
this.dataWatcher.updateObject(DATAWATCHER_DAMAGE, Float.valueOf(damage));
}
public float getDamage() {
return this.dataWatcher.getWatchableObjectFloat(DATAWATCHER_DAMAGE);
}
public void setComeSailAway(boolean sail) {
this.dataWatcher.updateObject(DATAWATCHER_COMESAILAWAY, sail ? Byte.valueOf((byte)1) : Byte.valueOf((byte)0));
}
public boolean getComeSailAway() {
return this.dataWatcher.getWatchableObjectByte(DATAWATCHER_COMESAILAWAY) == (byte)1;
}
/**
* Sets the forward direction of the entity.
*/
public void setForwardDirection(int dir) {
this.dataWatcher.updateObject(DATAWATCHER_FORWARD_DIRECTION, Integer.valueOf(dir));
}
/**
* Gets the forward direction of the entity.
*/
public int getForwardDirection() {
return this.dataWatcher.getWatchableObjectInt(DATAWATCHER_FORWARD_DIRECTION);
}
/**
* Sets the time to count down from since the last time entity was hit.
*/
public void setTimeSinceHit(int time) {
this.dataWatcher.updateObject(DATAWATCHER_TIME_SINCE_HIT, Integer.valueOf(time));
}
/**
* Gets the time since the last hit.
*/
public int getTimeSinceHit() {
return this.dataWatcher.getWatchableObjectInt(DATAWATCHER_TIME_SINCE_HIT);
}
}