diff --git a/src/main/scala/li/cil/oc/common/EventHandler.scala b/src/main/scala/li/cil/oc/common/EventHandler.scala index d7e32c70f..f807c3ac3 100644 --- a/src/main/scala/li/cil/oc/common/EventHandler.scala +++ b/src/main/scala/li/cil/oc/common/EventHandler.scala @@ -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? diff --git a/src/main/scala/li/cil/oc/common/block/Item.scala b/src/main/scala/li/cil/oc/common/block/Item.scala index a83ba8417..66666d44c 100644 --- a/src/main/scala/li/cil/oc/common/block/Item.scala +++ b/src/main/scala/li/cil/oc/common/block/Item.scala @@ -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 { diff --git a/src/main/scala/li/cil/oc/common/block/Microcontroller.scala b/src/main/scala/li/cil/oc/common/block/Microcontroller.scala index 5228067f9..8b7631a1b 100644 --- a/src/main/scala/li/cil/oc/common/block/Microcontroller.scala +++ b/src/main/scala/li/cil/oc/common/block/Microcontroller.scala @@ -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()) } } diff --git a/src/main/scala/li/cil/oc/common/block/Raid.scala b/src/main/scala/li/cil/oc/common/block/Raid.scala index 321958eaa..7c32128e3 100644 --- a/src/main/scala/li/cil/oc/common/block/Raid.scala +++ b/src/main/scala/li/cil/oc/common/block/Raid.scala @@ -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) + } } diff --git a/src/main/scala/li/cil/oc/common/block/RobotAfterimage.scala b/src/main/scala/li/cil/oc/common/block/RobotAfterimage.scala index 0bc42e235..981199ffb 100644 --- a/src/main/scala/li/cil/oc/common/block/RobotAfterimage.scala +++ b/src/main/scala/li/cil/oc/common/block/RobotAfterimage.scala @@ -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) } diff --git a/src/main/scala/li/cil/oc/common/block/RobotProxy.scala b/src/main/scala/li/cil/oc/common/block/RobotProxy.scala index 8d7042ab1..b825a14d7 100644 --- a/src/main/scala/li/cil/oc/common/block/RobotProxy.scala +++ b/src/main/scala/li/cil/oc/common/block/RobotProxy.scala @@ -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")) diff --git a/src/main/scala/li/cil/oc/common/block/traits/CustomDrops.scala b/src/main/scala/li/cil/oc/common/block/traits/CustomDrops.scala new file mode 100644 index 000000000..8a74a8897 --- /dev/null +++ b/src/main/scala/li/cil/oc/common/block/traits/CustomDrops.scala @@ -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 = {} +} diff --git a/src/main/scala/li/cil/oc/common/entity/Drone.scala b/src/main/scala/li/cil/oc/common/entity/Drone.scala index eb1925db3..a42ae9be4 100644 --- a/src/main/scala/li/cil/oc/common/entity/Drone.scala +++ b/src/main/scala/li/cil/oc/common/entity/Drone.scala @@ -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) diff --git a/src/main/scala/li/cil/oc/common/init/Items.scala b/src/main/scala/li/cil/oc/common/init/Items.scala index df48e7b0e..65917615f 100644 --- a/src/main/scala/li/cil/oc/common/init/Items.scala +++ b/src/main/scala/li/cil/oc/common/init/Items.scala @@ -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 diff --git a/src/main/scala/li/cil/oc/common/item/Drone.scala b/src/main/scala/li/cil/oc/common/item/Drone.scala index 7e8df8a8f..3b95cf722 100644 --- a/src/main/scala/li/cil/oc/common/item/Drone.scala +++ b/src/main/scala/li/cil/oc/common/item/Drone.scala @@ -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) } diff --git a/src/main/scala/li/cil/oc/common/item/Tablet.scala b/src/main/scala/li/cil/oc/common/item/Tablet.scala index 414b3f9a5..b3e864005 100644 --- a/src/main/scala/li/cil/oc/common/item/Tablet.scala +++ b/src/main/scala/li/cil/oc/common/item/Tablet.scala @@ -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 } diff --git a/src/main/scala/li/cil/oc/common/item/data/ItemData.scala b/src/main/scala/li/cil/oc/common/item/data/ItemData.scala new file mode 100644 index 000000000..1df64ade7 --- /dev/null +++ b/src/main/scala/li/cil/oc/common/item/data/ItemData.scala @@ -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) + } +} diff --git a/src/main/scala/li/cil/oc/common/item/data/MicrocontrollerData.scala b/src/main/scala/li/cil/oc/common/item/data/MicrocontrollerData.scala new file mode 100644 index 000000000..a8657920f --- /dev/null +++ b/src/main/scala/li/cil/oc/common/item/data/MicrocontrollerData.scala @@ -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 + } +} diff --git a/src/main/scala/li/cil/oc/common/item/data/NavigationUpgradeData.scala b/src/main/scala/li/cil/oc/common/item/data/NavigationUpgradeData.scala new file mode 100644 index 000000000..0173c41de --- /dev/null +++ b/src/main/scala/li/cil/oc/common/item/data/NavigationUpgradeData.scala @@ -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) + } + } +} diff --git a/src/main/scala/li/cil/oc/common/item/data/RaidData.scala b/src/main/scala/li/cil/oc/common/item/data/RaidData.scala new file mode 100644 index 000000000..b98f7b19d --- /dev/null +++ b/src/main/scala/li/cil/oc/common/item/data/RaidData.scala @@ -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 + } +} diff --git a/src/main/scala/li/cil/oc/common/item/data/RobotData.scala b/src/main/scala/li/cil/oc/common/item/data/RobotData.scala new file mode 100644 index 000000000..8f3e29840 --- /dev/null +++ b/src/main/scala/li/cil/oc/common/item/data/RobotData.scala @@ -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 + } +} diff --git a/src/main/scala/li/cil/oc/common/item/data/TabletData.scala b/src/main/scala/li/cil/oc/common/item/data/TabletData.scala new file mode 100644 index 000000000..fbada126b --- /dev/null +++ b/src/main/scala/li/cil/oc/common/item/data/TabletData.scala @@ -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) + } +} diff --git a/src/main/scala/li/cil/oc/common/recipe/ExtendedRecipe.scala b/src/main/scala/li/cil/oc/common/recipe/ExtendedRecipe.scala index d1568ffed..e2a92a13d 100644 --- a/src/main/scala/li/cil/oc/common/recipe/ExtendedRecipe.scala +++ b/src/main/scala/li/cil/oc/common/recipe/ExtendedRecipe.scala @@ -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) diff --git a/src/main/scala/li/cil/oc/common/template/DroneTemplate.scala b/src/main/scala/li/cil/oc/common/template/DroneTemplate.scala index 64c9b9ef3..fada5345c 100644 --- a/src/main/scala/li/cil/oc/common/template/DroneTemplate.scala +++ b/src/main/scala/li/cil/oc/common/template/DroneTemplate.scala @@ -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 diff --git a/src/main/scala/li/cil/oc/common/template/MicrocontrollerTemplate.scala b/src/main/scala/li/cil/oc/common/template/MicrocontrollerTemplate.scala index ed8a7c6f2..4bbfe4080 100644 --- a/src/main/scala/li/cil/oc/common/template/MicrocontrollerTemplate.scala +++ b/src/main/scala/li/cil/oc/common/template/MicrocontrollerTemplate.scala @@ -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 diff --git a/src/main/scala/li/cil/oc/common/template/NavigationUpgradeTemplate.scala b/src/main/scala/li/cil/oc/common/template/NavigationUpgradeTemplate.scala index 282eac6c1..a98635f02 100644 --- a/src/main/scala/li/cil/oc/common/template/NavigationUpgradeTemplate.scala +++ b/src/main/scala/li/cil/oc/common/template/NavigationUpgradeTemplate.scala @@ -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 diff --git a/src/main/scala/li/cil/oc/common/template/RobotTemplate.scala b/src/main/scala/li/cil/oc/common/template/RobotTemplate.scala index 852cf69d2..08890dc45 100644 --- a/src/main/scala/li/cil/oc/common/template/RobotTemplate.scala +++ b/src/main/scala/li/cil/oc/common/template/RobotTemplate.scala @@ -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 diff --git a/src/main/scala/li/cil/oc/common/template/TabletTemplate.scala b/src/main/scala/li/cil/oc/common/template/TabletTemplate.scala index cc6581ed0..4f0a78c1a 100644 --- a/src/main/scala/li/cil/oc/common/template/TabletTemplate.scala +++ b/src/main/scala/li/cil/oc/common/template/TabletTemplate.scala @@ -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. diff --git a/src/main/scala/li/cil/oc/common/tileentity/Charger.scala b/src/main/scala/li/cil/oc/common/tileentity/Charger.scala index b26cb8f03..d4ccfa3f3 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Charger.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Charger.scala @@ -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) diff --git a/src/main/scala/li/cil/oc/common/tileentity/Microcontroller.scala b/src/main/scala/li/cil/oc/common/tileentity/Microcontroller.scala index 10de62d08..f3a85ecaa 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Microcontroller.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Microcontroller.scala @@ -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"). diff --git a/src/main/scala/li/cil/oc/common/tileentity/Raid.scala b/src/main/scala/li/cil/oc/common/tileentity/Raid.scala index 8b2df850d..da162ccab 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Raid.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Raid.scala @@ -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), diff --git a/src/main/scala/li/cil/oc/common/tileentity/Robot.scala b/src/main/scala/li/cil/oc/common/tileentity/Robot.scala index 7e1e11c71..c0a5cd84b 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Robot.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Robot.scala @@ -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 diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverTablet.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverTablet.scala index 9c28a2e73..e451197e3 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/DriverTablet.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverTablet.scala @@ -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 diff --git a/src/main/scala/li/cil/oc/server/component/UpgradeNavigation.scala b/src/main/scala/li/cil/oc/server/component/UpgradeNavigation.scala index 22f639368..aefdd926a 100644 --- a/src/main/scala/li/cil/oc/server/component/UpgradeNavigation.scala +++ b/src/main/scala/li/cil/oc/server/component/UpgradeNavigation.scala @@ -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 { diff --git a/src/main/scala/li/cil/oc/util/ItemUtils.scala b/src/main/scala/li/cil/oc/util/ItemUtils.scala index b7589040e..9c7468468 100644 --- a/src/main/scala/li/cil/oc/util/ItemUtils.scala +++ b/src/main/scala/li/cil/oc/util/ItemUtils.scala @@ -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) - } - } - }