Merge branch 'master' of github.com:MightyPirates/OpenComputers into master-MC1.7.10

Conflicts:
	src/main/scala/li/cil/oc/OpenComputers.scala
	src/main/scala/li/cil/oc/client/gui/RobotAssembler.scala
	src/main/scala/li/cil/oc/common/tileentity/RobotAssembler.scala
This commit is contained in:
Florian Nücke 2014-08-29 19:17:21 +02:00
commit 9a8109b3f3
14 changed files with 543 additions and 290 deletions

View File

@ -24,7 +24,7 @@ oc:tile.PowerDistributor.name=Stromverteiler
oc:tile.Redstone.name=Redstone-I/O
oc:tile.Robot.name=Roboter
oc:tile.RobotAfterimage.name=Roboter
oc:tile.RobotAssembler.name=Roboter-Werkbank
oc:tile.RobotAssembler.name=Elektronik-Werkbank
oc:tile.Screen0.name=Bildschirm (Stufe 1)
oc:tile.Screen1.name=Bildschirm (Stufe 2)
oc:tile.Screen2.name=Bildschirm (Stufe 3)
@ -132,9 +132,9 @@ oc:gui.Error.OutOfMemory=Nicht genug Arbeitsspeicher.
oc:gui.Robot.Power=Energie
oc:gui.Robot.TurnOff=Ausschalten
oc:gui.Robot.TurnOn=Einschalten
oc:gui.RobotAssembler.CollectRobot=Roboter entnehmen
oc:gui.RobotAssembler.CollectRobot=Ergebnis entnehmen
oc:gui.RobotAssembler.Complexity=Komplexität: %s/%s
oc:gui.RobotAssembler.InsertCase=Computergehäuse einlegen
oc:gui.RobotAssembler.InsertCase=Grundbaustein einlegen
oc:gui.RobotAssembler.InsertCPU=CPU benötigt
oc:gui.RobotAssembler.InsertRAM=RAM benötigt
oc:gui.RobotAssembler.Progress=Fortschritt: %s%% (%s)
@ -232,7 +232,7 @@ oc:tooltip.Robot=Im Gegensatz zu normalen Computern können sich Roboter in der
# The underscore makes sure this isn't hidden with the rest of the tooltip.
oc:tooltip.Robot_Level=§fStufe§7: §a%s§7.
oc:tooltip.Robot_StoredEnergy=§fGespeicherte Energie§7: §a%s§7.
oc:tooltip.RobotAssembler=Erlaubt die Fertigung von Robotern aus diversen anderen Computerteilen.
oc:tooltip.RobotAssembler=Erlaubt die Fertigung von Robotern und weiteren Geräten aus diversen anderen Computerteilen.
oc:tooltip.Screen=Zeigt Text an, gesteuert von Grafikkarten in Computern.[nl] Höchstauflösung: §f%sx%s§7.[nl] Maximale Farbtiefe: §f%s§7.
oc:tooltip.Server=Ein Server kann wie ein gewöhnliches Computergehäuse mit Komponenten verbessert werden. Um den Server zu starten, muss er in einem Servergehäuse installiert werden.[nl] Anzahl unterstützter Fernbedienungen: §f%s§7.
oc:tooltip.Server.Components=Installierte Komponenten:

View File

@ -24,7 +24,7 @@ oc:tile.PowerDistributor.name=Power Distributor
oc:tile.Redstone.name=Redstone I/O
oc:tile.Robot.name=Robot
oc:tile.RobotAfterimage.name=Robot
oc:tile.RobotAssembler.name=Robot Assembler
oc:tile.RobotAssembler.name=Electronics Assembler
oc:tile.Screen0.name=Screen (Tier 1)
oc:tile.Screen1.name=Screen (Tier 2)
oc:tile.Screen2.name=Screen (Tier 3)
@ -133,9 +133,9 @@ oc:gui.Error.OutOfMemory=Out of memory.
oc:gui.Robot.Power=Energy
oc:gui.Robot.TurnOff=Turn off
oc:gui.Robot.TurnOn=Turn on
oc:gui.RobotAssembler.CollectRobot=Collect robot
oc:gui.RobotAssembler.CollectRobot=Collect output
oc:gui.RobotAssembler.Complexity=Complexity: %s/%s
oc:gui.RobotAssembler.InsertCase=Insert a Computer Case
oc:gui.RobotAssembler.InsertCase=Insert a base part
oc:gui.RobotAssembler.InsertCPU=Insert a CPU
oc:gui.RobotAssembler.InsertRAM=Insert some RAM
oc:gui.RobotAssembler.Progress=Progress: %s%% (%s)
@ -233,7 +233,7 @@ oc:tooltip.Robot=Unlike computers, robots can move around and interact with the
# The underscore makes sure this isn't hidden with the rest of the tooltip.
oc:tooltip.Robot_Level=§fLevel§7: §a%s§7.
oc:tooltip.Robot_StoredEnergy=§fStored energy§7: §a%s§7.
oc:tooltip.RobotAssembler=Allows constructing robots from a number of different computer parts.
oc:tooltip.RobotAssembler=Allows constructing robots and other devices from a number of different computer parts.
oc:tooltip.Screen=Display text, controlled by a Graphics Card in a Case.[nl] Maximum resolution: §f%sx%s§7.[nl] Maximum color depth: §f%s§7.
oc:tooltip.Server=This is a server, there are many like it, but this one can be upgraded with components much like a computer case can be. It can be run by inserting it into a server rack.[nl] Number of supported terminals: §f%s§7.
oc:tooltip.Server.Components=Installed components:

View File

