generated from tilera/1710mod
450 lines
14 KiB
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);
|
|
}
|
|
}
|