electrodynamics/atomic/src/main/scala/resonantinduction/atomic/particle/accelerator/TileAccelerator.java

359 lines
13 KiB
Java

package resonantinduction.atomic.particle.accelerator;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.ISidedInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.packet.Packet;
import net.minecraftforge.common.ForgeDirection;
import resonant.api.IElectromagnet;
import resonant.api.IRotatable;
import resonant.lib.network.Synced;
import resonant.lib.prefab.tile.TileElectricalInventory;
import resonantinduction.atomic.Atomic;
import resonantinduction.atomic.particle.fulmination.ItemAntimatter;
import resonantinduction.core.Reference;
import resonantinduction.core.ResonantInduction;
import resonantinduction.core.Settings;
import universalelectricity.api.electricity.IVoltageInput;
import universalelectricity.api.energy.EnergyStorageHandler;
import universalelectricity.api.energy.IEnergyInterface;
import universalelectricity.api.vector.Vector3;
import cpw.mods.fml.common.network.PacketDispatcher;
import cpw.mods.fml.common.network.Player;
/** Accelerator TileEntity */
public class TileAccelerator extends TileElectricalInventory implements IElectromagnet, IRotatable, IInventory, ISidedInventory, IVoltageInput
{
/** Joules required per ticks. */
public static final int energyPerTick = 4800000;
/** User client side to determine the velocity of the particle. */
public static final float clientParticleVelocity = 0.9f;
/** The total amount of energy consumed by this particle. In Joules. */
@Synced
public float totalEnergyConsumed = 0;
/** The amount of anti-matter stored within the accelerator. Measured in milligrams. */
@Synced
public int antimatter;
public EntityParticle entityParticle;
@Synced
public float velocity;
@Synced
private long clientEnergy = 0;
private int lastSpawnTick = 0;
/** Multiplier that is used to give extra anti-matter based on density (hardness) of a given ore. */
private int antiMatterDensityMultiplyer = DENSITY_MULTIPLYER_DEFAULT;
private static final int DENSITY_MULTIPLYER_DEFAULT = 1;
public TileAccelerator()
{
energy = new EnergyStorageHandler(energyPerTick * 2, energyPerTick / 20);
maxSlots = 4;
antiMatterDensityMultiplyer = DENSITY_MULTIPLYER_DEFAULT;
}
@Override
public boolean canConnect(ForgeDirection direction, Object obj)
{
return obj instanceof IEnergyInterface;
}
@Override
public long onReceiveEnergy(ForgeDirection from, long receive, boolean doReceive)
{
if (doReceive)
{
totalEnergyConsumed += receive;
}
if (getStackInSlot(0) != null && (worldObj.isBlockIndirectlyGettingPowered(xCoord, yCoord, zCoord) || worldObj.getBlockPowerInput(xCoord, yCoord, zCoord) > 0))
{
return super.onReceiveEnergy(from, receive, doReceive);
}
return 0;
}
@Override
public void updateEntity()
{
super.updateEntity();
if (!worldObj.isRemote)
{
clientEnergy = energy.getEnergy();
velocity = 0;
// Calculate accelerated particle velocity if it is spawned.
if (entityParticle != null)
{
velocity = (float) entityParticle.getParticleVelocity();
}
// Check if item inside of empty cell slot is indeed an empty slot.
if (Atomic.isItemStackEmptyCell(getStackInSlot(1)))
{
// Check if there are any empty cells we can store anti-matter in.
if (getStackInSlot(1).stackSize > 0)
{
// Craft anti-matter item if there is enough anti-matter to actually do so.
if (antimatter >= 125)
{
if (getStackInSlot(2) != null)
{
// Increase the existing amount of anti-matter if stack already exists.
if (getStackInSlot(2).itemID == Atomic.itemAntimatter.itemID)
{
ItemStack newStack = getStackInSlot(2).copy();
if (newStack.stackSize < newStack.getMaxStackSize())
{
// Remove an empty cell which we will put the anti-matter into.
decrStackSize(1, 1);
// Remove anti-matter from internal reserve and increase stack count.
antimatter -= 125;
newStack.stackSize++;
setInventorySlotContents(2, newStack);
}
}
}
else
{
// Remove some of the internal reserves of anti-matter and use it to craft an individual item.
antimatter -= 125;
decrStackSize(1, 1);
setInventorySlotContents(2, new ItemStack(Atomic.itemAntimatter));
}
}
}
}
// Check if redstone signal is currently being applied.
if (worldObj.isBlockIndirectlyGettingPowered(xCoord, yCoord, zCoord))
{
if (energy.checkExtract())
{
if (entityParticle == null)
{
// Creates a accelerated particle if one needs to exist (on world load for example or player login).
if (getStackInSlot(0) != null && lastSpawnTick >= 40)
{
Vector3 spawnAcceleratedParticle = new Vector3(this);
spawnAcceleratedParticle.translate(getDirection().getOpposite());
spawnAcceleratedParticle.translate(0.5f);
// Only render the particle if container within the proper environment for it.
if (EntityParticle.canRenderAcceleratedParticle(worldObj, spawnAcceleratedParticle))
{
// Spawn the particle.
totalEnergyConsumed = 0;
entityParticle = new EntityParticle(worldObj, spawnAcceleratedParticle, new Vector3(this), getDirection().getOpposite());
worldObj.spawnEntityInWorld(entityParticle);
// Grabs input block hardness if available, otherwise defaults are used.
CalculateParticleDensity();
// Decrease particle we want to collide.
decrStackSize(0, 1);
lastSpawnTick = 0;
}
}
}
else
{
if (entityParticle.isDead)
{
// On particle collision we roll the dice to see if dark-matter is generated.
if (entityParticle.didParticleCollide)
{
if (worldObj.rand.nextFloat() <= Settings.darkMatterSpawnChance)
{
incrStackSize(3, new ItemStack(Atomic.itemDarkMatter));
}
}
entityParticle = null;
}
else if (velocity > clientParticleVelocity)
{
// Play sound of anti-matter being created.
worldObj.playSoundEffect(xCoord, yCoord, zCoord, Reference.PREFIX + "antimatter", 2f, 1f - worldObj.rand.nextFloat() * 0.3f);
// Create anti-matter in the internal reserve.
int generatedAntimatter = 5 + worldObj.rand.nextInt(antiMatterDensityMultiplyer);
antimatter += generatedAntimatter;
// AtomicScience.LOGGER.info("[Particle Accelerator] Generated " + String.valueOf(generatedAntimatter) + " mg of anti-matter.");
// Reset energy consumption levels and destroy accelerated particle.
totalEnergyConsumed = 0;
entityParticle.setDead();
entityParticle = null;
}
// Plays sound of particle accelerating past the speed based on total velocity at the time of anti-matter creation.
if (entityParticle != null)
{
worldObj.playSoundEffect(xCoord, yCoord, zCoord, Reference.PREFIX + "accelerator", 1.5f, (float) (0.6f + (0.4 * (entityParticle.getParticleVelocity()) / TileAccelerator.clientParticleVelocity)));
}
}
energy.extractEnergy();
}
else
{
if (entityParticle != null)
{
entityParticle.setDead();
}
entityParticle = null;
}
}
else
{
if (entityParticle != null)
{
entityParticle.setDead();
}
entityParticle = null;
}
if (ticks % 5 == 0)
{
for (EntityPlayer player : getPlayersUsing())
{
PacketDispatcher.sendPacketToPlayer(getDescriptionPacket(), (Player) player);
}
}
lastSpawnTick++;
}
}
private void CalculateParticleDensity()
{
ItemStack itemToAccelerate = this.getStackInSlot(0);
if (itemToAccelerate != null)
{
// Calculate block density multiplier if ore dictionary block.
antiMatterDensityMultiplyer = DENSITY_MULTIPLYER_DEFAULT;
try
{
Block potentialBlock = Block.blocksList[itemToAccelerate.getItem().itemID];
if (potentialBlock != null)
{
// Prevent negative numbers and disallow zero for density multiplier.
antiMatterDensityMultiplyer = (int) Math.abs(potentialBlock.blockHardness);
if (antiMatterDensityMultiplyer <= 0)
{
antiMatterDensityMultiplyer = 1;
}
// AtomicScience.LOGGER.info("[Particle Accelerator] " + String.valueOf(potentialBlock.getUnlocalizedName()) + " Hardness: " + String.valueOf(antiMatterDensityMultiplyer));
}
}
catch (Exception err)
{
antiMatterDensityMultiplyer = DENSITY_MULTIPLYER_DEFAULT;
// AtomicScience.LOGGER.info("[Particle Accelerator] Attempted to query Minecraft block-list with value out of index.");
}
}
}
@Override
public Packet getDescriptionPacket()
{
return ResonantInduction.PACKET_ANNOTATION.getPacket(this);
}
/** Reads a tile entity from NBT. */
@Override
public void readFromNBT(NBTTagCompound par1NBTTagCompound)
{
super.readFromNBT(par1NBTTagCompound);
totalEnergyConsumed = par1NBTTagCompound.getFloat("totalEnergyConsumed");
antimatter = par1NBTTagCompound.getInteger("antimatter");
}
/** Writes a tile entity to NBT. */
@Override
public void writeToNBT(NBTTagCompound par1NBTTagCompound)
{
super.writeToNBT(par1NBTTagCompound);
par1NBTTagCompound.setFloat("totalEnergyConsumed", totalEnergyConsumed);
par1NBTTagCompound.setInteger("antimatter", antimatter);
}
@Override
public long getVoltageInput(ForgeDirection dir)
{
return 1000;
}
@Override
public int[] getAccessibleSlotsFromSide(int side)
{
return new int[]
{ 0, 1, 2, 3 };
}
@Override
public boolean canInsertItem(int slotID, ItemStack itemStack, int j)
{
return isItemValidForSlot(slotID, itemStack) && slotID != 2 && slotID != 3;
}
@Override
public boolean canExtractItem(int slotID, ItemStack itemstack, int j)
{
return slotID == 2 || slotID == 3;
}
@Override
public boolean isItemValidForSlot(int i, ItemStack itemStack)
{
switch (i)
{
case 0:
return true;
case 1:
return Atomic.isItemStackEmptyCell(itemStack);
case 2:
return itemStack.getItem() instanceof ItemAntimatter;
case 3:
return itemStack.getItem() instanceof ItemDarkMatter;
}
return false;
}
@Override
public long onExtractEnergy(ForgeDirection from, long extract, boolean doExtract)
{
return 0;
}
@Override
public void onWrongVoltage(ForgeDirection direction, long voltage)
{
}
@Override
public boolean isRunning()
{
return true;
}
}