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) } }