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.client.renderer.PetRenderer
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.integration.Mods
import li.cil.oc.integration.util
@ -163,12 +164,12 @@ object EventHandler {
didRecraft = recraft(e, mcu, stack => {
// 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 = recraft(e, drone, stack => {
// 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
// Presents?

View File

@ -5,9 +5,9 @@ import java.util
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.client.KeyBindings
import li.cil.oc.common.item.data.RobotData
import li.cil.oc.common.tileentity
import li.cil.oc.util.ItemCosts
import li.cil.oc.util.ItemUtils
import net.minecraft.block.Block
import net.minecraft.entity.player.EntityPlayer
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
// 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 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 it's a rotatable block try to make it face the player.
world.getTileEntity(x, y, z) match {

View File

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

View File

@ -1,10 +1,19 @@
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.item.data.RaidData
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
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(
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 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 _ => 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 li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.common.item.data.RobotData
import li.cil.oc.common.tileentity
import li.cil.oc.integration.util.NEI
import li.cil.oc.util.ItemUtils
import li.cil.oc.util.Rarity
import net.minecraft.client.renderer.texture.IIconRegister
import net.minecraft.entity.player.EntityPlayer
@ -52,7 +52,7 @@ class RobotAfterimage extends SimpleBlock with traits.SpecialBlock {
// ----------------------------------------------------------------------- //
override def rarity(stack: ItemStack) = {
val data = new ItemUtils.RobotData(stack)
val data = new RobotData(stack)
Rarity.byTier(data.tier)
}

View File

@ -9,11 +9,11 @@ import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.client.KeyBindings
import li.cil.oc.common.GuiType
import li.cil.oc.common.item.data.RobotData
import li.cil.oc.common.tileentity
import li.cil.oc.integration.util.NEI
import li.cil.oc.server.PacketSender
import li.cil.oc.server.component.robot
import li.cil.oc.util.ItemUtils
import li.cil.oc.util.Rarity
import li.cil.oc.util.Tooltip
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) = {
val data = new ItemUtils.RobotData(stack)
val data = new RobotData(stack)
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) {
super.tooltipTail(metadata, stack, player, tooltip, advanced)
if (KeyBindings.showExtendedTooltips) {
val info = new ItemUtils.RobotData(stack)
val info = new RobotData(stack)
val components = info.containers ++ info.components
if (components.length > 0) {
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.Inventory
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.util.BlockPosition
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ExtendedWorld._
import li.cil.oc.util.InventoryUtils
import li.cil.oc.util.ItemUtils
import net.minecraft.block.material.Material
import net.minecraft.entity.Entity
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
// Logic stuff, components, machine and such.
val info = new ItemUtils.MicrocontrollerData()
val info = new MicrocontrollerData()
val machine = if (!world.isRemote) {
val m = Machine.create(this)
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 targetX = dataWatcher.getWatchableObjectFloat(3)
def targetY = dataWatcher.getWatchableObjectFloat(4)
def targetZ = dataWatcher.getWatchableObjectFloat(5)
def targetAcceleration = dataWatcher.getWatchableObjectFloat(6)
def selectedSlot = dataWatcher.getWatchableObjectByte(7) & 0xFF
def globalBuffer = dataWatcher.getWatchableObjectInt(8)
def globalBufferSize = dataWatcher.getWatchableObjectInt(9)
def statusText = dataWatcher.getWatchableObjectString(10)
def inventorySize = dataWatcher.getWatchableObjectByte(11) & 0xFF
def lightColor = dataWatcher.getWatchableObjectInt(12)
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.
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 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 selectedSlot_=(value: Int) = dataWatcher.updateObject(7, byte2Byte(value.toByte))
def globalBuffer_=(value: Int) = dataWatcher.updateObject(8, 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 inventorySize_=(value: Int) = dataWatcher.updateObject(11, byte2Byte(value.toByte))
def lightColor_=(value: Int) = dataWatcher.updateObject(12, int2Integer(value))
@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.SimpleItem
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.integration.Mods
import li.cil.oc.util.Color
import li.cil.oc.util.ItemUtils
import net.minecraft.block.Block
import net.minecraft.creativetab.CreativeTabs
import net.minecraft.entity.player.EntityPlayer
@ -141,7 +142,7 @@ object Items extends ItemAPI {
}
def createConfiguredDrone() = {
val data = new ItemUtils.MicrocontrollerData()
val data = new MicrocontrollerData()
data.tier = Tier.Four
data.storedEnergy = Settings.get.bufferDrone.toInt
@ -167,7 +168,7 @@ object Items extends ItemAPI {
}
def createConfiguredMicrocontroller() = {
val data = new ItemUtils.MicrocontrollerData()
val data = new MicrocontrollerData()
data.tier = Tier.Four
data.storedEnergy = Settings.get.bufferMicrocontroller.toInt
@ -190,7 +191,7 @@ object Items extends ItemAPI {
}
def createConfiguredRobot() = {
val data = new ItemUtils.RobotData()
val data = new RobotData()
data.name = "Creatix"
data.tier = Tier.Four

View File

@ -6,9 +6,9 @@ import cpw.mods.fml.relauncher.Side
import cpw.mods.fml.relauncher.SideOnly
import li.cil.oc.client.KeyBindings
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.util.BlockPosition
import li.cil.oc.util.ItemUtils
import li.cil.oc.util.Rarity
import net.minecraft.entity.player.EntityPlayer
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 = {
if (KeyBindings.showExtendedTooltips) {
val info = new ItemUtils.MicrocontrollerData(stack)
val info = new MicrocontrollerData(stack)
for (component <- info.components) {
tooltip.add("- " + component.getDisplayName)
}
@ -28,7 +28,7 @@ class Drone(val parent: Delegator) extends Delegate {
}
override def rarity(stack: ItemStack) = {
val data = new ItemUtils.MicrocontrollerData(stack)
val data = new MicrocontrollerData(stack)
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.Slot
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.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.Tooltip
import net.minecraft.entity.Entity
@ -58,7 +57,7 @@ class Tablet(val parent: Delegator) extends Delegate {
@SideOnly(Side.CLIENT)
override def icon(stack: ItemStack, pass: Int) = {
if (stack.hasTagCompound) {
val data = new ItemUtils.TabletData(stack)
val data = new TabletData(stack)
if (data.isRunning) iconOn else iconOff
} 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 = {
if (KeyBindings.showExtendedTooltips) {
val info = new ItemUtils.TabletData(stack)
val info = new TabletData(stack)
// Ignore/hide the screen.
val components = info.items.drop(1)
if (components.length > 1) {
@ -91,7 +90,7 @@ class Tablet(val parent: Delegator) extends Delegate {
override def damage(stack: ItemStack) = {
val nbt = stack.getTagCompound
if (nbt != null) {
val data = new ItemUtils.TabletData()
val data = new TabletData()
data.load(nbt)
(data.maxEnergy - data.energy).toInt
}
@ -101,7 +100,7 @@ class Tablet(val parent: Delegator) extends Delegate {
override def maxDamage(stack: ItemStack) = {
val nbt = stack.getTagCompound
if (nbt != null) {
val data = new ItemUtils.TabletData()
val data = new TabletData()
data.load(nbt)
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.detail.ItemInfo
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.util.ExtendedNBT._
import li.cil.oc.util.ItemUtils
import li.cil.oc.util.SideTracker
import net.minecraft.init.Blocks
import net.minecraft.inventory.InventoryCrafting
@ -97,7 +97,7 @@ object ExtendedRecipe {
// Find old Microcontroller.
(0 until inventory.getSizeInventory).map(inventory.getStackInSlot).find(api.Items.get(_) == descriptor) match {
case Some(oldMcu) =>
val data = new ItemUtils.MicrocontrollerData(oldMcu)
val data = new MicrocontrollerData(oldMcu)
// Remove old 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.common.Slot
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.ItemUtils
import net.minecraft.inventory.IInventory
@ -29,7 +30,7 @@ object DroneTemplate extends Template {
def assemble(inventory: IInventory) = {
val items = (0 until inventory.getSizeInventory).map(inventory.getStackInSlot)
val data = new ItemUtils.MicrocontrollerData()
val data = new MicrocontrollerData()
data.tier = caseTier(inventory)
data.components = items.drop(1).filter(_ != null).toArray
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 disassemble(stack: ItemStack, ingredients: Array[ItemStack]) = {
val info = new ItemUtils.MicrocontrollerData(stack)
val info = new MicrocontrollerData(stack)
val itemName = ItemUtils.caseNameWithTierSuffix("droneCase", info.tier)
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.common.Slot
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.ItemUtils
import net.minecraft.inventory.IInventory
@ -29,7 +30,7 @@ object MicrocontrollerTemplate extends Template {
def assemble(inventory: IInventory) = {
val items = (0 until inventory.getSizeInventory).map(inventory.getStackInSlot)
val data = new ItemUtils.MicrocontrollerData()
val data = new MicrocontrollerData()
data.tier = caseTier(inventory)
data.components = items.drop(1).filter(_ != null).toArray
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 disassemble(stack: ItemStack, ingredients: Array[ItemStack]) = {
val info = new ItemUtils.MicrocontrollerData(stack)
val info = new MicrocontrollerData(stack)
val itemName = ItemUtils.caseNameWithTierSuffix("microcontrollerCase", info.tier)
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 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.nbt.NBTTagCompound
@ -12,7 +12,7 @@ object NavigationUpgradeTemplate {
def selectDisassembler(stack: ItemStack) = api.Items.get(stack) == api.Items.get("navigationUpgrade")
def disassemble(stack: ItemStack, ingredients: Array[ItemStack]) = {
val info = new ItemUtils.NavigationUpgradeData(stack)
val info = new NavigationUpgradeData(stack)
ingredients.map {
case part if part.getItem == net.minecraft.init.Items.filled_map => info.map
case part => part

View File

@ -6,6 +6,7 @@ import li.cil.oc.api
import li.cil.oc.api.internal
import li.cil.oc.common.Slot
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.ItemUtils
import net.minecraft.inventory.IInventory
@ -28,9 +29,9 @@ object RobotTemplate extends Template {
def assemble(inventory: IInventory) = {
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.name = ItemUtils.RobotData.randomName
data.name = RobotData.randomName
data.robotEnergy = Settings.get.bufferRobot.toInt
data.totalEnergy = data.robotEnergy
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 disassemble(stack: ItemStack, ingredients: Array[ItemStack]) = {
val info = new ItemUtils.RobotData(stack)
val info = new RobotData(stack)
val itemName = ItemUtils.caseNameWithTierSuffix("case", info.tier)
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.common.Slot
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.ItemUtils
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
@ -32,7 +32,7 @@ object TabletTemplate extends Template {
val items = mutable.ArrayBuffer(
Option(api.Items.get("screen1").createItemStack(1))
) ++ (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.energy = Settings.get.bufferTablet
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 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 {
case Some(item) => item
}.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.entity.Drone
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.util.BlockPosition
import li.cil.oc.util.ExtendedWorld._
import li.cil.oc.util.ItemUtils
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
@ -100,7 +100,7 @@ class Charger extends traits.Environment with traits.PowerAcceptor with traits.R
handler(itemCharge)
}
}
val data = new ItemUtils.TabletData(stack)
val data = new TabletData(stack)
tryCharge(data.energy, data.maxEnergy, (amount) => {
data.energy = math.min(data.maxEnergy, data.energy + amount)
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.common.Slot
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.ItemUtils
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
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.
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).
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) {
val fs = api.FileSystem.asManagedEnvironment(
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.MultiTank
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.DriverRedstoneCard
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.ExtendedWorld._
import li.cil.oc.util.InventoryUtils
import li.cil.oc.util.ItemUtils
import net.minecraft.block.Block
import net.minecraft.block.BlockLiquid
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 {
var proxy: RobotProxy = _
val info = new ItemUtils.RobotData()
val info = new RobotData()
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.driver.EnvironmentHost
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.nbt.NBTTagCompound
import net.minecraftforge.common.util.Constants.NBT
@ -14,7 +14,7 @@ object DriverTablet extends Item {
isOneOf(stack, api.Items.get("tablet"))
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = {
val data = new ItemUtils.TabletData(stack)
val data = new TabletData(stack)
data.items.collect {
case Some(fs) if DriverFileSystem.worksWith(fs) => fs
}.headOption.map(DriverFileSystem.createEnvironment(_, host)).orNull
@ -23,7 +23,7 @@ object DriverTablet extends Item {
override def slot(stack: ItemStack) = Slot.Tablet
override def dataTag(stack: ItemStack) = {
val data = new ItemUtils.TabletData(stack)
val data = new TabletData(stack)
val index = data.items.indexWhere {
case Some(fs) => DriverFileSystem.worksWith(fs)
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.network._
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
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 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.api.Persistable
import li.cil.oc.common.Tier
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.ItemMap
import net.minecraft.item.ItemStack
import net.minecraft.item.crafting.CraftingManager
import net.minecraft.item.crafting.IRecipe
import net.minecraft.item.crafting.ShapedRecipes
import net.minecraft.item.crafting.ShapelessRecipes
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.ShapelessOreRecipe
import scala.collection.convert.WrapAsScala._
import scala.collection.mutable
import scala.io.Source
object ItemUtils {
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))
}
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)
}
}
}