electrodynamics/src/main/scala/edx/electrical/circuit/source/battery/TileBattery.scala

282 lines
9.6 KiB
Scala

package edx.electrical.circuit.source.battery
import java.util.ArrayList
import cpw.mods.fml.relauncher.{Side, SideOnly}
import edx.core.Reference
import io.netty.buffer.ByteBuf
import net.minecraft.block.material.Material
import net.minecraft.client.Minecraft
import net.minecraft.entity.EntityLivingBase
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.util.ResourceLocation
import net.minecraftforge.client.IItemRenderer.ItemRenderType
import net.minecraftforge.client.model.AdvancedModelLoader
import net.minecraftforge.common.util.ForgeDirection
import org.lwjgl.opengl.GL11._
import resonantengine.api.item.ISimpleItemRenderer
import resonantengine.core.network.discriminator.PacketType
import resonantengine.lib.content.prefab.TIO
import resonantengine.lib.grid.energy.EnergyStorage
import resonantengine.lib.grid.energy.electric.NodeElectricComponent
import resonantengine.lib.modcontent.block.ResonantTile
import resonantengine.lib.render.RenderUtility
import resonantengine.lib.transform.vector.Vector3
import resonantengine.lib.utility.science.UnitDisplay
import resonantengine.lib.wrapper.ByteBufWrapper._
import resonantengine.prefab.block.impl.{TBlockNodeProvider, TEnergyProvider}
import resonantengine.prefab.network.{TPacketReceiver, TPacketSender}
/** A modular battery box that allows shared connections with boxes next to it.
*
* @author Calclavia
*/
object TileBattery
{
/** Tiers: 0, 1, 2 */
final val maxTier = 2
@SideOnly(Side.CLIENT)
val model = AdvancedModelLoader.loadModel(new ResourceLocation(Reference.domain, Reference.modelPath + "battery/battery.tcn"))
/**
* @param tier - 0, 1, 2
* @return
*/
def getEnergyForTier(tier: Int) = Math.round(Math.pow(500000000, (tier / (maxTier + 0.7f)) + 1) / 500000000) * 500000000
}
class TileBattery extends ResonantTile(Material.iron) with TIO with TBlockNodeProvider with TPacketSender with TPacketReceiver with TEnergyProvider with ISimpleItemRenderer
{
private val electricNode = new NodeElectricComponent(this)
var energyRenderLevel = 0
nodes.add(electricNode)
energy = new EnergyStorage
textureName = "material_metal_side"
ioMap = 0
saveIOMap = true
normalRender = false
isOpaqueCube = false
itemBlock = classOf[ItemBlockBattery]
electricNode.resistance = 10
override def start()
{
super.start()
updateConnectionMask()
}
override def update()
{
super.update()
if (!world.isRemote)
{
if (isIndirectlyPowered)
{
//Discharge battery when current is flowing positive direction
//TODO: Allow player to set the power output
electricNode.generatePower(Math.min(energy.max * 0.0001, energy.value))
val dissipatedEnergy = electricNode.power / 20
energy -= dissipatedEnergy
}
else
{
//Recharge battery when current is flowing negative direction
energy += electricNode.power / 20
}
if (energy.prev != energy.value)
{
energyRenderLevel = Math.round((energy.value / TileBattery.getEnergyForTier(getBlockMetadata).toDouble) * 8).toInt
sendDescPacket()
}
/**
* Update packet when energy level changes.
val prevEnergyLevel = energyRenderLevel
energyRenderLevel = Math.round((energy.value / TileBattery.getEnergyForTier(getBlockMetadata).toDouble) * 8).toInt
if (prevEnergyLevel != energyRenderLevel)
{
markUpdate()
}*/
}
}
override def write(buf: ByteBuf, id: Int)
{
super.write(buf, id)
buf <<< energy.value
buf <<< energyRenderLevel.toByte
buf <<< ioMap
}
override def read(buf: ByteBuf, id: Int, packetType: PacketType)
{
super.read(buf, id, packetType)
energy.max = TileBattery.getEnergyForTier(metadata)
energy.value = buf.readDouble()
energyRenderLevel = buf.readByte()
ioMap = buf.readInt()
}
override def setIO(dir: ForgeDirection, packet: Int)
{
super.setIO(dir, packet)
updateConnectionMask()
}
def updateConnectionMask()
{
electricNode.setPositives(getInputDirections())
electricNode.setNegatives(getOutputDirections())
electricNode.reconstruct()
markUpdate()
notifyChange()
}
override def onPlaced(entityLiving: EntityLivingBase, itemStack: ItemStack)
{
if (!world.isRemote && itemStack.getItem.isInstanceOf[ItemBlockBattery])
{
energy.max = (TileBattery.getEnergyForTier(ItemBlockBattery.getTier(itemStack)))
energy.value = itemStack.getItem.asInstanceOf[ItemBlockBattery].getEnergy(itemStack)
world.setBlockMetadataWithNotify(x.toInt, y.toInt, z.toInt, ItemBlockBattery.getTier(itemStack), 3)
}
}
override def getDrops(metadata: Int, fortune: Int): ArrayList[ItemStack] =
{
val ret = new ArrayList[ItemStack]
val itemStack: ItemStack = new ItemStack(getBlockType, 1)
val itemBlock: ItemBlockBattery = itemStack.getItem.asInstanceOf[ItemBlockBattery]
ItemBlockBattery.setTier(itemStack, world.getBlockMetadata(x.toInt, y.toInt, z.toInt).asInstanceOf[Byte])
itemBlock.setEnergy(itemStack, energy.value)
ret.add(itemStack)
return ret
}
@SideOnly(Side.CLIENT)
override def renderInventoryItem(`type`: ItemRenderType, itemStack: ItemStack, data: AnyRef*)
{
glPushMatrix()
val energyLevel = ((itemStack.getItem.asInstanceOf[ItemBlockBattery].getEnergy(itemStack) / itemStack.getItem.asInstanceOf[ItemBlockBattery].getEnergyCapacity(itemStack)) * 8).toInt
RenderUtility.bind(Reference.domain, Reference.modelPath + "battery/battery.png")
var disabledParts = Set.empty[String]
disabledParts ++= Set("connector", "connectorIn", "connectorOut")
disabledParts ++= Set("coil1", "coil2", "coil3", "coil4", "coil5", "coil6", "coil7", "coil8")
disabledParts ++= Set("coil1lit", "coil2lit", "coil3lit", "coil4lit", "coil5lit", "coil6lit", "coil7lit", "coil8lit")
disabledParts ++= Set("frame1con", "frame2con", "frame3con", "frame4con")
TileBattery.model.renderAllExcept(disabledParts.toList: _*)
for (i <- 1 until 8)
{
if (i != 1 || !disabledParts.contains("coil1"))
{
if ((8 - i) <= energyLevel)
TileBattery.model.renderOnly("coil" + i + "lit")
else
TileBattery.model.renderOnly("coil" + i)
}
}
glPopMatrix()
}
@SideOnly(Side.CLIENT)
override def renderDynamic(pos: Vector3, frame: Float, pass: Int)
{
val partToDisable = Array[Array[String]](Array[String]("bottom"), Array[String]("top"), Array[String]("frame1", "frame2"), Array[String]("frame3", "frame4"), Array[String]("frame4", "frame1"), Array[String]("frame2", "frame3"))
val connectionPartToEnable = Array[Array[String]](null, null, Array[String]("frame1con", "frame2con"), Array[String]("frame3con", "frame4con"), Array[String]("frame4con", "frame1con"), Array[String]("frame2con", "frame3con"))
glPushMatrix()
glTranslated(pos.x + 0.5, pos.y + 0.5, pos.z + 0.5)
RenderUtility.bind(Reference.domain, Reference.modelPath + "battery/battery.png")
var disabledParts = Set.empty[String]
var enabledParts = Set.empty[String]
for (check <- ForgeDirection.VALID_DIRECTIONS)
{
if ((toVectorWorld + check).getTileEntity.isInstanceOf[TileBattery])
{
disabledParts ++= partToDisable(check.ordinal)
if (check == ForgeDirection.UP)
{
enabledParts ++= partToDisable(check.ordinal)
enabledParts += "coil1"
}
else if (check == ForgeDirection.DOWN)
{
var connectionParts = Set.empty[String]
val downDirs = ForgeDirection.VALID_DIRECTIONS.filter(_.offsetY == 0)
downDirs.foreach(s => connectionParts ++= connectionPartToEnable(s.ordinal))
downDirs.filter(s => (toVectorWorld + s).getTileEntity.isInstanceOf[TileBattery]).foreach(s => connectionParts --= connectionPartToEnable(s.ordinal))
enabledParts ++= connectionParts
}
}
//Render connectors
if (check.offsetY == 0)
{
glPushMatrix()
RenderUtility.rotateBlockBasedOnDirection(check)
glRotatef(-90, 0, 1, 0)
getIO(check) match
{
case 1 => TileBattery.model.renderOnly("connectorIn")
case 2 => TileBattery.model.renderOnly("connectorOut")
case _ =>
}
glPopMatrix()
}
}
enabledParts --= disabledParts
for (i <- 1 to 8)
{
if (i != 1 || enabledParts.contains("coil1"))
{
if ((8 - i) < energyRenderLevel)
TileBattery.model.renderOnly("coil" + i + "lit")
else
TileBattery.model.renderOnly("coil" + i)
}
}
disabledParts ++= Set("connector", "connectorIn", "connectorOut")
disabledParts ++= Set("coil1", "coil2", "coil3", "coil4", "coil5", "coil6", "coil7", "coil8")
disabledParts ++= Set("coil1lit", "coil2lit", "coil3lit", "coil4lit", "coil5lit", "coil6lit", "coil7lit", "coil8lit")
disabledParts ++= Set("frame1con", "frame2con", "frame3con", "frame4con")
enabledParts --= Set("coil1", "coil2", "coil3", "coil4", "coil5", "coil6", "coil7", "coil8")
TileBattery.model.renderAllExcept(disabledParts.toList: _*)
TileBattery.model.renderOnly(enabledParts.toList: _*)
/**
* Render energy tooltip
*/
if (isPlayerLooking(Minecraft.getMinecraft.thePlayer))
RenderUtility.renderFloatingText(new UnitDisplay(UnitDisplay.Unit.JOULES, energy.value).symbol + " / " + new UnitDisplay(UnitDisplay.Unit.JOULES, energy.max).symbol, new Vector3(0, 0.9, 0))
glPopMatrix()
}
override def readFromNBT(nbt: NBTTagCompound)
{
super.readFromNBT(nbt)
energy.load(nbt)
}
override def writeToNBT(nbt: NBTTagCompound)
{
super.writeToNBT(nbt)
energy.save(nbt)
}
}