electrodynamics/src/main/scala/edx/quantum/machine/accelerator/TileAccelerator.scala

323 lines
10 KiB
Scala

package edx.quantum.machine.accelerator
import cpw.mods.fml.relauncher.{Side, SideOnly}
import edx.core.{Electrodynamics, Reference, Settings}
import edx.quantum.QuantumContent
import edx.quantum.items.ItemAntimatter
import io.netty.buffer.ByteBuf
import net.minecraft.block.Block
import net.minecraft.block.material.Material
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.util.IIcon
import net.minecraftforge.common.util.ForgeDirection
import resonantengine.api.tile.{IElectromagnet, IRotatable}
import resonantengine.core.network.discriminator.{PacketTile, PacketType}
import resonantengine.lib.content.prefab.TInventory
import resonantengine.lib.grid.energy.EnergyStorage
import resonantengine.lib.modcontent.block.ResonantTile
import resonantengine.lib.transform.vector.Vector3
import resonantengine.lib.utility.BlockUtility
import resonantengine.prefab.block.impl.TEnergyProvider
import resonantengine.prefab.network.{TPacketReceiver, TPacketSender}
import scala.collection.JavaConversions._
class TileAccelerator extends ResonantTile(Material.iron) with TInventory with IElectromagnet with IRotatable with TPacketReceiver with TPacketSender with TEnergyProvider
{
final val DESC_PACKET_ID = 2
/**
* The total amount of energy consumed by this particle. In Joules.
*/
var totalEnergyConsumed: Double = 0
/**
* The amount of anti-matter stored within the accelerator. Measured in milligrams.
*/
var antimatter: Int = 0
var entityParticle: EntityParticle = null
var velocity: Float = 0
var clientEnergy: Double = 0
var lastSpawnTick: Int = 0
/**
* Multiplier that is used to give extra anti-matter based on density (hardness) of a given ore.
*/
private var antiMatterDensityMultiplyer: Int = Settings.ACCELERATOR_ANITMATTER_DENSITY_MULTIPLIER
//Constructor
//TODO: Dummy
energy = new EnergyStorage
override def getSizeInventory: Int = 4
override def update
{
super.update
if (!worldObj.isRemote)
{
clientEnergy = energy.value
velocity = getParticleVel()
outputAntimatter()
if (worldObj.isBlockIndirectlyGettingPowered(xCoord, yCoord, zCoord))
{
if (energy >= Settings.ACCELERATOR_ENERGY_COST_PER_TICK)
{
if (entityParticle == null)
{
//Create new particle if we have materials to spawn it with
if (getStackInSlot(0) != null && lastSpawnTick >= 40)
{
val spawn_vec: Vector3 = toVectorWorld
spawn_vec.add(getDirection.getOpposite)
spawn_vec.add(0.5f)
if (EntityParticle.canSpawnParticle(worldObj, spawn_vec))
{
totalEnergyConsumed = 0
entityParticle = new EntityParticle(worldObj, spawn_vec, toVectorWorld, getDirection.getOpposite)
worldObj.spawnEntityInWorld(entityParticle)
CalculateParticleDensity
decrStackSize(0, 1)
lastSpawnTick = 0
}
}
}
else
{
if (entityParticle.isDead)
{
//Handle strange matter creation
if (entityParticle.didParticleCollide)
{
if (worldObj.rand.nextFloat <= Settings.darkMatterSpawnChance)
{
incrStackSize(3, new ItemStack(QuantumContent.itemDarkMatter))
}
}
entityParticle = null
}
else if (velocity > EntityParticle.ANITMATTER_CREATION_SPEED)
{
//Create antimatter if we have hit max speed
worldObj.playSoundEffect(xCoord, yCoord, zCoord, Reference.prefix + "antimatter", 2f, 1f - worldObj.rand.nextFloat * 0.3f)
val generatedAntimatter: Int = 5 + worldObj.rand.nextInt(antiMatterDensityMultiplyer)
antimatter += generatedAntimatter
//Cleanup
totalEnergyConsumed = 0
entityParticle.setDead
entityParticle = null
}
if (entityParticle != null)
{
worldObj.playSoundEffect(xCoord, yCoord, zCoord, Reference.prefix + "accelerator", 1.5f, (0.6f + (0.4 * (entityParticle.getParticleVelocity) / EntityParticle.ANITMATTER_CREATION_SPEED)).asInstanceOf[Float])
}
}
energy -= Settings.ACCELERATOR_ENERGY_COST_PER_TICK
}
else
{
if (entityParticle != null)
{
entityParticle.setDead
}
entityParticle = null
}
}
else
{
if (entityParticle != null)
{
entityParticle.setDead
}
entityParticle = null
}
if (ticks % 5 == 0)
{
for (player <- getPlayersUsing)
{
sendPacket(getDescPacket, player)
}
}
lastSpawnTick += 1
}
}
/**
* Converts antimatter storage into item if the condition are meet
*/
def outputAntimatter()
{
//Do we have an empty cell in slot one
if (QuantumContent.isItemStackEmptyCell(getStackInSlot(1)) && getStackInSlot(1).stackSize > 0)
{
// Each cell can only hold 125mg of antimatter TODO maybe a config for this?
if (antimatter >= 125)
{
if (getStackInSlot(2) != null)
{
// If the output slot is not empty we must increase stack size
if (getStackInSlot(2).getItem == QuantumContent.itemAntimatter)
{
val newStack: ItemStack = getStackInSlot(2).copy
if (newStack.stackSize < newStack.getMaxStackSize)
{
decrStackSize(1, 1)
antimatter -= 125
newStack.stackSize += 1
setInventorySlotContents(2, newStack)
}
}
}
else
{
//Output to slot 2 and decrease volume of antimatter
antimatter -= 125
decrStackSize(1, 1)
setInventorySlotContents(2, new ItemStack(QuantumContent.itemAntimatter))
}
}
}
}
private def CalculateParticleDensity
{
val itemToAccelerate: ItemStack = this.getStackInSlot(0)
if (itemToAccelerate != null)
{
antiMatterDensityMultiplyer = Settings.ACCELERATOR_ANITMATTER_DENSITY_MULTIPLIER
val potentialBlock: Block = Block.getBlockFromItem(itemToAccelerate.getItem)
if (potentialBlock != null)
{
antiMatterDensityMultiplyer = BlockUtility.getBlockHardness(potentialBlock).asInstanceOf[Int] * Settings.ACCELERATOR_ANITMATTER_DENSITY_MULTIPLIER
if (antiMatterDensityMultiplyer <= 0)
{
antiMatterDensityMultiplyer = Settings.ACCELERATOR_ANITMATTER_DENSITY_MULTIPLIER
}
if (antiMatterDensityMultiplyer > 1000)
{
antiMatterDensityMultiplyer = 1000 * Settings.ACCELERATOR_ANITMATTER_DENSITY_MULTIPLIER
}
}
}
}
override def getDescPacket: PacketTile =
{
return new PacketTile(x.toInt, y.toInt, z.toInt, Array[Any](DESC_PACKET_ID, velocity, totalEnergyConsumed, antimatter, energy.value))
}
/////////////////////////////////////////
/// Packet Handling ///
////////////////////////////////////////
/** get velocity for the particle and @return it as a float */
def getParticleVel(): Float =
{
if (entityParticle != null)
return entityParticle.getParticleVelocity.asInstanceOf[Float]
else
return 0
}
override def activate(player: EntityPlayer, side: Int, hit: Vector3): Boolean =
{
player.openGui(Electrodynamics, 0, world, x.toInt, y.toInt, z.toInt)
return true
}
/////////////////////////////////////////
/// Save handling ///
////////////////////////////////////////
override def read(buf: ByteBuf, id: Int, packetType: PacketType)
{
//Client only packets
if (world.isRemote)
{
if (id == DESC_PACKET_ID)
{
this.velocity = buf.readFloat()
this.totalEnergyConsumed = buf.readDouble()
this.antimatter = buf.readInt()
this.energy.value = buf.readDouble()
}
}
}
override def readFromNBT(par1NBTTagCompound: NBTTagCompound)
{
super.readFromNBT(par1NBTTagCompound)
totalEnergyConsumed = par1NBTTagCompound.getDouble("energyUsed")
antimatter = par1NBTTagCompound.getInteger("antimatter")
}
/////////////////////////////////////////
/// Inventory Overrides ///
////////////////////////////////////////
override def writeToNBT(par1NBTTagCompound: NBTTagCompound)
{
super.writeToNBT(par1NBTTagCompound)
par1NBTTagCompound.setDouble("energyUsed", totalEnergyConsumed)
par1NBTTagCompound.setInteger("antimatter", antimatter)
}
override def canInsertItem(slotID: Int, itemStack: ItemStack, j: Int): Boolean =
{
return isItemValidForSlot(slotID, itemStack) && slotID != 2 && slotID != 3
}
override def isItemValidForSlot(i: Int, itemStack: ItemStack): Boolean =
{
i match
{
case 0 =>
return true
case 1 =>
return QuantumContent.isItemStackEmptyCell(itemStack)
case 2 =>
return itemStack.getItem.isInstanceOf[ItemAntimatter]
case 3 =>
return itemStack.getItem != null && itemStack.getItem.getUnlocalizedName.contains("DarkMatter")
}
return false
}
/////////////////////////////////////////
/// Field Getters & Setters ///
////////////////////////////////////////
override def canExtractItem(slotID: Int, itemstack: ItemStack, j: Int): Boolean =
{
return slotID == 2 || slotID == 3
}
override def isRunning: Boolean =
{
return true
}
@SideOnly(Side.CLIENT)
override def getIcon(side: Int, meta: Int): IIcon =
{
if (side == getDirection.getOpposite.ordinal())
{
return QuantumContent.blockElectromagnet.getIcon(side, meta)
}
return getIcon
}
override def getDirection: ForgeDirection =
{
return ForgeDirection.getOrientation(getBlockMetadata)
}
override def setDirection(direction: ForgeDirection)
{
world.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, direction.ordinal, 3)
}
}