492 lines
14 KiB
Java

package com.hbm.entity.item;
import java.util.List;
import com.hbm.items.ModItems;
import com.hbm.util.TrackerUtil;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
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.EntityTrackerEntry;
import net.minecraft.entity.item.EntityBoat;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.DamageSource;
import net.minecraft.util.MathHelper;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
public class EntityBoatRubber extends Entity {
private boolean isBoatEmpty;
private double speedMultiplier;
private int boatPosRotationIncrements;
private double boatX;
private double boatY;
private double boatZ;
private double boatYaw;
private double boatPitch;
@SideOnly(Side.CLIENT) private double velocityX;
@SideOnly(Side.CLIENT) private double velocityY;
@SideOnly(Side.CLIENT) private double velocityZ;
public float prevRenderYaw;
public EntityBoatRubber(World world) {
super(world);
this.isBoatEmpty = true;
this.speedMultiplier = 0.07D;
this.preventEntitySpawning = true;
this.setSize(1.5F, 0.6F);
this.yOffset = this.height / 2.0F;
}
public EntityBoatRubber(World world, double x, double y, double z) {
this(world);
this.setPosition(x, y + (double) this.yOffset, z);
this.motionX = 0.0D;
this.motionY = 0.0D;
this.motionZ = 0.0D;
this.prevPosX = x;
this.prevPosY = y;
this.prevPosZ = z;
}
protected void entityInit() {
this.dataWatcher.addObject(17, new Integer(0));
this.dataWatcher.addObject(18, new Integer(1));
this.dataWatcher.addObject(19, new Float(0.0F));
}
@Override
protected boolean canTriggerWalking() {
return false;
}
@Override
public AxisAlignedBB getCollisionBox(Entity entity) {
return entity.boundingBox;
}
@Override
public AxisAlignedBB getBoundingBox() {
return this.boundingBox;
}
@Override
public boolean canBePushed() {
return true;
}
@Override
public double getMountedYOffset() {
return (double) this.height * 0.0D - 0.3D;
}
@Override
public boolean attackEntityFrom(DamageSource source, float amount) {
if(this.isEntityInvulnerable()) {
return false;
} else if(!this.worldObj.isRemote && !this.isDead) {
this.setForwardDirection(-this.getForwardDirection());
this.setTimeSinceHit(10);
this.setDamageTaken(this.getDamageTaken() + amount * 10.0F);
this.setBeenAttacked();
boolean hitByCreative = source.getEntity() instanceof EntityPlayer && ((EntityPlayer) source.getEntity()).capabilities.isCreativeMode;
if(hitByCreative || this.getDamageTaken() > 40.0F) {
if(this.riddenByEntity != null) {
this.riddenByEntity.mountEntity(this);
}
if(!hitByCreative) {
this.dropBoat();
}
this.setDead();
}
return true;
} else {
return true;
}
}
@Override
@SideOnly(Side.CLIENT)
public void performHurtAnimation() {
this.setForwardDirection(-this.getForwardDirection());
this.setTimeSinceHit(10);
this.setDamageTaken(this.getDamageTaken() * 11.0F);
}
@Override
public boolean canBeCollidedWith() {
return !this.isDead;
}
@Override
@SideOnly(Side.CLIENT)
public void setPositionAndRotation2(double x, double y, double z, float yaw, float pitch, int interp) {
if(this.isBoatEmpty) {
this.boatPosRotationIncrements = interp;
} else {
double d3 = x - this.posX;
double d4 = y - this.posY;
double d5 = z - this.posZ;
double d6 = d3 * d3 + d4 * d4 + d5 * d5;
if(d6 <= 1.0D) {
return;
}
this.boatPosRotationIncrements = 3;
}
this.boatX = x;
this.boatY = y;
this.boatZ = z;
this.boatYaw = (double) yaw;
this.boatPitch = (double) pitch;
this.motionX = this.velocityX;
this.motionY = this.velocityY;
this.motionZ = this.velocityZ;
}
@Override
@SideOnly(Side.CLIENT)
public void setVelocity(double x, double y, double z) {
this.velocityX = this.motionX = x;
this.velocityY = this.motionY = y;
this.velocityZ = this.motionZ = z;
}
@Override
public void onUpdate() {
super.onUpdate();
if(this.getTimeSinceHit() > 0) {
this.setTimeSinceHit(this.getTimeSinceHit() - 1);
}
if(this.getDamageTaken() > 0.0F) {
this.setDamageTaken(this.getDamageTaken() - 1.0F);
}
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
byte b0 = 5;
double d0 = 0.0D;
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;
}
}
if(this.worldObj.isRemote && this.isBoatEmpty) {
if(this.boatPosRotationIncrements > 0) {
double x = this.posX + (this.boatX - this.posX) / (double) this.boatPosRotationIncrements;
double y = this.posY + (this.boatY - this.posY) / (double) this.boatPosRotationIncrements;
double z = this.posZ + (this.boatZ - this.posZ) / (double) this.boatPosRotationIncrements;
double yaw = MathHelper.wrapAngleTo180_double(this.boatYaw - (double) this.rotationYaw);
this.rotationYaw = (float) ((double) this.rotationYaw + yaw / (double) this.boatPosRotationIncrements);
this.rotationPitch = (float) ((double) this.rotationPitch + (this.boatPitch - (double) this.rotationPitch) / (double) this.boatPosRotationIncrements);
--this.boatPosRotationIncrements;
this.setPosition(x, y, z);
} else {
double x = this.posX + this.motionX;
double y = this.posY + this.motionY;
double z = this.posZ + this.motionZ;
this.setPosition(x, y, z);
if(this.onGround) {
this.motionX *= 0.5D;
this.motionY *= 0.5D;
this.motionZ *= 0.5D;
}
this.passiveDeccelerate();
}
} else {
if(d0 < 1.0D) {
double d2 = d0 * 2.0D - 1.0D;
this.motionY += 0.04D * d2;
} else {
if(this.motionY < 0.0D) {
this.motionY /= 2.0D;
}
this.motionY += 0.007000000216066837D;
}
double prevSpeedSq = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ);
this.isAirBorne = false;
if(this.riddenByEntity != null && this.riddenByEntity instanceof EntityLivingBase) {
EntityLivingBase entitylivingbase = (EntityLivingBase) this.riddenByEntity;
if(entitylivingbase.moveForward != 0 || entitylivingbase.moveStrafing != 0) {
Vec3 dir = Vec3.createVectorHelper(0, 0, 1);
dir.rotateAroundY((float) -((this.rotationYaw + 90) * Math.PI / 180D));
this.motionX += dir.xCoord * this.speedMultiplier * entitylivingbase.moveForward * 0.05D;
this.motionZ += dir.zCoord * this.speedMultiplier * entitylivingbase.moveForward * 0.05D;
float prevYaw = this.rotationYaw;
this.rotationYaw -= entitylivingbase.moveStrafing * 3;
Vec3 newMotion = Vec3.createVectorHelper(motionX, 0, motionZ);
newMotion.rotateAroundY((float) (-(this.rotationYaw - prevYaw) * Math.PI / 180D));
this.motionX = newMotion.xCoord;
this.motionZ = newMotion.zCoord;
//HOLY HELL! if we don't shit ourselves over packets and send them at proper intervals, entities are suddenly smooth! who would have thought! mojang certainly didn't!
EntityTrackerEntry entry = TrackerUtil.getTrackerEntry((WorldServer) worldObj, this.getEntityId());
entry.lastYaw = MathHelper.floor_float(this.rotationYaw * 256.0F / 360.0F) + 10; //force-trigger rotation update
}
} else {
this.motionX *= 0.95D;
this.motionY *= 0.95D;
this.motionZ *= 0.95D;
}
double speedSq = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ);
if(speedSq > 0.5D) {
double d4 = 0.5D / speedSq;
this.motionX *= d4;
this.motionZ *= d4;
speedSq = 0.5D;
}
if(speedSq > prevSpeedSq && this.speedMultiplier < 0.5D) {
this.speedMultiplier += (0.5D - this.speedMultiplier) / 50.0D;
if(this.speedMultiplier > 0.5D) {
this.speedMultiplier = 0.5D;
}
} else {
this.speedMultiplier -= (this.speedMultiplier - 0.07D) / 35.0D;
if(this.speedMultiplier < 0.07D) {
this.speedMultiplier = 0.07D;
}
}
for(int index = 0; index < 4; ++index) {
int x = MathHelper.floor_double(this.posX + ((double) (index % 2) - 0.5D) * 0.8D);
int z = MathHelper.floor_double(this.posZ + ((double) (index / 2) - 0.5D) * 0.8D);
for(int yOff = 0; yOff < 2; ++yOff) {
int y = MathHelper.floor_double(this.posY) + yOff;
Block block = this.worldObj.getBlock(x, y, z);
if(block == Blocks.snow_layer) {
this.worldObj.setBlockToAir(x, y, z);
this.isCollidedHorizontally = false;
} else if(block == Blocks.waterlily) {
this.worldObj.func_147480_a(x, y, z, true);
this.isCollidedHorizontally = false;
}
}
}
if(this.onGround) {
this.motionX *= 0.5D;
this.motionY *= 0.5D;
this.motionZ *= 0.5D;
}
this.moveEntity(this.motionX, this.motionY, this.motionZ);
if(this.isCollidedHorizontally && prevSpeedSq > 0.2D) {
this.motionX *= 0.25D;
this.motionY *= 0.25D;
this.motionZ *= 0.25D;
} else {
this.passiveDeccelerate();
}
this.rotationPitch = 0.0F;
if(!(this.riddenByEntity instanceof EntityLivingBase)) {
double yaw = (double) this.rotationYaw;
double deltaX = this.prevPosX - this.posX;
double deltaZ = this.prevPosZ - this.posZ;
if(deltaX * deltaX + deltaZ * deltaZ > 0.001D) {
yaw = (double) ((float) (Math.atan2(deltaZ, deltaX) * 180.0D / Math.PI));
}
double rotationSpeed = MathHelper.wrapAngleTo180_double(yaw - (double) this.rotationYaw);
if(rotationSpeed > 20.0D) {
rotationSpeed = 20.0D;
}
if(rotationSpeed < -20.0D) {
rotationSpeed = -20.0D;
}
this.rotationYaw = (float) ((double) this.rotationYaw + rotationSpeed);
}
this.setRotation(this.rotationYaw, this.rotationPitch);
if(!this.worldObj.isRemote) {
List list = this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.boundingBox.expand(0.2D, 0.0D, 0.2D));
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 EntityBoatRubber || entity instanceof EntityBoat)) {
entity.applyEntityCollision(this);
}
}
}
if(this.riddenByEntity != null && this.riddenByEntity.isDead) {
this.riddenByEntity = null;
}
}
}
double moX = this.prevPosX - this.posX;
double moZ = this.prevPosZ - this.posZ;
double prevSpeedSq = Math.sqrt(moX * moX + moZ * moZ);
if(prevSpeedSq > 0.2625D) {
double cosYaw = Math.cos(this.rotationYaw * Math.PI / 180.0D);
double sinYaw = Math.sin(this.rotationYaw * Math.PI / 180.0D);
for(double j = 0; j < 1.0D + prevSpeedSq * 60.0D; ++j) {
double offset = (double) (this.rand.nextFloat() * 2.0F - 1.0F);
double side = (double) (this.rand.nextInt(2) * 2 - 1) * 0.7D;
double magX;
double magZ;
if(this.rand.nextBoolean()) {
magX = this.posX - cosYaw * offset * 0.8D + sinYaw * side;
magZ = this.posZ - sinYaw * offset * 0.8D - cosYaw * side;
this.worldObj.spawnParticle("splash", magX, this.posY - 0.125D, magZ, moX, 0.1, moZ);
} else {
magX = this.posX + cosYaw + sinYaw * offset * 0.7D;
magZ = this.posZ + sinYaw - cosYaw * offset * 0.7D;
this.worldObj.spawnParticle("splash", magX, this.posY - 0.125D, magZ, moX, 0.1, moZ);
}
}
}
}
protected void passiveDeccelerate() {
this.motionX *= 0.99D;
this.motionY *= 0.95D;
this.motionZ *= 0.99D;
}
@Override
public void updateRiderPosition() {
if(this.riddenByEntity != null) {
double offX = Math.cos((double) this.rotationYaw * Math.PI / 180.0D) * 0.4D;
double offZ = Math.sin((double) this.rotationYaw * Math.PI / 180.0D) * 0.4D;
this.riddenByEntity.setPosition(this.posX + offX, this.posY + this.getMountedYOffset() + this.riddenByEntity.getYOffset(), this.posZ + offZ);
if(this.riddenByEntity instanceof EntityPlayer) {
EntityPlayer player = (EntityPlayer) this.riddenByEntity;
player.renderYawOffset = MathHelper.wrapAngleTo180_float(this.rotationYaw + 90F);
}
}
}
@Override protected void writeEntityToNBT(NBTTagCompound p_70014_1_) { }
@Override protected void readEntityFromNBT(NBTTagCompound p_70037_1_) { }
@Override
@SideOnly(Side.CLIENT)
public float getShadowSize() {
return 0.0F;
}
@Override
public boolean interactFirst(EntityPlayer player) {
if(this.riddenByEntity != null && this.riddenByEntity instanceof EntityPlayer && this.riddenByEntity != player) {
return true;
} else {
if(!this.worldObj.isRemote) {
player.mountEntity(this);
}
return true;
}
}
@Override
protected void updateFallState(double fall, boolean onGround) {
int x = MathHelper.floor_double(this.posX);
int y = MathHelper.floor_double(this.posY);
int z = MathHelper.floor_double(this.posZ);
if(onGround) {
if(this.fallDistance > 5.0F) {
this.fall(this.fallDistance);
if(!this.worldObj.isRemote && !this.isDead) {
this.setDead();
this.dropBoat();
}
this.fallDistance = 0.0F;
}
} else if(this.worldObj.getBlock(x, y - 1, z).getMaterial() != Material.water && fall < 0.0D) {
this.fallDistance = (float) ((double) this.fallDistance - fall);
}
}
public void dropBoat() {
this.func_145778_a(ModItems.boat_rubber, 1, 0.0F);
}
public void setDamageTaken(float amount) {
this.dataWatcher.updateObject(19, Float.valueOf(amount));
}
public float getDamageTaken() {
return this.dataWatcher.getWatchableObjectFloat(19);
}
public void setTimeSinceHit(int time) {
this.dataWatcher.updateObject(17, Integer.valueOf(time));
}
public int getTimeSinceHit() {
return this.dataWatcher.getWatchableObjectInt(17);
}
public void setForwardDirection(int dir) {
this.dataWatcher.updateObject(18, Integer.valueOf(dir));
}
public int getForwardDirection() {
return this.dataWatcher.getWatchableObjectInt(18);
}
@SideOnly(Side.CLIENT)
public void setIsBoatEmpty(boolean empty) {
this.isBoatEmpty = empty;
}
}