| package li.cil.oc.util |
| |
| 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.server |
| import li.cil.oc.util.ExtendedNBT._ |
| import net.minecraft.item.ItemMap |
| import net.minecraft.item.ItemStack |
| import net.minecraft.nbt.NBTTagCompound |
| import net.minecraft.world.World |
| import net.minecraftforge.common.util.Constants.NBT |
| |
| import scala.io.Source |
| |
| object ItemUtils { |
| def caseTier(stack: ItemStack) = { |
| val descriptor = api.Items.get(stack) |
| if (descriptor == api.Items.get("case1")) Tier.One |
| else if (descriptor == api.Items.get("case2")) Tier.Two |
| else if (descriptor == api.Items.get("case3")) Tier.Three |
| else if (descriptor == api.Items.get("caseCreative")) Tier.Four |
| else Tier.None |
| } |
| |
| 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 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] |
| |
| 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") |
| if (nbt.hasKey(Settings.namespace + "components")) { |
| tier = nbt.getInteger(Settings.namespace + "tier") |
| components = nbt.getTagList(Settings.namespace + "components", NBT.TAG_COMPOUND).map((list, index) => { |
| ItemStack.loadItemStackFromNBT(list.getCompoundTagAt(index)) |
| }).toArray |
| containers = nbt.getTagList(Settings.namespace + "containers", NBT.TAG_COMPOUND).map((list, index) => { |
| ItemStack.loadItemStackFromNBT(list.getCompoundTagAt(index)) |
| }).toArray |
| } |
| else { |
| // Old robot, upgrade to new modular model. |
| tier = 0 |
| val experienceUpgrade = api.Items.get("experienceUpgrade").createItemStack(1) |
| server.driver.item.UpgradeExperience.dataTag(experienceUpgrade).setDouble(Settings.namespace + "xp", nbt.getDouble(Settings.namespace + "xp")) |
| components = Array( |
| api.Items.get("screen1").createItemStack(1), |
| api.Items.get("keyboard").createItemStack(1), |
| api.Items.get("inventoryUpgrade").createItemStack(1), |
| experienceUpgrade, |
| api.Items.get("openOS").createItemStack(1), |
| api.Items.get("graphicsCard1").createItemStack(1), |
| api.Items.get("cpu1").createItemStack(1), |
| api.Items.get("ram2").createItemStack(1) |
| ) |
| containers = Array( |
| api.Items.get("cardContainer2").createItemStack(1), |
| api.Items.get("diskDrive").createItemStack(1), |
| api.Items.get("upgradeContainer3").createItemStack(1) |
| ) |
| robotEnergy = totalEnergy |
| } |
| } |
| |
| override def save(nbt: NBTTagCompound) { |
| if (name != null) { |
| 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) |
| } |
| |
| 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 == server.driver.item.Screen => |
| 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 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 = ItemStack.loadItemStackFromNBT(nbt.getCompoundTag(Settings.namespace + "map")) |
| } |
| } |
| |
| override def save(nbt: NBTTagCompound) { |
| if (map != null) { |
| nbt.setNewCompoundTag(Settings.namespace + "map", map.writeToNBT) |
| } |
| } |
| } |
| |
| 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((list, index) => { |
| val slotNbt = list.getCompoundTagAt(index) |
| val slot = slotNbt.getByte("slot") |
| if (slot >= 0 && slot < items.length) { |
| items(slot) = Option(ItemStack.loadItemStackFromNBT(slotNbt.getCompoundTag("item"))) |
| } |
| }) |
| isRunning = nbt.getBoolean(Settings.namespace + "isRunning") |
| energy = nbt.getDouble(Settings.namespace + "energy") |
| maxEnergy = nbt.getDouble(Settings.namespace + "maxEnergy") |
| } |
| |
| 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) |
| } |
| } |
| |
| } |