mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-16 10:51:55 -04:00
getRange callback for navigation upgrade to query area the upgrade works in; extended API for block drivers to allow querying for item stacks, used in adapter block to only allow adding filter for supported blocks
This commit is contained in:
parent
4d1f568db2
commit
aa682750d0
@ -32,7 +32,7 @@ object CraftingHandler extends ICraftingHandler {
|
||||
}
|
||||
|
||||
if (craftedStack.isItemEqual(Items.upgradeNavigation.createItemStack())) {
|
||||
Registry.driverFor(craftedStack) match {
|
||||
Registry.itemDriverFor(craftedStack) match {
|
||||
case Some(driver) =>
|
||||
var oldMap = None: Option[ItemStack]
|
||||
for (i <- 0 to inventory.getSizeInventory) {
|
||||
|
@ -4,7 +4,24 @@ import li.cil.oc.api.driver.Block;
|
||||
import li.cil.oc.api.driver.Item;
|
||||
|
||||
public interface DriverAPI {
|
||||
/**
|
||||
* Registers a new driver for a block component.
|
||||
* <p/>
|
||||
* Whenever the neighboring blocks of an Adapter block change, it checks if
|
||||
* there exists a driver for the changed block, and if it is configured to
|
||||
* interface that block type connects it to the component network.
|
||||
*
|
||||
* @param driver the driver for a block component.
|
||||
*/
|
||||
void add(Block driver);
|
||||
|
||||
/**
|
||||
* Registers a new driver for an item component.
|
||||
* <p/>
|
||||
* Item components can inserted into a computers component slots. They have
|
||||
* to specify their type, to determine into which slots they can fit.
|
||||
*
|
||||
* @param driver the driver for an item component.
|
||||
*/
|
||||
void add(Item driver);
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package li.cil.oc.api.driver;
|
||||
|
||||
import li.cil.oc.api.network.ManagedEnvironment;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
/**
|
||||
@ -39,6 +40,21 @@ public interface Block {
|
||||
*/
|
||||
boolean worksWith(World world, int x, int y, int z);
|
||||
|
||||
/**
|
||||
* Used to determine the block types this driver handles.
|
||||
* <p/>
|
||||
* This is used to determine whether there is a driver for the specified
|
||||
* block type when an Adapter block is being configured, i.e. when the
|
||||
* player tries to place an item into the adapter's GUI.
|
||||
* <p/>
|
||||
* Note that the passed item stacks are not necessarily item blocks, they
|
||||
* can be anything at all.
|
||||
*
|
||||
* @param stack the item stack to check.
|
||||
* @return <tt>true</tt> if the block is supported; <tt>false</tt> otherwise.
|
||||
*/
|
||||
boolean worksWith(ItemStack stack);
|
||||
|
||||
/**
|
||||
* Create a new managed environment interfacing the specified block.
|
||||
* <p/>
|
||||
|
@ -37,5 +37,5 @@
|
||||
@cpw.mods.fml.common.API(
|
||||
owner = "OpenComputers",
|
||||
provides = "OpenComputersAPI",
|
||||
apiVersion = "1.0.0")
|
||||
apiVersion = "1.1.0")
|
||||
package li.cil.oc.api;
|
@ -28,7 +28,7 @@ class Adapter extends Environment with Inventory {
|
||||
def neighborChanged() = if (node != null && node.network != null) {
|
||||
for (d <- ForgeDirection.VALID_DIRECTIONS) {
|
||||
val (x, y, z) = (this.x + d.offsetX, this.y + d.offsetY, this.z + d.offsetZ)
|
||||
driver.Registry.driverFor(world, x, y, z) match {
|
||||
driver.Registry.blockDriverFor(world, x, y, z) match {
|
||||
case Some(newDriver) => blocks(d.ordinal()) match {
|
||||
case Some((oldEnvironment, driver)) =>
|
||||
if (newDriver != driver || !isBlockSupported(x, y, z)) {
|
||||
@ -84,6 +84,11 @@ class Adapter extends Environment with Inventory {
|
||||
override def readFromNBT(nbt: NBTTagCompound) {
|
||||
super.readFromNBT(nbt)
|
||||
|
||||
items(0) match {
|
||||
case Some(stack) if driver.Registry.blockDriverFor(stack).isEmpty => setInventorySlotContents(0, null)
|
||||
case _ =>
|
||||
}
|
||||
|
||||
val blocksNbt = nbt.getTagList(Settings.namespace + "adapter.blocks")
|
||||
(0 until (blocksNbt.tagCount min blocksData.length)).
|
||||
map(blocksNbt.tagAt).
|
||||
@ -129,10 +134,7 @@ class Adapter extends Environment with Inventory {
|
||||
override def getInventoryStackRequired = 0
|
||||
|
||||
def isItemValidForSlot(i: Int, stack: ItemStack) =
|
||||
stack != null && stack.stackSize > 0 && (stack.getItem match {
|
||||
case block: ItemBlock => true
|
||||
case _ => false
|
||||
})
|
||||
stack != null && stack.stackSize > 0 && driver.Registry.blockDriverFor(stack).isDefined
|
||||
|
||||
override def onInventoryChanged() {
|
||||
super.onInventoryChanged()
|
||||
|
@ -41,21 +41,21 @@ class Case(var tier: Int, isRemote: Boolean) extends Computer(isRemote) {
|
||||
}
|
||||
|
||||
def isItemValidForSlot(slot: Int, stack: ItemStack) = tier match {
|
||||
case 0 => (slot, Registry.driverFor(stack)) match {
|
||||
case 0 => (slot, Registry.itemDriverFor(stack)) match {
|
||||
case (_, None) => false // Invalid item.
|
||||
case (0 | 1, Some(driver)) => driver.slot(stack) == Slot.Card
|
||||
case (2, Some(driver)) => driver.slot(stack) == Slot.Memory
|
||||
case (3, Some(driver)) => driver.slot(stack) == Slot.HardDiskDrive
|
||||
case _ => false // Invalid slot.
|
||||
}
|
||||
case 1 => (slot, Registry.driverFor(stack)) match {
|
||||
case 1 => (slot, Registry.itemDriverFor(stack)) match {
|
||||
case (_, None) => false // Invalid item.
|
||||
case (0 | 1, Some(driver)) => driver.slot(stack) == Slot.Card
|
||||
case (2 | 3, Some(driver)) => driver.slot(stack) == Slot.Memory
|
||||
case (4 | 5, Some(driver)) => driver.slot(stack) == Slot.HardDiskDrive
|
||||
case _ => false // Invalid slot.
|
||||
}
|
||||
case 2 => (slot, Registry.driverFor(stack)) match {
|
||||
case 2 => (slot, Registry.itemDriverFor(stack)) match {
|
||||
case (_, None) => false // Invalid item.
|
||||
case (0 | 1 | 2, Some(driver)) => driver.slot(stack) == Slot.Card
|
||||
case (3 | 4, Some(driver)) => driver.slot(stack) == Slot.Memory
|
||||
|
@ -18,7 +18,7 @@ trait ComponentInventory extends Inventory with network.Environment { self: MCTi
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
def installedMemory = items.foldLeft(0)((sum, stack) => sum + (stack match {
|
||||
case Some(item) => Registry.driverFor(item) match {
|
||||
case Some(item) => Registry.itemDriverFor(item) match {
|
||||
case Some(driver: driver.Memory) => driver.amount(item)
|
||||
case _ => 0
|
||||
}
|
||||
@ -33,7 +33,7 @@ trait ComponentInventory extends Inventory with network.Environment { self: MCTi
|
||||
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.driverFor(stack) match {
|
||||
components(slot) = Registry.itemDriverFor(stack) match {
|
||||
case Some(driver) =>
|
||||
Option(driver.createEnvironment(stack, this)) match {
|
||||
case Some(component) =>
|
||||
@ -72,7 +72,7 @@ trait ComponentInventory extends Inventory with network.Environment { self: MCTi
|
||||
case (stack, slot) => components(slot) match {
|
||||
case Some(environment) =>
|
||||
// We're guaranteed to have a driver for entries.
|
||||
environment.save(dataTag(Registry.driverFor(stack).get, stack))
|
||||
environment.save(dataTag(Registry.itemDriverFor(stack).get, stack))
|
||||
case _ => // Nothing special to save.
|
||||
}
|
||||
}
|
||||
@ -84,7 +84,7 @@ trait ComponentInventory extends Inventory with network.Environment { self: MCTi
|
||||
def getInventoryStackLimit = 1
|
||||
|
||||
override protected def onItemAdded(slot: Int, stack: ItemStack) = if (isServer && isComponentSlot(slot)) {
|
||||
Registry.driverFor(stack) match {
|
||||
Registry.itemDriverFor(stack) match {
|
||||
case Some(driver) => Option(driver.createEnvironment(stack, this)) match {
|
||||
case Some(component) => this.synchronized {
|
||||
components(slot) = Some(component)
|
||||
@ -113,7 +113,7 @@ trait ComponentInventory extends Inventory with network.Environment { self: MCTi
|
||||
components(slot) = None
|
||||
updatingComponents -= component
|
||||
component.node.remove()
|
||||
Registry.driverFor(stack).foreach(driver =>
|
||||
Registry.itemDriverFor(stack).foreach(driver =>
|
||||
component.save(dataTag(driver, stack)))
|
||||
}
|
||||
case _ => // Nothing to do.
|
||||
|
@ -28,7 +28,7 @@ class DiskDrive extends Environment with ComponentInventory with Rotatable with
|
||||
|
||||
def getSizeInventory = 1
|
||||
|
||||
def isItemValidForSlot(slot: Int, stack: ItemStack) = (slot, Registry.driverFor(stack)) match {
|
||||
def isItemValidForSlot(slot: Int, stack: ItemStack) = (slot, Registry.itemDriverFor(stack)) match {
|
||||
case (0, Some(driver)) => driver.slot(stack) == Slot.Disk
|
||||
case _ => false
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
|
||||
case Some(environment) =>
|
||||
val stack = getStackInSlot(3)
|
||||
// We're guaranteed to have a driver for entries.
|
||||
environment.save(dataTag(Registry.driverFor(stack).get, stack))
|
||||
environment.save(dataTag(Registry.itemDriverFor(stack).get, stack))
|
||||
ServerPacketSender.sendRobotEquippedUpgradeChange(this, stack)
|
||||
case _ =>
|
||||
}
|
||||
@ -383,7 +383,7 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
|
||||
case Some(environment) =>
|
||||
val stack = getStackInSlot(3)
|
||||
// We're guaranteed to have a driver for entries.
|
||||
environment.save(dataTag(Registry.driverFor(stack).get, stack))
|
||||
environment.save(dataTag(Registry.itemDriverFor(stack).get, stack))
|
||||
case _ => // See onConnect()
|
||||
}
|
||||
nbt.setNewCompoundTag("upgrade", getStackInSlot(3).writeToNBT)
|
||||
@ -516,7 +516,7 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
|
||||
case _ => false
|
||||
}
|
||||
|
||||
def isItemValidForSlot(slot: Int, stack: ItemStack) = (slot, Registry.driverFor(stack)) match {
|
||||
def isItemValidForSlot(slot: Int, stack: ItemStack) = (slot, Registry.itemDriverFor(stack)) match {
|
||||
case (0, _) => true // Allow anything in the tool slot.
|
||||
case (1, Some(driver)) => driver.slot(stack) == Slot.Card
|
||||
case (2, Some(driver)) => driver.slot(stack) == Slot.Disk
|
||||
|
@ -30,4 +30,9 @@ class UpgradeNavigation(val owner: MCTileEntity, val xCenter: Int, val zCenter:
|
||||
def getFacing(context: RobotContext, args: Arguments): Array[AnyRef] = {
|
||||
result(RotationHelper.fromYaw(context.player().rotationYaw).ordinal())
|
||||
}
|
||||
|
||||
@LuaCallback("getRange")
|
||||
def getRange(context: RobotContext, args: Arguments): Array[AnyRef] = {
|
||||
result(size / 2)
|
||||
}
|
||||
}
|
||||
|
@ -21,65 +21,36 @@ import scala.collection.mutable.ArrayBuffer
|
||||
* the computer, but may also provide context-free functions.
|
||||
*/
|
||||
private[oc] object Registry extends api.detail.DriverAPI {
|
||||
/** The list of registered block drivers. */
|
||||
private val blocks = ArrayBuffer.empty[api.driver.Block]
|
||||
|
||||
/** The list of registered item drivers. */
|
||||
private val items = ArrayBuffer.empty[api.driver.Item]
|
||||
|
||||
/** Used to keep track of whether we're past the init phase. */
|
||||
var locked = false
|
||||
|
||||
/**
|
||||
* Registers a new driver for a block component.
|
||||
*
|
||||
* Whenever the neighboring blocks of a computer change, it checks if there
|
||||
* exists a driver for the changed block, and if so installs it.
|
||||
*
|
||||
* @param driver the driver for that block type.
|
||||
*/
|
||||
def add(driver: api.driver.Block) {
|
||||
if (locked) throw new IllegalStateException("Please register all drivers in the init phase.")
|
||||
if (!blocks.contains(driver)) blocks += driver
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new driver for an item component.
|
||||
*
|
||||
* Item components can inserted into a computers component slots. They have
|
||||
* to specify their type, to determine into which slots they can fit.
|
||||
*
|
||||
* @param driver the driver for that item type.
|
||||
*/
|
||||
def add(driver: api.driver.Item) {
|
||||
if (locked) throw new IllegalStateException("Please register all drivers in the init phase.")
|
||||
if (!blocks.contains(driver)) items += driver
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when a new block is placed next to a computer to see if we have a
|
||||
* driver for it. If we have one, we'll return it.
|
||||
*
|
||||
* @param world the world in which the block to check lives.
|
||||
* @param x the X coordinate of the block to check.
|
||||
* @param y the Y coordinate of the block to check.
|
||||
* @param z the Z coordinate of the block to check.
|
||||
* @return the driver for that block if we have one.
|
||||
*/
|
||||
def driverFor(world: World, x: Int, y: Int, z: Int) =
|
||||
def blockDriverFor(world: World, x: Int, y: Int, z: Int) =
|
||||
blocks.find(_.worksWith(world, x, y, z)) match {
|
||||
case None => None
|
||||
case Some(driver) => Some(driver)
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when an item component is added to a computer to see if we have a
|
||||
* driver for it. If we have one, we'll return it.
|
||||
*
|
||||
* @param stack the type of item to check for a driver for.
|
||||
* @return the driver for that item type if we have one.
|
||||
*/
|
||||
def driverFor(stack: ItemStack) =
|
||||
def blockDriverFor(stack: ItemStack) =
|
||||
blocks.find(_.worksWith(stack)) match {
|
||||
case None => None
|
||||
case Some(driver) => Some(driver)
|
||||
}
|
||||
|
||||
def itemDriverFor(stack: ItemStack) =
|
||||
if (stack != null) items.find(_.worksWith(stack)) match {
|
||||
case None => None
|
||||
case Some(driver) => Some(driver)
|
||||
|
@ -4,6 +4,8 @@ import li.cil.oc.api.driver
|
||||
import li.cil.oc.server.component
|
||||
import li.cil.oc.util.mods.RedstoneInMotion
|
||||
import net.minecraft.world.World
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.item.ItemStack
|
||||
|
||||
object Carriage extends driver.Block {
|
||||
def worksWith(world: World, x: Int, y: Int, z: Int) =
|
||||
@ -12,6 +14,8 @@ object Carriage extends driver.Block {
|
||||
case _ => false
|
||||
}
|
||||
|
||||
def worksWith(stack: ItemStack) = RedstoneInMotion.isCarriageController(stack)
|
||||
|
||||
def createEnvironment(world: World, x: Int, y: Int, z: Int) =
|
||||
world.getBlockTileEntity(x, y, z) match {
|
||||
case entity if RedstoneInMotion.isCarriageController(entity) => new component.Carriage(entity)
|
||||
|
@ -3,6 +3,7 @@ package li.cil.oc.server.driver.block
|
||||
import li.cil.oc.api.driver
|
||||
import li.cil.oc.server.component
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.item.{ItemBlock, ItemStack}
|
||||
import net.minecraft.tileentity.TileEntityCommandBlock
|
||||
import net.minecraft.world.World
|
||||
|
||||
@ -10,6 +11,11 @@ object CommandBlock extends driver.Block {
|
||||
def worksWith(world: World, x: Int, y: Int, z: Int) =
|
||||
world.getBlockId(x, y, z) == Block.commandBlock.blockID
|
||||
|
||||
def worksWith(stack: ItemStack) = stack != null && (stack.getItem match {
|
||||
case itemBlock: ItemBlock => itemBlock.getBlockID == Block.commandBlock.blockID
|
||||
case _ => false
|
||||
})
|
||||
|
||||
def createEnvironment(world: World, x: Int, y: Int, z: Int) =
|
||||
world.getBlockTileEntity(x, y, z) match {
|
||||
case block: TileEntityCommandBlock => new component.CommandBlock(block)
|
||||
|
@ -3,6 +3,7 @@ package li.cil.oc.server.driver.block
|
||||
import li.cil.oc.api.driver
|
||||
import li.cil.oc.server.component
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.item.{ItemBlock, ItemStack}
|
||||
import net.minecraft.tileentity.TileEntityNote
|
||||
import net.minecraft.world.World
|
||||
|
||||
@ -10,6 +11,11 @@ object NoteBlock extends driver.Block {
|
||||
def worksWith(world: World, x: Int, y: Int, z: Int) =
|
||||
world.getBlockId(x, y, z) == Block.music.blockID
|
||||
|
||||
def worksWith(stack: ItemStack) = stack != null && (stack.getItem match {
|
||||
case itemBlock: ItemBlock => itemBlock.getBlockID == Block.music.blockID
|
||||
case _ => false
|
||||
})
|
||||
|
||||
def createEnvironment(world: World, x: Int, y: Int, z: Int) =
|
||||
world.getBlockTileEntity(x, y, z) match {
|
||||
case block: TileEntityNote => new component.NoteBlock(block)
|
||||
|
@ -11,7 +11,7 @@ object UpgradeNavigation extends Item {
|
||||
override def worksWith(stack: ItemStack) = isOneOf(stack, Items.upgradeNavigation)
|
||||
|
||||
override def createEnvironment(stack: ItemStack, container: MCTileEntity) = {
|
||||
val nbt = Registry.driverFor(stack) match {
|
||||
val nbt = Registry.itemDriverFor(stack) match {
|
||||
case Some(driver) => driver.dataTag(stack)
|
||||
case _ => null
|
||||
}
|
||||
|
@ -1,14 +1,17 @@
|
||||
package li.cil.oc.util.mods
|
||||
|
||||
import java.lang.reflect.InvocationTargetException
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.item.{ItemBlock, ItemStack}
|
||||
import scala.language.existentials
|
||||
|
||||
object RedstoneInMotion {
|
||||
private val (controller, setup, move, motionException, obstructionException, obstructionX, obstructionY, obstructionZ, directions) = try {
|
||||
private val (controller, setup, move, motionException, obstructionException, obstructionX, obstructionY, obstructionZ, directions, blocks) = try {
|
||||
val controller = Class.forName("JAKJ.RedstoneInMotion.CarriageControllerEntity")
|
||||
val motionException = Class.forName("JAKJ.RedstoneInMotion.CarriageMotionException")
|
||||
val obstructionException = Class.forName("JAKJ.RedstoneInMotion.CarriageObstructionException")
|
||||
val directions = Class.forName("JAKJ.RedstoneInMotion.Directions").getEnumConstants
|
||||
val blocks = Class.forName("JAKJ.RedstoneInMotion.Blocks")
|
||||
|
||||
val methods = controller.getDeclaredMethods
|
||||
val setup = methods.find(_.getName == "SetupMotion").get
|
||||
@ -18,10 +21,10 @@ object RedstoneInMotion {
|
||||
val obstructionY = obstructionException.getDeclaredField("Y")
|
||||
val obstructionZ = obstructionException.getDeclaredField("Z")
|
||||
|
||||
(Option(controller), setup, move, motionException, obstructionException, obstructionX, obstructionY, obstructionZ, directions)
|
||||
(Option(controller), setup, move, motionException, obstructionException, obstructionX, obstructionY, obstructionZ, directions, blocks)
|
||||
}
|
||||
catch {
|
||||
case _: Throwable => (None, null, null, null, null, null, null, null, null)
|
||||
case _: Throwable => (None, null, null, null, null, null, null, null, null, null)
|
||||
}
|
||||
|
||||
def available = controller.isDefined
|
||||
@ -31,6 +34,13 @@ object RedstoneInMotion {
|
||||
case _ => false
|
||||
}
|
||||
|
||||
def isCarriageController(stack: ItemStack) = available && stack != null && (stack.getItem match {
|
||||
case itemBlock: ItemBlock =>
|
||||
val block = Block.blocksList(itemBlock.getBlockID)
|
||||
block != null && driveBlock != null && block.blockID == driveBlock.blockID && itemBlock.getMetadata(stack.getItemDamage) == 2
|
||||
case _ => false
|
||||
})
|
||||
|
||||
def move(controller: AnyRef, direction: Int, simulating: Boolean, anchored: Boolean): (Boolean, Array[AnyRef]) = {
|
||||
if (!isCarriageController(controller))
|
||||
throw new IllegalArgumentException("Not a carriage controller.")
|
||||
@ -55,4 +65,11 @@ object RedstoneInMotion {
|
||||
(false, Array(e.getMessage: AnyRef))
|
||||
}
|
||||
}
|
||||
|
||||
private def driveBlock = try {
|
||||
blocks.getField("CarriageDrive").get(null).asInstanceOf[Block]
|
||||
}
|
||||
catch {
|
||||
case _: Throwable => null
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user