@ -62,24 +62,28 @@ object Localization {
def Power = localizeImmediately("gui.Robot.Power")
}
object RobotAssembler {
def InsertCase = localizeImmediately("gui.RobotAssembler.InsertCase")
object Assembler {
def InsertTemplate = localizeImmediately("gui.RobotAssembler.InsertCase")
def InsertCPU = localizeImmediately("gui.RobotAssembler.InsertCPU")
def CollectResult = localizeImmediately("gui.RobotAssembler.CollectRobot")
def InsertRAM = localizeImmediately("gui.RobotAssembler.InsertRAM")
def InsertCPU = localizeLater("gui.RobotAssembler.InsertCPU")
def Complexity(complexity: Int, maxComplexity: Int) = localizeImmediately("gui.RobotAssembler.Complexity", complexity.toString, maxComplexity.toString)
def InsertRAM = localizeLater("gui.RobotAssembler.InsertRAM")
def Complexity(complexity: Int, maxComplexity: Int) = {
val message = localizeLater("gui.RobotAssembler.Complexity", complexity.toString, maxComplexity.toString)
if (complexity > maxComplexity) new ChatComponentText("§4").appendSibling(message)
else message
}
def Run = localizeImmediately("gui.RobotAssembler.Run")
def CollectRobot = localizeImmediately("gui.RobotAssembler.CollectRobot")
def Progress(progress: Double, timeRemaining: String) = localizeImmediately("gui.RobotAssembler.Progress", progress.toInt.toString, timeRemaining)
def Warning(name: String) = "§7- " + localizeImmediately("gui.RobotAssembler.Warning." + name)
def Warning(name: String) = new ChatComponentText("§7- ").appendSibling(localizeLater("gui.RobotAssembler.Warning." + name))
def Warnings = localizeImmediately("gui.RobotAssembler.Warnings")
def Warnings = localizeLater("gui.RobotAssembler.Warnings")
}
object ServerRack {

View File

@ -1,13 +1,17 @@
package li.cil.oc
import cpw.mods.fml.common.Mod.EventHandler
import cpw.mods.fml.common.event.FMLInterModComms.IMCEvent
import cpw.mods.fml.common.event._
import cpw.mods.fml.common.network.FMLEventChannel
import cpw.mods.fml.common.{Mod, SidedProxy}
import li.cil.oc.common.Proxy
import li.cil.oc.common.template.AssemblerTemplates
import li.cil.oc.server.CommandHandler
import org.apache.logging.log4j.LogManager
import scala.collection.convert.WrapAsScala._
@Mod(modid = OpenComputers.ID, name = OpenComputers.Name,
version = OpenComputers.Version, /* certificateFingerprint = OpenComputers.Fingerprint, */
modLanguage = "scala", useMetadata = true)
@ -49,4 +53,14 @@ object OpenComputers {
@EventHandler
def serverStart(e: FMLServerStartingEvent) = CommandHandler.register(e)
}
@EventHandler
def imc(e: IMCEvent) = {
for (message <- e.getMessages) {
if (message.key == "registerAssemblerTemplate" && message.isNBTMessage) {
log.info(s"Registering new assembler template from mod ${message.getSender}.")
AssemblerTemplates.add(message.getNBTValue)
}
}
}
}

View File

@ -2,17 +2,16 @@ package li.cil.oc.client.gui
import java.util
import li.cil.oc.api.driver.{Inventory, Memory, Processor}
import li.cil.oc.Localization
import li.cil.oc.client.gui.widget.ProgressBar
import li.cil.oc.client.{Textures, PacketSender => ClientPacketSender}
import li.cil.oc.common.{Slot, container, tileentity}
import li.cil.oc.{Localization, api}
import li.cil.oc.common.template.AssemblerTemplates
import li.cil.oc.common.{container, tileentity}
import net.minecraft.client.gui.GuiButton
import net.minecraft.entity.player.InventoryPlayer
import org.lwjgl.opengl.GL11
import scala.collection.convert.WrapAsJava._
import scala.collection.mutable
class RobotAssembler(playerInventory: InventoryPlayer, val assembler: tileentity.RobotAssembler) extends DynamicGuiContainer(new container.RobotAssembler(playerInventory, assembler)) {
xSize = 176
@ -24,60 +23,11 @@ class RobotAssembler(playerInventory: InventoryPlayer, val assembler: tileentity
private val progress = addWidget(new ProgressBar(28, 92))
val suggestedComponents = Array(
"Screen" -> (() => hasComponent("screen1")),
"Keyboard" -> (() => hasComponent("keyboard")),
"GraphicsCard" -> (() => Array("graphicsCard1", "graphicsCard2", "graphicsCard3").exists(hasComponent)),
"Inventory" -> (() => hasInventory),
"OS" -> (() => hasFileSystem))
def add[T](list: util.List[T], value: Any) = list.add(value.asInstanceOf[T])
private def hasCase = assembler.isItemValidForSlot(0, assembler.getStackInSlot(0))
private def validate = AssemblerTemplates.select(assemblerContainer.getSlot(0).getStack).map(_.validate(assemblerContainer.otherInventory))
private def hasCPU = assembler.items.exists {
case Some(stack) => api.Driver.driverFor(stack) match {
case _: Processor => true
case _ => false
}
case _ => false
}
private def hasRAM = assembler.items.exists {
case Some(stack) => api.Driver.driverFor(stack) match {
case _: Memory => true
case _ => false
}
case _ => false
}
private def hasComponent(name: String) = assembler.items.exists {
case Some(stack) => Option(api.Items.get(stack)) match {
case Some(descriptor) => descriptor.name == name
case _ => false
}
case _ => false
}
private def hasInventory = assembler.items.exists {
case Some(stack) => api.Driver.driverFor(stack) match {
case _: Inventory => true
case _ => false
}
case _ => false
}
private def hasFileSystem = assembler.items.exists {
case Some(stack) => Option(api.Driver.driverFor(stack)) match {
case Some(driver) => Slot.fromApi(driver.slot(stack)) == Slot.Floppy || Slot.fromApi(driver.slot(stack)) == Slot.HDD
case _ => false
}
case _ => false
}
private def isCapacityValid = assembler.complexity <= assembler.maxComplexity
private def canBuild = !assemblerContainer.isAssembling && hasCase && hasCPU && hasRAM && isCapacityValid
private def canBuild = !assemblerContainer.isAssembling && validate.exists(_._1)
protected override def actionPerformed(button: GuiButton) {
if (button.id == 0 && canBuild) {
@ -100,37 +50,23 @@ class RobotAssembler(playerInventory: InventoryPlayer, val assembler: tileentity
override def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) = {
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS) // Me lazy... prevents NEI render glitch.
if (!assemblerContainer.isAssembling) {
def drawMessage(message: String) {
fontRendererObj.drawString(message, 30, 94, 0x404040)
}
if (!inventorySlots.getSlot(0).getHasStack) {
drawMessage(Localization.RobotAssembler.InsertCase)
}
else if (api.Items.get(inventorySlots.getSlot(0).getStack) == api.Items.get("robot")) {
drawMessage(Localization.RobotAssembler.CollectRobot)
}
else if (!hasCPU) {
drawMessage(Localization.RobotAssembler.InsertCPU)
}
else if (!hasRAM) {
drawMessage(Localization.RobotAssembler.InsertRAM)
}
else {
fontRendererObj.drawString(Localization.RobotAssembler.Complexity(assembler.complexity, assembler.maxComplexity), 30, 94, if (isCapacityValid) 0x404040 else 0x804040)
}
val info = validate
val message =
if (!assemblerContainer.getSlot(0).getHasStack) {
Localization.Assembler.InsertTemplate
}
else info match {
case Some((_, value, _)) if value != null => value.getUnformattedText
case _ if assemblerContainer.getSlot(0).getHasStack => Localization.Assembler.CollectResult
case _ => ""
}
fontRendererObj.drawString(message, 30, 94, 0x404040)
if (runButton.func_146115_a) {
val tooltip = new java.util.ArrayList[String]
tooltip.add(Localization.RobotAssembler.Run)
if (canBuild) {
var warnings = mutable.ArrayBuffer.empty[String]
for ((name, check) <- suggestedComponents) {
if (!check()) {
warnings += Localization.RobotAssembler.Warning(name)
}
}
if (warnings.length > 0) {
tooltip.add(Localization.RobotAssembler.Warnings)
tooltip.addAll(warnings)
tooltip.add(Localization.Assembler.Run)
info.foreach {
case (valid, _, warnings) => if (valid && warnings.length > 0) {
tooltip.addAll(warnings.map(_.getUnformattedText).toList)
}
}
drawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRendererObj)
@ -139,7 +75,7 @@ class RobotAssembler(playerInventory: InventoryPlayer, val assembler: tileentity
else if (func_146978_c(progress.x, progress.y, progress.width, progress.height, mouseX, mouseY)) {
val tooltip = new java.util.ArrayList[String]
val timeRemaining = formatTime(assemblerContainer.assemblyRemainingTime)
tooltip.add(Localization.RobotAssembler.Progress(assemblerContainer.assemblyProgress, timeRemaining))
tooltip.add(Localization.Assembler.Progress(assemblerContainer.assemblyProgress, timeRemaining))
copiedDrawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRendererObj)
}
GL11.glPopAttrib()

View File

@ -46,108 +46,6 @@ object InventorySlots {
)
)
val assembler = Array(
Array(
InventorySlot(Slot.None, Tier.None), // Reserved for computer case.
InventorySlot(Slot.Container, Tier.Two),
InventorySlot(Slot.Container, Tier.One),
InventorySlot(Slot.Container, Tier.One),
InventorySlot(Slot.Upgrade, Tier.One),
InventorySlot(Slot.Upgrade, Tier.One),
InventorySlot(Slot.Upgrade, Tier.One),
InventorySlot(Slot.None, Tier.None),
InventorySlot(Slot.None, Tier.None),
InventorySlot(Slot.None, Tier.None),
InventorySlot(Slot.None, Tier.None),
InventorySlot(Slot.None, Tier.None),
InventorySlot(Slot.None, Tier.None),
InventorySlot(Slot.Card, Tier.One),
InventorySlot(Slot.None, Tier.None),
InventorySlot(Slot.None, Tier.None),
InventorySlot(Slot.CPU, Tier.One),
InventorySlot(Slot.Memory, Tier.One),
InventorySlot(Slot.Memory, Tier.One),
InventorySlot(Slot.Floppy, Tier.Any),
InventorySlot(Slot.HDD, Tier.One),
InventorySlot(Slot.None, Tier.None)
),
Array(
InventorySlot(Slot.None, Tier.None),
InventorySlot(Slot.Container, Tier.Three),
InventorySlot(Slot.Container, Tier.Two),
InventorySlot(Slot.Container, Tier.One),
InventorySlot(Slot.Upgrade, Tier.Two),
InventorySlot(Slot.Upgrade, Tier.Two),
InventorySlot(Slot.Upgrade, Tier.Two),
InventorySlot(Slot.Upgrade, Tier.One),
InventorySlot(Slot.Upgrade, Tier.One),
InventorySlot(Slot.Upgrade, Tier.One),
InventorySlot(Slot.None, Tier.None),
InventorySlot(Slot.None, Tier.None),
InventorySlot(Slot.None, Tier.None),
InventorySlot(Slot.Card, Tier.Two),
InventorySlot(Slot.Card, Tier.One),
InventorySlot(Slot.None, Tier.None),
InventorySlot(Slot.CPU, Tier.Two),
InventorySlot(Slot.Memory, Tier.Two),
InventorySlot(Slot.Memory, Tier.Two),
InventorySlot(Slot.Floppy, Tier.Any),
InventorySlot(Slot.HDD, Tier.Two),
InventorySlot(Slot.None, Tier.None)
),
Array(
InventorySlot(Slot.None, Tier.None),
InventorySlot(Slot.Container, Tier.Three),
InventorySlot(Slot.Container, Tier.Three),
InventorySlot(Slot.Container, Tier.Two),
InventorySlot(Slot.Upgrade, Tier.Three),
InventorySlot(Slot.Upgrade, Tier.Three),
InventorySlot(Slot.Upgrade, Tier.Three),
InventorySlot(Slot.Upgrade, Tier.Two),
InventorySlot(Slot.Upgrade, Tier.Two),
InventorySlot(Slot.Upgrade, Tier.Two),
InventorySlot(Slot.Upgrade, Tier.One),
InventorySlot(Slot.Upgrade, Tier.One),
InventorySlot(Slot.Upgrade, Tier.One),
InventorySlot(Slot.Card, Tier.Three),
InventorySlot(Slot.Card, Tier.Two),
InventorySlot(Slot.Card, Tier.Two),
InventorySlot(Slot.CPU, Tier.Three),
InventorySlot(Slot.Memory, Tier.Three),
InventorySlot(Slot.Memory, Tier.Three),
InventorySlot(Slot.Floppy, Tier.Any),
InventorySlot(Slot.HDD, Tier.Three),
InventorySlot(Slot.HDD, Tier.Two)
),
Array(
InventorySlot(Slot.None, Tier.None),
InventorySlot(Slot.Container, Tier.Three),
InventorySlot(Slot.Container, Tier.Three),
InventorySlot(Slot.Container, Tier.Three),
InventorySlot(Slot.Upgrade, Tier.Three),
InventorySlot(Slot.Upgrade, Tier.Three),
InventorySlot(Slot.Upgrade, Tier.Three),
InventorySlot(Slot.Upgrade, Tier.Three),
InventorySlot(Slot.Upgrade, Tier.Three),
InventorySlot(Slot.Upgrade, Tier.Three),
InventorySlot(Slot.Upgrade, Tier.Three),
InventorySlot(Slot.Upgrade, Tier.Three),
InventorySlot(Slot.Upgrade, Tier.Three),
InventorySlot(Slot.Card, Tier.Three),
InventorySlot(Slot.Card, Tier.Three),
InventorySlot(Slot.Card, Tier.Three),
InventorySlot(Slot.CPU, Tier.Three),
InventorySlot(Slot.Memory, Tier.Three),
InventorySlot(Slot.Memory, Tier.Three),
InventorySlot(Slot.Floppy, Tier.Any),
InventorySlot(Slot.HDD, Tier.Three),
InventorySlot(Slot.HDD, Tier.Three)
)
)
val server = Array(
Array(
InventorySlot(Slot.Card, Tier.Two),

View File

@ -10,6 +10,7 @@ import li.cil.oc.common.event._
import li.cil.oc.common.item.Tablet
import li.cil.oc.common.multipart.MultiPart
import li.cil.oc.common.recipe.Recipes
import li.cil.oc.common.template.RobotTemplate
import li.cil.oc.server._
import li.cil.oc.server.component.machine
import li.cil.oc.server.component.machine.{LuaJLuaArchitecture, NativeLuaArchitecture}
@ -115,6 +116,9 @@ class Proxy {
api.Driver.add(driver.converter.FluidTankInfo)
api.Driver.add(driver.converter.ItemStack)
OpenComputers.log.info("Initializing assembler templates.")
RobotTemplate.register()
OpenComputers.log.info("Initializing loot disks.")
Loot.init()

View File

@ -7,18 +7,18 @@ import li.cil.oc.util.SideTracker
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.inventory.{IInventory, Slot}
class DynamicComponentSlot(val container: Player, inventory: IInventory, index: Int, x: Int, y: Int, val info: Array[Array[InventorySlot]], val tierGetter: () => Int) extends Slot(inventory, index, x, y) with ComponentSlot {
class DynamicComponentSlot(val container: Player, inventory: IInventory, index: Int, x: Int, y: Int, val info: DynamicComponentSlot => InventorySlot, val containerTierGetter: () => Int) extends Slot(inventory, index, x, y) with ComponentSlot {
override def tier = {
val mainTier = tierGetter()
if (mainTier >= 0) info(mainTier)(getSlotIndex).tier
val mainTier = containerTierGetter()
if (mainTier >= 0) info(this).tier
else mainTier
}
def tierIcon = Icons.get(tier)
def slot = {
val mainTier = tierGetter()
if (mainTier >= 0) info(tierGetter())(getSlotIndex).slot
val mainTier = containerTierGetter()
if (mainTier >= 0) info(this).slot
else common.Slot.None
}

View File

@ -2,6 +2,7 @@ package li.cil.oc.common.container
import li.cil.oc.common
import li.cil.oc.common.InventorySlots.InventorySlot
import li.cil.oc.common.Tier
import li.cil.oc.util.SideTracker
import net.minecraft.entity.player.{EntityPlayer, InventoryPlayer}
import net.minecraft.inventory.{Container, ICrafting, IInventory, Slot}
@ -90,9 +91,14 @@ abstract class Player(val playerInventory: InventoryPlayer, val otherInventory:
addSlotToContainer(new StaticComponentSlot(this, otherInventory, index, x, y, slot, tier))
}
def addSlotToContainer(x: Int, y: Int, info: Array[Array[InventorySlot]], tierGetter: () => Int) {
def addSlotToContainer(x: Int, y: Int, info: Array[Array[InventorySlot]], containerTierGetter: () => Int) {
val index = inventorySlots.size
addSlotToContainer(new DynamicComponentSlot(this, otherInventory, index, x, y, info, tierGetter))
addSlotToContainer(new DynamicComponentSlot(this, otherInventory, index, x, y, slot => info(slot.containerTierGetter())(slot.getSlotIndex), containerTierGetter))
}
def addSlotToContainer(x: Int, y: Int, info: DynamicComponentSlot => InventorySlot) {
val index = inventorySlots.size
addSlotToContainer(new DynamicComponentSlot(this, otherInventory, index, x, y, info, () => Tier.One))
}
/** Render player inventory at the specified coordinates. */

View File

@ -2,11 +2,12 @@ package li.cil.oc.common.container
import cpw.mods.fml.relauncher.{Side, SideOnly}
import li.cil.oc.client.gui.Icons
import li.cil.oc.common.InventorySlots.InventorySlot
import li.cil.oc.common.template.AssemblerTemplates
import li.cil.oc.common.tileentity
import li.cil.oc.util.SideTracker
import li.cil.oc.{Settings, common}
import li.cil.oc.common.{InventorySlots, tileentity}
import li.cil.oc.util.{ItemUtils, SideTracker}
import net.minecraft.entity.player.InventoryPlayer
import net.minecraft.inventory.Slot
class RobotAssembler(playerInventory: InventoryPlayer, val assembler: tileentity.RobotAssembler) extends Player(playerInventory, assembler) {
// Computer case.
@ -20,34 +21,46 @@ class RobotAssembler(playerInventory: InventoryPlayer, val assembler: tileentity
})
}
def caseTier = ItemUtils.caseTier(inventorySlots.get(0).asInstanceOf[Slot].getStack)
private def slotInfo(slot: DynamicComponentSlot) = {
AssemblerTemplates.select(getSlot(0).getStack) match {
case Some(template) =>
val index = slot.getSlotIndex
val tplSlot =
if ((1 until 4) contains index) template.containerSlots(index - 1)
else if ((4 until 13) contains index) template.upgradeSlots(index - 4)
else if ((13 until 21) contains index) template.componentSlots(index - 13)
else AssemblerTemplates.NoSlot
new InventorySlot(tplSlot.kind, tplSlot.tier)
case _ => new InventorySlot(common.Slot.None, common.Tier.None)
}
}
// Component containers.
for (i <- 0 until 3) {
addSlotToContainer(34 + i * slotSize, 70, InventorySlots.assembler, () => caseTier)
addSlotToContainer(34 + i * slotSize, 70, slotInfo _)
}
// Components.
for (i <- 0 until 9) {
addSlotToContainer(34 + (i % 3) * slotSize, 12 + (i / 3) * slotSize, InventorySlots.assembler, () => caseTier)
addSlotToContainer(34 + (i % 3) * slotSize, 12 + (i / 3) * slotSize, slotInfo _)
}
// Cards.
for (i <- 0 until 3) {
addSlotToContainer(104, 12 + i * slotSize, InventorySlots.assembler, () => caseTier)
addSlotToContainer(104, 12 + i * slotSize, slotInfo _)
}
// CPU.
addSlotToContainer(126, 12, InventorySlots.assembler, () => caseTier)
addSlotToContainer(126, 12, slotInfo _)
// RAM.
for (i <- 0 until 2) {
addSlotToContainer(126, 30 + i * slotSize, InventorySlots.assembler, () => caseTier)
addSlotToContainer(126, 30 + i * slotSize, slotInfo _)
}
// Floppy + HDDs.
for (i <- 0 until 3) {
addSlotToContainer(148, 12 + i * slotSize, InventorySlots.assembler, () => caseTier)
addSlotToContainer(148, 12 + i * slotSize, slotInfo _)
}
// Show the player's inventory.

View File

@ -0,0 +1,93 @@
package li.cil.oc.common.template
import java.lang.reflect.{Method, Modifier}
import li.cil.oc.common.{Slot, Tier}
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.{OpenComputers, api}
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.util.IChatComponent
import net.minecraftforge.common.util.Constants.NBT
import scala.collection.mutable
object AssemblerTemplates {
val NoSlot = new Slot(Slot.None, Tier.None, None)
val templates = mutable.ArrayBuffer.empty[Template]
def add(template: NBTTagCompound): Unit = try {
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
templates += new Template(selector, validator, assembler, containerSlots, upgradeSlots, componentSlots)
}
catch {
case t: Throwable => OpenComputers.log.warn("Failed registering assembler template.", t)
}
def select(stack: ItemStack) = templates.find(_.select(stack))
class Template(val selector: Method,
val validator: Method,
val assembler: Method,
val containerSlots: Array[Slot],
val upgradeSlots: Array[Slot],
val componentSlots: Array[Slot]) {
def select(stack: ItemStack) = tryInvokeStatic(selector, stack)(false)
def validate(inventory: IInventory) = tryInvokeStatic(validator, inventory)(null: Array[AnyRef]) match {
case Array(valid: java.lang.Boolean, progress: IChatComponent, warnings: Array[IChatComponent]) => (valid: Boolean, progress, warnings)
case Array(valid: java.lang.Boolean, progress: IChatComponent) => (valid: Boolean, progress, Array.empty[IChatComponent])
case Array(valid: java.lang.Boolean) => (valid: Boolean, null, Array.empty[IChatComponent])
case _ => (false, null, Array.empty[IChatComponent])
}
def assemble(inventory: IInventory) = tryInvokeStatic(assembler, inventory)(null: Array[AnyRef]) match {
case Array(stack: ItemStack, energy: java.lang.Double) => (stack, energy: Double)
case Array(stack: ItemStack) => (stack, 0.0)
case _ => (null, 0.0)
}
}
class Slot(val kind: String, val tier: Int, val validator: Option[Method]) {
def validate(inventory: IInventory, slot: Int, stack: ItemStack) = validator match {
case Some(method) => tryInvokeStatic(method, inventory, slot.underlying(), stack)(false)
case _ => Option(api.Driver.driverFor(stack)) match {
case Some(driver) => validateInternal(stack, driver) && Slot.fromApi(driver.slot(stack)) == kind
case _ => false
}
}
protected def validateInternal(stack: ItemStack, driver: api.driver.Item) = driver.tier(stack) <= tier
}
private def parseSlot(nbt: NBTTagCompound, kindOverride: Option[String] = 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.None
val validator = if (nbt.hasKey("validator")) Option(getStaticMethod(nbt.getString("validator"), classOf[ItemStack], classOf[Int], classOf[ItemStack])) else None
new Slot(kind, tier, validator)
}
private def getStaticMethod(name: String, signature: Class[_]*) = {
val nameSplit = name.lastIndexOf('.')
val className = name.substring(0, nameSplit)
val methodName = name.substring(nameSplit + 1)
val clazz = Class.forName(className)
val method = clazz.getDeclaredMethod(methodName, signature: _*)
if (!Modifier.isStatic(method.getModifiers)) throw new IllegalArgumentException(s"Method $name is not static.")
method
}
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)
default
}
}

View File

@ -0,0 +1,286 @@
package li.cil.oc.common.template
import cpw.mods.fml.common.event.FMLInterModComms
import li.cil.oc.api.driver.{Inventory, Memory, Processor, UpgradeContainer}
import li.cil.oc.common.{Slot, Tier}
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ItemUtils
import li.cil.oc.{Localization, Settings, api}
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack
import net.minecraft.nbt.{NBTTagCompound, NBTTagList}
import net.minecraft.util.IChatComponent
import scala.collection.mutable
object RobotTemplate {
def selectTier1(stack: ItemStack) = ItemUtils.caseTier(stack) == Tier.One
def selectTier2(stack: ItemStack) = ItemUtils.caseTier(stack) == Tier.Two
def selectTier3(stack: ItemStack) = ItemUtils.caseTier(stack) == Tier.Three
def selectCreative(stack: ItemStack) = ItemUtils.caseTier(stack) == Tier.Four
def validate(inventory: IInventory): Array[AnyRef] = {
val hasCase = ItemUtils.caseTier(inventory.getStackInSlot(0)) != Tier.None
val hasCPU = RobotTemplate.hasCPU(inventory)
val hasRAM = RobotTemplate.hasRAM(inventory)
val complexity = RobotTemplate.complexity(inventory)
val maxComplexity = RobotTemplate.maxComplexity(inventory)
val valid = hasCase && hasCPU && hasRAM && complexity <= maxComplexity
val progress =
if (!hasCPU) Localization.Assembler.InsertCPU
else if (!hasRAM) Localization.Assembler.InsertRAM
else Localization.Assembler.Complexity(complexity, maxComplexity)
val warnings = mutable.ArrayBuffer.empty[IChatComponent]
for ((name, check) <- suggestedComponents) {
if (!check(inventory)) {
warnings += Localization.Assembler.Warning(name)
}
}
if (warnings.length > 0) {
warnings.prepend(Localization.Assembler.Warnings)
}
Array(valid: java.lang.Boolean, progress, warnings.toArray)
}
def assemble(inventory: IInventory) = {
val items = (0 until inventory.getSizeInventory).map(inventory.getStackInSlot)
val data = new ItemUtils.RobotData()
data.tier = ItemUtils.caseTier(inventory.getStackInSlot(0))
data.name = ItemUtils.RobotData.randomName
data.robotEnergy = 50000
data.totalEnergy = data.robotEnergy
data.containers = items.slice(1, 4).filter(_ != null).toArray
data.components = items.drop(4).filter(_ != null).toArray
val stack = api.Items.get("robot").createItemStack(1)
data.save(stack)
val energy = Settings.get.robotBaseCost + complexity(inventory) * Settings.get.robotComplexityCost
Array(stack, energy: java.lang.Double)
}
def register() {
// Tier 1
{
val nbt = new NBTTagCompound()
nbt.setString("select", "li.cil.oc.common.template.RobotTemplate.selectTier1")
nbt.setString("validate", "li.cil.oc.common.template.RobotTemplate.validate")
nbt.setString("assemble", "li.cil.oc.common.template.RobotTemplate.assemble")
val containerSlots = new NBTTagList()
containerSlots.appendTag(Map("tier" -> Tier.Two))
containerSlots.appendTag(Map("tier" -> Tier.One))
containerSlots.appendTag(Map("tier" -> Tier.One))
nbt.setTag("containerSlots", containerSlots)
val upgradeSlots = new NBTTagList()
upgradeSlots.appendTag(Map("tier" -> Tier.One))
upgradeSlots.appendTag(Map("tier" -> Tier.One))
upgradeSlots.appendTag(Map("tier" -> Tier.One))
nbt.setTag("upgradeSlots", upgradeSlots)
val componentSlots = new NBTTagList()
componentSlots.appendTag(Map("type" -> Slot.Card, "tier" -> Tier.One))
componentSlots.appendTag(new NBTTagCompound())
componentSlots.appendTag(new NBTTagCompound())
componentSlots.appendTag(Map("type" -> Slot.CPU, "tier" -> Tier.One))
componentSlots.appendTag(Map("type" -> Slot.Memory, "tier" -> Tier.One))
componentSlots.appendTag(Map("type" -> Slot.Memory, "tier" -> Tier.One))
componentSlots.appendTag(Map("type" -> Slot.Floppy, "tier" -> Tier.Any))
componentSlots.appendTag(Map("type" -> Slot.HDD, "tier" -> Tier.One))
nbt.setTag("componentSlots", componentSlots)
FMLInterModComms.sendMessage("OpenComputers", "registerAssemblerTemplate", nbt)
}
// Tier 2
{
val nbt = new NBTTagCompound()
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")
val containerSlots = new NBTTagList()
containerSlots.appendTag(Map("tier" -> Tier.Three))
containerSlots.appendTag(Map("tier" -> Tier.Two))
containerSlots.appendTag(Map("tier" -> Tier.One))
nbt.setTag("containerSlots", containerSlots)
val upgradeSlots = new NBTTagList()
upgradeSlots.appendTag(Map("tier" -> Tier.Two))
upgradeSlots.appendTag(Map("tier" -> Tier.Two))
upgradeSlots.appendTag(Map("tier" -> Tier.Two))
upgradeSlots.appendTag(Map("tier" -> Tier.One))
upgradeSlots.appendTag(Map("tier" -> Tier.One))
upgradeSlots.appendTag(Map("tier" -> Tier.One))
nbt.setTag("upgradeSlots", upgradeSlots)
val componentSlots = new NBTTagList()
componentSlots.appendTag(Map("type" -> Slot.Card, "tier" -> Tier.Two))
componentSlots.appendTag(Map("type" -> Slot.Card, "tier" -> Tier.One))
componentSlots.appendTag(new NBTTagCompound())
componentSlots.appendTag(Map("type" -> Slot.CPU, "tier" -> Tier.Two))
componentSlots.appendTag(Map("type" -> Slot.Memory, "tier" -> Tier.Two))
componentSlots.appendTag(Map("type" -> Slot.Memory, "tier" -> Tier.Two))
componentSlots.appendTag(Map("type" -> Slot.Floppy, "tier" -> Tier.Any))
componentSlots.appendTag(Map("type" -> Slot.HDD, "tier" -> Tier.Two))
nbt.setTag("componentSlots", componentSlots)
FMLInterModComms.sendMessage("OpenComputers", "registerAssemblerTemplate", nbt)
}
// Tier 3
{
val nbt = new NBTTagCompound()
nbt.setString("select", "li.cil.oc.common.template.RobotTemplate.selectTier3")
nbt.setString("validate", "li.cil.oc.common.template.RobotTemplate.validate")
nbt.setString("assemble", "li.cil.oc.common.template.RobotTemplate.assemble")
val containerSlots = new NBTTagList()
containerSlots.appendTag(Map("tier" -> Tier.Three))
containerSlots.appendTag(Map("tier" -> Tier.Two))
containerSlots.appendTag(Map("tier" -> Tier.Two))
nbt.setTag("containerSlots", containerSlots)
val upgradeSlots = new NBTTagList()
upgradeSlots.appendTag(Map("tier" -> Tier.Three))
upgradeSlots.appendTag(Map("tier" -> Tier.Three))
upgradeSlots.appendTag(Map("tier" -> Tier.Three))
upgradeSlots.appendTag(Map("tier" -> Tier.Two))
upgradeSlots.appendTag(Map("tier" -> Tier.Two))
upgradeSlots.appendTag(Map("tier" -> Tier.Two))
upgradeSlots.appendTag(Map("tier" -> Tier.One))
upgradeSlots.appendTag(Map("tier" -> Tier.One))
upgradeSlots.appendTag(Map("tier" -> Tier.One))
nbt.setTag("upgradeSlots", upgradeSlots)
val componentSlots = new NBTTagList()
componentSlots.appendTag(Map("type" -> Slot.Card, "tier" -> Tier.Three))
componentSlots.appendTag(Map("type" -> Slot.Card, "tier" -> Tier.Two))
componentSlots.appendTag(Map("type" -> Slot.Card, "tier" -> Tier.Two))
componentSlots.appendTag(Map("type" -> Slot.CPU, "tier" -> Tier.Three))
componentSlots.appendTag(Map("type" -> Slot.Memory, "tier" -> Tier.Three))
componentSlots.appendTag(Map("type" -> Slot.Memory, "tier" -> Tier.Three))
componentSlots.appendTag(Map("type" -> Slot.Floppy, "tier" -> Tier.Any))
componentSlots.appendTag(Map("type" -> Slot.HDD, "tier" -> Tier.Three))
componentSlots.appendTag(Map("type" -> Slot.HDD, "tier" -> Tier.Two))
nbt.setTag("componentSlots", componentSlots)
FMLInterModComms.sendMessage("OpenComputers", "registerAssemblerTemplate", nbt)
}
// Creative
{
val nbt = new NBTTagCompound()
nbt.setString("select", "li.cil.oc.common.template.RobotTemplate.selectCreative")
nbt.setString("validate", "li.cil.oc.common.template.RobotTemplate.validate")
nbt.setString("assemble", "li.cil.oc.common.template.RobotTemplate.assemble")
val containerSlots = new NBTTagList()
containerSlots.appendTag(Map("tier" -> Tier.Three))
containerSlots.appendTag(Map("tier" -> Tier.Three))
containerSlots.appendTag(Map("tier" -> Tier.Three))
nbt.setTag("containerSlots", containerSlots)
val upgradeSlots = new NBTTagList()
upgradeSlots.appendTag(Map("tier" -> Tier.Three))
upgradeSlots.appendTag(Map("tier" -> Tier.Three))
upgradeSlots.appendTag(Map("tier" -> Tier.Three))
upgradeSlots.appendTag(Map("tier" -> Tier.Three))
upgradeSlots.appendTag(Map("tier" -> Tier.Three))
upgradeSlots.appendTag(Map("tier" -> Tier.Three))
upgradeSlots.appendTag(Map("tier" -> Tier.Three))
upgradeSlots.appendTag(Map("tier" -> Tier.Three))
upgradeSlots.appendTag(Map("tier" -> Tier.Three))
nbt.setTag("upgradeSlots", upgradeSlots)
val componentSlots = new NBTTagList()
componentSlots.appendTag(Map("type" -> Slot.Card, "tier" -> Tier.Three))
componentSlots.appendTag(Map("type" -> Slot.Card, "tier" -> Tier.Three))
componentSlots.appendTag(Map("type" -> Slot.Card, "tier" -> Tier.Three))
componentSlots.appendTag(Map("type" -> Slot.CPU, "tier" -> Tier.Three))
componentSlots.appendTag(Map("type" -> Slot.Memory, "tier" -> Tier.Three))
componentSlots.appendTag(Map("type" -> Slot.Memory, "tier" -> Tier.Three))
componentSlots.appendTag(Map("type" -> Slot.Floppy, "tier" -> Tier.Any))
componentSlots.appendTag(Map("type" -> Slot.HDD, "tier" -> Tier.Three))
componentSlots.appendTag(Map("type" -> Slot.HDD, "tier" -> Tier.Three))
nbt.setTag("componentSlots", componentSlots)
FMLInterModComms.sendMessage("OpenComputers", "registerAssemblerTemplate", nbt)
}
}
private val suggestedComponents = Array(
"Screen" -> hasComponent("screen1") _,
"Keyboard" -> hasComponent("keyboard") _,
"GraphicsCard" -> ((inventory: IInventory) => Array("graphicsCard1", "graphicsCard2", "graphicsCard3").exists(name => hasComponent(name)(inventory))),
"Inventory" -> hasInventory _,
"OS" -> hasFileSystem _)
private def exists(inventory: IInventory, p: ItemStack => Boolean) = {
(0 until inventory.getSizeInventory).exists(slot => Option(inventory.getStackInSlot(slot)) match {
case Some(stack) => p(stack)
case _ => false
})
}
private def hasCPU(inventory: IInventory) = exists(inventory, api.Driver.driverFor(_) match {
case _: Processor => true
case _ => false
})
private def hasRAM(inventory: IInventory) = exists(inventory, api.Driver.driverFor(_) match {
case _: Memory => true
case _ => false
})
private def hasComponent(name: String)(inventory: IInventory) = exists(inventory, stack => Option(api.Items.get(stack)) match {
case Some(descriptor) => descriptor.name == name
case _ => false
})
private def hasInventory(inventory: IInventory) = exists(inventory, api.Driver.driverFor(_) match {
case _: Inventory => true
case _ => false
})
private def hasFileSystem(inventory: IInventory) = exists(inventory, stack => Option(api.Driver.driverFor(stack)) match {
case Some(driver) => Slot.fromApi(driver.slot(stack)) == Slot.Floppy || Slot.fromApi(driver.slot(stack)) == Slot.HDD
case _ => false
})
private def complexity(inventory: IInventory) = {
var acc = 0
for (slot <- 1 until inventory.getSizeInventory) {
val stack = inventory.getStackInSlot(slot)
acc += (Option(api.Driver.driverFor(stack)) match {
case Some(driver: Processor) => 0 // CPUs are exempt, since they control the limit.
case Some(driver: UpgradeContainer) => (1 + driver.tier(stack)) * 2
case Some(driver) => 1 + driver.tier(stack)
case _ => 0
})
}
acc
}
private def maxComplexity(inventory: IInventory) = {
val caseTier = ItemUtils.caseTier(inventory.getStackInSlot(0))
val cpuTier = (0 until inventory.getSizeInventory).foldRight(0)((slot, acc) => {
val stack = inventory.getStackInSlot(slot)
acc + (api.Driver.driverFor(stack) match {
case processor: Processor => processor.tier(stack)
case _ => 0
})
})
if (caseTier >= Tier.One && cpuTier >= Tier.One) {
Settings.robotComplexityByTier(caseTier) - (caseTier - cpuTier) * 6
}
else 0
}
}

View File

@ -1,13 +1,10 @@
package li.cil.oc.common.tileentity
import cpw.mods.fml.relauncher.{Side, SideOnly}
import li.cil.oc.api.Driver
import li.cil.oc.api.driver.UpgradeContainer
import li.cil.oc.api.network._
import li.cil.oc.common.{InventorySlots, Slot, Tier}
import li.cil.oc.common.template.AssemblerTemplates
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ItemUtils
import li.cil.oc.{Settings, api}
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
@ -19,7 +16,7 @@ class RobotAssembler extends traits.Environment with traits.PowerAcceptor with t
withConnector(Settings.get.bufferConverter).
create()
var robot: Option[ItemStack] = None
var output: Option[ItemStack] = None
var totalRequiredEnergy = 0.0
@ -45,61 +42,41 @@ class RobotAssembler extends traits.Environment with traits.PowerAcceptor with t
// ----------------------------------------------------------------------- //
def complexity = items.drop(1).foldLeft(0)((acc, stack) => acc + (Option(api.Driver.driverFor(stack.orNull)) match {
case Some(driver: UpgradeContainer) => (1 + driver.tier(stack.get)) * 2
case Some(driver) => 1 + driver.tier(stack.get)
case _ => 0
}))
def maxComplexity = {
val caseTier = ItemUtils.caseTier(items(0).orNull)
if (caseTier >= 0) Settings.robotComplexityByTier(caseTier) else 0
}
def start(finishImmediately: Boolean = false): Boolean = this.synchronized {
if (!isAssembling && robot.isEmpty && complexity <= maxComplexity) {
for (slot <- 0 until getSizeInventory) {
val stack = getStackInSlot(slot)
if (stack != null && !isItemValidForSlot(slot, stack)) return false
}
val data = new ItemUtils.RobotData()
data.tier = ItemUtils.caseTier(items(0).get)
data.name = ItemUtils.RobotData.randomName
data.robotEnergy = 50000
data.totalEnergy = data.robotEnergy
data.containers = items.take(4).drop(1).collect {
case Some(item) => item
}
data.components = items.drop(4).collect {
case Some(item) => item
}
val stack = api.Items.get("robot").createItemStack(1)
data.save(stack)
robot = Some(stack)
if (finishImmediately || data.tier == Tier.Four) {
// Creative tier, finish instantly.
totalRequiredEnergy = 0
}
else {
totalRequiredEnergy = math.max(1, Settings.get.robotBaseCost + complexity * Settings.get.robotComplexityCost)
}
requiredEnergy = totalRequiredEnergy
ServerPacketSender.sendRobotAssembling(this, assembling = true)
AssemblerTemplates.select(getStackInSlot(0)) match {
case Some(template) if !isAssembling && output.isEmpty && template.validate(this)._1 =>
for (slot <- 0 until getSizeInventory) {
val stack = getStackInSlot(slot)
if (stack != null && !isItemValidForSlot(slot, stack)) return false
}
val (stack, energy) = template.assemble(this)
output = Some(stack)
if (finishImmediately) {
totalRequiredEnergy = 0
}
else {
totalRequiredEnergy = math.max(1, energy)
}
requiredEnergy = totalRequiredEnergy
ServerPacketSender.sendRobotAssembling(this, assembling = true)
for (slot <- 0 until getSizeInventory) items(slot) = None
markDirty()
for (slot <- 0 until getSizeInventory) items(slot) = None
markDirty()
true
true
case _ => false
}
else false
}
// ----------------------------------------------------------------------- //
@Callback(doc = """function(): string, number[, number] -- The current state of the assember, `busy' or `idle', followed by the progress or complexity and maximum complexity, respectively.""")
@Callback(doc = """function(): string, number or boolean -- The current state of the assembler, `busy' or `idle', followed by the progress or template validity, respectively.""")
def status(context: Context, args: Arguments): Array[Object] = {
if (isAssembling) result("busy", progress)
else result("idle", complexity, maxComplexity)
else AssemblerTemplates.select(getStackInSlot(0)) match {
case Some(template) if template.validate(this)._1 => result("idle", true)
case _ => result("idle", false)
}
}
@Callback(doc = """function():boolean -- Start assembling, if possible. Returns whether assembly was started or not.""")
@ -111,25 +88,29 @@ class RobotAssembler extends traits.Environment with traits.PowerAcceptor with t
override def updateEntity() {
super.updateEntity()
if (robot.isDefined && world.getTotalWorldTime % Settings.get.tickFrequency == 0) {
if (output.isDefined && world.getTotalWorldTime % Settings.get.tickFrequency == 0) {
val want = math.max(1, math.min(requiredEnergy, Settings.get.assemblerTickAmount * Settings.get.tickFrequency))
val success = Settings.get.ignorePower || node.tryChangeBuffer(-want)
if (success) {
requiredEnergy -= want
}
if (requiredEnergy <= 0) {
setInventorySlotContents(0, robot.get)
robot = None
setInventorySlotContents(0, output.get)
output = None
requiredEnergy = 0
}
ServerPacketSender.sendRobotAssembling(this, success && robot.isDefined)
ServerPacketSender.sendRobotAssembling(this, success && output.isDefined)
}
}
override def readFromNBT(nbt: NBTTagCompound) {
super.readFromNBT(nbt)
if (nbt.hasKey(Settings.namespace + "robot")) {
robot = Option(ItemStack.loadItemStackFromNBT(nbt.getCompoundTag(Settings.namespace + "robot")))
if (nbt.hasKey(Settings.namespace + "output")) {
output = Option(ItemStack.loadItemStackFromNBT(nbt.getCompoundTag(Settings.namespace + "output")))
}
else if (nbt.hasKey(Settings.namespace + "robot")) {
// Backwards compatibility.
output = Option(ItemStack.loadItemStackFromNBT(nbt.getCompoundTag(Settings.namespace + "robot")))
}
totalRequiredEnergy = nbt.getDouble(Settings.namespace + "total")
requiredEnergy = nbt.getDouble(Settings.namespace + "remaining")
@ -137,7 +118,7 @@ class RobotAssembler extends traits.Environment with traits.PowerAcceptor with t
override def writeToNBT(nbt: NBTTagCompound) {
super.writeToNBT(nbt)
robot.foreach(stack => nbt.setNewCompoundTag(Settings.namespace + "robot", stack.writeToNBT))
output.foreach(stack => nbt.setNewCompoundTag(Settings.namespace + "output", stack.writeToNBT))
nbt.setDouble(Settings.namespace + "total", totalRequiredEnergy)
nbt.setDouble(Settings.namespace + "remaining", requiredEnergy)
}
@ -155,22 +136,22 @@ class RobotAssembler extends traits.Environment with traits.PowerAcceptor with t
// ----------------------------------------------------------------------- //
override def getSizeInventory = InventorySlots.assembler(0).length
override def getSizeInventory = 22
override def getInventoryStackLimit = 1
override def isItemValidForSlot(slot: Int, stack: ItemStack) =
if (slot == 0) {
!isAssembling && ItemUtils.caseTier(stack) != Tier.None
!isAssembling && AssemblerTemplates.select(stack).isDefined
}
else {
val caseTier = ItemUtils.caseTier(items(0).orNull)
caseTier != Tier.None && {
val info = InventorySlots.assembler(caseTier)(slot)
Option(Driver.driverFor(stack)) match {
case Some(driver) if info.slot != Slot.None && info.tier != Tier.None => Slot.fromApi(driver.slot(stack)) == info.slot && driver.tier(stack) <= info.tier
case _ => false
}
}
else AssemblerTemplates.select(getStackInSlot(0)) match {
case Some(template) =>
val tplSlot =
if ((1 until 4) contains slot) template.containerSlots(slot - 1)
else if ((4 until 13) contains slot) template.upgradeSlots(slot - 4)
else if ((13 until 21) contains slot) template.componentSlots(slot - 13)
else AssemblerTemplates.NoSlot
tplSlot.validate(this, slot, stack)
case _ => false
}
}

View File

@ -33,6 +33,24 @@ object ExtendedNBT {
nbt
}
implicit def toNbt(value: Map[String, _]): NBTTagCompound = {
val nbt = new NBTTagCompound()
for ((key, value) <- value) value match {
case value: Byte => nbt.setTag(key, value)
case value: Short => nbt.setTag(key, value)
case value: Int => nbt.setTag(key, value)
case value: Array[Int] => nbt.setTag(key, value)
case value: Long => nbt.setTag(key, value)
case value: Float => nbt.setTag(key, value)
case value: Double => nbt.setTag(key, value)
case value: Array[Byte] => nbt.setTag(key, value)
case value: String => nbt.setTag(key, value)
case value: ItemStack => nbt.setTag(key, value)
case _ =>
}
nbt
}
implicit def byteIterableToNbt(value: Iterable[Byte]) = value.map(toNbt)
implicit def shortIterableToNbt(value: Iterable[Short]) = value.map(toNbt)