329 lines
11 KiB
Java
329 lines
11 KiB
Java
package resonantinduction.atomic.machine.accelerator;
|
|
|
|
import java.util.List;
|
|
|
|
import net.minecraft.block.Block;
|
|
import net.minecraft.entity.Entity;
|
|
import net.minecraft.entity.EntityLiving;
|
|
import net.minecraft.nbt.NBTTagCompound;
|
|
import net.minecraft.tileentity.TileEntity;
|
|
import net.minecraft.util.AxisAlignedBB;
|
|
import net.minecraft.world.ChunkCoordIntPair;
|
|
import net.minecraft.world.World;
|
|
import net.minecraftforge.common.ForgeChunkManager;
|
|
import net.minecraftforge.common.ForgeChunkManager.Ticket;
|
|
import net.minecraftforge.common.ForgeChunkManager.Type;
|
|
import net.minecraftforge.common.ForgeDirection;
|
|
import resonant.api.IElectromagnet;
|
|
import resonant.lib.prefab.poison.PoisonRadiation;
|
|
import resonantinduction.atomic.Atomic;
|
|
import resonantinduction.core.Reference;
|
|
import universalelectricity.api.vector.Vector3;
|
|
import universalelectricity.api.vector.VectorHelper;
|
|
|
|
import com.google.common.io.ByteArrayDataInput;
|
|
import com.google.common.io.ByteArrayDataOutput;
|
|
|
|
import cpw.mods.fml.common.registry.IEntityAdditionalSpawnData;
|
|
|
|
/** The particle entity used to determine the particle acceleration. */
|
|
public class EntityParticle extends Entity implements IEntityAdditionalSpawnData
|
|
{
|
|
private static final int MOVE_TICK_RATE = 20;
|
|
public Ticket updateTicket;
|
|
public boolean didParticleCollide = false;
|
|
private int lastTurn = 60;
|
|
private Vector3 movementVector = new Vector3();
|
|
private ForgeDirection movementDirection = ForgeDirection.NORTH;
|
|
|
|
public EntityParticle(World par1World)
|
|
{
|
|
super(par1World);
|
|
this.setSize(0.3f, 0.3f);
|
|
this.renderDistanceWeight = 4f;
|
|
this.ignoreFrustumCheck = true;
|
|
}
|
|
|
|
public EntityParticle(World world, Vector3 pos, Vector3 movementVec, ForgeDirection dir)
|
|
{
|
|
this(world);
|
|
this.setPosition(pos.x, pos.y, pos.z);
|
|
this.movementVector = movementVec;
|
|
this.movementDirection = dir;
|
|
}
|
|
|
|
public static boolean canSpawnParticle(World world, Vector3 pos)
|
|
{
|
|
Block block = Block.blocksList[pos.getBlockID(world)];
|
|
if (block != null && !block.isAirBlock(world, pos.intX(), pos.intY(), pos.intZ()))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
for (int i = 0; i <= 1; i++)
|
|
{
|
|
ForgeDirection dir = ForgeDirection.getOrientation(i);
|
|
|
|
if (!isElectromagnet(world, pos, dir))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public static boolean isElectromagnet(World world, Vector3 position, ForgeDirection dir)
|
|
{
|
|
Vector3 checkPos = position.clone().translate(dir);
|
|
TileEntity tile = checkPos.getTileEntity(world);
|
|
|
|
if (tile instanceof IElectromagnet)
|
|
{
|
|
return ((IElectromagnet) tile).isRunning();
|
|
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public void writeSpawnData(ByteArrayDataOutput data)
|
|
{
|
|
data.writeInt(this.movementVector.intX());
|
|
data.writeInt(this.movementVector.intY());
|
|
data.writeInt(this.movementVector.intZ());
|
|
data.writeInt(this.movementDirection.ordinal());
|
|
}
|
|
|
|
@Override
|
|
public void readSpawnData(ByteArrayDataInput data)
|
|
{
|
|
this.movementVector.x = data.readInt();
|
|
this.movementVector.y = data.readInt();
|
|
this.movementVector.z = data.readInt();
|
|
this.movementDirection = ForgeDirection.getOrientation(data.readInt());
|
|
}
|
|
|
|
@Override
|
|
protected void entityInit()
|
|
{
|
|
this.dataWatcher.addObject(MOVE_TICK_RATE, (byte) 3);
|
|
|
|
if (this.updateTicket == null)
|
|
{
|
|
this.updateTicket = ForgeChunkManager.requestTicket(Atomic.INSTANCE, this.worldObj, Type.ENTITY);
|
|
this.updateTicket.getModData();
|
|
this.updateTicket.bindEntity(this);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onUpdate()
|
|
{
|
|
/** Play sound fxs. */
|
|
if (this.ticksExisted % 10 == 0)
|
|
{
|
|
this.worldObj.playSoundAtEntity(this, Reference.PREFIX + "accelerator", 1f, (float) (0.6f + (0.4 * (this.getParticleVelocity() / TileAccelerator.clientParticleVelocity))));
|
|
}
|
|
|
|
/** Check if the accelerator tile entity exists. */
|
|
TileEntity t = this.worldObj.getBlockTileEntity(this.movementVector.intX(), this.movementVector.intY(), this.movementVector.intZ());
|
|
|
|
if (!(t instanceof TileAccelerator))
|
|
{
|
|
setDead();
|
|
return;
|
|
}
|
|
|
|
TileAccelerator tileEntity = (TileAccelerator) t;
|
|
|
|
if (tileEntity.entityParticle == null)
|
|
{
|
|
tileEntity.entityParticle = this;
|
|
}
|
|
|
|
for (int x = -1; x < 1; x++)
|
|
{
|
|
for (int z = -1; z < 1; z++)
|
|
{
|
|
ForgeChunkManager.forceChunk(this.updateTicket, new ChunkCoordIntPair(((int) this.posX >> 4) + x, ((int) this.posZ >> 4) + z));
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
if (!this.worldObj.isRemote)
|
|
{
|
|
this.dataWatcher.updateObject(MOVE_TICK_RATE, (byte) this.movementDirection.ordinal());
|
|
}
|
|
else
|
|
{
|
|
this.movementDirection = ForgeDirection.getOrientation(this.dataWatcher.getWatchableObjectByte(MOVE_TICK_RATE));
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
e.printStackTrace();
|
|
}
|
|
|
|
double acceleration = 0.0006f;
|
|
|
|
if ((!isElectromagnet(worldObj, new Vector3(this), movementDirection.getRotation(ForgeDirection.UP)) || !isElectromagnet(worldObj, new Vector3(this), movementDirection.getRotation(ForgeDirection.DOWN))) && this.lastTurn <= 0)
|
|
{
|
|
acceleration = turn();
|
|
this.motionX = 0;
|
|
this.motionY = 0;
|
|
this.motionZ = 0;
|
|
this.lastTurn = 40;
|
|
}
|
|
|
|
this.lastTurn--;
|
|
|
|
/** Checks if the current block condition allows the particle to exist */
|
|
if (!canSpawnParticle(this.worldObj, new Vector3(this)) || this.isCollided)
|
|
{
|
|
explode();
|
|
return;
|
|
}
|
|
|
|
Vector3 dongLi = new Vector3();
|
|
dongLi.translate(this.movementDirection);
|
|
dongLi.scale(acceleration);
|
|
this.motionX = Math.min(dongLi.x + this.motionX, TileAccelerator.clientParticleVelocity);
|
|
this.motionY = Math.min(dongLi.y + this.motionY, TileAccelerator.clientParticleVelocity);
|
|
this.motionZ = Math.min(dongLi.z + this.motionZ, TileAccelerator.clientParticleVelocity);
|
|
this.isAirBorne = true;
|
|
|
|
this.lastTickPosX = this.posX;
|
|
this.lastTickPosY = this.posY;
|
|
this.lastTickPosZ = this.posZ;
|
|
|
|
this.moveEntity(this.motionX, this.motionY, this.motionZ);
|
|
|
|
this.setPosition(this.posX, this.posY, this.posZ);
|
|
|
|
if (this.lastTickPosX == this.posX && this.lastTickPosY == this.posY && this.lastTickPosZ == this.posZ && this.getParticleVelocity() <= 0 && this.lastTurn <= 0)
|
|
{
|
|
this.setDead();
|
|
}
|
|
|
|
this.worldObj.spawnParticle("portal", this.posX, this.posY, this.posZ, 0, 0, 0);
|
|
this.worldObj.spawnParticle("largesmoke", this.posX, this.posY, this.posZ, 0, 0, 0);
|
|
|
|
float radius = 0.5f;
|
|
|
|
AxisAlignedBB bounds = AxisAlignedBB.getBoundingBox(this.posX - radius, this.posY - radius, this.posZ - radius, this.posX + radius, this.posY + radius, this.posZ + radius);
|
|
List<Entity> entitiesNearby = this.worldObj.getEntitiesWithinAABB(Entity.class, bounds);
|
|
|
|
if (entitiesNearby.size() > 1)
|
|
{
|
|
this.explode();
|
|
return;
|
|
}
|
|
}
|
|
|
|
/** Try to move the particle left or right depending on which side is empty.
|
|
*
|
|
* @return The new velocity. */
|
|
private double turn()
|
|
{
|
|
ForgeDirection zuoFangXiang = VectorHelper.getOrientationFromSide(this.movementDirection, ForgeDirection.EAST);
|
|
Vector3 zuoBian = new Vector3(this).floor();
|
|
zuoBian.translate(zuoFangXiang);
|
|
|
|
ForgeDirection youFangXiang = VectorHelper.getOrientationFromSide(this.movementDirection, ForgeDirection.WEST);
|
|
Vector3 youBian = new Vector3(this).floor();
|
|
youBian.translate(youFangXiang);
|
|
|
|
if (zuoBian.getBlockID(this.worldObj) == 0)
|
|
{
|
|
this.movementDirection = zuoFangXiang;
|
|
}
|
|
else if (youBian.getBlockID(this.worldObj) == 0)
|
|
{
|
|
this.movementDirection = youFangXiang;
|
|
}
|
|
else
|
|
{
|
|
setDead();
|
|
return 0;
|
|
}
|
|
|
|
this.setPosition(Math.floor(this.posX) + 0.5, Math.floor(this.posY) + 0.5, Math.floor(this.posZ) + 0.5);
|
|
|
|
return this.getParticleVelocity() - (this.getParticleVelocity() / Math.min(Math.max(70 * this.getParticleVelocity(), 4), 30));
|
|
|
|
}
|
|
|
|
public void explode()
|
|
{
|
|
this.worldObj.playSoundAtEntity(this, Reference.PREFIX + "antimatter", 1.5f, 1f - this.worldObj.rand.nextFloat() * 0.3f);
|
|
|
|
if (!this.worldObj.isRemote)
|
|
{
|
|
if (this.getParticleVelocity() > TileAccelerator.clientParticleVelocity / 2)
|
|
{
|
|
/* Check for nearby particles and if colliding with another one, drop strange matter. */
|
|
float radius = 1f;
|
|
|
|
AxisAlignedBB bounds = AxisAlignedBB.getBoundingBox(this.posX - radius, this.posY - radius, this.posZ - radius, this.posX + radius, this.posY + radius, this.posZ + radius);
|
|
List<EntityParticle> entitiesNearby = this.worldObj.getEntitiesWithinAABB(EntityParticle.class, bounds);
|
|
|
|
if (entitiesNearby.size() > 0)
|
|
{
|
|
didParticleCollide = true;
|
|
setDead();
|
|
return;
|
|
}
|
|
}
|
|
|
|
this.worldObj.createExplosion(this, this.posX, this.posY, this.posZ, (float) this.getParticleVelocity() * 2.5f, true);
|
|
}
|
|
|
|
float radius = 6;
|
|
|
|
AxisAlignedBB bounds = AxisAlignedBB.getBoundingBox(this.posX - radius, this.posY - radius, this.posZ - radius, this.posX + radius, this.posY + radius, this.posZ + radius);
|
|
List<EntityLiving> livingNearby = this.worldObj.getEntitiesWithinAABB(EntityLiving.class, bounds);
|
|
|
|
for (EntityLiving entity : livingNearby)
|
|
{
|
|
PoisonRadiation.INSTANCE.poisonEntity(new Vector3(entity), entity);
|
|
}
|
|
|
|
setDead();
|
|
}
|
|
|
|
public double getParticleVelocity()
|
|
{
|
|
return Math.abs(this.motionX) + Math.abs(this.motionY) + Math.abs(this.motionZ);
|
|
}
|
|
|
|
@Override
|
|
public void applyEntityCollision(Entity par1Entity)
|
|
{
|
|
this.explode();
|
|
}
|
|
|
|
@Override
|
|
public void setDead()
|
|
{
|
|
ForgeChunkManager.releaseTicket(this.updateTicket);
|
|
super.setDead();
|
|
}
|
|
|
|
@Override
|
|
protected void readEntityFromNBT(NBTTagCompound nbt)
|
|
{
|
|
this.movementVector = new Vector3(nbt.getCompoundTag("jiqi"));
|
|
ForgeDirection.getOrientation(nbt.getByte("fangXiang"));
|
|
}
|
|
|
|
@Override
|
|
protected void writeEntityToNBT(NBTTagCompound nbt)
|
|
{
|
|
nbt.setTag("jiqi", this.movementVector.writeToNBT(new NBTTagCompound()));
|
|
nbt.setByte("fangXiang", (byte) this.movementDirection.ordinal());
|
|
}
|
|
|
|
}
|