Added parameter for template IMC registration to specify host type.

This commit is contained in:
Florian Nücke 2014-10-05 18:15:10 +02:00
parent 14d23781a6
commit ef3bd0e229
9 changed files with 51 additions and 55 deletions

View File

@ -3,11 +3,13 @@ package li.cil.oc.common.template
import java.lang.reflect.Method
import java.lang.reflect.Modifier
import com.google.common.base.Strings
import li.cil.oc.OpenComputers
import li.cil.oc.api
import li.cil.oc.api.driver.EnvironmentHost
import li.cil.oc.common.Slot
import li.cil.oc.common.Tier
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.OpenComputers
import li.cil.oc.api
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
@ -17,7 +19,7 @@ import net.minecraftforge.common.util.Constants.NBT
import scala.collection.mutable
object AssemblerTemplates {
val NoSlot = new Slot(Slot.None, Tier.None, None)
val NoSlot = new Slot(Slot.None, Tier.None, None, None)
val templates = mutable.ArrayBuffer.empty[Template]
@ -25,9 +27,10 @@ object AssemblerTemplates {
val selector = getStaticMethod(template.getString("select"), classOf[ItemStack])
val validator = getStaticMethod(template.getString("validate"), classOf[IInventory])
val assembler = getStaticMethod(template.getString("assemble"), classOf[IInventory])
val containerSlots = template.getTagList("containerSlots", NBT.TAG_COMPOUND).map((list, index) => parseSlot(list.getCompoundTagAt(index), Some(Slot.Container))).take(3).padTo(3, NoSlot).toArray
val upgradeSlots = template.getTagList("upgradeSlots", NBT.TAG_COMPOUND).map((list, index) => parseSlot(list.getCompoundTagAt(index), Some(Slot.Upgrade))).take(9).padTo(9, NoSlot).toArray
val componentSlots = template.getTagList("componentSlots", NBT.TAG_COMPOUND).map((list, index) => parseSlot(list.getCompoundTagAt(index))).take(9).padTo(9, NoSlot).toArray
val hostClass = tryGetHostClass(template.getString("hostClass"))
val containerSlots = template.getTagList("containerSlots", NBT.TAG_COMPOUND).map((list, index) => parseSlot(list.getCompoundTagAt(index), Some(Slot.Container), hostClass)).take(3).padTo(3, NoSlot).toArray
val upgradeSlots = template.getTagList("upgradeSlots", NBT.TAG_COMPOUND).map((list, index) => parseSlot(list.getCompoundTagAt(index), Some(Slot.Upgrade), hostClass)).take(9).padTo(9, NoSlot).toArray
val componentSlots = template.getTagList("componentSlots", NBT.TAG_COMPOUND).map((list, index) => parseSlot(list.getCompoundTagAt(index), None, hostClass)).take(9).padTo(9, NoSlot).toArray
templates += new Template(selector, validator, assembler, containerSlots, upgradeSlots, componentSlots)
}
@ -59,21 +62,21 @@ object AssemblerTemplates {
}
}
class Slot(val kind: String, val tier: Int, val validator: Option[Method]) {
class Slot(val kind: String, val tier: Int, val validator: Option[Method], val hostClass: Option[Class[_ <: EnvironmentHost]]) {
def validate(inventory: IInventory, slot: Int, stack: ItemStack) = validator match {
case Some(method) => tryInvokeStatic(method, inventory, slot.underlying(), tier.underlying(), stack)(false)
case _ => Option(api.Driver.driverFor(stack)) match {
case _ => Option(hostClass.fold(api.Driver.driverFor(stack))(api.Driver.driverFor(stack, _))) match {
case Some(driver) => driver.slot(stack) == kind && driver.tier(stack) <= tier
case _ => false
}
}
}
private def parseSlot(nbt: NBTTagCompound, kindOverride: Option[String] = None) = {
private def parseSlot(nbt: NBTTagCompound, kindOverride: Option[String], hostClass: Option[Class[_ <: EnvironmentHost]]) = {
val kind = kindOverride.getOrElse(if (nbt.hasKey("type")) nbt.getString("type") else Slot.None)
val tier = if (nbt.hasKey("tier")) nbt.getInteger("tier") else Tier.Any
val validator = if (nbt.hasKey("validate")) Option(getStaticMethod(nbt.getString("validate"), classOf[IInventory], classOf[Int], classOf[Int], classOf[ItemStack])) else None
new Slot(kind, tier, validator)
new Slot(kind, tier, validator, hostClass)
}
private def getStaticMethod(name: String, signature: Class[_]*) = {
@ -86,6 +89,10 @@ object AssemblerTemplates {
method
}
private def tryGetHostClass(name: String) =
if (Strings.isNullOrEmpty(name)) None
else Option(Class.forName(name).asSubclass(classOf[EnvironmentHost]))
private def tryInvokeStatic[T](method: Method, args: AnyRef*)(default: T): T = try method.invoke(null, args: _*).asInstanceOf[T] catch {
case t: Throwable =>
OpenComputers.log.warn(s"Error invoking callback ${method.getDeclaringClass.getCanonicalName + "." + method.getName}.", t)

View File

@ -1,13 +1,13 @@
package li.cil.oc.common.template
import cpw.mods.fml.common.event.FMLInterModComms
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.common.Slot
import li.cil.oc.common.Tier
import li.cil.oc.common.tileentity
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ItemUtils
import li.cil.oc.Settings
import li.cil.oc.api
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
@ -82,6 +82,7 @@ object RobotTemplate extends Template {
nbt.setString("select", "li.cil.oc.common.template.RobotTemplate.selectTier2")
nbt.setString("validate", "li.cil.oc.common.template.RobotTemplate.validate")
nbt.setString("assemble", "li.cil.oc.common.template.RobotTemplate.assemble")
nbt.setString("hostClass", "li.cil.oc.api.tileentity.Robot")
val containerSlots = new NBTTagList()
containerSlots.appendTag(Map("tier" -> Tier.Three))

View File

@ -1,14 +1,13 @@
package li.cil.oc.common.template
import cpw.mods.fml.common.event.FMLInterModComms
import li.cil.oc.common.item.TabletWrapper
import li.cil.oc.common.Slot
import li.cil.oc.common.Tier
import li.cil.oc.server.driver.item
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ItemUtils
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.common.Slot
import li.cil.oc.common.Tier
import li.cil.oc.common.item.TabletWrapper
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ItemUtils
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
@ -27,13 +26,6 @@ object TabletTemplate extends Template {
def validate(inventory: IInventory): Array[AnyRef] = validateComputer(inventory)
def validateUpgrade(inventory: IInventory, slot: Int, tier: Int, stack: ItemStack): Boolean = Option(api.Driver.driverFor(stack, hostClass)) match {
case Some(driver) if driver.slot(stack) == Slot.Upgrade =>
driver != item.Screen &&
driver.slot(stack) == Slot.Upgrade && driver.tier(stack) <= tier
case _ => false
}
def assemble(inventory: IInventory): Array[AnyRef] = {
val items = mutable.ArrayBuffer(
Option(api.Items.get("screen1").createItemStack(1))
@ -54,11 +46,12 @@ object TabletTemplate extends Template {
nbt.setString("select", "li.cil.oc.common.template.TabletTemplate.select")
nbt.setString("validate", "li.cil.oc.common.template.TabletTemplate.validate")
nbt.setString("assemble", "li.cil.oc.common.template.TabletTemplate.assemble")
nbt.setString("hostClass", "li.cil.oc.common.item.TabletWrapper")
val upgradeSlots = new NBTTagList()
upgradeSlots.appendTag(Map("tier" -> Tier.Three, "validate" -> "li.cil.oc.common.template.TabletTemplate.validateUpgrade"))
upgradeSlots.appendTag(Map("tier" -> Tier.Two, "validate" -> "li.cil.oc.common.template.TabletTemplate.validateUpgrade"))
upgradeSlots.appendTag(Map("tier" -> Tier.One, "validate" -> "li.cil.oc.common.template.TabletTemplate.validateUpgrade"))
upgradeSlots.appendTag(Map("tier" -> Tier.Three))
upgradeSlots.appendTag(Map("tier" -> Tier.Two))
upgradeSlots.appendTag(Map("tier" -> Tier.One))
nbt.setTag("upgradeSlots", upgradeSlots)
val componentSlots = new NBTTagList()

View File

@ -10,8 +10,6 @@ import li.cil.oc.util.ExtendedNBT._
import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.util.ForgeDirection
import scala.math.ScalaNumber
trait Environment extends TileEntity with network.Environment with driver.EnvironmentHost {
protected var isChangeScheduled = false
@ -86,11 +84,5 @@ trait Environment extends TileEntity with network.Environment with driver.Enviro
// ----------------------------------------------------------------------- //
final protected def result(args: Any*): Array[AnyRef] = {
def unwrap(arg: Any): AnyRef = arg match {
case x: ScalaNumber => x.underlying
case x => x.asInstanceOf[AnyRef]
}
Array(args map unwrap: _*)
}
protected def result(args: Any*) = li.cil.oc.util.ResultWrapper.result(args: _*)
}

View File

@ -16,8 +16,6 @@ import net.minecraft.world.World
import net.minecraft.world.WorldSettings.GameType
import net.minecraftforge.common.DimensionManager
import scala.math.ScalaNumber
class DebugCard(host: EnvironmentHost) extends prefab.ManagedEnvironment {
override val node = Network.newNode(this, Visibility.Neighbors).
withComponent("debug").
@ -66,15 +64,10 @@ class DebugCard(host: EnvironmentHost) extends prefab.ManagedEnvironment {
}
object DebugCard {
def checkEnabled() = if (!Settings.get.enableDebugCard) throw new Exception("debug card functionality is disabled")
final private def result(args: Any*): Array[AnyRef] = {
def unwrap(arg: Any): AnyRef = arg match {
case x: ScalaNumber => x.underlying
case x => x.asInstanceOf[AnyRef]
}
Array(args map unwrap: _*)
}
import li.cil.oc.util.ResultWrapper.result
def checkEnabled() = if (!Settings.get.enableDebugCard) throw new Exception("debug card functionality is disabled")
class PlayerValue(var name: String) extends prefab.AbstractValue {
def this() = this("") // For loading.

View File

@ -63,7 +63,7 @@ private[oc] object Registry extends api.detail.DriverAPI {
def driverFor(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
if (stack != null) {
val hostAware = items.collect {
case driver: HostAware => driver
case driver: HostAware if driver.worksWith(stack) => driver
}
if (hostAware.size > 0) {
hostAware.find(_.worksWith(stack, host)).orNull

View File

@ -19,11 +19,11 @@ trait Item extends driver.Item {
protected def isRotatable(host: Class[_ <: EnvironmentHost]) = classOf[api.tileentity.Rotatable].isAssignableFrom(host)
protected def isComputer(host: Class[_ <: EnvironmentHost]) = host.isInstanceOf[tileentity.traits.Computer] || host.isInstanceOf[tileentity.ServerRack]
protected def isComputer(host: Class[_ <: EnvironmentHost]) = classOf[tileentity.traits.Computer].isAssignableFrom(host) || classOf[tileentity.ServerRack].isAssignableFrom(host)
protected def isRobot(host: Class[_ <: EnvironmentHost]) = classOf[api.tileentity.Robot].isAssignableFrom(host)
protected def isTablet(host: Class[_ <: EnvironmentHost]) = host.isInstanceOf[item.TabletWrapper]
protected def isTablet(host: Class[_ <: EnvironmentHost]) = classOf[item.TabletWrapper].isAssignableFrom(host)
}
object Item {

View File

@ -2,12 +2,17 @@ package li.cil.oc.server.driver.item
import li.cil.oc.api
import li.cil.oc.api.driver.EnvironmentHost
import li.cil.oc.api.driver.item.HostAware
import li.cil.oc.common.Slot
import li.cil.oc.server.component
import net.minecraft.item.ItemStack
object UpgradeTank extends Item {
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("tankUpgrade"))
object UpgradeTank extends Item with HostAware {
override def worksWith(stack: ItemStack) =
isOneOf(stack, api.Items.get("tankUpgrade"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && isRobot(host)
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = new component.UpgradeTank(host, 16000)

View File

@ -2,14 +2,19 @@ package li.cil.oc.server.driver.item
import li.cil.oc.api
import li.cil.oc.api.driver.EnvironmentHost
import li.cil.oc.common.tileentity.Robot
import li.cil.oc.api.driver.item.HostAware
import li.cil.oc.common.Slot
import li.cil.oc.common.Tier
import li.cil.oc.common.tileentity.Robot
import li.cil.oc.server.component
import net.minecraft.item.ItemStack
object UpgradeTankController extends Item {
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("tankControllerUpgrade"))
object UpgradeTankController extends Item with HostAware {
override def worksWith(stack: ItemStack) =
isOneOf(stack, api.Items.get("tankControllerUpgrade"))
override def worksWith(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
worksWith(stack) && isRobot(host)
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = host match {
case robot: EnvironmentHost with Robot => new component.UpgradeTankController(robot)