icbm/src/main/java/icbm/zhapin/daodan/EMissile.java

727 lines
25 KiB
Java

package icbm.zhapin.daodan;
import java.util.Random;
import cpw.mods.fml.common.registry.IEntityAdditionalSpawnData;
import icbm.api.ILauncherContainer;
import icbm.api.IMissile;
import icbm.api.IMissileLockable;
import icbm.api.RadarRegistry;
import icbm.api.explosion.IExplosive;
import icbm.api.sentry.IAATarget;
import icbm.core.MainBase;
import icbm.zhapin.ICBMExplosion;
import icbm.zhapin.jiqi.TCruiseLauncher;
import icbm.zhapin.zhapin.ZhaPin;
import io.netty.buffer.ByteBuf;
import net.minecraft.block.Block;
import net.minecraft.block.BlockLiquid;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.server.gui.IUpdatePlayerListBox;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.world.ChunkCoordIntPair;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.common.ForgeChunkManager;
import universalelectricity.core.vector.Vector2;
import universalelectricity.core.vector.Vector3;
import universalelectricity.prefab.TranslationHelper;
public class EMissile extends Entity
implements IMissileLockable, IEntityAdditionalSpawnData, IMissile, IAATarget {
public static final float THRUST = 0.012f;
public int missileId;
public int skyHeight;
public Vector3 target;
public Vector3 origin;
public Vector3 launcherPos;
public boolean exploded;
public int explosionHeight;
public int flyingTicks;
public double xDiff;
public double yDiff;
public double zDiff;
public double targetDistance;
public float flightDuration;
public float acceleration;
public int protectionTicks;
private ForgeChunkManager.Ticket chunkTicket;
public Entity lockedTarget;
public boolean didTargetLockBefore;
public int targetEntityId;
public int missileCount;
public double missileHeight;
private boolean setExplode;
private boolean setNormalExplode;
public MissileType missileType;
public Vector3 smallMissileMotion;
private double startHeight;
protected final IUpdatePlayerListBox sound;
public EMissile(final World par1World) {
super(par1World);
this.missileId = 0;
this.skyHeight = 200;
this.target = null;
this.origin = null;
this.launcherPos = null;
this.exploded = false;
this.explosionHeight = 0;
this.flyingTicks = -1;
this.protectionTicks = 2;
this.didTargetLockBefore = false;
this.targetEntityId = -1;
this.missileCount = 0;
this.missileHeight = 2.0;
this.missileType = MissileType.MISSILE;
this.smallMissileMotion = new Vector3();
this.startHeight = 3.0;
this.setSize(1.0f, 1.0f);
super.renderDistanceWeight = 3.0;
super.isImmuneToFire = true;
super.ignoreFrustumCheck = true;
this.sound
= ((super.worldObj != null) ? ICBMExplosion.proxy.getDaoDanShengYin(this)
: null);
}
public EMissile(
final World par1World,
final Vector3 diDian,
final Vector3 faSheQiDiDian,
final int missileId
) {
this(par1World);
this.missileId = missileId;
this.origin = diDian;
this.launcherPos = faSheQiDiDian;
this.setPosition(this.origin.x, this.origin.y, this.origin.z);
this.setRotation(0.0f, 90.0f);
}
public EMissile(
final World par1World,
final Vector3 diDian,
final int haoMa,
final float yaw,
final float pitch
) {
this(par1World);
this.missileId = haoMa;
this.origin = diDian;
this.launcherPos = diDian;
this.missileType = MissileType.ROCKET;
this.protectionTicks = 10;
this.setPosition(this.origin.x, this.origin.y, this.origin.z);
this.setRotation(yaw, pitch);
}
@Override
public String getCommandSenderName() {
if (this.missileId >= 100) {
return TranslationHelper.getLocal(
"icbm.missile." + MissileBase.list[this.missileId].getUnlocalizedName()
+ ".name"
);
}
return TranslationHelper.getLocal(
"icbm.missile." + ZhaPin.list[this.missileId].getUnlocalizedName() + ".name"
);
}
@Override
public void writeSpawnData(final ByteBuf data) {
try {
data.writeInt(this.missileId);
data.writeInt(this.missileType.ordinal());
data.writeDouble(this.origin.x);
data.writeDouble(this.origin.y);
data.writeDouble(this.origin.z);
data.writeInt(this.launcherPos.intX());
data.writeInt(this.launcherPos.intY());
data.writeInt(this.launcherPos.intZ());
} catch (final Exception e) {
e.printStackTrace();
}
}
@Override
public void readSpawnData(final ByteBuf data) {
try {
this.missileId = data.readInt();
this.missileType = MissileType.values()[data.readInt()];
this.origin
= new Vector3(data.readDouble(), data.readDouble(), data.readDouble());
this.launcherPos
= new Vector3(data.readInt(), data.readInt(), data.readInt());
} catch (final Exception e) {
e.printStackTrace();
}
}
public void launch(final Vector3 target) {
this.origin = new Vector3(this);
this.target = target;
this.explosionHeight = this.target.intY();
MissileBase.list[this.missileId].launch(this);
this.flyingTicks = 0;
this.jiSuan();
super.worldObj.playSoundAtEntity(
(Entity) this,
"icbm:missilelaunch",
4.0f,
(1.0f
+ (super.worldObj.rand.nextFloat() - super.worldObj.rand.nextFloat()) * 0.2f)
* 0.7f
);
RadarRegistry.register(this);
MainBase.LOGGER.info(
"Launching " + this.getCommandSenderName() + " from " + this.origin.intX()
+ ", " + this.origin.intY() + ", " + this.origin.intZ() + " to "
+ this.target.intX() + ", " + this.target.intY() + ", " + this.target.intZ()
);
}
public void launch(final Vector3 target, final int height) {
this.startHeight = height;
this.launch(target);
}
public void jiSuan() {
if (this.target != null) {
this.xDiff = this.target.x - this.origin.x;
this.yDiff = this.target.y - this.origin.y;
this.zDiff = this.target.z - this.origin.z;
this.targetDistance
= Vector2.distance(this.origin.toVector2(), this.target.toVector2());
this.skyHeight = 160 + (int) (this.targetDistance * 3.0);
this.flightDuration
= (float) Math.max(100.0, 2.0 * this.targetDistance) - this.flyingTicks;
this.acceleration
= this.skyHeight * 2.0f / (this.flightDuration * this.flightDuration);
}
}
@Override
public void entityInit() {
super.dataWatcher.addObject(16, (Object) (-1));
this.daoDanInit(ForgeChunkManager.requestTicket(
(Object) ICBMExplosion.instance, super.worldObj, ForgeChunkManager.Type.ENTITY
));
}
public void daoDanInit(final ForgeChunkManager.Ticket ticket) {
if (ticket != null) {
if (this.chunkTicket == null) {
(this.chunkTicket = ticket).bindEntity((Entity) this);
this.chunkTicket.getModData();
}
ForgeChunkManager.forceChunk(
this.chunkTicket,
new ChunkCoordIntPair(super.chunkCoordX, super.chunkCoordZ)
);
}
}
public void updateLoadChunk(final int newChunkX, final int newChunkZ) {
if (!super.worldObj.isRemote && MainBase.ZAI_KUAI && this.chunkTicket != null) {
for (int x = -2; x <= 2; ++x) {
for (int z = -2; z <= 2; ++z) {
super.worldObj.getChunkFromChunkCoords(newChunkX + x, newChunkZ + z);
}
}
for (int x = -1; x <= 1; ++x) {
for (int z = -1; z <= 1; ++z) {
ForgeChunkManager.forceChunk(
this.chunkTicket,
new ChunkCoordIntPair(newChunkX + x, newChunkZ + z)
);
}
}
}
}
@Override
public boolean canBeCollidedWith() {
return true;
}
@Override
public void onUpdate() {
if (this.sound != null) {
this.sound.update();
}
if (!super.worldObj.isRemote
&& ICBMExplosion.shiBaoHu(
super.worldObj,
new Vector3(this),
ZhaPin.ZhaPinType.DAO_DAN,
this.missileId
)) {
if (this.flyingTicks >= 0) {
this.dropMissileAsItem();
}
this.setDead();
return;
}
if (this.setNormalExplode) {
this.normalExplode();
return;
}
if (this.setExplode) {
this.explode();
return;
}
try {
if (super.worldObj.isRemote) {
this.flyingTicks = super.dataWatcher.getWatchableObjectInt(16);
} else {
super.dataWatcher.updateObject(16, (Object) this.flyingTicks);
}
} catch (final Exception e) {
e.printStackTrace();
}
this.updateLoadChunk(super.chunkCoordX, super.chunkCoordZ);
if (this.flyingTicks >= 0) {
RadarRegistry.register(this);
if (!super.worldObj.isRemote) {
if (this.missileType == MissileType.SMALL_MISSILE
|| this.missileType == MissileType.ROCKET) {
if (this.flyingTicks == 0 && this.smallMissileMotion != null) {
this.smallMissileMotion = new Vector3(
this.xDiff / (this.flightDuration * 0.3),
this.yDiff / (this.flightDuration * 0.3),
this.zDiff / (this.flightDuration * 0.3)
);
}
super.motionX = this.smallMissileMotion.x;
super.motionY = this.smallMissileMotion.y;
super.motionZ = this.smallMissileMotion.z;
super.rotationPitch = (float
) (Math.atan(
super.motionY
/ Math.sqrt(
super.motionX * super.motionX
+ super.motionZ * super.motionZ
)
)
* 180.0 / 3.141592653589793);
super.rotationYaw = (float
) (Math.atan2(super.motionX, super.motionZ) * 180.0
/ 3.141592653589793);
MissileBase.list[this.missileId].update(this);
final Block block = super.worldObj.getBlock(
(int) super.posX, (int) super.posY, (int) super.posZ
);
if (this.protectionTicks <= 0
&& ((block != Blocks.air && !(block instanceof BlockLiquid))
|| super.posY > 1000.0 || super.isCollided
|| this.flyingTicks > 20000
|| (super.motionX == 0.0 && super.motionY == 0.0
&& super.motionZ == 0.0))) {
this.explode();
return;
}
this.moveEntity(super.motionX, super.motionY, super.motionZ);
} else if (this.startHeight > 0.0) {
super.motionY = 0.012f * this.flyingTicks * (this.flyingTicks / 2);
super.motionX = 0.0;
super.motionZ = 0.0;
this.startHeight -= super.motionY;
this.moveEntity(super.motionX, super.motionY, super.motionZ);
if (this.startHeight <= 0.0) {
super.motionY = this.acceleration * (this.flightDuration / 2.0f);
super.motionX = this.xDiff / this.flightDuration;
super.motionZ = this.zDiff / this.flightDuration;
}
} else {
super.motionY -= this.acceleration;
super.rotationPitch = (float
) (Math.atan(
super.motionY
/ Math.sqrt(
super.motionX * super.motionX
+ super.motionZ * super.motionZ
)
)
* 180.0 / 3.141592653589793);
super.rotationYaw = (float
) (Math.atan2(super.motionX, super.motionZ) * 180.0
/ 3.141592653589793);
MissileBase.list[this.missileId].update(this);
this.moveEntity(super.motionX, super.motionY, super.motionZ);
if (super.isCollided) {
this.explode();
}
if (this.explosionHeight > 0 && super.motionY < 0.0) {
final Block blockBelow = super.worldObj.getBlock(
(int) super.posX,
(int) super.posY - this.explosionHeight,
(int) super.posZ
);
if (blockBelow != Blocks.air) {
this.explosionHeight = 0;
this.explode();
}
}
}
} else {
super.rotationPitch = (float
) (Math.atan(
super.motionY
/ Math.sqrt(
super.motionX * super.motionX + super.motionZ * super.motionZ
)
)
* 180.0 / 3.141592653589793);
super.rotationYaw = (float
) (Math.atan2(super.motionX, super.motionZ) * 180.0 / 3.141592653589793);
}
super.lastTickPosX = super.posX;
super.lastTickPosY = super.posY;
super.lastTickPosZ = super.posZ;
this.spawnMissileSmoke();
--this.protectionTicks;
++this.flyingTicks;
} else if (this.missileType != MissileType.ROCKET) {
final ILauncherContainer launcher = this.getLauncher();
if (launcher != null) {
launcher.setContainingMissile(this);
if (launcher instanceof TCruiseLauncher) {
this.missileType = MissileType.SMALL_MISSILE;
super.noClip = true;
if (super.worldObj.isRemote) {
super.rotationYaw
= -((TCruiseLauncher) launcher).rotationYaw + 90.0f;
super.rotationPitch = ((TCruiseLauncher) launcher).rotationPitch;
}
super.posY = ((TCruiseLauncher) launcher).yCoord + 1;
}
} else {
this.setDead();
}
}
super.onUpdate();
}
public ILauncherContainer getLauncher() {
if (this.launcherPos != null) {
final TileEntity tileEntity
= this.launcherPos.getTileEntity((IBlockAccess) super.worldObj);
if (tileEntity != null && tileEntity instanceof ILauncherContainer
&& !tileEntity.isInvalid()) {
return (ILauncherContainer) tileEntity;
}
}
return null;
}
@Override
public boolean interactFirst(final EntityPlayer entityPlayer) {
if (MissileBase.list[this.missileId] != null
&& MissileBase.list[this.missileId].onInteract(this, entityPlayer)) {
return true;
}
if (!super.worldObj.isRemote
&& (super.riddenByEntity == null || super.riddenByEntity == entityPlayer)) {
entityPlayer.mountEntity((Entity) this);
return true;
}
return false;
}
@Override
public double getMountedYOffset() {
if (this.flightDuration <= 0.0f && this.missileType == MissileType.MISSILE) {
return super.height;
}
if (this.missileType == MissileType.SMALL_MISSILE) {
return super.height * 0.1;
}
return super.height / 2.0f + super.motionY;
}
private void spawnMissileSmoke() {
if (super.worldObj.isRemote) {
final Vector3 position = new Vector3(this);
final double distance = -this.missileHeight - 0.20000000298023224;
final Vector3 delta = new Vector3();
delta.y = Math.sin(Math.toRadians(super.rotationPitch)) * distance;
final double dH = Math.cos(Math.toRadians(super.rotationPitch)) * distance;
delta.x = Math.sin(Math.toRadians(super.rotationYaw)) * dH;
delta.z = Math.cos(Math.toRadians(super.rotationYaw)) * dH;
position.add(delta);
super.worldObj.spawnParticle(
"flame", position.x, position.y, position.z, 0.0, 0.0, 0.0
);
ICBMExplosion.proxy.spawnParticle(
"missile_smoke", super.worldObj, position, 4.0f, 2.0
);
position.multiply(1.0 - 0.001 * Math.random());
ICBMExplosion.proxy.spawnParticle(
"missile_smoke", super.worldObj, position, 4.0f, 2.0
);
position.multiply(1.0 - 0.001 * Math.random());
ICBMExplosion.proxy.spawnParticle(
"missile_smoke", super.worldObj, position, 4.0f, 2.0
);
position.multiply(1.0 - 0.001 * Math.random());
ICBMExplosion.proxy.spawnParticle(
"missile_smoke", super.worldObj, position, 4.0f, 2.0
);
}
}
@Override
public AxisAlignedBB getCollisionBox(final Entity entity) {
if (!(entity instanceof EntityItem) && entity != super.riddenByEntity
&& this.protectionTicks <= 0) {
if (entity instanceof EMissile) {
((EMissile) entity).setNormalExplode();
}
this.setExplode();
}
return null;
}
public Vector3 getPredictedPosition(final int t) {
final Vector3 guJiDiDian = new Vector3(this);
double tempMotionY = super.motionY;
if (this.flyingTicks > 20) {
for (int i = 0; i < t; ++i) {
if (this.missileType == MissileType.SMALL_MISSILE
|| this.missileType == MissileType.ROCKET) {
final Vector3 vector3 = guJiDiDian;
vector3.x += this.smallMissileMotion.x;
final Vector3 vector4 = guJiDiDian;
vector4.y += this.smallMissileMotion.y;
final Vector3 vector5 = guJiDiDian;
vector5.z += this.smallMissileMotion.z;
} else {
final Vector3 vector6 = guJiDiDian;
vector6.x += super.motionX;
final Vector3 vector7 = guJiDiDian;
vector7.y += tempMotionY;
final Vector3 vector8 = guJiDiDian;
vector8.z += super.motionZ;
tempMotionY -= this.acceleration;
}
}
}
return guJiDiDian;
}
public void setNormalExplode() {
this.setNormalExplode = true;
}
public void setExplode() {
this.setExplode = true;
}
@Override
public void setDead() {
RadarRegistry.unregister(this);
if (this.chunkTicket != null) {
ForgeChunkManager.releaseTicket(this.chunkTicket);
}
super.setDead();
if (this.sound != null) {
this.sound.update();
}
}
public void explode() {
try {
if (!this.exploded && !this.isDead) {
if (this.missileId == 0) {
if (!super.worldObj.isRemote) {
super.worldObj.createExplosion(
(Entity) this, super.posX, super.posY, super.posZ, 5.0f, true
);
}
} else {
MissileBase.list[this.missileId].onExplode(this);
}
this.exploded = true;
MainBase.LOGGER.info(
this.getCommandSenderName() + " exploded in " + (int) super.posX
+ ", " + (int) super.posY + ", " + (int) super.posZ
);
}
this.setDead();
} catch (final Exception e) {
MainBase.LOGGER.severe(
"Missile failed to explode properly. Report this to the developers."
);
e.printStackTrace();
}
}
public void normalExplode() {
if (!this.exploded) {
this.exploded = true;
if (!super.worldObj.isRemote) {
super.worldObj.createExplosion(
(Entity) this, super.posX, super.posY, super.posZ, 5.0f, true
);
}
this.setDead();
}
}
public void dropMissileAsItem() {
if (!this.exploded && !super.worldObj.isRemote) {
EntityItem entityItem;
if (this.missileId >= 100) {
entityItem = new EntityItem(
super.worldObj,
super.posX,
super.posY,
super.posZ,
new ItemStack(ICBMExplosion.itTeBieDaoDan, 1, this.missileId - 100)
);
} else {
entityItem = new EntityItem(
super.worldObj,
super.posX,
super.posY,
super.posZ,
new ItemStack(ICBMExplosion.itDaoDan, 1, this.missileId)
);
}
final float var13 = 0.05f;
final Random random = new Random();
((Entity) entityItem).motionX = (float) random.nextGaussian() * var13;
((Entity) entityItem).motionY = (float) random.nextGaussian() * var13 + 0.2f;
((Entity) entityItem).motionZ = (float) random.nextGaussian() * var13;
super.worldObj.spawnEntityInWorld((Entity) entityItem);
}
this.setDead();
}
@Override
protected void readEntityFromNBT(final NBTTagCompound nbt) {
this.origin = Vector3.readFromNBT(nbt.getCompoundTag("kaiShi"));
this.target = Vector3.readFromNBT(nbt.getCompoundTag("muBiao"));
this.launcherPos = Vector3.readFromNBT(nbt.getCompoundTag("faSheQi"));
this.acceleration = nbt.getFloat("jiaSu");
this.explosionHeight = nbt.getInteger("baoZhaGaoDu");
this.missileId = nbt.getInteger("haoMa");
this.flyingTicks = nbt.getInteger("feiXingTick");
this.startHeight = nbt.getDouble("qiFeiGaoDu");
this.missileType = MissileType.values()[nbt.getInteger("xingShi")];
}
@Override
protected void writeEntityToNBT(final NBTTagCompound nbt) {
nbt.setTag("kaiShi", this.origin.writeToNBT(new NBTTagCompound()));
if (this.target != null) {
nbt.setTag("muBiao", this.target.writeToNBT(new NBTTagCompound()));
}
if (this.launcherPos != null) {
nbt.setTag("faSheQi", this.launcherPos.writeToNBT(new NBTTagCompound()));
}
nbt.setFloat("jiaSu", this.acceleration);
nbt.setInteger("haoMa", this.missileId);
nbt.setInteger("baoZhaGaoDu", this.explosionHeight);
nbt.setInteger("feiXingTick", this.flyingTicks);
nbt.setDouble("qiFeiGaoDu", this.startHeight);
nbt.setInteger("xingShi", this.missileType.ordinal());
}
@Override
public float getShadowSize() {
return 1.0f;
}
@Override
public int getTicksInAir() {
return this.flyingTicks;
}
public IExplosive getExplosiveType() {
if (this.missileId > ZhaPin.list.length) {
return MissileBase.list[this.missileId];
}
return ZhaPin.list[this.missileId];
}
public boolean canLock(final IMissile missile) {
return this.flyingTicks > 0;
}
public void destroyCraft() {
this.normalExplode();
}
public int doDamage(final int damage) {
return -1;
}
@Override
public boolean canBeTargeted(final Object turret) {
return this.getTicksInAir() > 0;
}
public enum MissileType {
MISSILE,
SMALL_MISSILE,
ROCKET;
}
}