Made driver lookup available in the API.

This commit is contained in:
Florian Nücke 2014-05-02 13:17:16 +02:00
parent 2cea730d3d
commit e1eaeb0e60
12 changed files with 148 additions and 99 deletions

View File

@ -4,6 +4,8 @@ import li.cil.oc.api.detail.DriverAPI;
import li.cil.oc.api.driver.Block;
import li.cil.oc.api.driver.Converter;
import li.cil.oc.api.driver.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
/**
* This API allows registering new drivers with the mod.
@ -68,6 +70,43 @@ public final class Driver {
instance.add(converter);
}
/**
* Looks up a driver for the block at the specified position in the
* specified world.
* <p/>
* Note that several drivers for a single block can exist. Because of this
* block drivers are always encapsulated in a 'compound' driver, which is
* what will be returned here. In other words, you should will <em>not</em>
* get actual instances of drivers registered via {@link #add(li.cil.oc.api.driver.Block)}.
*
* @param world the world containing the block.
* @param x the X coordinate of the block.
* @param y the Y coordinate of the block.
* @param z the Z coordinate of the block.
* @return a driver for the block, or <tt>null</tt> if there is none.
*/
public static Block driverFor(World world, int x, int y, int z) {
if (instance != null)
return instance.driverFor(world, x, y, z);
return null;
}
/**
* Looks up a driver for the specified item stack.
* <p/>
* Note that unlike for blocks, there can always only be one item driver
* per item. If there are multiple ones, the first one that was registered
* will be used.
*
* @param stack the item stack to get a driver for.
* @return a driver for the item, or <tt>null</tt> if there is none.
*/
public static Item driverFor(ItemStack stack) {
if (instance != null)
return instance.driverFor(stack);
return null;
}
// ----------------------------------------------------------------------- //
private Driver() {

View File

@ -3,6 +3,8 @@ package li.cil.oc.api.detail;
import li.cil.oc.api.driver.Block;
import li.cil.oc.api.driver.Converter;
import li.cil.oc.api.driver.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
public interface DriverAPI {
/**
@ -44,4 +46,33 @@ public interface DriverAPI {
* @param converter the converter to register.
*/
void add(Converter converter);
/**
* Looks up a driver for the block at the specified position in the
* specified world.
* <p/>
* Note that several drivers for a single block can exist. Because of this
* block drivers are always encapsulated in a 'compound' driver, which is
* what will be returned here. In other words, you should will <em>not</em>
* get actual instances of drivers registered via {@link #add(li.cil.oc.api.driver.Block)}.
*
* @param world the world containing the block.
* @param x the X coordinate of the block.
* @param y the Y coordinate of the block.
* @param z the Z coordinate of the block.
* @return a driver for the block, or <tt>null</tt> if there is none.
*/
Block driverFor(World world, int x, int y, int z);
/**
* Looks up a driver for the specified item stack.
* <p/>
* Note that unlike for blocks, there can always only be one item driver
* per item. If there are multiple ones, the first one that was registered
* will be used.
*
* @param stack the item stack to get a driver for.
* @return a driver for the item, or <tt>null</tt> if there is none.
*/
Item driverFor(ItemStack stack);
}

View File

@ -1,7 +1,6 @@
package li.cil.oc
import cpw.mods.fml.common.ICraftingHandler
import li.cil.oc.server.driver.Registry
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.inventory.IInventory
import net.minecraft.item.{Item, ItemStack}
@ -35,8 +34,7 @@ object CraftingHandler extends ICraftingHandler {
}
if (api.Items.get(craftedStack) == navigationUpgrade) {
Registry.itemDriverFor(craftedStack) match {
case Some(driver) =>
Option(api.Driver.driverFor(craftedStack)).foreach(driver =>
for (i <- 0 until inventory.getSizeInventory) {
val stack = inventory.getStackInSlot(i)
if (stack != null && api.Items.get(stack) == navigationUpgrade) {
@ -47,9 +45,7 @@ object CraftingHandler extends ICraftingHandler {
player.dropPlayerItemWithRandomChoice(map, false)
}
}
}
case _ =>
}
})
}
}

View File

