icbm/src/main/java/icbm/gangshao/turret/TTurretBase.java

450 lines
14 KiB
Java

package icbm.gangshao.turret;
import java.util.HashMap;
import calclavia.lib.CalculationHelper;
import calclavia.lib.render.ITagRender;
import cpw.mods.fml.common.network.NetworkRegistry.TargetPoint;
import icbm.gangshao.ICBMSentry;
import icbm.gangshao.ISentry;
import icbm.gangshao.damage.EntityTileDamagable;
import icbm.gangshao.damage.IHealthTile;
import icbm.gangshao.packet.PacketTurret;
import icbm.gangshao.platform.TTurretPlatform;
import icbm.gangshao.task.LookHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.Packet;
import net.minecraft.network.play.server.S35PacketUpdateTileEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.DamageSource;
import net.minecraft.util.MathHelper;
import net.minecraftforge.common.util.ForgeDirection;
import universalelectricity.core.block.IVoltage;
import universalelectricity.core.vector.Vector3;
import universalelectricity.prefab.tile.TileEntityAdvanced;
public abstract class TTurretBase
extends TileEntityAdvanced implements ITagRender, IVoltage, ISentry, IHealthTile {
public float maxPitch;
public float minPitch;
protected boolean allowFreePitch;
private ForgeDirection platformDirection;
public LookHelper lookHelper;
protected boolean speedUpRotation;
public int health;
public int baseFiringDelay;
public int tickSinceFired;
public int minFiringDelay;
private EntityTileDamagable damageEntity;
public float wantedRotationYaw;
public float wantedRotationPitch;
public float currentRotationYaw;
public float currentRotationPitch;
public int lastRotateTick;
public TTurretBase() {
this.maxPitch = 35.0f;
this.minPitch = -35.0f;
this.allowFreePitch = false;
this.platformDirection = ForgeDirection.DOWN;
this.lookHelper = new LookHelper(this);
this.speedUpRotation = false;
this.health = -1;
this.baseFiringDelay = 10;
this.tickSinceFired = 0;
this.minFiringDelay = 5;
this.wantedRotationPitch = 0.0f;
this.currentRotationPitch = 0.0f;
this.lastRotateTick = 0;
}
@Override
public void updateEntity() {
super.updateEntity();
if (this.tickSinceFired > 0) {
--this.tickSinceFired;
}
if (!this.worldObj.isRemote && !this.isInvul() && this.getDamageEntity() == null
&& this.getHealth() > 0) {
this.setDamageEntity(new EntityTileDamagable(this));
this.worldObj.spawnEntityInWorld((Entity) this.getDamageEntity());
}
this.updateRotation();
}
public void onTurretPacket(PacketTurret.Type type, NBTTagCompound data) {
if (type == PacketTurret.Type.ROTATION) {
this.setRotation(data.getFloat("yaw"), data.getFloat("pitch"));
} else if (type == PacketTurret.Type.STATS) {
this.health = data.getInteger("health");
}
}
@Override
public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) {
NBTTagCompound nbt = pkt.func_148857_g();
this.readFromNBT(nbt);
}
public PacketTurret getStatsPacket() {
return PacketTurret.stats(new Vector3(this), this.health);
}
public PacketTurret getRotationPacket() {
return PacketTurret.rotation(
new Vector3(this), this.wantedRotationYaw, this.wantedRotationPitch
);
}
@Override
public Packet getDescriptionPacket() {
final NBTTagCompound nbt = new NBTTagCompound();
this.writeToNBT(nbt);
return new S35PacketUpdateTileEntity(
this.xCoord, this.yCoord, this.zCoord, this.getBlockMetadata(), nbt
);
}
@Override
public void writeToNBT(final NBTTagCompound nbt) {
super.writeToNBT(nbt);
nbt.setFloat("yaw", this.wantedRotationYaw);
nbt.setFloat("pitch", this.wantedRotationPitch);
nbt.setFloat("cYaw", this.currentRotationYaw);
nbt.setFloat("cPitch", this.currentRotationPitch);
nbt.setInteger("dir", this.platformDirection.ordinal());
nbt.setInteger("health", this.getHealth());
}
@Override
public void readFromNBT(final NBTTagCompound nbt) {
super.readFromNBT(nbt);
this.wantedRotationYaw = nbt.getFloat("yaw");
this.wantedRotationPitch = nbt.getFloat("pitch");
this.currentRotationYaw = nbt.getFloat("cYaw");
this.currentRotationPitch = nbt.getFloat("cPitch");
this.platformDirection = ForgeDirection.getOrientation(nbt.getInteger("dir"));
if (nbt.hasKey("health")) {
this.health = nbt.getInteger("health");
}
}
public abstract double getFiringRequest();
public boolean isRunning() {
return this.getPlatform() != null && this.getPlatform().isRunning()
&& this.isAlive();
}
public TTurretPlatform getPlatform() {
final TileEntity tileEntity = this.worldObj.getTileEntity(
this.xCoord + this.platformDirection.offsetX,
this.yCoord + this.platformDirection.offsetY,
this.zCoord + this.platformDirection.offsetZ
);
if (tileEntity instanceof TTurretPlatform) {
return (TTurretPlatform) tileEntity;
}
return null;
}
public void destroy(final boolean doExplosion) {
if (doExplosion) {
if (!this.isInvalid()) {
this.worldObj.setBlockToAir(this.xCoord, this.yCoord, this.zCoord);
this.worldObj.createExplosion(
(Entity) this.getDamageEntity(),
(double) this.xCoord,
(double) this.yCoord,
(double) this.zCoord,
2.0f,
true
);
} else {
this.worldObj.setBlockToAir(this.xCoord, this.yCoord, this.zCoord);
}
} else if (!this.worldObj.isRemote) {
this.getBlockType().dropBlockAsItem(
this.worldObj,
this.xCoord,
this.yCoord,
this.zCoord,
this.getBlockMetadata(),
0
);
this.worldObj.setBlockToAir(this.xCoord, this.yCoord, this.zCoord);
}
}
public int getBarrels() {
return 1;
}
public void setDeploySide(final ForgeDirection side) {
this.platformDirection = side.getOpposite();
}
@Override
public float addInformation(final HashMap map, final EntityPlayer player) {
map.put(this.getName(), 8978312);
return 1.0f;
}
@Override
public String getName() {
return new ItemStack(this.getBlockType(), 1, this.getBlockMetadata())
.getDisplayName()
+ " " + this.getHealth() + "/" + this.getMaxHealth();
}
@Override
public Vector3 getMuzzle() {
return this.getCenter().add(Vector3.multiply(
CalculationHelper.getDeltaPositionFromRotation(
this.currentRotationYaw, this.currentRotationPitch
),
1.0
));
}
@Override
public void onWeaponActivated() {
this.tickSinceFired += this.getFireDelay();
}
public int getFireDelay() {
return this.baseFiringDelay;
}
public abstract int getMaxHealth();
public boolean isInvul() {
return false;
}
@Override
public int getHealth() {
if (this.health == -1) {
this.health = this.getMaxHealth();
}
return this.health;
}
@Override
public void setHealth(int i, final boolean increase) {
if (increase) {
i += this.health;
}
this.health = Math.min(Math.max(i, 0), this.getMaxHealth());
if (!this.worldObj.isRemote) {
ICBMSentry.channel.sendToAllAround(
this.getStatsPacket(),
new TargetPoint(
this.worldObj.provider.dimensionId,
this.xCoord,
this.yCoord,
this.zCoord,
100.0
)
);
}
}
@Override
public boolean isAlive() {
return this.getHealth() > 0 || this.isInvul();
}
@Override
public boolean onDamageTaken(final DamageSource source, final int amount) {
if (this.isInvul()) {
return false;
}
if (source != null && source.equals(DamageSource.onFire)) {
return true;
}
this.health -= amount;
if (this.health <= 0) {
this.destroy(true);
} else {
ICBMSentry.channel.sendToAllAround(
this.getStatsPacket(),
new TargetPoint(
this.worldObj.provider.dimensionId,
this.xCoord,
this.yCoord,
this.zCoord,
100.0
)
);
}
return true;
}
public EntityTileDamagable getDamageEntity() {
return this.damageEntity;
}
public void setDamageEntity(final EntityTileDamagable damageEntity) {
this.damageEntity = damageEntity;
}
public void updateRotation() {
final float yawDifference = Math.abs(
LookHelper.getAngleDif(this.currentRotationYaw, this.wantedRotationYaw)
);
if (yawDifference > 0.001f) {
final float speedYaw = Math.min(this.getRotationSpeed(), yawDifference);
if (this.currentRotationYaw > this.wantedRotationYaw) {
this.currentRotationYaw -= speedYaw;
} else {
this.currentRotationYaw += speedYaw;
}
if (Math.abs(this.currentRotationYaw - this.wantedRotationYaw)
<= speedYaw + 0.1) {
this.currentRotationYaw = this.wantedRotationYaw;
}
}
final float pitchDifference = Math.abs(
LookHelper.getAngleDif(this.currentRotationPitch, this.wantedRotationPitch)
);
if (pitchDifference > 0.001f) {
final float speedPitch = Math.min(this.getRotationSpeed(), pitchDifference);
if (this.currentRotationPitch > this.wantedRotationPitch) {
this.currentRotationPitch -= speedPitch;
} else {
this.currentRotationPitch += speedPitch;
}
if (Math.abs(this.currentRotationPitch - this.wantedRotationPitch)
<= speedPitch + 0.1) {
this.currentRotationPitch = this.wantedRotationPitch;
}
}
if (Math.abs(this.currentRotationPitch - this.wantedRotationPitch) <= 0.001f
&& Math.abs(this.currentRotationYaw - this.wantedRotationYaw) <= 0.001f) {
++this.lastRotateTick;
}
this.currentRotationPitch
= MathHelper.wrapAngleTo180_float(this.currentRotationPitch);
this.wantedRotationYaw = MathHelper.wrapAngleTo180_float(this.wantedRotationYaw);
this.wantedRotationPitch
= MathHelper.wrapAngleTo180_float(this.wantedRotationPitch);
}
public float getRotationSpeed() {
return Float.MAX_VALUE;
}
@Override
public void setRotation(final float yaw, final float pitch) {
this.wantedRotationYaw = MathHelper.wrapAngleTo180_float(yaw);
if (!this.allowFreePitch) {
this.wantedRotationPitch = Math.max(
Math.min(MathHelper.wrapAngleTo180_float(pitch), this.maxPitch),
this.minPitch
);
} else {
this.wantedRotationPitch = MathHelper.wrapAngleTo180_float(pitch);
}
}
public void rotateTo(final float wantedRotationYaw, final float wantedRotationPitch) {
if (!this.worldObj.isRemote && this.lastRotateTick > 0
&& (this.wantedRotationYaw != wantedRotationYaw
|| this.wantedRotationPitch != wantedRotationPitch)) {
this.setRotation(wantedRotationYaw, wantedRotationPitch);
this.lastRotateTick = 0;
if (!this.worldObj.isRemote) {
ICBMSentry.channel.sendToAllAround(
this.getRotationPacket(),
new TargetPoint(
this.worldObj.provider.dimensionId,
this.xCoord,
this.yCoord,
this.zCoord,
50.0
)
);
}
}
}
public void cancelRotation() {
this.setRotation(this.currentRotationYaw, this.currentRotationPitch);
}
public void drawParticleStreamTo(final Vector3 endPosition) {
if (this.worldObj.isRemote) {
final Vector3 startPosition = this.getMuzzle();
final Vector3 direction = CalculationHelper.getDeltaPositionFromRotation(
this.currentRotationYaw, this.currentRotationPitch
);
final double xoffset = 0.0;
final double yoffset = 0.0;
final double zoffset = 0.0;
Vector3 horzdir = direction.normalize();
horzdir.y = 0.0;
horzdir = horzdir.normalize();
for (double cx = startPosition.x + direction.x * xoffset
- direction.y * horzdir.x * yoffset - horzdir.z * zoffset,
cy = startPosition.y + direction.y * xoffset
+ (1.0 - Math.abs(direction.y)) * yoffset,
cz = startPosition.z + direction.x * xoffset
- direction.y * horzdir.x * yoffset + horzdir.x * zoffset,
dx = endPosition.x - cx,
dy = endPosition.y - cy,
dz = endPosition.z - cz,
ratio = Math.sqrt(dx * dx + dy * dy + dz * dz);
Math.abs(cx - endPosition.x) > Math.abs(dx / ratio);
cx += dx * 0.1 / ratio, cy += dy * 0.1 / ratio, cz += dz * 0.1 / ratio) {
this.worldObj.spawnParticle("townaura", cx, cy, cz, 0.0, 0.0, 0.0);
}
}
}
public abstract void renderShot(final Vector3 p0);
public abstract void playFiringSound();
@Override
public AxisAlignedBB getRenderBoundingBox() {
return TileEntity.INFINITE_EXTENT_AABB;
}
public Vector3 getCenter() {
return new Vector3(this).add(0.5);
}
}