diff --git a/assets/items.psd b/assets/items.psd index 7b2ca3a50..70c88bab6 100644 Binary files a/assets/items.psd and b/assets/items.psd differ diff --git a/src/main/resources/assets/opencomputers/textures/items/tablet.png b/src/main/resources/assets/opencomputers/textures/items/tablet.png new file mode 100644 index 000000000..69878fb60 Binary files /dev/null and b/src/main/resources/assets/opencomputers/textures/items/tablet.png differ diff --git a/src/main/scala/li/cil/oc/Items.scala b/src/main/scala/li/cil/oc/Items.scala index 4d38c950c..c108e286f 100644 --- a/src/main/scala/li/cil/oc/Items.scala +++ b/src/main/scala/li/cil/oc/Items.scala @@ -228,6 +228,7 @@ object Items extends ItemAPI { Recipes.addItem(new item.UpgradeBattery(multi, Tier.One), "batteryUpgrade1", "oc:batteryUpgrade1") Recipes.addItem(new item.UpgradeBattery(multi, Tier.Two), "batteryUpgrade2", "oc:batteryUpgrade2") Recipes.addItem(new item.UpgradeBattery(multi, Tier.Three), "batteryUpgrade3", "oc:batteryUpgrade3") + // Experimental registerItem(new item.Tablet(multi), "tablet") } diff --git a/src/main/scala/li/cil/oc/client/GuiHandler.scala b/src/main/scala/li/cil/oc/client/GuiHandler.scala index 00775c956..bba1c2ec2 100644 --- a/src/main/scala/li/cil/oc/client/GuiHandler.scala +++ b/src/main/scala/li/cil/oc/client/GuiHandler.scala @@ -41,7 +41,7 @@ object GuiHandler extends CommonGuiHandler { Tablet.get(stack, player).components.collect { case Some(buffer: TextBuffer) => buffer }.headOption match { - case Some(buffer: TextBuffer) => return new gui.Screen(buffer, true, () => true) + case Some(buffer: TextBuffer) => return new gui.Screen(buffer, true, () => true, () => true) case _ => } } diff --git a/src/main/scala/li/cil/oc/common/Proxy.scala b/src/main/scala/li/cil/oc/common/Proxy.scala index 3ceea9e72..315f11a96 100644 --- a/src/main/scala/li/cil/oc/common/Proxy.scala +++ b/src/main/scala/li/cil/oc/common/Proxy.scala @@ -7,6 +7,7 @@ import cpw.mods.fml.relauncher.Side import li.cil.oc._ import li.cil.oc.common.asm.SimpleComponentTickHandler import li.cil.oc.common.event._ +import li.cil.oc.common.item.Tablet import li.cil.oc.common.multipart.MultiPart import li.cil.oc.common.recipe.Recipes import li.cil.oc.server._ @@ -148,10 +149,13 @@ class Proxy { TickRegistry.registerTickHandler(EventHandler, Side.SERVER) TickRegistry.registerTickHandler(SimpleComponentTickHandler.Instance, Side.SERVER) + TickRegistry.registerTickHandler(Tablet, Side.CLIENT) + TickRegistry.registerTickHandler(Tablet, Side.SERVER) GameRegistry.registerPlayerTracker(Keyboard) NetworkRegistry.instance.registerConnectionHandler(EventHandler) MinecraftForge.EVENT_BUS.register(WirelessNetwork) MinecraftForge.EVENT_BUS.register(SaveHandler) + MinecraftForge.EVENT_BUS.register(Tablet) } private def registerExclusive(name: String, items: ItemStack*) { 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 1719cf220..01f0447a7 100644 --- a/src/main/scala/li/cil/oc/common/item/Tablet.scala +++ b/src/main/scala/li/cil/oc/common/item/Tablet.scala @@ -1,26 +1,38 @@ package li.cil.oc.common.item -import java.util.concurrent.{Callable, TimeUnit} +import java.util import java.util.UUID -import com.google.common.cache.{RemovalNotification, RemovalListener, CacheBuilder} -import li.cil.oc.{OpenComputers, Settings, api} +import java.util.concurrent.{Callable, TimeUnit} + +import com.google.common.cache.{CacheBuilder, RemovalListener, RemovalNotification} +import cpw.mods.fml.common.{ITickHandler, TickType} import li.cil.oc.api.Machine import li.cil.oc.api.driver.Container import li.cil.oc.api.machine.Owner import li.cil.oc.api.network.{Connector, Message, Node} import li.cil.oc.common.GuiType import li.cil.oc.common.inventory.ComponentInventory +import li.cil.oc.{OpenComputers, Settings, api} +import net.minecraft.client.renderer.texture.IconRegister import net.minecraft.entity.Entity import net.minecraft.entity.player.EntityPlayer import net.minecraft.item.ItemStack -import net.minecraft.world.World import net.minecraft.nbt.NBTTagCompound +import net.minecraft.world.World +import net.minecraftforge.event.ForgeSubscribe +import net.minecraftforge.event.world.WorldEvent class Tablet(val parent: Delegator) extends Delegate { val unlocalizedName = "Tablet" override def maxStackSize = 1 + override def registerIcons(iconRegister: IconRegister) = { + super.registerIcons(iconRegister) + + icon_=(iconRegister.registerIcon(Settings.resourceDomain + ":tablet")) + } + override def update(stack: ItemStack, world: World, player: Entity, slot: Int, selected: Boolean) = Tablet.get(stack, player).update(world, player, slot, selected) @@ -42,16 +54,24 @@ class TabletWrapper(val stack: ItemStack, var holder: Entity) extends ComponentI lazy val computer = if (holder.worldObj.isRemote) null else Machine.create(this) val items = Array( + Option(api.Items.get("cpu1").createItemStack(1)), + Option(api.Items.get("ram4").createItemStack(1)), Option(api.Items.get("screen1").createItemStack(1)), Option(api.Items.get("keyboard").createItemStack(1)), - Option(api.Items.get("graphicsCard1").createItemStack(1)), + Option(api.Items.get("graphicsCard2").createItemStack(1)), + Option(api.Items.get("batteryUpgrade2").createItemStack(1)), + Option(api.Items.get("navigationUpgrade").createItemStack(1)), Option(api.Items.get("openOS").createItemStack(1)), Option(api.Items.get("wlanCard").createItemStack(1)) ) def readFromNBT() { if (stack.hasTagCompound) { - load(stack.getTagCompound.getCompoundTag(Settings.namespace + "data")) + val data = stack.getTagCompound.getCompoundTag(Settings.namespace + "data") + if (!world.isRemote) { + computer.node.load(data) + } + load(data) } } @@ -63,12 +83,21 @@ class TabletWrapper(val stack: ItemStack, var holder: Entity) extends ComponentI if (!nbt.hasKey(Settings.namespace + "data")) { nbt.setTag(Settings.namespace + "data", new NBTTagCompound()) } - save(stack.getTagCompound.getCompoundTag(Settings.namespace + "data")) + val data = stack.getTagCompound.getCompoundTag(Settings.namespace + "data") + if (!world.isRemote) { + computer.node.save(data) + } + save(data) } readFromNBT() if (world.isRemote) { connectComponents() + components collect { + case Some(buffer: api.component.TextBuffer) => + buffer.setMaximumColorDepth(api.component.TextBuffer.ColorDepth.FourBit) + buffer.setMaximumResolution(80, 25) + } } else { api.Network.joinNewNetwork(computer.node) @@ -81,6 +110,12 @@ class TabletWrapper(val stack: ItemStack, var holder: Entity) extends ComponentI if (node == this.node) { connectComponents() } + else node.host match { + case buffer: api.component.TextBuffer => + buffer.setMaximumColorDepth(api.component.TextBuffer.ColorDepth.FourBit) + buffer.setMaximumResolution(80, 25) + case _ => + } } override def onDisconnect(node: Node) { @@ -123,9 +158,21 @@ class TabletWrapper(val stack: ItemStack, var holder: Entity) extends ComponentI override def world = holder.worldObj - override def installedMemory = 256 * 1024 + override def installedMemory = items.foldLeft(0)((acc, itemOption) => acc + (itemOption match { + case Some(item) => Option(api.Driver.driverFor(item)) match { + case Some(driver: api.driver.Memory) => driver.amount(item) + case _ => 0 + } + case _ => 0 + })) - override def maxComponents() = 8 + override def maxComponents = items.foldLeft(0)((acc, itemOption) => acc + (itemOption match { + case Some(item) => Option(api.Driver.driverFor(item)) match { + case Some(driver: api.driver.Processor) => driver.supportedComponents(item) + case _ => 0 + } + case _ => 0 + })) override def markAsChanged() {} @@ -163,7 +210,7 @@ class TabletWrapper(val stack: ItemStack, var holder: Entity) extends ComponentI } } -object Tablet extends Callable[TabletWrapper] with RemovalListener[String, TabletWrapper] { +object Tablet extends Callable[TabletWrapper] with RemovalListener[String, TabletWrapper] with ITickHandler { val clientCache = com.google.common.cache.CacheBuilder.newBuilder(). expireAfterAccess(10, TimeUnit.SECONDS). removalListener(this). @@ -197,6 +244,14 @@ object Tablet extends Callable[TabletWrapper] with RemovalListener[String, Table serverCache.get(id, this) } + def get(stack: ItemStack) = clientCache.synchronized { + if (stack.hasTagCompound && stack.getTagCompound.hasKey(Settings.namespace + "tablet")) { + val id = stack.getTagCompound.getString(Settings.namespace + "tablet") + Option(clientCache.getIfPresent(id)) + } + else None + } + def call = { new TabletWrapper(currentStack, currentHolder) } @@ -209,4 +264,23 @@ object Tablet extends Callable[TabletWrapper] with RemovalListener[String, Table } tablet.writeToNBT() } + + @ForgeSubscribe + def onWorldUnload(e: WorldEvent.Unload) { + clientCache.invalidateAll() + clientCache.cleanUp() + serverCache.invalidateAll() + serverCache.cleanUp() + } + + override def getLabel = "OpenComputers Tablet Cleanup Ticker" + + override def ticks = util.EnumSet.of(TickType.CLIENT, TickType.SERVER) + + override def tickStart(tickType: util.EnumSet[TickType], tickData: AnyRef*) { + clientCache.cleanUp() + serverCache.cleanUp() + } + + override def tickEnd(tickType: util.EnumSet[TickType], tickData: AnyRef*) {} } \ No newline at end of file