Raid blocks will now keep their inventory when broken, allowing relocation without losing their data.

This commit is contained in:
Florian Nücke 2015-01-22 21:02:46 +01:00
parent fe4f63dc23
commit dfa9633491
30 changed files with 528 additions and 350 deletions

View File

@ -13,6 +13,7 @@ import li.cil.oc.api.Network
import li.cil.oc.api.detail.ItemInfo import li.cil.oc.api.detail.ItemInfo
import li.cil.oc.client.renderer.PetRenderer import li.cil.oc.client.renderer.PetRenderer
import li.cil.oc.client.{PacketSender => ClientPacketSender} import li.cil.oc.client.{PacketSender => ClientPacketSender}
import li.cil.oc.common.item.data.MicrocontrollerData
import li.cil.oc.common.tileentity.traits.power import li.cil.oc.common.tileentity.traits.power
import li.cil.oc.integration.Mods import li.cil.oc.integration.Mods
import li.cil.oc.integration.util import li.cil.oc.integration.util
@ -163,12 +164,12 @@ object EventHandler {
didRecraft = recraft(e, mcu, stack => { didRecraft = recraft(e, mcu, stack => {
// Restore EEPROM currently used in microcontroller. // Restore EEPROM currently used in microcontroller.
new ItemUtils.MicrocontrollerData(stack).components.find(api.Items.get(_) == eeprom) new MicrocontrollerData(stack).components.find(api.Items.get(_) == eeprom)
}) || didRecraft }) || didRecraft
didRecraft = recraft(e, drone, stack => { didRecraft = recraft(e, drone, stack => {
// Restore EEPROM currently used in drone. // Restore EEPROM currently used in drone.
new ItemUtils.MicrocontrollerData(stack).components.find(api.Items.get(_) == eeprom) new MicrocontrollerData(stack).components.find(api.Items.get(_) == eeprom)
}) || didRecraft }) || didRecraft
// Presents? // Presents?

View File

@ -5,9 +5,9 @@ import java.util
import li.cil.oc.Settings import li.cil.oc.Settings
import li.cil.oc.api import li.cil.oc.api
import li.cil.oc.client.KeyBindings import li.cil.oc.client.KeyBindings
import li.cil.oc.common.item.data.RobotData
import li.cil.oc.common.tileentity import li.cil.oc.common.tileentity
import li.cil.oc.util.ItemCosts import li.cil.oc.util.ItemCosts
import li.cil.oc.util.ItemUtils
import net.minecraft.block.Block import net.minecraft.block.Block
import net.minecraft.entity.player.EntityPlayer import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.EnumRarity import net.minecraft.item.EnumRarity
@ -60,7 +60,7 @@ class Item(value: Block) extends ItemBlock(value) {
// manually before it's placed to ensure different component addresses // manually before it's placed to ensure different component addresses
// in the different robots, to avoid interference of screens e.g. // in the different robots, to avoid interference of screens e.g.
val needsCopying = player.capabilities.isCreativeMode && api.Items.get(stack) == api.Items.get("robot") val needsCopying = player.capabilities.isCreativeMode && api.Items.get(stack) == api.Items.get("robot")
val stackToUse = if (needsCopying) new ItemUtils.RobotData(stack).copyItemStack() else stack val stackToUse = if (needsCopying) new RobotData(stack).copyItemStack() else stack
if (super.placeBlockAt(stackToUse, player, world, x, y, z, side, hitX, hitY, hitZ, metadata)) { if (super.placeBlockAt(stackToUse, player, world, x, y, z, side, hitX, hitY, hitZ, metadata)) {
// If it's a rotatable block try to make it face the player. // If it's a rotatable block try to make it face the player.
world.getTileEntity(x, y, z) match { world.getTileEntity(x, y, z) match {

View File

@ -5,11 +5,11 @@ import java.util
import li.cil.oc.Settings import li.cil.oc.Settings
import li.cil.oc.client.KeyBindings import li.cil.oc.client.KeyBindings
import li.cil.oc.common.Tier import li.cil.oc.common.Tier
import li.cil.oc.common.item.data.MicrocontrollerData
import li.cil.oc.common.tileentity import li.cil.oc.common.tileentity
import li.cil.oc.integration.util.NEI import li.cil.oc.integration.util.NEI
import li.cil.oc.integration.util.Wrench import li.cil.oc.integration.util.Wrench
import li.cil.oc.util.BlockPosition import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ItemUtils
import li.cil.oc.util.Rarity import li.cil.oc.util.Rarity
import net.minecraft.entity.EntityLivingBase import net.minecraft.entity.EntityLivingBase
import net.minecraft.entity.player.EntityPlayer import net.minecraft.entity.player.EntityPlayer
@ -18,7 +18,9 @@ import net.minecraft.util.MovingObjectPosition
import net.minecraft.world.World import net.minecraft.world.World
import net.minecraftforge.common.util.ForgeDirection import net.minecraftforge.common.util.ForgeDirection
class Microcontroller extends RedstoneAware with traits.PowerAcceptor with traits.StateAware { import scala.reflect.ClassTag
class Microcontroller(protected implicit val tileTag: ClassTag[tileentity.Microcontroller]) extends RedstoneAware with traits.PowerAcceptor with traits.StateAware with traits.CustomDrops[tileentity.Microcontroller] {
setCreativeTab(null) setCreativeTab(null)
NEI.hide(this) NEI.hide(this)
@ -39,17 +41,12 @@ class Microcontroller extends RedstoneAware with traits.PowerAcceptor with trait
case _ => null case _ => null
} }
// Custom drop logic for NBT tagged item stack.
override def getDrops(world: World, x: Int, y: Int, z: Int, metadata: Int, fortune: Int) = new java.util.ArrayList[ItemStack]()
override def onBlockPreDestroy(world: World, x: Int, y: Int, z: Int, metadata: Int) {}
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
override protected def tooltipTail(metadata: Int, stack: ItemStack, player: EntityPlayer, tooltip: util.List[String], advanced: Boolean) { override protected def tooltipTail(metadata: Int, stack: ItemStack, player: EntityPlayer, tooltip: util.List[String], advanced: Boolean) {
super.tooltipTail(metadata, stack, player, tooltip, advanced) super.tooltipTail(metadata, stack, player, tooltip, advanced)
if (KeyBindings.showExtendedTooltips) { if (KeyBindings.showExtendedTooltips) {
val info = new ItemUtils.MicrocontrollerData(stack) val info = new MicrocontrollerData(stack)
for (component <- info.components) { for (component <- info.components) {
tooltip.add("- " + component.getDisplayName) tooltip.add("- " + component.getDisplayName)
} }
@ -57,7 +54,7 @@ class Microcontroller extends RedstoneAware with traits.PowerAcceptor with trait
} }
override def rarity(stack: ItemStack) = { override def rarity(stack: ItemStack) = {
val data = new ItemUtils.MicrocontrollerData(stack) val data = new MicrocontrollerData(stack)
Rarity.byTier(data.tier) Rarity.byTier(data.tier)
} }
@ -85,26 +82,16 @@ class Microcontroller extends RedstoneAware with traits.PowerAcceptor with trait
else false else false
} }
override def onBlockPlacedBy(world: World, x: Int, y: Int, z: Int, entity: EntityLivingBase, stack: ItemStack) { override protected def doCustomInit(tileEntity: tileentity.Microcontroller, player: EntityLivingBase, stack: ItemStack): Unit = {
super.onBlockPlacedBy(world, x, y, z, entity, stack) super.doCustomInit(tileEntity, player, stack)
if (!world.isRemote) world.getTileEntity(x, y, z) match { tileEntity.info.load(stack)
case mcu: tileentity.Microcontroller => tileEntity.snooperNode.changeBuffer(tileEntity.info.storedEnergy - tileEntity.snooperNode.localBuffer)
mcu.info.load(stack)
mcu.snooperNode.changeBuffer(mcu.info.storedEnergy - mcu.snooperNode.localBuffer)
case _ =>
}
} }
override def removedByPlayer(world: World, player: EntityPlayer, x: Int, y: Int, z: Int, willHarvest: Boolean): Boolean = { override protected def doCustomDrops(tileEntity: tileentity.Microcontroller, player: EntityPlayer, willHarvest: Boolean): Unit = {
if (!world.isRemote) { super.doCustomDrops(tileEntity, player, willHarvest)
world.getTileEntity(x, y, z) match { tileEntity.saveComponents()
case mcu: tileentity.Microcontroller => tileEntity.info.storedEnergy = tileEntity.snooperNode.localBuffer.toInt
mcu.saveComponents() dropBlockAsItem(tileEntity.world, tileEntity.x, tileEntity.y, tileEntity.z, tileEntity.info.createItemStack())
mcu.info.storedEnergy = mcu.snooperNode.localBuffer.toInt
dropBlockAsItem(world, x, y, z, mcu.info.createItemStack())
case _ =>
}
}
super.removedByPlayer(world, player, x, y, z, willHarvest)
} }
} }

View File

@ -1,10 +1,19 @@
package li.cil.oc.common.block package li.cil.oc.common.block
import java.util
import li.cil.oc.client.KeyBindings
import li.cil.oc.common.GuiType import li.cil.oc.common.GuiType
import li.cil.oc.common.item.data.RaidData
import li.cil.oc.common.tileentity import li.cil.oc.common.tileentity
import net.minecraft.entity.EntityLivingBase
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack
import net.minecraft.world.World import net.minecraft.world.World
class Raid extends SimpleBlock with traits.GUI { import scala.reflect.ClassTag
class Raid(protected implicit val tileTag: ClassTag[tileentity.Raid]) extends SimpleBlock with traits.GUI with traits.CustomDrops[tileentity.Raid] {
override protected def customTextures = Array( override protected def customTextures = Array(
None, None,
None, None,
@ -16,6 +25,18 @@ class Raid extends SimpleBlock with traits.GUI {
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
override protected def tooltipTail(metadata: Int, stack: ItemStack, player: EntityPlayer, tooltip: util.List[String], advanced: Boolean) {
super.tooltipTail(metadata, stack, player, tooltip, advanced)
if (KeyBindings.showExtendedTooltips) {
val data = new RaidData(stack)
for (disk <- data.disks) {
tooltip.add("- " + disk.getDisplayName)
}
}
}
// ----------------------------------------------------------------------- //
override def guiType = GuiType.Raid override def guiType = GuiType.Raid
override def hasTileEntity(metadata: Int) = true override def hasTileEntity(metadata: Int) = true
@ -31,4 +52,28 @@ class Raid extends SimpleBlock with traits.GUI {
case raid: tileentity.Raid if raid.presence.forall(ok => ok) => 15 case raid: tileentity.Raid if raid.presence.forall(ok => ok) => 15
case _ => 0 case _ => 0
} }
override protected def doCustomInit(tileEntity: tileentity.Raid, player: EntityLivingBase, stack: ItemStack): Unit = {
super.doCustomInit(tileEntity, player, stack)
val data = new RaidData(stack)
for (i <- 0 until math.min(data.disks.length, tileEntity.getSizeInventory)) {
tileEntity.setInventorySlotContents(i, data.disks(i))
}
data.label.foreach(tileEntity.label.setLabel)
if (!data.filesystem.hasNoTags) {
tileEntity.tryCreateRaid(data.filesystem.getCompoundTag("node").getString("address"))
tileEntity.filesystem.foreach(_.load(data.filesystem))
}
}
override protected def doCustomDrops(tileEntity: tileentity.Raid, player: EntityPlayer, willHarvest: Boolean): Unit = {
super.doCustomDrops(tileEntity, player, willHarvest)
val stack = createItemStack()
val data = new RaidData()
data.disks = tileEntity.items.map(_.orNull)
tileEntity.filesystem.foreach(_.save(data.filesystem))
data.label = Option(tileEntity.label.getLabel)
data.save(stack)
dropBlockAsItem(tileEntity.world, tileEntity.x, tileEntity.y, tileEntity.z, stack)
}
} }

View File

@ -6,9 +6,9 @@ import cpw.mods.fml.relauncher.Side
import cpw.mods.fml.relauncher.SideOnly import cpw.mods.fml.relauncher.SideOnly
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.item.data.RobotData
import li.cil.oc.common.tileentity import li.cil.oc.common.tileentity
import li.cil.oc.integration.util.NEI import li.cil.oc.integration.util.NEI
import li.cil.oc.util.ItemUtils
import li.cil.oc.util.Rarity import li.cil.oc.util.Rarity
import net.minecraft.client.renderer.texture.IIconRegister import net.minecraft.client.renderer.texture.IIconRegister
import net.minecraft.entity.player.EntityPlayer import net.minecraft.entity.player.EntityPlayer
@ -52,7 +52,7 @@ class RobotAfterimage extends SimpleBlock with traits.SpecialBlock {
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
override def rarity(stack: ItemStack) = { override def rarity(stack: ItemStack) = {
val data = new ItemUtils.RobotData(stack) val data = new RobotData(stack)
Rarity.byTier(data.tier) Rarity.byTier(data.tier)
} }

View File

@ -9,11 +9,11 @@ import li.cil.oc.Settings
import li.cil.oc.api import li.cil.oc.api
import li.cil.oc.client.KeyBindings import li.cil.oc.client.KeyBindings
import li.cil.oc.common.GuiType import li.cil.oc.common.GuiType
import li.cil.oc.common.item.data.RobotData
import li.cil.oc.common.tileentity import li.cil.oc.common.tileentity
import li.cil.oc.integration.util.NEI import li.cil.oc.integration.util.NEI
import li.cil.oc.server.PacketSender import li.cil.oc.server.PacketSender
import li.cil.oc.server.component.robot import li.cil.oc.server.component.robot
import li.cil.oc.util.ItemUtils
import li.cil.oc.util.Rarity import li.cil.oc.util.Rarity
import li.cil.oc.util.Tooltip import li.cil.oc.util.Tooltip
import net.minecraft.client.renderer.texture.IIconRegister import net.minecraft.client.renderer.texture.IIconRegister
@ -68,7 +68,7 @@ class RobotProxy extends RedstoneAware with traits.SpecialBlock with traits.Stat
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
override def rarity(stack: ItemStack) = { override def rarity(stack: ItemStack) = {
val data = new ItemUtils.RobotData(stack) val data = new RobotData(stack)
Rarity.byTier(data.tier) Rarity.byTier(data.tier)
} }
@ -84,7 +84,7 @@ class RobotProxy extends RedstoneAware with traits.SpecialBlock with traits.Stat
override protected def tooltipTail(metadata: Int, stack: ItemStack, player: EntityPlayer, tooltip: util.List[String], advanced: Boolean) { override protected def tooltipTail(metadata: Int, stack: ItemStack, player: EntityPlayer, tooltip: util.List[String], advanced: Boolean) {
super.tooltipTail(metadata, stack, player, tooltip, advanced) super.tooltipTail(metadata, stack, player, tooltip, advanced)
if (KeyBindings.showExtendedTooltips) { if (KeyBindings.showExtendedTooltips) {
val info = new ItemUtils.RobotData(stack) val info = new RobotData(stack)
val components = info.containers ++ info.components val components = info.containers ++ info.components
if (components.length > 0) { if (components.length > 0) {
tooltip.addAll(Tooltip.get("Server.Components")) tooltip.addAll(Tooltip.get("Server.Components"))

View File

@ -0,0 +1,46 @@
package li.cil.oc.common.block.traits
import java.util
import li.cil.oc.common.block.SimpleBlock
import net.minecraft.entity.EntityLivingBase
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack
import net.minecraft.tileentity.TileEntity
import net.minecraft.world.World
import scala.reflect.ClassTag
trait CustomDrops[Tile <: TileEntity] extends SimpleBlock {
protected def tileTag: ClassTag[Tile]
override def getDrops(world: World, x: Int, y: Int, z: Int, metadata: Int, fortune: Int): util.ArrayList[ItemStack] = new java.util.ArrayList[ItemStack]()
override def onBlockPreDestroy(world: World, x: Int, y: Int, z: Int, metadata: Int): Unit = {}
override def removedByPlayer(world: World, player: EntityPlayer, x: Int, y: Int, z: Int, willHarvest: Boolean): Boolean = {
if (!world.isRemote) {
val matcher = tileTag
world.getTileEntity(x, y, z) match {
case matcher(tileEntity) => doCustomDrops(tileEntity, player, willHarvest)
case _ =>
}
}
super.removedByPlayer(world, player, x, y, z, willHarvest)
}
override def onBlockPlacedBy(world: World, x: Int, y: Int, z: Int, player: EntityLivingBase, stack: ItemStack): Unit = {
super.onBlockPlacedBy(world, x, y, z, player, stack)
if (!world.isRemote) {
val matcher = tileTag
world.getTileEntity(x, y, z) match {
case matcher(tileEntity) => doCustomInit(tileEntity, player, stack)
case _ =>
}
}
}
protected def doCustomInit(tileEntity: Tile, player: EntityLivingBase, stack: ItemStack): Unit = {}
protected def doCustomDrops(tileEntity: Tile, player: EntityPlayer, willHarvest: Boolean): Unit = {}
}

View File

@ -20,12 +20,12 @@ import li.cil.oc.common.Slot
import li.cil.oc.common.inventory.ComponentInventory import li.cil.oc.common.inventory.ComponentInventory
import li.cil.oc.common.inventory.Inventory import li.cil.oc.common.inventory.Inventory
import li.cil.oc.common.inventory.MultiTank import li.cil.oc.common.inventory.MultiTank
import li.cil.oc.common.item.data.MicrocontrollerData
import li.cil.oc.server.component import li.cil.oc.server.component
import li.cil.oc.util.BlockPosition import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedNBT._ import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ExtendedWorld._ import li.cil.oc.util.ExtendedWorld._
import li.cil.oc.util.InventoryUtils import li.cil.oc.util.InventoryUtils
import li.cil.oc.util.ItemUtils
import net.minecraft.block.material.Material import net.minecraft.block.material.Material
import net.minecraft.entity.Entity import net.minecraft.entity.Entity
import net.minecraft.entity.item.EntityItem import net.minecraft.entity.item.EntityItem
@ -62,7 +62,7 @@ class Drone(val world: World) extends Entity(world) with MachineHost with intern
var lastEnergyUpdate = 0 var lastEnergyUpdate = 0
// Logic stuff, components, machine and such. // Logic stuff, components, machine and such.
val info = new ItemUtils.MicrocontrollerData() val info = new MicrocontrollerData()
val machine = if (!world.isRemote) { val machine = if (!world.isRemote) {
val m = Machine.create(this) val m = Machine.create(this)
m.node.asInstanceOf[Connector].setLocalBufferSize(0) m.node.asInstanceOf[Connector].setLocalBufferSize(0)
@ -276,28 +276,48 @@ class Drone(val world: World) extends Entity(world) with MachineHost with intern
} }
def isRunning = dataWatcher.getWatchableObjectByte(2) != 0 def isRunning = dataWatcher.getWatchableObjectByte(2) != 0
def targetX = dataWatcher.getWatchableObjectFloat(3) def targetX = dataWatcher.getWatchableObjectFloat(3)
def targetY = dataWatcher.getWatchableObjectFloat(4) def targetY = dataWatcher.getWatchableObjectFloat(4)
def targetZ = dataWatcher.getWatchableObjectFloat(5) def targetZ = dataWatcher.getWatchableObjectFloat(5)
def targetAcceleration = dataWatcher.getWatchableObjectFloat(6) def targetAcceleration = dataWatcher.getWatchableObjectFloat(6)
def selectedSlot = dataWatcher.getWatchableObjectByte(7) & 0xFF def selectedSlot = dataWatcher.getWatchableObjectByte(7) & 0xFF
def globalBuffer = dataWatcher.getWatchableObjectInt(8) def globalBuffer = dataWatcher.getWatchableObjectInt(8)
def globalBufferSize = dataWatcher.getWatchableObjectInt(9) def globalBufferSize = dataWatcher.getWatchableObjectInt(9)
def statusText = dataWatcher.getWatchableObjectString(10) def statusText = dataWatcher.getWatchableObjectString(10)
def inventorySize = dataWatcher.getWatchableObjectByte(11) & 0xFF def inventorySize = dataWatcher.getWatchableObjectByte(11) & 0xFF
def lightColor = dataWatcher.getWatchableObjectInt(12) def lightColor = dataWatcher.getWatchableObjectInt(12)
def setRunning(value: Boolean) = dataWatcher.updateObject(2, byte2Byte(if (value) 1: Byte else 0: Byte)) def setRunning(value: Boolean) = dataWatcher.updateObject(2, byte2Byte(if (value) 1: Byte else 0: Byte))
// Round target values to low accuracy to avoid floating point errors accumulating. // Round target values to low accuracy to avoid floating point errors accumulating.
def targetX_=(value: Float): Unit = dataWatcher.updateObject(3, float2Float(math.round(value * 4) / 4f)) def targetX_=(value: Float): Unit = dataWatcher.updateObject(3, float2Float(math.round(value * 4) / 4f))
def targetY_=(value: Float): Unit = dataWatcher.updateObject(4, float2Float(math.round(value * 4) / 4f)) def targetY_=(value: Float): Unit = dataWatcher.updateObject(4, float2Float(math.round(value * 4) / 4f))
def targetZ_=(value: Float): Unit = dataWatcher.updateObject(5, float2Float(math.round(value * 4) / 4f)) def targetZ_=(value: Float): Unit = dataWatcher.updateObject(5, float2Float(math.round(value * 4) / 4f))
def targetAcceleration_=(value: Float): Unit = dataWatcher.updateObject(6, float2Float(math.max(0, math.min(maxAcceleration, value)))) def targetAcceleration_=(value: Float): Unit = dataWatcher.updateObject(6, float2Float(math.max(0, math.min(maxAcceleration, value))))
def selectedSlot_=(value: Int) = dataWatcher.updateObject(7, byte2Byte(value.toByte)) def selectedSlot_=(value: Int) = dataWatcher.updateObject(7, byte2Byte(value.toByte))
def globalBuffer_=(value: Int) = dataWatcher.updateObject(8, int2Integer(value)) def globalBuffer_=(value: Int) = dataWatcher.updateObject(8, int2Integer(value))
def globalBufferSize_=(value: Int) = dataWatcher.updateObject(9, int2Integer(value)) def globalBufferSize_=(value: Int) = dataWatcher.updateObject(9, int2Integer(value))
def statusText_=(value: String) = dataWatcher.updateObject(10, Option(value).map(_.lines.map(_.take(10)).take(2).mkString("\n")).getOrElse("")) def statusText_=(value: String) = dataWatcher.updateObject(10, Option(value).map(_.lines.map(_.take(10)).take(2).mkString("\n")).getOrElse(""))
def inventorySize_=(value: Int) = dataWatcher.updateObject(11, byte2Byte(value.toByte)) def inventorySize_=(value: Int) = dataWatcher.updateObject(11, byte2Byte(value.toByte))
def lightColor_=(value: Int) = dataWatcher.updateObject(12, int2Integer(value)) def lightColor_=(value: Int) = dataWatcher.updateObject(12, int2Integer(value))
@SideOnly(Side.CLIENT) @SideOnly(Side.CLIENT)

View File

@ -12,10 +12,11 @@ import li.cil.oc.common.block.SimpleBlock
import li.cil.oc.common.item import li.cil.oc.common.item
import li.cil.oc.common.item.SimpleItem import li.cil.oc.common.item.SimpleItem
import li.cil.oc.common.item.UpgradeLeash import li.cil.oc.common.item.UpgradeLeash
import li.cil.oc.common.item.data.MicrocontrollerData
import li.cil.oc.common.item.data.RobotData
import li.cil.oc.common.recipe.Recipes import li.cil.oc.common.recipe.Recipes
import li.cil.oc.integration.Mods import li.cil.oc.integration.Mods
import li.cil.oc.util.Color import li.cil.oc.util.Color
import li.cil.oc.util.ItemUtils
import net.minecraft.block.Block import net.minecraft.block.Block
import net.minecraft.creativetab.CreativeTabs import net.minecraft.creativetab.CreativeTabs
import net.minecraft.entity.player.EntityPlayer import net.minecraft.entity.player.EntityPlayer
@ -141,7 +142,7 @@ object Items extends ItemAPI {
} }
def createConfiguredDrone() = { def createConfiguredDrone() = {
val data = new ItemUtils.MicrocontrollerData() val data = new MicrocontrollerData()
data.tier = Tier.Four data.tier = Tier.Four
data.storedEnergy = Settings.get.bufferDrone.toInt data.storedEnergy = Settings.get.bufferDrone.toInt
@ -167,7 +168,7 @@ object Items extends ItemAPI {
} }
def createConfiguredMicrocontroller() = { def createConfiguredMicrocontroller() = {
val data = new ItemUtils.MicrocontrollerData() val data = new MicrocontrollerData()
data.tier = Tier.Four data.tier = Tier.Four
data.storedEnergy = Settings.get.bufferMicrocontroller.toInt data.storedEnergy = Settings.get.bufferMicrocontroller.toInt
@ -190,7 +191,7 @@ object Items extends ItemAPI {
} }
def createConfiguredRobot() = { def createConfiguredRobot() = {
val data = new ItemUtils.RobotData() val data = new RobotData()
data.name = "Creatix" data.name = "Creatix"
data.tier = Tier.Four data.tier = Tier.Four

View File

@ -6,9 +6,9 @@ import cpw.mods.fml.relauncher.Side
import cpw.mods.fml.relauncher.SideOnly import cpw.mods.fml.relauncher.SideOnly
import li.cil.oc.client.KeyBindings import li.cil.oc.client.KeyBindings
import li.cil.oc.common.entity import li.cil.oc.common.entity
import li.cil.oc.common.item.data.MicrocontrollerData
import li.cil.oc.integration.util.NEI import li.cil.oc.integration.util.NEI
import li.cil.oc.util.BlockPosition import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ItemUtils
import li.cil.oc.util.Rarity import li.cil.oc.util.Rarity
import net.minecraft.entity.player.EntityPlayer import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
@ -20,7 +20,7 @@ class Drone(val parent: Delegator) extends Delegate {
override protected def tooltipExtended(stack: ItemStack, tooltip: util.List[String]): Unit = { override protected def tooltipExtended(stack: ItemStack, tooltip: util.List[String]): Unit = {
if (KeyBindings.showExtendedTooltips) { if (KeyBindings.showExtendedTooltips) {
val info = new ItemUtils.MicrocontrollerData(stack) val info = new MicrocontrollerData(stack)
for (component <- info.components) { for (component <- info.components) {
tooltip.add("- " + component.getDisplayName) tooltip.add("- " + component.getDisplayName)
} }
@ -28,7 +28,7 @@ class Drone(val parent: Delegator) extends Delegate {
} }
override def rarity(stack: ItemStack) = { override def rarity(stack: ItemStack) = {
val data = new ItemUtils.MicrocontrollerData(stack) val data = new MicrocontrollerData(stack)
Rarity.byTier(data.tier) Rarity.byTier(data.tier)
} }

View File

@ -29,10 +29,9 @@ import li.cil.oc.client.KeyBindings
import li.cil.oc.common.GuiType import li.cil.oc.common.GuiType
import li.cil.oc.common.Slot import li.cil.oc.common.Slot
import li.cil.oc.common.inventory.ComponentInventory import li.cil.oc.common.inventory.ComponentInventory
import li.cil.oc.common.item.data.TabletData
import li.cil.oc.server.component import li.cil.oc.server.component
import li.cil.oc.util.ExtendedNBT._ import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ItemUtils
import li.cil.oc.util.ItemUtils.TabletData
import li.cil.oc.util.RotationHelper import li.cil.oc.util.RotationHelper
import li.cil.oc.util.Tooltip import li.cil.oc.util.Tooltip
import net.minecraft.entity.Entity import net.minecraft.entity.Entity
@ -58,7 +57,7 @@ class Tablet(val parent: Delegator) extends Delegate {
@SideOnly(Side.CLIENT) @SideOnly(Side.CLIENT)
override def icon(stack: ItemStack, pass: Int) = { override def icon(stack: ItemStack, pass: Int) = {
if (stack.hasTagCompound) { if (stack.hasTagCompound) {
val data = new ItemUtils.TabletData(stack) val data = new TabletData(stack)
if (data.isRunning) iconOn else iconOff if (data.isRunning) iconOn else iconOff
} else super.icon(stack, pass) } else super.icon(stack, pass)
} }
@ -74,7 +73,7 @@ class Tablet(val parent: Delegator) extends Delegate {
override protected def tooltipExtended(stack: ItemStack, tooltip: util.List[String]): Unit = { override protected def tooltipExtended(stack: ItemStack, tooltip: util.List[String]): Unit = {
if (KeyBindings.showExtendedTooltips) { if (KeyBindings.showExtendedTooltips) {
val info = new ItemUtils.TabletData(stack) val info = new TabletData(stack)
// Ignore/hide the screen. // Ignore/hide the screen.
val components = info.items.drop(1) val components = info.items.drop(1)
if (components.length > 1) { if (components.length > 1) {
@ -91,7 +90,7 @@ class Tablet(val parent: Delegator) extends Delegate {
override def damage(stack: ItemStack) = { override def damage(stack: ItemStack) = {
val nbt = stack.getTagCompound val nbt = stack.getTagCompound
if (nbt != null) { if (nbt != null) {
val data = new ItemUtils.TabletData() val data = new TabletData()
data.load(nbt) data.load(nbt)
(data.maxEnergy - data.energy).toInt (data.maxEnergy - data.energy).toInt
} }
@ -101,7 +100,7 @@ class Tablet(val parent: Delegator) extends Delegate {
override def maxDamage(stack: ItemStack) = { override def maxDamage(stack: ItemStack) = {
val nbt = stack.getTagCompound val nbt = stack.getTagCompound
if (nbt != null) { if (nbt != null) {
val data = new ItemUtils.TabletData() val data = new TabletData()
data.load(nbt) data.load(nbt)
data.maxEnergy.toInt max 1 data.maxEnergy.toInt max 1
} }

View File

@ -0,0 +1,26 @@
package li.cil.oc.common.item.data
import li.cil.oc.api.Persistable
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
object ItemData {
}
abstract class ItemData extends Persistable {
def load(stack: ItemStack) {
if (stack.hasTagCompound) {
// Because ItemStack's load function doesn't copy the compound tag,
// but keeps it as is, leading to oh so fun bugs!
load(stack.getTagCompound.copy().asInstanceOf[NBTTagCompound])
}
}
def save(stack: ItemStack) {
if (!stack.hasTagCompound) {
stack.setTagCompound(new NBTTagCompound())
}
save(stack.getTagCompound)
}
}

View File

@ -0,0 +1,49 @@
package li.cil.oc.common.item.data
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.common.Tier
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ItemUtils
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.util.Constants.NBT
class MicrocontrollerData extends ItemData {
def this(stack: ItemStack) {
this()
load(stack)
}
var tier = Tier.One
var components = Array.empty[ItemStack]
var storedEnergy = 0
override def load(nbt: NBTTagCompound) {
tier = nbt.getByte(Settings.namespace + "tier")
components = nbt.getTagList(Settings.namespace + "components", NBT.TAG_COMPOUND).
toArray[NBTTagCompound].map(ItemUtils.loadStack)
storedEnergy = nbt.getInteger(Settings.namespace + "storedEnergy")
}
override def save(nbt: NBTTagCompound) {
nbt.setByte(Settings.namespace + "tier", tier.toByte)
nbt.setNewTagList(Settings.namespace + "components", components.toIterable)
nbt.setInteger(Settings.namespace + "storedEnergy", storedEnergy)
}
def createItemStack() = {
val stack = api.Items.get("microcontroller").createItemStack(1)
save(stack)
stack
}
def copyItemStack() = {
val stack = createItemStack()
val newInfo = new MicrocontrollerData(stack)
newInfo.save(stack)
stack
}
}

View File

@ -0,0 +1,47 @@
package li.cil.oc.common.item.data
import li.cil.oc.Settings
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ItemUtils
import net.minecraft.item.ItemMap
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.world.World
class NavigationUpgradeData extends ItemData {
def this(stack: ItemStack) {
this()
load(stack)
}
var map = new ItemStack(net.minecraft.init.Items.filled_map)
def mapData(world: World) = try map.getItem.asInstanceOf[ItemMap].getMapData(map, world) catch {
case _: Throwable => throw new Exception("invalid map")
}
override def load(stack: ItemStack) {
if (stack.hasTagCompound) {
load(stack.getTagCompound.getCompoundTag(Settings.namespace + "data"))
}
}
override def save(stack: ItemStack) {
if (!stack.hasTagCompound) {
stack.setTagCompound(new NBTTagCompound())
}
save(stack.getCompoundTag(Settings.namespace + "data"))
}
override def load(nbt: NBTTagCompound) {
if (nbt.hasKey(Settings.namespace + "map")) {
map = ItemUtils.loadStack(nbt.getCompoundTag(Settings.namespace + "map"))
}
}
override def save(nbt: NBTTagCompound) {
if (map != null) {
nbt.setNewCompoundTag(Settings.namespace + "map", map.writeToNBT)
}
}
}

View File

@ -0,0 +1,44 @@
package li.cil.oc.common.item.data
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.common.tileentity
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ItemUtils
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.util.Constants.NBT
class RaidData extends ItemData {
def this(stack: ItemStack) {
this()
load(stack)
}
var disks = Array.empty[ItemStack]
var filesystem = new NBTTagCompound()
var label: Option[String] = None
override def load(nbt: NBTTagCompound): Unit = {
disks = nbt.getTagList(Settings.namespace + "disks", NBT.TAG_COMPOUND).
toArray[NBTTagCompound].map(ItemUtils.loadStack)
filesystem = nbt.getCompoundTag(Settings.namespace + "filesystem")
if (nbt.hasKey(Settings.namespace + "label")) {
label = Option(nbt.getString(Settings.namespace + "label"))
}
}
override def save(nbt: NBTTagCompound): Unit = {
nbt.setNewTagList(Settings.namespace + "disks", disks.toIterable)
nbt.setTag(Settings.namespace + "filesystem", filesystem)
label.foreach(nbt.setString(Settings.namespace + "label", _))
}
def createItemStack() = {
val stack = api.Items.get("raid").createItemStack(1)
save(stack)
stack
}
}

View File

@ -0,0 +1,124 @@
package li.cil.oc.common.item.data
import com.google.common.base.Charsets
import com.google.common.base.Strings
import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.common.init.Items
import li.cil.oc.integration.opencomputers.DriverScreen
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ItemUtils
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.util.Constants.NBT
import scala.io.Source
object RobotData {
val names = try {
Source.fromInputStream(getClass.getResourceAsStream(
"/assets/" + Settings.resourceDomain + "/robot.names"))(Charsets.UTF_8).
getLines().map(_.takeWhile(_ != '#').trim()).filter(_ != "").toArray
}
catch {
case t: Throwable =>
OpenComputers.log.warn("Failed loading robot name list.", t)
Array.empty[String]
}
def randomName = if (names.length > 0) names((math.random * names.length).toInt) else "Robot"
}
class RobotData extends ItemData {
def this(stack: ItemStack) {
this()
load(stack)
}
var name = ""
// Overall energy including components.
var totalEnergy = 0
// Energy purely stored in robot component - this is what we have to restore manually.
var robotEnergy = 0
var tier = 0
var components = Array.empty[ItemStack]
var containers = Array.empty[ItemStack]
var lightColor = 0xF23030
override def load(nbt: NBTTagCompound) {
if (nbt.hasKey("display") && nbt.getCompoundTag("display").hasKey("Name")) {
name = nbt.getCompoundTag("display").getString("Name")
}
if (Strings.isNullOrEmpty(name)) {
name = RobotData.randomName
}
totalEnergy = nbt.getInteger(Settings.namespace + "storedEnergy")
robotEnergy = nbt.getInteger(Settings.namespace + "robotEnergy")
tier = nbt.getInteger(Settings.namespace + "tier")
components = nbt.getTagList(Settings.namespace + "components", NBT.TAG_COMPOUND).
toArray[NBTTagCompound].map(ItemUtils.loadStack)
containers = nbt.getTagList(Settings.namespace + "containers", NBT.TAG_COMPOUND).
toArray[NBTTagCompound].map(ItemUtils.loadStack)
if (nbt.hasKey(Settings.namespace + "lightColor")) {
lightColor = nbt.getInteger(Settings.namespace + "lightColor")
}
// Code for migrating from 1.4.1 -> 1.4.2, add EEPROM.
// TODO Remove in 1.5
if (!nbt.hasKey(Settings.namespace + "biosFlag")) {
components :+= Items.createLuaBios()
}
}
override def save(nbt: NBTTagCompound) {
if (!Strings.isNullOrEmpty(name)) {
if (!nbt.hasKey("display")) {
nbt.setTag("display", new NBTTagCompound())
}
nbt.getCompoundTag("display").setString("Name", name)
}
nbt.setInteger(Settings.namespace + "storedEnergy", totalEnergy)
nbt.setInteger(Settings.namespace + "robotEnergy", robotEnergy)
nbt.setInteger(Settings.namespace + "tier", tier)
nbt.setNewTagList(Settings.namespace + "components", components.toIterable)
nbt.setNewTagList(Settings.namespace + "containers", containers.toIterable)
nbt.setInteger(Settings.namespace + "lightColor", lightColor)
// TODO Remove in 1.5
nbt.setBoolean(Settings.namespace + "biosFlag", true)
}
def createItemStack() = {
val stack = api.Items.get("robot").createItemStack(1)
save(stack)
stack
}
def copyItemStack() = {
val stack = createItemStack()
// Forget all node addresses and so on. This is used when 'picking' a
// robot in creative mode.
val newInfo = new RobotData(stack)
newInfo.components.foreach(cs => Option(api.Driver.driverFor(cs)) match {
case Some(driver) if driver == DriverScreen =>
val nbt = driver.dataTag(cs)
for (tagName <- nbt.func_150296_c().toArray) {
nbt.removeTag(tagName.asInstanceOf[String])
}
case _ =>
})
// Don't show energy info (because it's unreliable) but fill up the
// internal buffer. This is for creative use only, anyway.
newInfo.totalEnergy = 0
newInfo.robotEnergy = 50000
newInfo.save(stack)
stack
}
}

View File

@ -0,0 +1,58 @@
package li.cil.oc.common.item.data
import li.cil.oc.Settings
import li.cil.oc.common.init.Items
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ItemUtils
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.util.Constants.NBT
class TabletData extends ItemData {
def this(stack: ItemStack) {
this()
load(stack)
}
var items = Array.fill[Option[ItemStack]](32)(None)
var isRunning = false
var energy = 0.0
var maxEnergy = 0.0
override def load(nbt: NBTTagCompound) {
nbt.getTagList(Settings.namespace + "items", NBT.TAG_COMPOUND).foreach((slotNbt: NBTTagCompound) => {
val slot = slotNbt.getByte("slot")
if (slot >= 0 && slot < items.length) {
items(slot) = Option(ItemUtils.loadStack(slotNbt.getCompoundTag("item")))
}
})
isRunning = nbt.getBoolean(Settings.namespace + "isRunning")
energy = nbt.getDouble(Settings.namespace + "energy")
maxEnergy = nbt.getDouble(Settings.namespace + "maxEnergy")
// Code for migrating from 1.4.1 -> 1.4.2, add EEPROM.
// TODO Remove in 1.5
if (!nbt.hasKey(Settings.namespace + "biosFlag")) {
val firstEmpty = items.indexWhere(_.isEmpty)
items(firstEmpty) = Option(Items.createLuaBios())
}
}
override def save(nbt: NBTTagCompound) {
nbt.setNewTagList(Settings.namespace + "items",
items.zipWithIndex collect {
case (Some(stack), slot) => (stack, slot)
} map {
case (stack, slot) =>
val slotNbt = new NBTTagCompound()
slotNbt.setByte("slot", slot.toByte)
slotNbt.setNewCompoundTag("item", stack.writeToNBT)
})
nbt.setBoolean(Settings.namespace + "isRunning", isRunning)
nbt.setDouble(Settings.namespace + "energy", energy)
nbt.setDouble(Settings.namespace + "maxEnergy", maxEnergy)
// TODO Remove in 1.5
nbt.setBoolean(Settings.namespace + "biosFlag", true)
}
}

View File

@ -6,9 +6,9 @@ import li.cil.oc.Settings
import li.cil.oc.api import li.cil.oc.api
import li.cil.oc.api.detail.ItemInfo import li.cil.oc.api.detail.ItemInfo
import li.cil.oc.common.init.Items import li.cil.oc.common.init.Items
import li.cil.oc.common.item.data.MicrocontrollerData
import li.cil.oc.integration.Mods import li.cil.oc.integration.Mods
import li.cil.oc.util.ExtendedNBT._ import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ItemUtils
import li.cil.oc.util.SideTracker import li.cil.oc.util.SideTracker
import net.minecraft.init.Blocks import net.minecraft.init.Blocks
import net.minecraft.inventory.InventoryCrafting import net.minecraft.inventory.InventoryCrafting
@ -97,7 +97,7 @@ object ExtendedRecipe {
// Find old Microcontroller. // Find old Microcontroller.
(0 until inventory.getSizeInventory).map(inventory.getStackInSlot).find(api.Items.get(_) == descriptor) match { (0 until inventory.getSizeInventory).map(inventory.getStackInSlot).find(api.Items.get(_) == descriptor) match {
case Some(oldMcu) => case Some(oldMcu) =>
val data = new ItemUtils.MicrocontrollerData(oldMcu) val data = new MicrocontrollerData(oldMcu)
// Remove old EEPROM. // Remove old EEPROM.
val oldRom = data.components.filter(api.Items.get(_) == eeprom) val oldRom = data.components.filter(api.Items.get(_) == eeprom)

View File

@ -6,6 +6,7 @@ import li.cil.oc.api
import li.cil.oc.api.internal import li.cil.oc.api.internal
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.item.data.MicrocontrollerData
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 net.minecraft.inventory.IInventory import net.minecraft.inventory.IInventory
@ -29,7 +30,7 @@ object DroneTemplate extends Template {
def assemble(inventory: IInventory) = { def assemble(inventory: IInventory) = {
val items = (0 until inventory.getSizeInventory).map(inventory.getStackInSlot) val items = (0 until inventory.getSizeInventory).map(inventory.getStackInSlot)
val data = new ItemUtils.MicrocontrollerData() val data = new MicrocontrollerData()
data.tier = caseTier(inventory) data.tier = caseTier(inventory)
data.components = items.drop(1).filter(_ != null).toArray data.components = items.drop(1).filter(_ != null).toArray
data.storedEnergy = Settings.get.bufferDrone.toInt data.storedEnergy = Settings.get.bufferDrone.toInt
@ -43,7 +44,7 @@ object DroneTemplate extends Template {
def selectDisassembler(stack: ItemStack) = api.Items.get(stack) == api.Items.get("drone") def selectDisassembler(stack: ItemStack) = api.Items.get(stack) == api.Items.get("drone")
def disassemble(stack: ItemStack, ingredients: Array[ItemStack]) = { def disassemble(stack: ItemStack, ingredients: Array[ItemStack]) = {
val info = new ItemUtils.MicrocontrollerData(stack) val info = new MicrocontrollerData(stack)
val itemName = ItemUtils.caseNameWithTierSuffix("droneCase", info.tier) val itemName = ItemUtils.caseNameWithTierSuffix("droneCase", info.tier)
Array(api.Items.get(itemName).createItemStack(1)) ++ info.components Array(api.Items.get(itemName).createItemStack(1)) ++ info.components

View File

@ -6,6 +6,7 @@ import li.cil.oc.api
import li.cil.oc.api.internal import li.cil.oc.api.internal
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.item.data.MicrocontrollerData
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 net.minecraft.inventory.IInventory import net.minecraft.inventory.IInventory
@ -29,7 +30,7 @@ object MicrocontrollerTemplate extends Template {
def assemble(inventory: IInventory) = { def assemble(inventory: IInventory) = {
val items = (0 until inventory.getSizeInventory).map(inventory.getStackInSlot) val items = (0 until inventory.getSizeInventory).map(inventory.getStackInSlot)
val data = new ItemUtils.MicrocontrollerData() val data = new MicrocontrollerData()
data.tier = caseTier(inventory) data.tier = caseTier(inventory)
data.components = items.drop(1).filter(_ != null).toArray data.components = items.drop(1).filter(_ != null).toArray
data.storedEnergy = Settings.get.bufferMicrocontroller.toInt data.storedEnergy = Settings.get.bufferMicrocontroller.toInt
@ -43,7 +44,7 @@ object MicrocontrollerTemplate extends Template {
def selectDisassembler(stack: ItemStack) = api.Items.get(stack) == api.Items.get("microcontroller") def selectDisassembler(stack: ItemStack) = api.Items.get(stack) == api.Items.get("microcontroller")
def disassemble(stack: ItemStack, ingredients: Array[ItemStack]) = { def disassemble(stack: ItemStack, ingredients: Array[ItemStack]) = {
val info = new ItemUtils.MicrocontrollerData(stack) val info = new MicrocontrollerData(stack)
val itemName = ItemUtils.caseNameWithTierSuffix("microcontrollerCase", info.tier) val itemName = ItemUtils.caseNameWithTierSuffix("microcontrollerCase", info.tier)
Array(api.Items.get(itemName).createItemStack(1)) ++ info.components Array(api.Items.get(itemName).createItemStack(1)) ++ info.components

View File

@ -2,7 +2,7 @@ package li.cil.oc.common.template
import cpw.mods.fml.common.event.FMLInterModComms import cpw.mods.fml.common.event.FMLInterModComms
import li.cil.oc.api import li.cil.oc.api
import li.cil.oc.util.ItemUtils import li.cil.oc.common.item.data.NavigationUpgradeData
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
@ -12,7 +12,7 @@ object NavigationUpgradeTemplate {
def selectDisassembler(stack: ItemStack) = api.Items.get(stack) == api.Items.get("navigationUpgrade") def selectDisassembler(stack: ItemStack) = api.Items.get(stack) == api.Items.get("navigationUpgrade")
def disassemble(stack: ItemStack, ingredients: Array[ItemStack]) = { def disassemble(stack: ItemStack, ingredients: Array[ItemStack]) = {
val info = new ItemUtils.NavigationUpgradeData(stack) val info = new NavigationUpgradeData(stack)
ingredients.map { ingredients.map {
case part if part.getItem == net.minecraft.init.Items.filled_map => info.map case part if part.getItem == net.minecraft.init.Items.filled_map => info.map
case part => part case part => part

View File

@ -6,6 +6,7 @@ import li.cil.oc.api
import li.cil.oc.api.internal import li.cil.oc.api.internal
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.item.data.RobotData
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 net.minecraft.inventory.IInventory import net.minecraft.inventory.IInventory
@ -28,9 +29,9 @@ object RobotTemplate extends Template {
def assemble(inventory: IInventory) = { def assemble(inventory: IInventory) = {
val items = (0 until inventory.getSizeInventory).map(inventory.getStackInSlot) val items = (0 until inventory.getSizeInventory).map(inventory.getStackInSlot)
val data = new ItemUtils.RobotData() val data = new RobotData()
data.tier = ItemUtils.caseTier(inventory.getStackInSlot(0)) data.tier = ItemUtils.caseTier(inventory.getStackInSlot(0))
data.name = ItemUtils.RobotData.randomName data.name = RobotData.randomName
data.robotEnergy = Settings.get.bufferRobot.toInt data.robotEnergy = Settings.get.bufferRobot.toInt
data.totalEnergy = data.robotEnergy data.totalEnergy = data.robotEnergy
data.containers = items.slice(1, 4).filter(_ != null).toArray data.containers = items.slice(1, 4).filter(_ != null).toArray
@ -45,7 +46,7 @@ object RobotTemplate extends Template {
def selectDisassembler(stack: ItemStack) = api.Items.get(stack) == api.Items.get("robot") def selectDisassembler(stack: ItemStack) = api.Items.get(stack) == api.Items.get("robot")
def disassemble(stack: ItemStack, ingredients: Array[ItemStack]) = { def disassemble(stack: ItemStack, ingredients: Array[ItemStack]) = {
val info = new ItemUtils.RobotData(stack) val info = new RobotData(stack)
val itemName = ItemUtils.caseNameWithTierSuffix("case", info.tier) val itemName = ItemUtils.caseNameWithTierSuffix("case", info.tier)
Array(api.Items.get(itemName).createItemStack(1)) ++ info.containers ++ info.components Array(api.Items.get(itemName).createItemStack(1)) ++ info.containers ++ info.components

View File

@ -6,8 +6,8 @@ import li.cil.oc.api
import li.cil.oc.api.internal import li.cil.oc.api.internal
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.item.data.TabletData
import li.cil.oc.util.ExtendedNBT._ 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
@ -32,7 +32,7 @@ object TabletTemplate extends Template {
val items = mutable.ArrayBuffer( val items = mutable.ArrayBuffer(
Option(api.Items.get("screen1").createItemStack(1)) Option(api.Items.get("screen1").createItemStack(1))
) ++ (1 until inventory.getSizeInventory).map(slot => Option(inventory.getStackInSlot(slot))) ) ++ (1 until inventory.getSizeInventory).map(slot => Option(inventory.getStackInSlot(slot)))
val data = new ItemUtils.TabletData() val data = new TabletData()
data.items = items.filter(_.isDefined).toArray data.items = items.filter(_.isDefined).toArray
data.energy = Settings.get.bufferTablet data.energy = Settings.get.bufferTablet
data.maxEnergy = data.energy data.maxEnergy = data.energy
@ -46,7 +46,7 @@ object TabletTemplate extends Template {
def selectDisassembler(stack: ItemStack) = api.Items.get(stack) == api.Items.get("tablet") def selectDisassembler(stack: ItemStack) = api.Items.get(stack) == api.Items.get("tablet")
def disassemble(stack: ItemStack, ingredients: Array[ItemStack]) = { def disassemble(stack: ItemStack, ingredients: Array[ItemStack]) = {
val info = new ItemUtils.TabletData(stack) val info = new TabletData(stack)
Array(api.Items.get("tabletCase").createItemStack(1)) ++ info.items.collect { Array(api.Items.get("tabletCase").createItemStack(1)) ++ info.items.collect {
case Some(item) => item case Some(item) => item
}.drop(1) // Screen. }.drop(1) // Screen.

View File

@ -12,10 +12,10 @@ import li.cil.oc.api.network._
import li.cil.oc.common.Slot import li.cil.oc.common.Slot
import li.cil.oc.common.entity.Drone import li.cil.oc.common.entity.Drone
import li.cil.oc.common.item.Tablet import li.cil.oc.common.item.Tablet
import li.cil.oc.common.item.data.TabletData
import li.cil.oc.server.{PacketSender => ServerPacketSender} import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.BlockPosition import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedWorld._ import li.cil.oc.util.ExtendedWorld._
import li.cil.oc.util.ItemUtils
import net.minecraft.entity.player.EntityPlayer import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
@ -100,7 +100,7 @@ class Charger extends traits.Environment with traits.PowerAcceptor with traits.R
handler(itemCharge) handler(itemCharge)
} }
} }
val data = new ItemUtils.TabletData(stack) val data = new TabletData(stack)
tryCharge(data.energy, data.maxEnergy, (amount) => { tryCharge(data.energy, data.maxEnergy, (amount) => {
data.energy = math.min(data.maxEnergy, data.energy + amount) data.energy = math.min(data.maxEnergy, data.energy + amount)
data.save(stack) data.save(stack)

View File

@ -14,15 +14,15 @@ import li.cil.oc.api.machine.Context
import li.cil.oc.api.network._ import li.cil.oc.api.network._
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.item.data.MicrocontrollerData
import li.cil.oc.util.ExtendedNBT._ import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ItemUtils
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.util.ForgeDirection import net.minecraftforge.common.util.ForgeDirection
// TODO Remove internal.Tiered in 1.5, only here for compatibility if someone ships an older 1.4 API. // TODO Remove internal.Tiered in 1.5, only here for compatibility if someone ships an older 1.4 API.
class Microcontroller extends traits.PowerAcceptor with traits.Computer with SidedEnvironment with internal.Microcontroller with internal.Tiered { class Microcontroller extends traits.PowerAcceptor with traits.Computer with SidedEnvironment with internal.Microcontroller with internal.Tiered {
val info = new ItemUtils.MicrocontrollerData() val info = new MicrocontrollerData()
override val node = api.Network.newNode(this, Visibility.Network). override val node = api.Network.newNode(this, Visibility.Network).
withComponent("microcontroller"). withComponent("microcontroller").

View File

@ -76,7 +76,7 @@ class Raid extends traits.Environment with traits.Inventory with traits.Rotatabl
} }
} }
private def tryCreateRaid(id: String) { def tryCreateRaid(id: String) {
if (items.count(_.isDefined) == items.length) { if (items.count(_.isDefined) == items.length) {
val fs = api.FileSystem.asManagedEnvironment( val fs = api.FileSystem.asManagedEnvironment(
api.FileSystem.fromSaveDirectory(id, wipeDisksAndComputeSpace, Settings.get.bufferChanges), api.FileSystem.fromSaveDirectory(id, wipeDisksAndComputeSpace, Settings.get.bufferChanges),

View File

@ -20,6 +20,7 @@ import li.cil.oc.common.Tier
import li.cil.oc.common.inventory.InventorySelection import li.cil.oc.common.inventory.InventorySelection
import li.cil.oc.common.inventory.MultiTank import li.cil.oc.common.inventory.MultiTank
import li.cil.oc.common.inventory.TankSelection import li.cil.oc.common.inventory.TankSelection
import li.cil.oc.common.item.data.RobotData
import li.cil.oc.integration.opencomputers.DriverKeyboard import li.cil.oc.integration.opencomputers.DriverKeyboard
import li.cil.oc.integration.opencomputers.DriverRedstoneCard import li.cil.oc.integration.opencomputers.DriverRedstoneCard
import li.cil.oc.integration.opencomputers.DriverScreen import li.cil.oc.integration.opencomputers.DriverScreen
@ -30,7 +31,6 @@ import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedNBT._ import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ExtendedWorld._ import li.cil.oc.util.ExtendedWorld._
import li.cil.oc.util.InventoryUtils import li.cil.oc.util.InventoryUtils
import li.cil.oc.util.ItemUtils
import net.minecraft.block.Block import net.minecraft.block.Block
import net.minecraft.block.BlockLiquid import net.minecraft.block.BlockLiquid
import net.minecraft.client.Minecraft import net.minecraft.client.Minecraft
@ -54,7 +54,7 @@ import scala.collection.mutable
class Robot extends traits.Computer with traits.PowerInformation with IFluidHandler with internal.Robot with internal.Tiered with MultiTank with InventorySelection with TankSelection { class Robot extends traits.Computer with traits.PowerInformation with IFluidHandler with internal.Robot with internal.Tiered with MultiTank with InventorySelection with TankSelection {
var proxy: RobotProxy = _ var proxy: RobotProxy = _
val info = new ItemUtils.RobotData() val info = new RobotData()
val bot = if (isServer) new robot.Robot(this) else null val bot = if (isServer) new robot.Robot(this) else null

View File

@ -4,7 +4,7 @@ import li.cil.oc.Settings
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.Slot import li.cil.oc.common.Slot
import li.cil.oc.util.ItemUtils import li.cil.oc.common.item.data.TabletData
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.util.Constants.NBT import net.minecraftforge.common.util.Constants.NBT
@ -14,7 +14,7 @@ object DriverTablet extends Item {
isOneOf(stack, api.Items.get("tablet")) isOneOf(stack, api.Items.get("tablet"))
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = { override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = {
val data = new ItemUtils.TabletData(stack) val data = new TabletData(stack)
data.items.collect { data.items.collect {
case Some(fs) if DriverFileSystem.worksWith(fs) => fs case Some(fs) if DriverFileSystem.worksWith(fs) => fs
}.headOption.map(DriverFileSystem.createEnvironment(_, host)).orNull }.headOption.map(DriverFileSystem.createEnvironment(_, host)).orNull
@ -23,7 +23,7 @@ object DriverTablet extends Item {
override def slot(stack: ItemStack) = Slot.Tablet override def slot(stack: ItemStack) = Slot.Tablet
override def dataTag(stack: ItemStack) = { override def dataTag(stack: ItemStack) = {
val data = new ItemUtils.TabletData(stack) val data = new TabletData(stack)
val index = data.items.indexWhere { val index = data.items.indexWhere {
case Some(fs) => DriverFileSystem.worksWith(fs) case Some(fs) => DriverFileSystem.worksWith(fs)
case _ => false case _ => false

View File

@ -8,7 +8,7 @@ import li.cil.oc.api.machine.Callback
import li.cil.oc.api.machine.Context import li.cil.oc.api.machine.Context
import li.cil.oc.api.network._ import li.cil.oc.api.network._
import li.cil.oc.api.prefab import li.cil.oc.api.prefab
import li.cil.oc.util.ItemUtils.NavigationUpgradeData import li.cil.oc.common.item.data.NavigationUpgradeData
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
class UpgradeNavigation(val host: EnvironmentHost with Rotatable) extends prefab.ManagedEnvironment { class UpgradeNavigation(val host: EnvironmentHost with Rotatable) extends prefab.ManagedEnvironment {

View File

@ -2,33 +2,22 @@ package li.cil.oc.util
import java.util.Random import java.util.Random
import com.google.common.base.Charsets
import com.google.common.base.Strings
import li.cil.oc.OpenComputers import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.api import li.cil.oc.api
import li.cil.oc.api.Persistable
import li.cil.oc.common.Tier import li.cil.oc.common.Tier
import li.cil.oc.common.block.DelegatorConverter import li.cil.oc.common.block.DelegatorConverter
import li.cil.oc.common.init.Items
import li.cil.oc.integration.opencomputers.DriverScreen
import li.cil.oc.util.ExtendedNBT._
import net.minecraft.item.ItemBucket import net.minecraft.item.ItemBucket
import net.minecraft.item.ItemMap
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.item.crafting.CraftingManager import net.minecraft.item.crafting.CraftingManager
import net.minecraft.item.crafting.IRecipe import net.minecraft.item.crafting.IRecipe
import net.minecraft.item.crafting.ShapedRecipes import net.minecraft.item.crafting.ShapedRecipes
import net.minecraft.item.crafting.ShapelessRecipes import net.minecraft.item.crafting.ShapelessRecipes
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
import net.minecraft.world.World
import net.minecraftforge.common.util.Constants.NBT
import net.minecraftforge.oredict.ShapedOreRecipe import net.minecraftforge.oredict.ShapedOreRecipe
import net.minecraftforge.oredict.ShapelessOreRecipe import net.minecraftforge.oredict.ShapelessOreRecipe
import scala.collection.convert.WrapAsScala._ import scala.collection.convert.WrapAsScala._
import scala.collection.mutable import scala.collection.mutable
import scala.io.Source
object ItemUtils { object ItemUtils {
def caseTier(stack: ItemStack) = { def caseTier(stack: ItemStack) = {
@ -106,265 +95,4 @@ object ItemUtils {
case list: java.util.ArrayList[ItemStack]@unchecked if !list.isEmpty => list.get(rng.nextInt(list.size)) case list: java.util.ArrayList[ItemStack]@unchecked if !list.isEmpty => list.get(rng.nextInt(list.size))
} }
abstract class ItemData extends Persistable {
def load(stack: ItemStack) {
if (stack.hasTagCompound) {
// Because ItemStack's load function doesn't copy the compound tag,
// but keeps it as is, leading to oh so fun bugs!
load(stack.getTagCompound.copy().asInstanceOf[NBTTagCompound])
}
}
def save(stack: ItemStack) {
if (!stack.hasTagCompound) {
stack.setTagCompound(new NBTTagCompound())
}
save(stack.getTagCompound)
}
}
class MicrocontrollerData extends ItemData {
def this(stack: ItemStack) {
this()
load(stack)
}
var tier = Tier.One
var components = Array.empty[ItemStack]
var storedEnergy = 0
override def load(nbt: NBTTagCompound) {
tier = nbt.getByte(Settings.namespace + "tier")
components = nbt.getTagList(Settings.namespace + "components", NBT.TAG_COMPOUND).
toArray[NBTTagCompound].map(loadStack)
storedEnergy = nbt.getInteger(Settings.namespace + "storedEnergy")
}
override def save(nbt: NBTTagCompound) {
nbt.setByte(Settings.namespace + "tier", tier.toByte)
nbt.setNewTagList(Settings.namespace + "components", components.toIterable)
nbt.setInteger(Settings.namespace + "storedEnergy", storedEnergy)
}
def createItemStack() = {
val stack = api.Items.get("microcontroller").createItemStack(1)
save(stack)
stack
}
def copyItemStack() = {
val stack = createItemStack()
// Forget all node addresses and so on. This is used when 'picking' a
// microcontroller in creative mode.
val newInfo = new MicrocontrollerData(stack)
newInfo.components.foreach(cs => Option(api.Driver.driverFor(cs)) match {
case Some(driver) if driver == DriverScreen =>
val nbt = driver.dataTag(cs)
for (tagName <- nbt.func_150296_c().toArray) {
nbt.removeTag(tagName.asInstanceOf[String])
}
case _ =>
})
newInfo.save(stack)
stack
}
}
class NavigationUpgradeData extends ItemData {
def this(stack: ItemStack) {
this()
load(stack)
}
var map = new ItemStack(net.minecraft.init.Items.filled_map)
def mapData(world: World) = try map.getItem.asInstanceOf[ItemMap].getMapData(map, world) catch {
case _: Throwable => throw new Exception("invalid map")
}
override def load(stack: ItemStack) {
if (stack.hasTagCompound) {
load(stack.getTagCompound.getCompoundTag(Settings.namespace + "data"))
}
}
override def save(stack: ItemStack) {
if (!stack.hasTagCompound) {
stack.setTagCompound(new NBTTagCompound())
}
save(stack.getCompoundTag(Settings.namespace + "data"))
}
override def load(nbt: NBTTagCompound) {
if (nbt.hasKey(Settings.namespace + "map")) {
map = loadStack(nbt.getCompoundTag(Settings.namespace + "map"))
}
}
override def save(nbt: NBTTagCompound) {
if (map != null) {
nbt.setNewCompoundTag(Settings.namespace + "map", map.writeToNBT)
}
}
}
class RobotData extends ItemData {
def this(stack: ItemStack) {
this()
load(stack)
}
var name = ""
// Overall energy including components.
var totalEnergy = 0
// Energy purely stored in robot component - this is what we have to restore manually.
var robotEnergy = 0
var tier = 0
var components = Array.empty[ItemStack]
var containers = Array.empty[ItemStack]
var lightColor = 0xF23030
override def load(nbt: NBTTagCompound) {
if (nbt.hasKey("display") && nbt.getCompoundTag("display").hasKey("Name")) {
name = nbt.getCompoundTag("display").getString("Name")
}
if (Strings.isNullOrEmpty(name)) {
name = RobotData.randomName
}
totalEnergy = nbt.getInteger(Settings.namespace + "storedEnergy")
robotEnergy = nbt.getInteger(Settings.namespace + "robotEnergy")
tier = nbt.getInteger(Settings.namespace + "tier")
components = nbt.getTagList(Settings.namespace + "components", NBT.TAG_COMPOUND).
toArray[NBTTagCompound].map(loadStack)
containers = nbt.getTagList(Settings.namespace + "containers", NBT.TAG_COMPOUND).
toArray[NBTTagCompound].map(loadStack)
if (nbt.hasKey(Settings.namespace + "lightColor")) {
lightColor = nbt.getInteger(Settings.namespace + "lightColor")
}
// Code for migrating from 1.4.1 -> 1.4.2, add EEPROM.
// TODO Remove in 1.5
if (!nbt.hasKey(Settings.namespace + "biosFlag")) {
components :+= Items.createLuaBios()
}
}
override def save(nbt: NBTTagCompound) {
if (!Strings.isNullOrEmpty(name)) {
if (!nbt.hasKey("display")) {
nbt.setTag("display", new NBTTagCompound())
}
nbt.getCompoundTag("display").setString("Name", name)
}
nbt.setInteger(Settings.namespace + "storedEnergy", totalEnergy)
nbt.setInteger(Settings.namespace + "robotEnergy", robotEnergy)
nbt.setInteger(Settings.namespace + "tier", tier)
nbt.setNewTagList(Settings.namespace + "components", components.toIterable)
nbt.setNewTagList(Settings.namespace + "containers", containers.toIterable)
nbt.setInteger(Settings.namespace + "lightColor", lightColor)
// TODO Remove in 1.5
nbt.setBoolean(Settings.namespace + "biosFlag", true)
}
def createItemStack() = {
val stack = api.Items.get("robot").createItemStack(1)
save(stack)
stack
}
def copyItemStack() = {
val stack = createItemStack()
// Forget all node addresses and so on. This is used when 'picking' a
// robot in creative mode.
val newInfo = new RobotData(stack)
newInfo.components.foreach(cs => Option(api.Driver.driverFor(cs)) match {
case Some(driver) if driver == DriverScreen =>
val nbt = driver.dataTag(cs)
for (tagName <- nbt.func_150296_c().toArray) {
nbt.removeTag(tagName.asInstanceOf[String])
}
case _ =>
})
// Don't show energy info (because it's unreliable) but fill up the
// internal buffer. This is for creative use only, anyway.
newInfo.totalEnergy = 0
newInfo.robotEnergy = 50000
newInfo.save(stack)
stack
}
}
object RobotData {
val names = try {
Source.fromInputStream(getClass.getResourceAsStream(
"/assets/" + Settings.resourceDomain + "/robot.names"))(Charsets.UTF_8).
getLines().map(_.takeWhile(_ != '#').trim()).filter(_ != "").toArray
}
catch {
case t: Throwable =>
OpenComputers.log.warn("Failed loading robot name list.", t)
Array.empty[String]
}
def randomName = if (names.length > 0) names((math.random * names.length).toInt) else "Robot"
}
class TabletData extends ItemData {
def this(stack: ItemStack) {
this()
load(stack)
}
var items = Array.fill[Option[ItemStack]](32)(None)
var isRunning = false
var energy = 0.0
var maxEnergy = 0.0
override def load(nbt: NBTTagCompound) {
nbt.getTagList(Settings.namespace + "items", NBT.TAG_COMPOUND).foreach((slotNbt: NBTTagCompound) => {
val slot = slotNbt.getByte("slot")
if (slot >= 0 && slot < items.length) {
items(slot) = Option(loadStack(slotNbt.getCompoundTag("item")))
}
})
isRunning = nbt.getBoolean(Settings.namespace + "isRunning")
energy = nbt.getDouble(Settings.namespace + "energy")
maxEnergy = nbt.getDouble(Settings.namespace + "maxEnergy")
// Code for migrating from 1.4.1 -> 1.4.2, add EEPROM.
// TODO Remove in 1.5
if (!nbt.hasKey(Settings.namespace + "biosFlag")) {
val firstEmpty = items.indexWhere(_.isEmpty)
items(firstEmpty) = Option(Items.createLuaBios())
}
}
override def save(nbt: NBTTagCompound) {
nbt.setNewTagList(Settings.namespace + "items",
items.zipWithIndex collect {
case (Some(stack), slot) => (stack, slot)
} map {
case (stack, slot) =>
val slotNbt = new NBTTagCompound()
slotNbt.setByte("slot", slot.toByte)
slotNbt.setNewCompoundTag("item", stack.writeToNBT)
})
nbt.setBoolean(Settings.namespace + "isRunning", isRunning)
nbt.setDouble(Settings.namespace + "energy", energy)
nbt.setDouble(Settings.namespace + "maxEnergy", maxEnergy)
// TODO Remove in 1.5
nbt.setBoolean(Settings.namespace + "biosFlag", true)
}
}
} }