From 62e54377b637f18cc77221b4ebe96b3d05d7fac2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Fri, 24 Apr 2015 17:22:24 +0200 Subject: [PATCH 1/2] Made charger more generic to allow charging addon items. Also allow charging battery upgrades in the charger now. Specifically, added `Chargeable` interface that can be implemented on items. This is what's used to actually charge items. This way the charger is also to (very slowly) charge items from other mods; built-in integration for now is for IEnergyContainerItem (CoFH) and IElectricItem (IC2). Addon items can also provide an environment to be connected to the charger's network by providing an item driver that generates such an environment and has the slot type `Tablet`. --- src/main/java/li/cil/oc/api/API.java | 2 +- .../li/cil/oc/api/driver/item/Chargeable.java | 34 +++++++++ src/main/scala/li/cil/oc/common/IMC.scala | 10 +++ .../common/inventory/ComponentInventory.scala | 6 +- .../li/cil/oc/common/item/Delegator.scala | 17 ++++- .../scala/li/cil/oc/common/item/Tablet.scala | 19 ++++- .../cil/oc/common/item/UpgradeBattery.scala | 30 ++++++-- .../li/cil/oc/common/item/data/NodeData.scala | 45 +++++++++++ .../li/cil/oc/common/tileentity/Charger.scala | 76 +++++++++---------- .../li/cil/oc/common/tileentity/Robot.scala | 16 ++-- .../traits/ComponentInventory.scala | 3 +- .../common/tileentity/traits/Computer.scala | 2 +- .../energy/EventHandlerRedstoneFlux.scala | 13 ++++ .../cofh/energy/ModCoFHEnergy.scala | 6 ++ .../ic2/EventHandlerIndustrialCraft2.scala | 17 +++++ .../integration/ic2/ModIndustrialCraft2.scala | 6 ++ .../opencomputers/DriverTablet.scala | 15 +++- .../opencomputers/ModOpenComputers.scala | 18 +++++ .../cil/oc/integration/util/ItemCharge.scala | 24 ++++++ .../li/cil/oc/server/component/Server.scala | 2 +- 20 files changed, 295 insertions(+), 66 deletions(-) create mode 100644 src/main/java/li/cil/oc/api/driver/item/Chargeable.java create mode 100644 src/main/scala/li/cil/oc/common/item/data/NodeData.scala create mode 100644 src/main/scala/li/cil/oc/integration/util/ItemCharge.scala 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 3e3fe7654..7f491004f 100644 --- a/src/main/scala/li/cil/oc/common/IMC.scala +++ b/src/main/scala/li/cil/oc/common/IMC.scala @@ -9,6 +9,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 @@ -56,6 +57,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/inventory/ComponentInventory.scala b/src/main/scala/li/cil/oc/common/inventory/ComponentInventory.scala index db4ffd005..cb401cc1b 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 87e9a371e..b792a7c2e 100644 --- a/src/main/scala/li/cil/oc/common/item/Delegator.scala +++ b/src/main/scala/li/cil/oc/common/item/Delegator.scala @@ -9,6 +9,7 @@ import li.cil.oc.CreativeTab import li.cil.oc.OpenComputers import li.cil.oc.Settings 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) setUnlocalizedName("oc.multi") @@ -254,6 +255,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 419b3068c..b98af7faa 100644 --- a/src/main/scala/li/cil/oc/common/item/Tablet.scala +++ b/src/main/scala/li/cil/oc/common/item/Tablet.scala @@ -21,6 +21,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 @@ -51,7 +52,7 @@ import net.minecraftforge.event.world.WorldEvent import scala.collection.convert.WrapAsJava._ import scala.collection.convert.WrapAsScala._ -class Tablet(val parent: Delegator) extends Delegate { +class Tablet(val parent: Delegator) extends Delegate with Chargeable { final val TimeToAnalyze = 10 // Must be assembled to be usable so we hide it in the item list. @@ -122,6 +123,20 @@ class Tablet(val parent: Delegator) extends Delegate { // ----------------------------------------------------------------------- // + 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 => @@ -346,7 +361,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 5c3ced242..8c9f07ea6 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,13 +15,27 @@ class UpgradeBattery(val parent: Delegator, val tier: Int) extends Delegate with override def isDamageable = true override def damage(stack: ItemStack) = { - val nbt = stack.getTagCompound - if (nbt != null) { - val stored = nbt.getCompoundTag(Settings.namespace + "data").getCompoundTag("node").getDouble("buffer") - ((1 - stored / Settings.get.bufferCapacitorUpgrades(tier)) * 100).toInt - } - else 100 + val data = new NodeData(stack) + ((1 - data.buffer.getOrElse(0.0) / Settings.get.bufferCapacitorUpgrades(tier)) * 100).toInt } override def maxDamage(stack: ItemStack) = 100 + + // ----------------------------------------------------------------------- // + + 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 + } + 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 ef41f4c10..b4fdb344e 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Charger.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Charger.scala @@ -11,8 +11,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._ @@ -74,8 +73,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 + var canCharge = false + + // 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) @@ -84,28 +107,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) { @@ -159,22 +160,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) } // ----------------------------------------------------------------------- // @@ -208,7 +204,7 @@ class Charger extends traits.Environment with traits.PowerAcceptor with traits.R } // Only update list when we have to, keeps pointless block updates to a minimum. - if (connectors.size != robotConnectors.size + droneConnectors.size || (connectors.size > 0 && connectors.map(_._2).diff((robotConnectors ++ droneConnectors).map(_._2).toSet).size > 0)) { + if (connectors.size != robotConnectors.length + droneConnectors.size || (connectors.size > 0 && connectors.map(_._2).diff((robotConnectors ++ droneConnectors).map(_._2).toSet).size > 0)) { connectors.clear() connectors ++= robotConnectors connectors ++= droneConnectors 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 4c1d23e00..0da64046e 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Robot.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Robot.scala @@ -562,7 +562,7 @@ class Robot extends traits.Computer with traits.PowerInformation with IFluidHand if (isFloppySlot(slot)) { common.Sound.playDiskInsert(this) } - if (isComponentSlot(slot)) { + if (isComponentSlot(slot, stack)) { super.onItemAdded(slot, stack) world.notifyBlocksOfNeighborChange(x, y, z, getBlockType) } @@ -588,7 +588,7 @@ class Robot extends traits.Computer with traits.PowerInformation with IFluidHand if (isInventorySlot(slot)) { machine.signal("inventory_changed", Int.box(slot - equipmentInventory.getSizeInventory + 1)) } - if (isComponentSlot(slot)) { + if (isComponentSlot(slot, stack)) { world.notifyBlocksOfNeighborChange(x, y, z, getBlockType) } } @@ -634,7 +634,7 @@ class Robot extends traits.Computer with traits.PowerInformation with IFluidHand } } - 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) @@ -660,13 +660,13 @@ class Robot extends traits.Computer with traits.PowerInformation with IFluidHand 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 @@ -734,7 +734,7 @@ class Robot extends traits.Computer with traits.PowerInformation with IFluidHand 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) 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 df36348af..a452da75b 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 @@ -4,12 +4,13 @@ import cpw.mods.fml.relauncher.Side import cpw.mods.fml.relauncher.SideOnly import li.cil.oc.api.network.Node import li.cil.oc.common.inventory +import net.minecraft.item.ItemStack import net.minecraft.nbt.NBTTagCompound 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 8e8d301bc..968cc5c86 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 @@ -74,7 +74,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) } override def installedComponents = components collect { 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 91e9406ae..eb4f82bce 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 @@ -2,6 +2,7 @@ package li.cil.oc.integration.cofh.energy import cofh.api.energy.IEnergyContainerItem import cpw.mods.fml.common.eventhandler.SubscribeEvent +import li.cil.oc.Settings import li.cil.oc.api.event.RobotUsedToolEvent import net.minecraft.item.ItemStack @@ -30,4 +31,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 9591b6e19..e2bb64843 100644 --- a/src/main/scala/li/cil/oc/integration/ic2/EventHandlerIndustrialCraft2.scala +++ b/src/main/scala/li/cil/oc/integration/ic2/EventHandlerIndustrialCraft2.scala @@ -5,6 +5,7 @@ import ic2.api.item.ElectricItem import ic2.api.item.IElectricItem import ic2.api.item.ISpecialElectricItem import ic2.core.item.tool.ItemToolWrench +import li.cil.oc.Settings import li.cil.oc.api.event.RobotUsedToolEvent import net.minecraft.entity.player.EntityPlayer import net.minecraft.item.ItemStack @@ -57,4 +58,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 d8c9c3225..47b520911 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala @@ -7,6 +7,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 @@ -55,6 +56,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) @@ -226,6 +232,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)) From 69ee8263e51c89888dd1f268b6f7154f4e5e5c9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Fri, 24 Apr 2015 17:22:58 +0200 Subject: [PATCH 2/2] Spawning OpenOS floppy in creative tablets in its container upgrade now. --- src/main/scala/li/cil/oc/common/init/Items.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 6e86c49f2..a61a5b81d 100644 --- a/src/main/scala/li/cil/oc/common/init/Items.scala +++ b/src/main/scala/li/cil/oc/common/init/Items.scala @@ -239,9 +239,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)