diff --git a/src/main/java/li/cil/oc/api/API.java b/src/main/java/li/cil/oc/api/API.java index c0981dc2b..eb7f7c73f 100644 --- a/src/main/java/li/cil/oc/api/API.java +++ b/src/main/java/li/cil/oc/api/API.java @@ -16,7 +16,7 @@ import li.cil.oc.api.detail.NetworkAPI; */ public class API { public static final String ID_OWNER = "OpenComputers|Core"; - public static final String VERSION = "5.2.1"; + public static final String VERSION = "5.2.2"; public static DriverAPI driver = null; public static FileSystemAPI fileSystem = null; diff --git a/src/main/java/li/cil/oc/api/driver/item/Chargeable.java b/src/main/java/li/cil/oc/api/driver/item/Chargeable.java new file mode 100644 index 000000000..12340b734 --- /dev/null +++ b/src/main/java/li/cil/oc/api/driver/item/Chargeable.java @@ -0,0 +1,34 @@ +package li.cil.oc.api.driver.item; + +import net.minecraft.item.ItemStack; + +/** + * This interface can be implemented on items that go into a charger. + *
+ * This provides a generic way of charging items, even such that are not + * components. Doing it this way enables items to provide another environment, + * that is unrelated to charging, such as tablets providing their file system, + * while in the charger. + */ +public interface Chargeable { + /** + * Whether the specified item stack can be charged. + * + * This is primarily meant to filter meta item subitems that are not meant + * to be chargeable. + * + * @param stack the stack to check for. + * @return whether the specified item stack is chargeable. + */ + boolean canCharge(ItemStack stack); + + /** + * Called when checking if an item can be charged or should be charged. + * + * @param stack the item to charge. + * @param amount the amount to inject into the item. + * @param simulate whether to only simulate injection. + * @return the remainder of the energy that could not be injected. + */ + double charge(ItemStack stack, double amount, boolean simulate); +} diff --git a/src/main/scala/li/cil/oc/common/IMC.scala b/src/main/scala/li/cil/oc/common/IMC.scala index 4b19d26c3..9b8a3c445 100644 --- a/src/main/scala/li/cil/oc/common/IMC.scala +++ b/src/main/scala/li/cil/oc/common/IMC.scala @@ -8,6 +8,7 @@ import li.cil.oc.OpenComputers import li.cil.oc.Settings import li.cil.oc.common.template.AssemblerTemplates import li.cil.oc.common.template.DisassemblerTemplates +import li.cil.oc.integration.util.ItemCharge import li.cil.oc.integration.util.Wrench import li.cil.oc.server.driver.Registry import net.minecraft.entity.player.EntityPlayer @@ -57,6 +58,15 @@ object IMC { case t: Throwable => OpenComputers.log.warn("Failed registering wrench tool.", t) } } + else if (message.key == "registerItemCharge" && message.isNBTMessage) { + OpenComputers.log.info(s"Registering new item charge implementation '${message.getNBTValue.getString("name")}' from mod ${message.getSender}.") + try ItemCharge.add( + getStaticMethod(message.getNBTValue.getString("canCharge"), classOf[ItemStack]), + getStaticMethod(message.getNBTValue.getString("charge"), classOf[ItemStack], classOf[Double], classOf[Boolean]) + ) catch { + case t: Throwable => OpenComputers.log.warn("Failed registering item charge implementation.", t) + } + } else if (message.key == "blacklistPeripheral" && message.isStringMessage) { OpenComputers.log.info(s"Blacklisting CC peripheral '${message.getStringValue}' as requested by mod ${message.getSender}.") if (!Settings.get.peripheralBlacklist.contains(message.getStringValue)) { diff --git a/src/main/scala/li/cil/oc/common/init/Items.scala b/src/main/scala/li/cil/oc/common/init/Items.scala index 78be08e56..d6fbed2e7 100644 --- a/src/main/scala/li/cil/oc/common/init/Items.scala +++ b/src/main/scala/li/cil/oc/common/init/Items.scala @@ -247,9 +247,9 @@ object Items extends ItemAPI { Option(get(Constants.ItemName.RAMTier6).createItemStack(1)), Option(createLuaBios()), - Option(createOpenOS()), Option(get(Constants.ItemName.HDDTier3).createItemStack(1)) - ) + ).padTo(32, None) + data.items(31) = Option(createOpenOS()) data.container = Option(get(Constants.BlockName.DiskDrive).createItemStack(1)) val stack = get(Constants.ItemName.Tablet).createItemStack(1) diff --git a/src/main/scala/li/cil/oc/common/inventory/ComponentInventory.scala b/src/main/scala/li/cil/oc/common/inventory/ComponentInventory.scala index fad585fc6..2f17d5021 100644 --- a/src/main/scala/li/cil/oc/common/inventory/ComponentInventory.scala +++ b/src/main/scala/li/cil/oc/common/inventory/ComponentInventory.scala @@ -38,7 +38,7 @@ trait ComponentInventory extends Inventory with network.Environment { def connectComponents() { for (slot <- 0 until getSizeInventory if slot >= 0 && slot < components.length) { val stack = getStackInSlot(slot) - if (stack != null && components(slot).isEmpty && isComponentSlot(slot)) { + if (stack != null && components(slot).isEmpty && isComponentSlot(slot, stack)) { components(slot) = Option(Driver.driverFor(stack)) match { case Some(driver) => Option(driver.createEnvironment(stack, host)) match { @@ -98,7 +98,7 @@ trait ComponentInventory extends Inventory with network.Environment { override def getInventoryStackLimit = 1 - override protected def onItemAdded(slot: Int, stack: ItemStack) = if (isComponentSlot(slot)) { + override protected def onItemAdded(slot: Int, stack: ItemStack) = if (isComponentSlot(slot, stack)) { Option(Driver.driverFor(stack)).foreach(driver => Option(driver.createEnvironment(stack, host)) match { case Some(component) => this.synchronized { @@ -140,7 +140,7 @@ trait ComponentInventory extends Inventory with network.Environment { } } - def isComponentSlot(slot: Int) = true + def isComponentSlot(slot: Int, stack: ItemStack) = true protected def connectItemNode(node: Node) { if (this.node != null && node != null) { diff --git a/src/main/scala/li/cil/oc/common/item/Delegator.scala b/src/main/scala/li/cil/oc/common/item/Delegator.scala index 4677a5fb2..37c62025b 100644 --- a/src/main/scala/li/cil/oc/common/item/Delegator.scala +++ b/src/main/scala/li/cil/oc/common/item/Delegator.scala @@ -6,6 +6,7 @@ import java.util.Random import li.cil.oc.CreativeTab import li.cil.oc.OpenComputers import li.cil.oc.api.driver +import li.cil.oc.api.driver.item.Chargeable import li.cil.oc.api.event.RobotRenderEvent.MountPoint import li.cil.oc.api.internal.Robot import li.cil.oc.client.renderer.item.UpgradeRenderer @@ -38,7 +39,7 @@ object Delegator { else None } -class Delegator extends Item with driver.item.UpgradeRenderer { +class Delegator extends Item with driver.item.UpgradeRenderer with Chargeable { setHasSubtypes(true) setCreativeTab(CreativeTab) @@ -217,6 +218,20 @@ class Delegator extends Item with driver.item.UpgradeRenderer { // ----------------------------------------------------------------------- // + def canCharge(stack: ItemStack): Boolean = + Delegator.subItem(stack) match { + case Some(subItem: Chargeable) => true + case _ => false + } + + def charge(stack: ItemStack, amount: Double, simulate: Boolean): Double = + Delegator.subItem(stack) match { + case Some(subItem: Chargeable) => subItem.charge(stack, amount, simulate) + case _ => 0.0 + } + + // ----------------------------------------------------------------------- // + override def computePreferredMountPoint(stack: ItemStack, robot: Robot, availableMountPoints: util.Set[String]): String = UpgradeRenderer.preferredMountPoint(stack, availableMountPoints) override def render(stack: ItemStack, mountPoint: MountPoint, robot: Robot, pt: Float): Unit = UpgradeRenderer.render(stack, mountPoint) diff --git a/src/main/scala/li/cil/oc/common/item/Tablet.scala b/src/main/scala/li/cil/oc/common/item/Tablet.scala index 31a3a488d..4bf15183f 100644 --- a/src/main/scala/li/cil/oc/common/item/Tablet.scala +++ b/src/main/scala/li/cil/oc/common/item/Tablet.scala @@ -16,6 +16,7 @@ import li.cil.oc.Settings import li.cil.oc.api import li.cil.oc.api.Driver import li.cil.oc.api.Machine +import li.cil.oc.api.driver.item.Chargeable import li.cil.oc.api.driver.item.Container import li.cil.oc.api.internal import li.cil.oc.api.machine.MachineHost @@ -53,7 +54,7 @@ import net.minecraftforge.fml.relauncher.SideOnly import scala.collection.convert.WrapAsJava._ import scala.collection.convert.WrapAsScala._ -class Tablet(val parent: Delegator) extends Delegate with CustomModel { +class Tablet(val parent: Delegator) extends Delegate with CustomModel with Chargeable { final val TimeToAnalyze = 10 // Must be assembled to be usable so we hide it in the item list. @@ -120,6 +121,20 @@ class Tablet(val parent: Delegator) extends Delegate with CustomModel { } } + def canCharge(stack: ItemStack): Boolean = true + + def charge(stack: ItemStack, amount: Double, simulate: Boolean): Double = { + val data = new TabletData(stack) + val charge = math.min(data.maxEnergy - data.energy, amount) + if (!simulate) { + data.energy += charge + data.save(stack) + } + amount - charge + } + + // ----------------------------------------------------------------------- // + override def update(stack: ItemStack, world: World, entity: Entity, slot: Int, selected: Boolean) = entity match { case player: EntityPlayer => @@ -344,7 +359,7 @@ class TabletWrapper(var stack: ItemStack, var player: EntityPlayer) extends Comp }) override def internalComponents(): Iterable[ItemStack] = (0 until getSizeInventory).collect { - case slot if isComponentSlot(slot) && getStackInSlot(slot) != null => getStackInSlot(slot) + case slot if getStackInSlot(slot) != null && isComponentSlot(slot, getStackInSlot(slot)) => getStackInSlot(slot) } override def componentSlot(address: String) = components.indexWhere(_.exists(env => env.node != null && env.node.address == address)) diff --git a/src/main/scala/li/cil/oc/common/item/UpgradeBattery.scala b/src/main/scala/li/cil/oc/common/item/UpgradeBattery.scala index b93a97344..482047117 100644 --- a/src/main/scala/li/cil/oc/common/item/UpgradeBattery.scala +++ b/src/main/scala/li/cil/oc/common/item/UpgradeBattery.scala @@ -1,9 +1,11 @@ package li.cil.oc.common.item import li.cil.oc.Settings +import li.cil.oc.api.driver.item.Chargeable +import li.cil.oc.common.item.data.NodeData import net.minecraft.item.ItemStack -class UpgradeBattery(val parent: Delegator, val tier: Int) extends Delegate with ItemTier { +class UpgradeBattery(val parent: Delegator, val tier: Int) extends Delegate with ItemTier with Chargeable { override val unlocalizedName = super.unlocalizedName + tier override protected def tooltipName = Option(super.unlocalizedName) @@ -13,10 +15,25 @@ class UpgradeBattery(val parent: Delegator, val tier: Int) extends Delegate with override def showDurabilityBar(stack: ItemStack) = true override def durability(stack: ItemStack) = { - if (stack.hasTagCompound) { - val stored = stack.getTagCompound.getCompoundTag(Settings.namespace + "data").getCompoundTag("node").getDouble("buffer") - 1 - stored / Settings.get.bufferCapacitorUpgrades(tier) + val data = new NodeData(stack) + 1 - data.buffer.getOrElse(0.0) / Settings.get.bufferCapacitorUpgrades(tier) + } + + // ----------------------------------------------------------------------- // + + def canCharge(stack: ItemStack): Boolean = true + + def charge(stack: ItemStack, amount: Double, simulate: Boolean): Double = { + val data = new NodeData(stack) + val buffer = data.buffer match { + case Some(value) => value + case _ => 0.0 } - else 1.0 + val charge = math.min(amount, Settings.get.bufferCapacitorUpgrades(tier).toInt - buffer) + if (!simulate) { + data.buffer = Option(buffer + charge) + data.save(stack) + } + amount - charge } } diff --git a/src/main/scala/li/cil/oc/common/item/data/NodeData.scala b/src/main/scala/li/cil/oc/common/item/data/NodeData.scala new file mode 100644 index 000000000..ee477a655 --- /dev/null +++ b/src/main/scala/li/cil/oc/common/item/data/NodeData.scala @@ -0,0 +1,45 @@ +package li.cil.oc.common.item.data + +import li.cil.oc.Settings +import li.cil.oc.api.network.Visibility +import net.minecraft.item.ItemStack +import net.minecraft.nbt.NBTTagCompound + +// Generic one for items that are used as components; gets the items node info. +class NodeData extends ItemData { + def this(stack: ItemStack) { + this() + load(stack) + } + + var address: Option[String] = None + var buffer: Option[Double] = None + var visibility: Option[Visibility] = None + + override def load(nbt: NBTTagCompound): Unit = { + val nodeNbt = nbt.getCompoundTag(Settings.namespace + "data").getCompoundTag("node") + if (nodeNbt.hasKey("address")) { + address = Option(nodeNbt.getString("address")) + } + if (nodeNbt.hasKey("buffer")) { + buffer = Option(nodeNbt.getDouble("buffer")) + } + if (nodeNbt.hasKey("visibility")) { + visibility = Option(Visibility.values()(nodeNbt.getInteger("visibility"))) + } + } + + override def save(nbt: NBTTagCompound): Unit = { + if (!nbt.hasKey(Settings.namespace + "data")) { + nbt.setTag(Settings.namespace + "data", new NBTTagCompound()) + } + val dataNbt = nbt.getCompoundTag(Settings.namespace + "data") + if (!dataNbt.hasKey("node")) { + dataNbt.setTag("node", new NBTTagCompound()) + } + val nodeNbt = dataNbt.getCompoundTag("node") + address.foreach(nodeNbt.setString("address", _)) + buffer.foreach(nodeNbt.setDouble("buffer", _)) + visibility.map(_.ordinal()).foreach(nodeNbt.setInteger("visibility", _)) + } +} diff --git a/src/main/scala/li/cil/oc/common/tileentity/Charger.scala b/src/main/scala/li/cil/oc/common/tileentity/Charger.scala index a50e96a04..c94aadc58 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Charger.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Charger.scala @@ -9,8 +9,7 @@ import li.cil.oc.api.Driver import li.cil.oc.api.network._ import li.cil.oc.common.Slot import li.cil.oc.common.entity.Drone -import li.cil.oc.common.item.Tablet -import li.cil.oc.common.item.data.TabletData +import li.cil.oc.integration.util.ItemCharge import li.cil.oc.server.{PacketSender => ServerPacketSender} import li.cil.oc.util.BlockPosition import li.cil.oc.util.ExtendedWorld._ @@ -75,8 +74,32 @@ class Charger extends traits.Environment with traits.PowerAcceptor with traits.R } if (isServer && world.getWorldInfo.getWorldTotalTime % Settings.get.tickFrequency == 0) { - val charge = Settings.get.chargeRateExternal * chargeSpeed * Settings.get.tickFrequency - val canCharge = charge > 0 && (node.globalBuffer >= charge * 0.5 || Settings.get.ignorePower) + var canCharge = Settings.get.ignorePower + + // Charging of external devices. + { + val charge = Settings.get.chargeRateExternal * chargeSpeed * Settings.get.tickFrequency + canCharge ||= charge > 0 && node.globalBuffer >= charge * 0.5 + if (canCharge) { + connectors.foreach { + case (_, connector) => node.changeBuffer(connector.changeBuffer(charge + node.changeBuffer(-charge))) + } + } + } + + // Charging of internal devices. + { + val charge = Settings.get.chargeRateTablet * chargeSpeed * Settings.get.tickFrequency + canCharge ||= charge > 0 && node.globalBuffer >= charge * 0.5 + if (canCharge) { + (0 until getSizeInventory).map(getStackInSlot).foreach(stack => if (stack != null) { + val offered = charge + node.changeBuffer(-charge) + val surplus = ItemCharge.charge(stack, offered) + node.changeBuffer(surplus) + }) + } + } + if (hasPower && !canCharge) { hasPower = false ServerPacketSender.sendChargerState(this) @@ -85,28 +108,6 @@ class Charger extends traits.Environment with traits.PowerAcceptor with traits.R hasPower = true ServerPacketSender.sendChargerState(this) } - if (canCharge) { - connectors.foreach { - case (_, connector) => node.changeBuffer(connector.changeBuffer(charge + node.changeBuffer(-charge))) - } - } - - // Charge tablet if present. - val stack = getStackInSlot(0) - if (stack != null && chargeSpeed > 0) { - def tryCharge(energy: Double, maxEnergy: Double, handler: (Double) => Unit) { - if (energy < maxEnergy) { - val itemCharge = math.min(maxEnergy - energy, Settings.get.chargeRateTablet * chargeSpeed * Settings.get.tickFrequency) - if (node.tryChangeBuffer(-itemCharge)) - handler(itemCharge) - } - } - val data = new TabletData(stack) - tryCharge(data.energy, data.maxEnergy, (amount) => { - data.energy = math.min(data.maxEnergy, data.energy + amount) - data.save(stack) - }) - } } if (isClient && chargeSpeed > 0 && hasPower && world.getWorldInfo.getWorldTotalTime % 10 == 0) { @@ -160,22 +161,17 @@ class Charger extends traits.Environment with traits.PowerAcceptor with traits.R // ----------------------------------------------------------------------- // + override def isComponentSlot(slot: Int, stack: ItemStack): Boolean = + super.isComponentSlot(slot, stack) && (Option(Driver.driverFor(stack, getClass)) match { + case Some(driver) => driver.slot(stack) == Slot.Tablet + case _ => false + }) + override def getSizeInventory = 1 override def isItemValidForSlot(slot: Int, stack: ItemStack) = (slot, Option(Driver.driverFor(stack, getClass))) match { - case (0, Some(driver)) => driver.slot(stack) == Slot.Tablet - case _ => false - } - - override protected def onItemAdded(slot: Int, stack: ItemStack) { - super.onItemAdded(slot, stack) - Tablet.Server.cache.invalidate(Tablet.getId(stack)) - components(slot) match { - case Some(environment) => environment.node match { - case component: Component => component.setVisibility(Visibility.Network) - } - case _ => - } + case (0, Some(driver)) if driver.slot(stack) == Slot.Tablet => true + case _ => ItemCharge.canCharge(stack) } // ----------------------------------------------------------------------- // diff --git a/src/main/scala/li/cil/oc/common/tileentity/Robot.scala b/src/main/scala/li/cil/oc/common/tileentity/Robot.scala index 07af42b97..f4c20cb1e 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Robot.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Robot.scala @@ -594,7 +594,7 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot if (isFloppySlot(slot)) { common.Sound.playDiskInsert(this) } - if (isComponentSlot(slot)) { + if (isComponentSlot(slot, stack)) { super.onItemAdded(slot, stack) world.notifyBlocksOfNeighborChange(position, getBlockType) } @@ -620,7 +620,7 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot if (isInventorySlot(slot)) { machine.signal("inventory_changed", Int.box(slot - equipmentInventory.getSizeInventory + 1)) } - if (isComponentSlot(slot)) { + if (isComponentSlot(slot, stack)) { world.notifyBlocksOfNeighborChange(position, getBlockType) } } @@ -666,7 +666,7 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot } } - override def isComponentSlot(slot: Int) = (containerSlots ++ componentSlots) contains slot + override def isComponentSlot(slot: Int, stack: ItemStack) = (containerSlots ++ componentSlots) contains slot def containerSlotType(slot: Int) = if (containerSlots contains slot) { val stack = info.containers(slot - 1) @@ -692,13 +692,13 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot def isInventorySlot(slot: Int) = inventorySlots contains slot - def isFloppySlot(slot: Int) = isComponentSlot(slot) && (Option(getStackInSlot(slot)) match { - case Some(stack) => Option(Driver.driverFor(stack, getClass)) match { + def isFloppySlot(slot: Int) = getStackInSlot(slot) != null && isComponentSlot(slot, getStackInSlot(slot)) && { + val stack = getStackInSlot(slot) + Option(Driver.driverFor(stack, getClass)) match { case Some(driver) => driver.slot(stack) == Slot.Floppy case _ => false } - case _ => false - }) + } def isUpgradeSlot(slot: Int) = containerSlotType(slot) == Slot.Upgrade @@ -766,7 +766,7 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot override def setInventorySlotContents(slot: Int, stack: ItemStack) { if (slot < getSizeInventory - componentCount && (isItemValidForSlot(slot, stack) || stack == null)) { - if (stack != null && stack.stackSize > 1 && isComponentSlot(slot)) { + if (stack != null && stack.stackSize > 1 && isComponentSlot(slot, stack)) { super.setInventorySlotContents(slot, stack.splitStack(1)) if (stack.stackSize > 0 && isServer) { player().inventory.addItemStackToInventory(stack) @@ -886,5 +886,5 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot override def getTankInfo(from: EnumFacing) = components.collect { case Some(t: IFluidTank) => t.getInfo - }.toArray + } } diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/ComponentInventory.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/ComponentInventory.scala index e2e13ca98..50afc5648 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/traits/ComponentInventory.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/traits/ComponentInventory.scala @@ -2,6 +2,7 @@ package li.cil.oc.common.tileentity.traits import li.cil.oc.api.network.Node import li.cil.oc.common.inventory +import net.minecraft.item.ItemStack import net.minecraft.nbt.NBTTagCompound import net.minecraftforge.fml.relauncher.Side import net.minecraftforge.fml.relauncher.SideOnly @@ -9,7 +10,7 @@ import net.minecraftforge.fml.relauncher.SideOnly trait ComponentInventory extends Environment with Inventory with inventory.ComponentInventory { override def host = this - override def isComponentSlot(slot: Int) = isServer + override def isComponentSlot(slot: Int, stack: ItemStack) = isServer override def onConnect(node: Node) { super.onConnect(node) diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/Computer.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/Computer.scala index 24d0051ad..129e5fe73 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/traits/Computer.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/traits/Computer.scala @@ -73,7 +73,7 @@ trait Computer extends Environment with ComponentInventory with Rotatable with B // ----------------------------------------------------------------------- // override def internalComponents(): lang.Iterable[ItemStack] = (0 until getSizeInventory).collect { - case i if isComponentSlot(i) && getStackInSlot(i) != null => getStackInSlot(i) + case slot if getStackInSlot(slot) != null && isComponentSlot(slot, getStackInSlot(slot)) => getStackInSlot(slot) } diff --git a/src/main/scala/li/cil/oc/integration/cofh/energy/EventHandlerRedstoneFlux.scala b/src/main/scala/li/cil/oc/integration/cofh/energy/EventHandlerRedstoneFlux.scala index 6f12a5611..8d1af1fa8 100644 --- a/src/main/scala/li/cil/oc/integration/cofh/energy/EventHandlerRedstoneFlux.scala +++ b/src/main/scala/li/cil/oc/integration/cofh/energy/EventHandlerRedstoneFlux.scala @@ -1,5 +1,6 @@ package li.cil.oc.integration.cofh.energy +import li.cil.oc.Settings import li.cil.oc.api.event.RobotUsedToolEvent import net.minecraft.item.ItemStack @@ -28,4 +29,16 @@ object EventHandlerRedstoneFlux { case _ => Double.NaN } } + + def canCharge(stack: ItemStack): Boolean = stack.getItem match { + case chargeable: IEnergyContainerItem => chargeable.getMaxEnergyStored(stack) > 0 + case _ => false + } + + def charge(stack: ItemStack, amount: Double, simulate: Boolean): Double = { + stack.getItem match { + case item: IEnergyContainerItem => amount - item.receiveEnergy(stack, (amount * Settings.get.ratioRedstoneFlux).toInt, simulate) / Settings.get.ratioRedstoneFlux + case _ => amount + } + } } diff --git a/src/main/scala/li/cil/oc/integration/cofh/energy/ModCoFHEnergy.scala b/src/main/scala/li/cil/oc/integration/cofh/energy/ModCoFHEnergy.scala index c10ebae1a..5ccfe31f4 100644 --- a/src/main/scala/li/cil/oc/integration/cofh/energy/ModCoFHEnergy.scala +++ b/src/main/scala/li/cil/oc/integration/cofh/energy/ModCoFHEnergy.scala @@ -6,6 +6,7 @@ import cpw.mods.fml.common.versioning.VersionRange import li.cil.oc.api.Driver import li.cil.oc.integration.ModProxy import li.cil.oc.integration.Mods +import net.minecraft.nbt.NBTTagCompound import net.minecraftforge.common.MinecraftForge import scala.collection.convert.WrapAsScala._ @@ -17,6 +18,11 @@ object ModCoFHEnergy extends ModProxy { override def initialize() { FMLInterModComms.sendMessage(Mods.IDs.OpenComputers, "registerToolDurabilityProvider", "li.cil.oc.integration.cofh.energy.EventHandlerRedstoneFlux.getDurability") + val chargerNbt = new NBTTagCompound() + chargerNbt.setString("name", "RedstoneFlux") + chargerNbt.setString("canCharge", "li.cil.oc.integration.cofh.energy.EventHandlerRedstoneFlux.canCharge") + chargerNbt.setString("charge", "li.cil.oc.integration.cofh.energy.EventHandlerRedstoneFlux.charge") + FMLInterModComms.sendMessage(Mods.IDs.OpenComputers, "registerItemCharge", chargerNbt) MinecraftForge.EVENT_BUS.register(EventHandlerRedstoneFlux) diff --git a/src/main/scala/li/cil/oc/integration/ic2/EventHandlerIndustrialCraft2.scala b/src/main/scala/li/cil/oc/integration/ic2/EventHandlerIndustrialCraft2.scala index 3fbbc3e1e..52f345cbd 100644 --- a/src/main/scala/li/cil/oc/integration/ic2/EventHandlerIndustrialCraft2.scala +++ b/src/main/scala/li/cil/oc/integration/ic2/EventHandlerIndustrialCraft2.scala @@ -1,5 +1,6 @@ package li.cil.oc.integration.ic2 +import li.cil.oc.Settings import li.cil.oc.api.event.RobotUsedToolEvent import net.minecraft.entity.player.EntityPlayer import net.minecraft.item.ItemStack @@ -52,4 +53,20 @@ object EventHandlerIndustrialCraft2 { case _ => false } } + + def canCharge(stack: ItemStack): Boolean = stack.getItem match { + case chargeable: IElectricItem => chargeable.getMaxCharge(stack) > 0 + case _ => false + } + + def charge(stack: ItemStack, amount: Double, simulate: Boolean): Double = { + (stack.getItem match { + case item: ISpecialElectricItem => Option(item.getManager(stack)) + case item: IElectricItem => Option(ElectricItem.manager) + case _ => None + }) match { + case Some(manager) => amount - manager.charge(stack, amount * Settings.get.ratioIndustrialCraft2, Int.MaxValue, true, false) / Settings.get.ratioIndustrialCraft2 + case _ => amount + } + } } diff --git a/src/main/scala/li/cil/oc/integration/ic2/ModIndustrialCraft2.scala b/src/main/scala/li/cil/oc/integration/ic2/ModIndustrialCraft2.scala index 00026997e..45d7add71 100644 --- a/src/main/scala/li/cil/oc/integration/ic2/ModIndustrialCraft2.scala +++ b/src/main/scala/li/cil/oc/integration/ic2/ModIndustrialCraft2.scala @@ -4,6 +4,7 @@ import cpw.mods.fml.common.event.FMLInterModComms import li.cil.oc.api.Driver import li.cil.oc.integration.ModProxy import li.cil.oc.integration.Mods +import net.minecraft.nbt.NBTTagCompound import net.minecraftforge.common.MinecraftForge object ModIndustrialCraft2 extends ModProxy { @@ -12,6 +13,11 @@ object ModIndustrialCraft2 extends ModProxy { override def initialize() { FMLInterModComms.sendMessage(Mods.IDs.OpenComputers, "registerToolDurabilityProvider", "li.cil.oc.integration.ic2.EventHandlerIndustrialCraft2.getDurability") FMLInterModComms.sendMessage(Mods.IDs.OpenComputers, "registerWrenchTool", "li.cil.oc.integration.ic2.EventHandlerIndustrialCraft2.useWrench") + val chargerNbt = new NBTTagCompound() + chargerNbt.setString("name", "IndustrialCraft2") + chargerNbt.setString("canCharge", "li.cil.oc.integration.ic2.EventHandlerIndustrialCraft2.canCharge") + chargerNbt.setString("charge", "li.cil.oc.integration.ic2.EventHandlerIndustrialCraft2.charge") + FMLInterModComms.sendMessage(Mods.IDs.OpenComputers, "registerItemCharge", chargerNbt) MinecraftForge.EVENT_BUS.register(EventHandlerIndustrialCraft2) diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverTablet.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverTablet.scala index 4a1689d16..2a66f61c1 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/DriverTablet.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverTablet.scala @@ -4,7 +4,10 @@ import li.cil.oc.Constants import li.cil.oc.Settings import li.cil.oc.api import li.cil.oc.api.driver.EnvironmentHost +import li.cil.oc.api.network.Component +import li.cil.oc.api.network.Visibility import li.cil.oc.common.Slot +import li.cil.oc.common.item.Tablet import li.cil.oc.common.item.data.TabletData import net.minecraft.item.ItemStack import net.minecraft.nbt.NBTTagCompound @@ -15,10 +18,20 @@ object DriverTablet extends Item { api.Items.get(Constants.ItemName.Tablet)) override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = { + Tablet.Server.cache.invalidate(Tablet.getId(stack)) val data = new TabletData(stack) data.items.collect { case Some(fs) if DriverFileSystem.worksWith(fs) => fs - }.headOption.map(DriverFileSystem.createEnvironment(_, host)).orNull + }.headOption.map(DriverFileSystem.createEnvironment(_, host)) match { + case Some(environment) => environment.node match { + case component: Component => + component.setVisibility(Visibility.Network) + environment.save(dataTag(stack)) + environment + case _ => null + } + case _ => null + } } override def slot(stack: ItemStack) = Slot.Tablet diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala b/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala index c5ed0c1ab..45b96b960 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala @@ -5,6 +5,7 @@ import li.cil.oc.OpenComputers import li.cil.oc.Settings import li.cil.oc.api import li.cil.oc.api.detail.ItemInfo +import li.cil.oc.api.driver.item.Chargeable import li.cil.oc.api.internal import li.cil.oc.api.internal.Wrench import li.cil.oc.api.manual.PathProvider @@ -56,6 +57,11 @@ object ModOpenComputers extends ModProxy { TemplateBlacklist.register() FMLInterModComms.sendMessage(Mods.IDs.OpenComputers, "registerWrenchTool", "li.cil.oc.integration.opencomputers.ModOpenComputers.useWrench") + val chargerNbt = new NBTTagCompound() + chargerNbt.setString("name", "OpenComputers") + chargerNbt.setString("canCharge", "li.cil.oc.integration.opencomputers.ModOpenComputers.canCharge") + chargerNbt.setString("charge", "li.cil.oc.integration.opencomputers.ModOpenComputers.charge") + FMLInterModComms.sendMessage(Mods.IDs.OpenComputers, "registerItemCharge", chargerNbt) ForgeChunkManager.setForcedChunkLoadingCallback(OpenComputers, ChunkloaderUpgradeHandler) @@ -227,6 +233,18 @@ object ModOpenComputers extends ModProxy { } } + def canCharge(stack: ItemStack): Boolean = stack.getItem match { + case chargeable: Chargeable => chargeable.canCharge(stack) + case _ => false + } + + def charge(stack: ItemStack, amount: Double, simulate: Boolean): Double = { + stack.getItem match { + case chargeable: Chargeable => chargeable.charge(stack, amount, simulate) + case _ => 0.0 + } + } + private def blacklistHost(host: Class[_], itemNames: String*) { for (itemName <- itemNames) { val nbt = new NBTTagCompound() diff --git a/src/main/scala/li/cil/oc/integration/util/ItemCharge.scala b/src/main/scala/li/cil/oc/integration/util/ItemCharge.scala new file mode 100644 index 000000000..22421d78b --- /dev/null +++ b/src/main/scala/li/cil/oc/integration/util/ItemCharge.scala @@ -0,0 +1,24 @@ +package li.cil.oc.integration.util + +import java.lang.reflect.Method + +import li.cil.oc.common.IMC +import net.minecraft.item.ItemStack + +import scala.collection.mutable + +object ItemCharge { + private val chargers = mutable.LinkedHashSet.empty[(Method, Method)] + + def add(canCharge: Method, charge: Method): Unit = chargers += ((canCharge, charge)) + + def canCharge(stack: ItemStack): Boolean = stack != null && chargers.exists(charger => IMC.tryInvokeStatic(charger._1, stack)(false)) + + def charge(stack: ItemStack, amount: Double): Double = { + if (stack != null) chargers.find(charger => IMC.tryInvokeStatic(charger._1, stack)(false)) match { + case Some(charger) => IMC.tryInvokeStatic(charger._2, stack, double2Double(amount), java.lang.Boolean.FALSE)(0.0) + case _ => 0.0 + } + else 0.0 + } +} diff --git a/src/main/scala/li/cil/oc/server/component/Server.scala b/src/main/scala/li/cil/oc/server/component/Server.scala index c7b792a2e..eb8faea29 100644 --- a/src/main/scala/li/cil/oc/server/component/Server.scala +++ b/src/main/scala/li/cil/oc/server/component/Server.scala @@ -39,7 +39,7 @@ class Server(val rack: tileentity.ServerRack, val slot: Int) extends Environment // ----------------------------------------------------------------------- // override def internalComponents(): Iterable[ItemStack] = (0 until inventory.getSizeInventory).collect { - case i if inventory.isComponentSlot(i) && inventory.getStackInSlot(i) != null => inventory.getStackInSlot(i) + case i if inventory.getStackInSlot(i) != null && inventory.isComponentSlot(i, inventory.getStackInSlot(i)) => inventory.getStackInSlot(i) } override def componentSlot(address: String) = inventory.components.indexWhere(_.exists(env => env.node != null && env.node.address == address))