@ -2,10 +2,10 @@ package li.cil.oc.common.inventory
import java.util.logging.Level
import li.cil.oc.OpenComputers
import li.cil.oc.api.Driver
import li.cil.oc.api.driver.{Item => ItemDriver}
import li.cil.oc.api.network
import li.cil.oc.api.network.{Node, ManagedEnvironment}
import li.cil.oc.server.driver.Registry
import li.cil.oc.server.driver.item.Item
import net.minecraft.item.ItemStack
import net.minecraft.nbt.{NBTBase, NBTTagCompound}
@ -37,13 +37,14 @@ trait ComponentInventory extends Inventory with network.Environment {
for ((stack, slot) <- items.zipWithIndex collect {
case (Some(stack), slot) if slot >= 0 && slot < components.length => (stack, slot)
} if components(slot).isEmpty && isComponentSlot(slot)) {
components(slot) = Registry.itemDriverFor(stack) match {
components(slot) = Option(Driver.driverFor(stack)) match {
case Some(driver) =>
Option(driver.createEnvironment(stack, componentContainer)) match {
case Some(component) =>
try {
component.load(dataTag(driver, stack))
} catch {
}
catch {
case e: Throwable => OpenComputers.log.log(Level.WARNING, "An item component of type '%s' (provided by driver '%s') threw an error while loading.".format(component.getClass.getName, driver.getClass.getName), e)
}
if (component.canUpdate) {
@ -76,7 +77,7 @@ trait ComponentInventory extends Inventory with network.Environment {
case (stack, slot) => components(slot) match {
case Some(component) =>
// We're guaranteed to have a driver for entries.
save(component, Registry.itemDriverFor(stack).get, stack)
save(component, Driver.driverFor(stack), stack)
case _ => // Nothing special to save.
}
}
@ -88,8 +89,8 @@ trait ComponentInventory extends Inventory with network.Environment {
override def getInventoryStackLimit = 1
override protected def onItemAdded(slot: Int, stack: ItemStack) = if (isComponentSlot(slot)) {
Registry.itemDriverFor(stack) match {
case Some(driver) => Option(driver.createEnvironment(stack, componentContainer)) match {
Option(Driver.driverFor(stack)).foreach(driver =>
Option(driver.createEnvironment(stack, componentContainer)) match {
case Some(component) => this.synchronized {
components(slot) = Some(component)
try {
@ -105,9 +106,7 @@ trait ComponentInventory extends Inventory with network.Environment {
save(component, driver, stack)
}
case _ => // No environment (e.g. RAM).
}
case _ => // No driver.
}
})
}
override protected def onItemRemoved(slot: Int, stack: ItemStack) {
@ -121,7 +120,7 @@ trait ComponentInventory extends Inventory with network.Environment {
components(slot) = None
updatingComponents -= component
component.node.remove()
Registry.itemDriverFor(stack).foreach(driver => save(component, driver, stack))
Option(Driver.driverFor(stack)).foreach(save(component, _, stack))
}
case _ => // Nothing to do.
}

View File

@ -1,10 +1,10 @@
package li.cil.oc.common.inventory
import li.cil.oc.Settings
import li.cil.oc.server.driver.Registry
import li.cil.oc.api.Driver
import li.cil.oc.common.InventorySlots
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack
import li.cil.oc.common.InventorySlots
trait ServerInventory extends ItemStackInventory {
def tier: Int
@ -22,10 +22,8 @@ trait ServerInventory extends ItemStackInventory {
override def isUseableByPlayer(player: EntityPlayer) = false
override def isItemValidForSlot(slot: Int, stack: ItemStack) =
Registry.itemDriverFor(stack) match {
case Some(driver) =>
Option(Driver.driverFor(stack)).fold(false)(driver => {
val provided = InventorySlots.server(tier)(slot)
driver.slot(stack) == provided.slot && driver.tier(stack) <= provided.tier
case _ => false // Invalid item.
}
})
}

View File

@ -1,12 +1,11 @@
package li.cil.oc.common.recipe
import net.minecraft.item.{Item, ItemStack}
import li.cil.oc.{Settings, api}
import li.cil.oc.server.driver.Registry
import li.cil.oc.util.ExtendedNBT._
import cpw.mods.fml.common.FMLCommonHandler
import java.util.UUID
import li.cil.oc.{Settings, api}
import li.cil.oc.util.ExtendedNBT._
import net.minecraft.inventory.InventoryCrafting
import net.minecraft.item.{Item, ItemStack}
object ExtendedRecipe {
private lazy val navigationUpgrade = api.Items.get("navigationUpgrade")
@ -14,8 +13,7 @@ object ExtendedRecipe {
def addNBTToResult(craftedStack: ItemStack, inventory: InventoryCrafting) = {
if (api.Items.get(craftedStack) == navigationUpgrade) {
Registry.itemDriverFor(craftedStack) match {
case Some(driver) =>
Option(api.Driver.driverFor(craftedStack)).foreach(driver =>
for (i <- 0 until inventory.getSizeInventory) {
val stack = inventory.getStackInSlot(i)
if (stack != null && stack.getItem == Item.map) {
@ -23,18 +21,14 @@ object ExtendedRecipe {
val nbt = driver.dataTag(craftedStack)
nbt.setNewCompoundTag(Settings.namespace + "map", stack.writeToNBT)
}
}
case _ =>
}
})
}
if (api.Items.get(craftedStack) == linkedCard && FMLCommonHandler.instance.getEffectiveSide.isServer) {
Registry.itemDriverFor(craftedStack) match {
case Some(driver) =>
Option(api.Driver.driverFor(craftedStack)).foreach(driver => {
val nbt = driver.dataTag(craftedStack)
nbt.setString(Settings.namespace + "tunnel", UUID.randomUUID().toString)
case _ =>
}
})
}
craftedStack

View File

@ -47,7 +47,7 @@ class Adapter extends traits.Environment with Analyzable {
// but the only 'downside' is that it can't be used to manipulate
// inventories, which I actually consider a plus :P
case _ =>
driver.Registry.blockDriverFor(world, x, y, z) match {
Option(api.Driver.driverFor(world, x, y, z)) match {
case Some(newDriver) => blocks(d.ordinal()) match {
case Some((oldEnvironment, driver)) =>
if (newDriver != driver) {

View File

@ -1,10 +1,9 @@
package li.cil.oc.common.tileentity
import cpw.mods.fml.relauncher.{SideOnly, Side}
import li.cil.oc.api.driver
import li.cil.oc.api.{Driver, driver}
import li.cil.oc.api.driver.Slot
import li.cil.oc.api.network.Connector
import li.cil.oc.server.driver.Registry
import li.cil.oc.Settings
import li.cil.oc.util.Color
import net.minecraft.entity.player.EntityPlayer
@ -29,7 +28,7 @@ class Case(var tier: Int, val isRemote: Boolean) extends traits.PowerAcceptor wi
def recomputeMaxComponents() {
maxComponents = items.foldLeft(0)((sum, stack) => sum + (stack match {
case Some(item) => Registry.itemDriverFor(item) match {
case Some(item) => Option(Driver.driverFor(item)) match {
case Some(driver: driver.Processor) => driver.supportedComponents(item)
case _ => 0
}
@ -38,7 +37,7 @@ class Case(var tier: Int, val isRemote: Boolean) extends traits.PowerAcceptor wi
}
override def installedMemory = items.foldLeft(0)((sum, stack) => sum + (stack match {
case Some(item) => Registry.itemDriverFor(item) match {
case Some(item) => Option(Driver.driverFor(item)) match {
case Some(driver: driver.Memory) => driver.amount(item)
case _ => 0
}
@ -46,7 +45,7 @@ class Case(var tier: Int, val isRemote: Boolean) extends traits.PowerAcceptor wi
}))
def hasCPU = items.exists {
case Some(stack) => Registry.itemDriverFor(stack) match {
case Some(stack) => Option(Driver.driverFor(stack)) match {
case Some(driver) => driver.slot(stack) == Slot.Processor
case _ => false
}
@ -102,10 +101,8 @@ class Case(var tier: Int, val isRemote: Boolean) extends traits.PowerAcceptor wi
}
override def isItemValidForSlot(slot: Int, stack: ItemStack) =
Registry.itemDriverFor(stack) match {
case Some(driver) =>
Option(Driver.driverFor(stack)).fold(false)(driver => {
val provided = InventorySlots.computer(tier)(slot)
driver.slot(stack) == provided.slot && driver.tier(stack) <= provided.tier
case _ => false // Invalid item.
}
})
}

View File

@ -1,9 +1,9 @@
package li.cil.oc.common.tileentity
import li.cil.oc.api.Driver
import li.cil.oc.api.driver.Slot
import li.cil.oc.api.network.{Analyzable, Component, Visibility}
import li.cil.oc.common.Sound
import li.cil.oc.server.driver.Registry
import li.cil.oc.{api, Settings}
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack
@ -27,7 +27,7 @@ class DiskDrive extends traits.Environment with traits.ComponentInventory with t
override def getSizeInventory = 1
override def isItemValidForSlot(slot: Int, stack: ItemStack) = (slot, Registry.itemDriverFor(stack)) match {
override def isItemValidForSlot(slot: Int, stack: ItemStack) = (slot, Option(Driver.driverFor(stack))) match {
case (0, Some(driver)) => driver.slot(stack) == Slot.Disk
case _ => false
}

View File

@ -3,12 +3,12 @@ package li.cil.oc.common.tileentity
import cpw.mods.fml.relauncher.{SideOnly, Side}
import java.util.logging.Level
import li.cil.oc._
import li.cil.oc.api.Driver
import li.cil.oc.api.driver.Slot
import li.cil.oc.api.network._
import li.cil.oc.common.block.Delegator
import li.cil.oc.server.component.GraphicsCard
import li.cil.oc.server.component.robot
import li.cil.oc.server.driver.Registry
import li.cil.oc.server.{PacketSender => ServerPacketSender, driver, component}
import li.cil.oc.util.ExtendedNBT._
import net.minecraft.block.{BlockFlowing, Block}
@ -61,7 +61,7 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.TextBuffe
case Some(environment) =>
val stack = getStackInSlot(3)
// We're guaranteed to have a driver for entries.
environment.save(dataTag(Registry.itemDriverFor(stack).get, stack))
environment.save(dataTag(Driver.driverFor(stack), stack))
ServerPacketSender.sendRobotEquippedUpgradeChange(this, stack)
case _ =>
}
@ -452,7 +452,7 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.TextBuffe
case Some(environment) =>
val stack = getStackInSlot(3)
// We're guaranteed to have a driver for entries.
environment.save(dataTag(Registry.itemDriverFor(stack).get, stack))
environment.save(dataTag(Driver.driverFor(stack), stack))
case _ => // See onConnect()
}
nbt.setNewCompoundTag("upgrade", getStackInSlot(3).writeToNBT)
@ -557,7 +557,7 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.TextBuffe
// ----------------------------------------------------------------------- //
override def installedMemory = Settings.get.ramSizes(1) * 1024 + (items(3) match {
case Some(stack) => Registry.itemDriverFor(stack) match {
case Some(stack) => Option(Driver.driverFor(stack)) match {
case Some(driver: api.driver.Memory) => driver.amount(stack)
case _ => 0
}
@ -601,7 +601,7 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.TextBuffe
case _ => false
}
override def isItemValidForSlot(slot: Int, stack: ItemStack) = (slot, Registry.itemDriverFor(stack)) match {
override def isItemValidForSlot(slot: Int, stack: ItemStack) = (slot, Option(Driver.driverFor(stack))) match {
case (0, _) => true // Allow anything in the tool slot.
case (1, Some(driver)) => driver.slot(stack) == Slot.Card && driver.tier(stack) < 2
case (2, Some(driver)) => driver.slot(stack) == Slot.Disk

View File

@ -4,7 +4,7 @@ import li.cil.oc.Items
import li.cil.oc.api.driver.Slot
import li.cil.oc.api.machine.Owner
import li.cil.oc.api.network.{Message, Node}
import li.cil.oc.api.{Machine, driver}
import li.cil.oc.api.{Driver, Machine, driver}
import li.cil.oc.common.inventory.ComponentInventory
import li.cil.oc.common.inventory.ServerInventory
import li.cil.oc.common.item
@ -45,7 +45,7 @@ class Server(val rack: tileentity.Rack, val number: Int) extends Owner {
// ----------------------------------------------------------------------- //
override def installedMemory = inventory.items.foldLeft(0)((sum, stack) => sum + (stack match {
case Some(item) => Registry.itemDriverFor(item) match {
case Some(item) => Option(Driver.driverFor(item)) match {
case Some(driver: driver.Memory) => driver.amount(item)
case _ => 0
}
@ -53,7 +53,7 @@ class Server(val rack: tileentity.Rack, val number: Int) extends Owner {
}))
lazy val maxComponents = inventory.items.foldLeft(0)((sum, stack) => sum + (stack match {
case Some(item) => Registry.itemDriverFor(item) match {
case Some(item) => Option(Driver.driverFor(item)) match {
case Some(driver: driver.Processor) => driver.supportedComponents(item)
case _ => 0
}
@ -61,7 +61,7 @@ class Server(val rack: tileentity.Rack, val number: Int) extends Owner {
}))
def hasCPU = inventory.items.exists {
case Some(stack) => Registry.itemDriverFor(stack) match {
case Some(stack) => Option(Driver.driverFor(stack)) match {
case Some(driver) => driver.slot(stack) == Slot.Processor
case _ => false
}

View File

@ -49,20 +49,15 @@ private[oc] object Registry extends api.detail.DriverAPI {
if (!converters.contains(converter)) converters += converter
}
// TODO Move this into the API?
def blockDriverFor(world: World, x: Int, y: Int, z: Int) =
def driverFor(world: World, x: Int, y: Int, z: Int) =
blocks.filter(_.worksWith(world, x, y, z)) match {
case drivers if !drivers.isEmpty => Some(new CompoundBlockDriver(drivers: _*))
case _ => None
case drivers if !drivers.isEmpty => new CompoundBlockDriver(drivers: _*)
case _ => null
}
// TODO Move this into the API?
def itemDriverFor(stack: ItemStack) =
if (stack != null) items.find(_.worksWith(stack)) match {
case None => None
case Some(driver) => Some(driver)
}
else None
def driverFor(stack: ItemStack) =
if (stack != null) items.find(_.worksWith(stack)).orNull
else null
def convert(value: Array[AnyRef]) = if (value != null) value.map(convertRecursively) else null