diff --git a/src/main/scala/li/cil/oc/common/template/AssemblerTemplates.scala b/src/main/scala/li/cil/oc/common/template/AssemblerTemplates.scala index 0e3ec40c1..671959670 100644 --- a/src/main/scala/li/cil/oc/common/template/AssemblerTemplates.scala +++ b/src/main/scala/li/cil/oc/common/template/AssemblerTemplates.scala @@ -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) diff --git a/src/main/scala/li/cil/oc/common/template/RobotTemplate.scala b/src/main/scala/li/cil/oc/common/template/RobotTemplate.scala index d6c3533a7..d59768f5b 100644 --- a/src/main/scala/li/cil/oc/common/template/RobotTemplate.scala +++ b/src/main/scala/li/cil/oc/common/template/RobotTemplate.scala @@ -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)) diff --git a/src/main/scala/li/cil/oc/common/template/TabletTemplate.scala b/src/main/scala/li/cil/oc/common/template/TabletTemplate.scala index c0e75cdc9..36fc83314 100644 --- a/src/main/scala/li/cil/oc/common/template/TabletTemplate.scala +++ b/src/main/scala/li/cil/oc/common/template/TabletTemplate.scala @@ -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() diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/Environment.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/Environment.scala index 68d8c7e3e..5fd536902 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/traits/Environment.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/traits/Environment.scala @@ -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: _*) } diff --git a/src/main/scala/li/cil/oc/server/component/DebugCard.scala b/src/main/scala/li/cil/oc/server/component/DebugCard.scala index de8d21594..56baf20b9 100644 --- a/src/main/scala/li/cil/oc/server/component/DebugCard.scala +++ b/src/main/scala/li/cil/oc/server/component/DebugCard.scala @@ -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. diff --git a/src/main/scala/li/cil/oc/server/driver/Registry.scala b/src/main/scala/li/cil/oc/server/driver/Registry.scala index d1f7fd459..9ac4ee11f 100644 --- a/src/main/scala/li/cil/oc/server/driver/Registry.scala +++ b/src/main/scala/li/cil/oc/server/driver/Registry.scala @@ -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 diff --git a/src/main/scala/li/cil/oc/server/driver/item/Item.scala b/src/main/scala/li/cil/oc/server/driver/item/Item.scala index 44d16c2bc..5f9f47038 100644 --- a/src/main/scala/li/cil/oc/server/driver/item/Item.scala +++ b/src/main/scala/li/cil/oc/server/driver/item/Item.scala @@ -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 { diff --git a/src/main/scala/li/cil/oc/server/driver/item/UpgradeTank.scala b/src/main/scala/li/cil/oc/server/driver/item/UpgradeTank.scala index 73d1b94c3..048bd28d8 100644 --- a/src/main/scala/li/cil/oc/server/driver/item/UpgradeTank.scala +++ b/src/main/scala/li/cil/oc/server/driver/item/UpgradeTank.scala @@ -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) diff --git a/src/main/scala/li/cil/oc/server/driver/item/UpgradeTankController.scala b/src/main/scala/li/cil/oc/server/driver/item/UpgradeTankController.scala index e43bb6b29..d9a58b9bb 100644 --- a/src/main/scala/li/cil/oc/server/driver/item/UpgradeTankController.scala +++ b/src/main/scala/li/cil/oc/server/driver/item/UpgradeTankController.scala @@ -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)