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.Method
import java.lang.reflect.Modifier 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.Slot
import li.cil.oc.common.Tier import li.cil.oc.common.Tier
import li.cil.oc.util.ExtendedNBT._ import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.OpenComputers
import li.cil.oc.api
import net.minecraft.inventory.IInventory import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
@ -17,7 +19,7 @@ import net.minecraftforge.common.util.Constants.NBT
import scala.collection.mutable import scala.collection.mutable
object AssemblerTemplates { 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] val templates = mutable.ArrayBuffer.empty[Template]
@ -25,9 +27,10 @@ object AssemblerTemplates {
val selector = getStaticMethod(template.getString("select"), classOf[ItemStack]) val selector = getStaticMethod(template.getString("select"), classOf[ItemStack])
val validator = getStaticMethod(template.getString("validate"), classOf[IInventory]) val validator = getStaticMethod(template.getString("validate"), classOf[IInventory])
val assembler = getStaticMethod(template.getString("assemble"), 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 hostClass = tryGetHostClass(template.getString("hostClass"))
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 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 componentSlots = template.getTagList("componentSlots", NBT.TAG_COMPOUND).map((list, index) => parseSlot(list.getCompoundTagAt(index))).take(9).padTo(9, 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) 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 { def validate(inventory: IInventory, slot: Int, stack: ItemStack) = validator match {
case Some(method) => tryInvokeStatic(method, inventory, slot.underlying(), tier.underlying(), stack)(false) 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 Some(driver) => driver.slot(stack) == kind && driver.tier(stack) <= tier
case _ => false 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 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 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 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[_]*) = { private def getStaticMethod(name: String, signature: Class[_]*) = {
@ -86,6 +89,10 @@ object AssemblerTemplates {
method 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 { private def tryInvokeStatic[T](method: Method, args: AnyRef*)(default: T): T = try method.invoke(null, args: _*).asInstanceOf[T] catch {
case t: Throwable => case t: Throwable =>
OpenComputers.log.warn(s"Error invoking callback ${method.getDeclaringClass.getCanonicalName + "." + method.getName}.", t) 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 package li.cil.oc.common.template
import cpw.mods.fml.common.event.FMLInterModComms 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.Slot
import li.cil.oc.common.Tier import li.cil.oc.common.Tier
import li.cil.oc.common.tileentity import li.cil.oc.common.tileentity
import li.cil.oc.util.ExtendedNBT._ import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ItemUtils import li.cil.oc.util.ItemUtils
import li.cil.oc.Settings
import li.cil.oc.api
import net.minecraft.inventory.IInventory import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound 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("select", "li.cil.oc.common.template.RobotTemplate.selectTier2")
nbt.setString("validate", "li.cil.oc.common.template.RobotTemplate.validate") nbt.setString("validate", "li.cil.oc.common.template.RobotTemplate.validate")
nbt.setString("assemble", "li.cil.oc.common.template.RobotTemplate.assemble") nbt.setString("assemble", "li.cil.oc.common.template.RobotTemplate.assemble")
nbt.setString("hostClass", "li.cil.oc.api.tileentity.Robot")
val containerSlots = new NBTTagList() val containerSlots = new NBTTagList()
containerSlots.appendTag(Map("tier" -> Tier.Three)) containerSlots.appendTag(Map("tier" -> Tier.Three))

View File

@ -1,14 +1,13 @@
package li.cil.oc.common.template package li.cil.oc.common.template
import cpw.mods.fml.common.event.FMLInterModComms 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.Settings
import li.cil.oc.api 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.inventory.IInventory
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
@ -27,13 +26,6 @@ object TabletTemplate extends Template {
def validate(inventory: IInventory): Array[AnyRef] = validateComputer(inventory) 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] = { def assemble(inventory: IInventory): Array[AnyRef] = {
val items = mutable.ArrayBuffer( val items = mutable.ArrayBuffer(
Option(api.Items.get("screen1").createItemStack(1)) 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("select", "li.cil.oc.common.template.TabletTemplate.select")
nbt.setString("validate", "li.cil.oc.common.template.TabletTemplate.validate") nbt.setString("validate", "li.cil.oc.common.template.TabletTemplate.validate")
nbt.setString("assemble", "li.cil.oc.common.template.TabletTemplate.assemble") nbt.setString("assemble", "li.cil.oc.common.template.TabletTemplate.assemble")
nbt.setString("hostClass", "li.cil.oc.common.item.TabletWrapper")
val upgradeSlots = new NBTTagList() val upgradeSlots = new NBTTagList()
upgradeSlots.appendTag(Map("tier" -> Tier.Three, "validate" -> "li.cil.oc.common.template.TabletTemplate.validateUpgrade")) upgradeSlots.appendTag(Map("tier" -> Tier.Three))
upgradeSlots.appendTag(Map("tier" -> Tier.Two, "validate" -> "li.cil.oc.common.template.TabletTemplate.validateUpgrade")) upgradeSlots.appendTag(Map("tier" -> Tier.Two))
upgradeSlots.appendTag(Map("tier" -> Tier.One, "validate" -> "li.cil.oc.common.template.TabletTemplate.validateUpgrade")) upgradeSlots.appendTag(Map("tier" -> Tier.One))
nbt.setTag("upgradeSlots", upgradeSlots) nbt.setTag("upgradeSlots", upgradeSlots)
val componentSlots = new NBTTagList() val componentSlots = new NBTTagList()

View File

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

View File

@ -16,8 +16,6 @@ import net.minecraft.world.World
import net.minecraft.world.WorldSettings.GameType import net.minecraft.world.WorldSettings.GameType
import net.minecraftforge.common.DimensionManager import net.minecraftforge.common.DimensionManager
import scala.math.ScalaNumber
class DebugCard(host: EnvironmentHost) extends prefab.ManagedEnvironment { class DebugCard(host: EnvironmentHost) extends prefab.ManagedEnvironment {
override val node = Network.newNode(this, Visibility.Neighbors). override val node = Network.newNode(this, Visibility.Neighbors).
withComponent("debug"). withComponent("debug").
@ -66,15 +64,10 @@ class DebugCard(host: EnvironmentHost) extends prefab.ManagedEnvironment {
} }
object DebugCard { object DebugCard {
def checkEnabled() = if (!Settings.get.enableDebugCard) throw new Exception("debug card functionality is disabled")
final private def result(args: Any*): Array[AnyRef] = { import li.cil.oc.util.ResultWrapper.result
def unwrap(arg: Any): AnyRef = arg match {
case x: ScalaNumber => x.underlying def checkEnabled() = if (!Settings.get.enableDebugCard) throw new Exception("debug card functionality is disabled")
case x => x.asInstanceOf[AnyRef]
}
Array(args map unwrap: _*)
}
class PlayerValue(var name: String) extends prefab.AbstractValue { class PlayerValue(var name: String) extends prefab.AbstractValue {
def this() = this("") // For loading. 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]) = def driverFor(stack: ItemStack, host: Class[_ <: EnvironmentHost]) =
if (stack != null) { if (stack != null) {
val hostAware = items.collect { val hostAware = items.collect {
case driver: HostAware => driver case driver: HostAware if driver.worksWith(stack) => driver
} }
if (hostAware.size > 0) { if (hostAware.size > 0) {
hostAware.find(_.worksWith(stack, host)).orNull 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 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 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 { 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
import li.cil.oc.api.driver.EnvironmentHost 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.common.Slot
import li.cil.oc.server.component import li.cil.oc.server.component
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
object UpgradeTank extends Item { object UpgradeTank extends Item with HostAware {
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("tankUpgrade")) 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) 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
import li.cil.oc.api.driver.EnvironmentHost 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.Slot
import li.cil.oc.common.Tier import li.cil.oc.common.Tier
import li.cil.oc.common.tileentity.Robot
import li.cil.oc.server.component import li.cil.oc.server.component
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
object UpgradeTankController extends Item { object UpgradeTankController extends Item with HostAware {
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("tankControllerUpgrade")) 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 { override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = host match {
case robot: EnvironmentHost with Robot => new component.UpgradeTankController(robot) case robot: EnvironmentHost with Robot => new component.UpgradeTankController(robot)