mirror of
https://github.com/HbmMods/Hbm-s-Nuclear-Tech-GIT.git
synced 2026-01-25 10:32:49 +00:00
378 lines
12 KiB
Java
378 lines
12 KiB
Java
package com.hbm.entity.projectile;
|
|
|
|
import java.util.List;
|
|
|
|
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.entity.Entity;
|
|
import net.minecraft.entity.EntityLivingBase;
|
|
import net.minecraft.entity.IProjectile;
|
|
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.MathHelper;
|
|
import net.minecraft.util.MovingObjectPosition;
|
|
import net.minecraft.util.Vec3;
|
|
import net.minecraft.world.World;
|
|
|
|
/**
|
|
* Near-identical copy of EntityThrowable but deobfuscated & untangled
|
|
* @author hbm
|
|
*
|
|
*/
|
|
public abstract class EntityThrowableNT extends Entity implements IProjectile {
|
|
|
|
private int stuckBlockX = -1;
|
|
private int stuckBlockY = -1;
|
|
private int stuckBlockZ = -1;
|
|
private Block stuckBlock;
|
|
protected boolean inGround;
|
|
public int throwableShake;
|
|
protected EntityLivingBase thrower;
|
|
private String throwerName;
|
|
public int ticksInGround;
|
|
private int ticksInAir;
|
|
|
|
public EntityThrowableNT(World world) {
|
|
super(world);
|
|
this.setSize(0.25F, 0.25F);
|
|
}
|
|
|
|
@Override
|
|
protected void entityInit() {
|
|
this.dataWatcher.addObject(2, Byte.valueOf((byte)0));
|
|
}
|
|
|
|
public void setStuckIn(int side) {
|
|
this.dataWatcher.updateObject(2, (byte) side);
|
|
}
|
|
|
|
public int getStuckIn() {
|
|
return this.dataWatcher.getWatchableObjectByte(2);
|
|
}
|
|
|
|
@Override
|
|
@SideOnly(Side.CLIENT)
|
|
public boolean isInRangeToRenderDist(double dist) {
|
|
|
|
double perimeter = this.boundingBox.getAverageEdgeLength() * 4.0D;
|
|
perimeter *= 64.0D;
|
|
return dist < perimeter * perimeter;
|
|
}
|
|
|
|
public EntityThrowableNT(World world, EntityLivingBase thrower) {
|
|
super(world);
|
|
this.thrower = thrower;
|
|
this.setSize(0.25F, 0.25F);
|
|
this.setLocationAndAngles(thrower.posX, thrower.posY + (double) thrower.getEyeHeight(), thrower.posZ, thrower.rotationYaw, thrower.rotationPitch);
|
|
this.posX -= (double) (MathHelper.cos(this.rotationYaw / 180.0F * (float) Math.PI) * 0.16F);
|
|
this.posY -= 0.1D;
|
|
this.posZ -= (double) (MathHelper.sin(this.rotationYaw / 180.0F * (float) Math.PI) * 0.16F);
|
|
this.setPosition(this.posX, this.posY, this.posZ);
|
|
this.yOffset = 0.0F;
|
|
float velocity = 0.4F;
|
|
this.motionX = (double) (-MathHelper.sin(this.rotationYaw / 180.0F * (float) Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float) Math.PI) * velocity);
|
|
this.motionZ = (double) (MathHelper.cos(this.rotationYaw / 180.0F * (float) Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float) Math.PI) * velocity);
|
|
this.motionY = (double) (-MathHelper.sin((this.rotationPitch + this.throwAngle()) / 180.0F * (float) Math.PI) * velocity);
|
|
this.setThrowableHeading(this.motionX, this.motionY, this.motionZ, this.throwForce(), 1.0F);
|
|
}
|
|
|
|
public EntityThrowableNT(World world, double x, double y, double z) {
|
|
super(world);
|
|
this.ticksInGround = 0;
|
|
this.setSize(0.25F, 0.25F);
|
|
this.setPosition(x, y, z);
|
|
this.yOffset = 0.0F;
|
|
}
|
|
|
|
protected float throwForce() {
|
|
return 1.5F;
|
|
}
|
|
|
|
protected double headingForceMult() {
|
|
return 0.0075D;
|
|
}
|
|
|
|
protected float throwAngle() {
|
|
return 0.0F;
|
|
}
|
|
|
|
protected double motionMult() {
|
|
return 1.0D;
|
|
}
|
|
|
|
@Override
|
|
public void setThrowableHeading(double motionX, double motionY, double motionZ, float velocity, float inaccuracy) {
|
|
float throwLen = MathHelper.sqrt_double(motionX * motionX + motionY * motionY + motionZ * motionZ);
|
|
motionX /= (double) throwLen;
|
|
motionY /= (double) throwLen;
|
|
motionZ /= (double) throwLen;
|
|
motionX += this.rand.nextGaussian() * headingForceMult() * (double) inaccuracy;
|
|
motionY += this.rand.nextGaussian() * headingForceMult() * (double) inaccuracy;
|
|
motionZ += this.rand.nextGaussian() * headingForceMult() * (double) inaccuracy;
|
|
motionX *= (double) velocity;
|
|
motionY *= (double) velocity;
|
|
motionZ *= (double) velocity;
|
|
this.motionX = motionX;
|
|
this.motionY = motionY;
|
|
this.motionZ = motionZ;
|
|
float hyp = MathHelper.sqrt_double(motionX * motionX + motionZ * motionZ);
|
|
this.prevRotationYaw = this.rotationYaw = (float) (Math.atan2(motionX, motionZ) * 180.0D / Math.PI);
|
|
this.prevRotationPitch = this.rotationPitch = (float) (Math.atan2(motionY, (double) hyp) * 180.0D / Math.PI);
|
|
this.ticksInGround = 0;
|
|
}
|
|
|
|
@Override
|
|
@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 hyp = MathHelper.sqrt_double(x * x + z * z);
|
|
this.prevRotationYaw = this.rotationYaw = (float) (Math.atan2(x, z) * 180.0D / Math.PI);
|
|
this.prevRotationPitch = this.rotationPitch = (float) (Math.atan2(y, (double) hyp) * 180.0D / Math.PI);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onUpdate() {
|
|
this.lastTickPosX = this.posX;
|
|
this.lastTickPosY = this.posY;
|
|
this.lastTickPosZ = this.posZ;
|
|
super.onUpdate();
|
|
|
|
if(this.throwableShake > 0) {
|
|
--this.throwableShake;
|
|
}
|
|
|
|
if(this.inGround) {
|
|
if(this.worldObj.getBlock(this.stuckBlockX, this.stuckBlockY, this.stuckBlockZ) == this.stuckBlock) {
|
|
++this.ticksInGround;
|
|
|
|
if(this.groundDespawn() > 0 && this.ticksInGround == this.groundDespawn()) {
|
|
this.setDead();
|
|
}
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
this.inGround = false;
|
|
this.motionX *= (double) (this.rand.nextFloat() * 0.2F);
|
|
this.motionY *= (double) (this.rand.nextFloat() * 0.2F);
|
|
this.motionZ *= (double) (this.rand.nextFloat() * 0.2F);
|
|
this.ticksInGround = 0;
|
|
this.ticksInAir = 0;
|
|
}
|
|
|
|
} else {
|
|
++this.ticksInAir;
|
|
|
|
Vec3 pos = Vec3.createVectorHelper(this.posX, this.posY, this.posZ);
|
|
Vec3 nextPos = Vec3.createVectorHelper(this.posX + this.motionX * motionMult(), this.posY + this.motionY * motionMult(), this.posZ + this.motionZ * motionMult());
|
|
MovingObjectPosition mop = null;
|
|
if(!this.isSpectral()) mop = this.worldObj.func_147447_a(pos, nextPos, false, true, false);
|
|
pos = Vec3.createVectorHelper(this.posX, this.posY, this.posZ);
|
|
nextPos = Vec3.createVectorHelper(this.posX + this.motionX * motionMult(), this.posY + this.motionY * motionMult(), this.posZ + this.motionZ * motionMult());
|
|
|
|
if(mop != null) {
|
|
nextPos = Vec3.createVectorHelper(mop.hitVec.xCoord, mop.hitVec.yCoord, mop.hitVec.zCoord);
|
|
}
|
|
|
|
if(!this.worldObj.isRemote) {
|
|
|
|
Entity hitEntity = null;
|
|
List list = this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.boundingBox.addCoord(this.motionX * motionMult(), this.motionY * motionMult(), this.motionZ * motionMult()).expand(1.0D, 1.0D, 1.0D));
|
|
double nearest = 0.0D;
|
|
EntityLivingBase thrower = this.getThrower();
|
|
MovingObjectPosition nonPenImpact = null;
|
|
|
|
for(int j = 0; j < list.size(); ++j) {
|
|
Entity entity = (Entity) list.get(j);
|
|
|
|
if(entity.canBeCollidedWith() && (entity != thrower || this.ticksInAir >= this.selfDamageDelay())) {
|
|
double hitbox = 0.3F;
|
|
AxisAlignedBB aabb = entity.boundingBox.expand(hitbox, hitbox, hitbox);
|
|
MovingObjectPosition hitMop = aabb.calculateIntercept(pos, nextPos);
|
|
|
|
if(hitMop != null) {
|
|
|
|
// if penetration is enabled, run impact for all intersecting entities
|
|
if(this.doesPenetrate()) {
|
|
this.onImpact(new MovingObjectPosition(entity, hitMop.hitVec));
|
|
} else {
|
|
|
|
double dist = pos.distanceTo(hitMop.hitVec);
|
|
|
|
if(dist < nearest || nearest == 0.0D) {
|
|
hitEntity = entity;
|
|
nearest = dist;
|
|
nonPenImpact = hitMop;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// if not, only run it for the closest MOP
|
|
if(!this.doesPenetrate() && hitEntity != null) {
|
|
mop = new MovingObjectPosition(hitEntity, nonPenImpact.hitVec);
|
|
}
|
|
}
|
|
|
|
if(mop != null) {
|
|
if(mop.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK && this.worldObj.getBlock(mop.blockX, mop.blockY, mop.blockZ) == Blocks.portal) {
|
|
this.setInPortal();
|
|
} else {
|
|
this.onImpact(mop);
|
|
}
|
|
}
|
|
|
|
if(!this.onGround) {
|
|
float hyp = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
|
|
this.rotationYaw = (float) (Math.atan2(this.motionX, this.motionZ) * 180.0D / Math.PI);
|
|
|
|
for(this.rotationPitch = (float) (Math.atan2(this.motionY, (double) hyp) * 180.0D / 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;
|
|
}
|
|
|
|
float drag = this.getAirDrag();
|
|
double gravity = this.getGravityVelocity();
|
|
|
|
this.posX += this.motionX * motionMult();
|
|
this.posY += this.motionY * motionMult();
|
|
this.posZ += this.motionZ * motionMult();
|
|
|
|
if(this.isInWater()) {
|
|
for(int i = 0; i < 4; ++i) {
|
|
float f = 0.25F;
|
|
this.worldObj.spawnParticle("bubble", this.posX - this.motionX * (double) f, this.posY - this.motionY * (double) f, this.posZ - this.motionZ * (double) f, this.motionX, this.motionY, this.motionZ);
|
|
}
|
|
|
|
drag = this.getWaterDrag();
|
|
}
|
|
|
|
this.motionX *= (double) drag;
|
|
this.motionY *= (double) drag;
|
|
this.motionZ *= (double) drag;
|
|
this.motionY -= gravity;
|
|
this.setPosition(this.posX, this.posY, this.posZ);
|
|
}
|
|
}
|
|
|
|
public boolean doesPenetrate() {
|
|
return false;
|
|
}
|
|
|
|
public boolean isSpectral() {
|
|
return false;
|
|
}
|
|
|
|
public int selfDamageDelay() {
|
|
return 5;
|
|
}
|
|
|
|
public void getStuck(int x, int y, int z, int side) {
|
|
this.stuckBlockX = x;
|
|
this.stuckBlockY = y;
|
|
this.stuckBlockZ = z;
|
|
this.stuckBlock = worldObj.getBlock(x, y, z);
|
|
this.inGround = true;
|
|
this.motionX = 0;
|
|
this.motionY = 0;
|
|
this.motionZ = 0;
|
|
this.setStuckIn(side);
|
|
TrackerUtil.sendTeleport(worldObj, this);
|
|
}
|
|
|
|
public double getGravityVelocity() {
|
|
return 0.03D;
|
|
}
|
|
|
|
protected abstract void onImpact(MovingObjectPosition mop);
|
|
|
|
@Override
|
|
public void writeEntityToNBT(NBTTagCompound nbt) {
|
|
nbt.setShort("xTile", (short) this.stuckBlockX);
|
|
nbt.setShort("yTile", (short) this.stuckBlockY);
|
|
nbt.setShort("zTile", (short) this.stuckBlockZ);
|
|
nbt.setByte("inTile", (byte) Block.getIdFromBlock(this.stuckBlock));
|
|
nbt.setByte("shake", (byte) this.throwableShake);
|
|
nbt.setByte("inGround", (byte) (this.inGround ? 1 : 0));
|
|
|
|
if((this.throwerName == null || this.throwerName.length() == 0) && this.thrower != null && this.thrower instanceof EntityPlayer) {
|
|
this.throwerName = this.thrower.getCommandSenderName();
|
|
}
|
|
|
|
nbt.setString("ownerName", this.throwerName == null ? "" : this.throwerName);
|
|
}
|
|
|
|
@Override
|
|
public void readEntityFromNBT(NBTTagCompound nbt) {
|
|
this.stuckBlockX = nbt.getShort("xTile");
|
|
this.stuckBlockY = nbt.getShort("yTile");
|
|
this.stuckBlockZ = nbt.getShort("zTile");
|
|
this.stuckBlock = Block.getBlockById(nbt.getByte("inTile") & 255);
|
|
this.throwableShake = nbt.getByte("shake") & 255;
|
|
this.inGround = nbt.getByte("inGround") == 1;
|
|
this.throwerName = nbt.getString("ownerName");
|
|
|
|
if(this.throwerName != null && this.throwerName.length() == 0) {
|
|
this.throwerName = null;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
@SideOnly(Side.CLIENT)
|
|
public float getShadowSize() {
|
|
return 0.0F;
|
|
}
|
|
|
|
public void setThrower(EntityLivingBase thrower) {
|
|
this.thrower = thrower;
|
|
}
|
|
|
|
public EntityLivingBase getThrower() {
|
|
if(this.thrower == null && this.throwerName != null && this.throwerName.length() > 0) {
|
|
this.thrower = this.worldObj.getPlayerEntityByName(this.throwerName);
|
|
}
|
|
return this.thrower;
|
|
}
|
|
|
|
/* ================================== Additional Getters =====================================*/
|
|
|
|
protected float getAirDrag() {
|
|
return 0.99F;
|
|
}
|
|
|
|
protected float getWaterDrag() {
|
|
return 0.8F;
|
|
}
|
|
|
|
protected int groundDespawn() {
|
|
return 1200;
|
|
}
|
|
}
|