diff --git a/src/main/scala/ocelot/desktop/OcelotDesktop.scala b/src/main/scala/ocelot/desktop/OcelotDesktop.scala index 3187f6d..692a931 100644 --- a/src/main/scala/ocelot/desktop/OcelotDesktop.scala +++ b/src/main/scala/ocelot/desktop/OcelotDesktop.scala @@ -2,9 +2,11 @@ package ocelot.desktop import li.flor.nativejfilechooser.NativeJFileChooser import ocelot.desktop.audio.{Audio, SoundSource} +import ocelot.desktop.graphics.IconDef import ocelot.desktop.ui.UiHandler -import ocelot.desktop.ui.widget.inventory.item.traits.PersistableItemPrototype +import ocelot.desktop.ui.widget.inventory.ItemRegistry import ocelot.desktop.ui.widget.inventory.item._ +import ocelot.desktop.ui.widget.inventory.item.traits.PersistableItemPrototype import ocelot.desktop.ui.widget.{ExitConfirmationDialog, RootWidget, SettingsDialog} import ocelot.desktop.util.FileUtils.getOcelotConfigDirectory import ocelot.desktop.util._ @@ -15,6 +17,7 @@ import totoro.ocelot.brain.event.FileSystemActivityType.Floppy import totoro.ocelot.brain.event._ import totoro.ocelot.brain.nbt.persistence.NBTPersistence import totoro.ocelot.brain.nbt.{CompressedStreamTools, NBTTagCompound} +import totoro.ocelot.brain.util.{DyeColor, Tier} import totoro.ocelot.brain.workspace.Workspace import java.io._ @@ -41,6 +44,7 @@ object OcelotDesktop extends Logging { Ocelot.initialize(LogManager.getLogger(Ocelot)) setupNbtConstructors() + setupItemRegistry() val settingsFile = getOcelotConfigDirectory.resolve("ocelot.conf") Settings.load(settingsFile) @@ -257,7 +261,6 @@ object OcelotDesktop extends Logging { } def setupNbtConstructors(): Unit = { - // FIXME: must construct and load an item's prototype first and use it then to build the item itself val itemConstructor = new PersistableItemPrototype.ItemConstructor val tieredConstructor = new NBTPersistence.TieredConstructor NBTPersistence.registerConstructor(classOf[CPUItemPrototype.CPU#Item].getName, itemConstructor) @@ -300,6 +303,125 @@ object OcelotDesktop extends Logging { NBTPersistence.registerConstructor(classOf[WirelessNetworkCardItemPrototype.Tier2#Item].getName, itemConstructor) } + private def setupItemRegistry(): Unit = { + ItemRegistry.register(new ItemRegistry.Group("Processor", Some(IconDef("items/CPU2"))) { + register(new ItemRegistry.Group("CPU", Some(IconDef("items/CPU2"))) { + for (tier <- Tier.One to Tier.Three) { + register(new CPUItemPrototype.CPU(tier)) + } + }) + + register(new ItemRegistry.Group("APU", Some(IconDef("items/APU2"))) { + for (tier <- Tier.One to Tier.Three) { + register(new CPUItemPrototype.APU(tier)) + } + }) + }) + ItemRegistry.register(new CPUItemPrototype.CPU.Recoverer) + ItemRegistry.register(new CPUItemPrototype.APU.Recoverer) + + ItemRegistry.register(new ItemRegistry.Group("Memory", Some(IconDef("items/Memory5"))) { + for (tier <- Tier.One to Tier.Six) { + register(new MemoryItemPrototype(tier)) + } + }) + ItemRegistry.register(new MemoryItemPrototype.Recoverer) + + ItemRegistry.register(new ItemRegistry.Group("GPU", Some(IconDef("items/GraphicsCard2"))) { + for (tier <- Tier.One to Tier.Three) { + register(new GraphicsCardItemPrototype(tier)) + } + }) + ItemRegistry.register(new GraphicsCardItemPrototype.Recoverer) + + ItemRegistry.register(new ItemRegistry.Group("HDD", Some(IconDef("items/HardDiskDrive2"))) { + register(new ItemRegistry.Group("Managed", None) { + for (tier <- Tier.One to Tier.Three) { + register(new HDDItemPrototype.Managed(tier)) + } + }) + + register(new ItemRegistry.Group("Unmanaged", None) { + for (tier <- Tier.One to Tier.Three) { + register(new HDDItemPrototype.Unmanaged(tier)) + } + }) + }) + ItemRegistry.register(new HDDItemPrototype.Managed.Recoverer) + ItemRegistry.register(new HDDItemPrototype.Unmanaged.Recoverer) + + ItemRegistry.register(new ItemRegistry.Group("Data Card", Some(IconDef("items/DataCard1"))) { + register(new DataCardItemPrototype.Tier1) + register(new DataCardItemPrototype.Tier2) + register(new DataCardItemPrototype.Tier3) + }) + ItemRegistry.register(new DataCardItemPrototype.Tier1.Recoverer) + ItemRegistry.register(new DataCardItemPrototype.Tier2.Recoverer) + ItemRegistry.register(new DataCardItemPrototype.Tier3.Recoverer) + + ItemRegistry.register(new InternetCardItemPrototype) + ItemRegistry.register(new InternetCardItemPrototype.Recoverer) + + ItemRegistry.register(new LinkedCardItemPrototype) + ItemRegistry.register(new LinkedCardItemPrototype.Recoverer) + + ItemRegistry.register(new ItemRegistry.Group("Network Card", Some(IconDef("items/WirelessNetworkCard1"))) { + register(new NetworkCardItemPrototype) + + register(new ItemRegistry.Group("Wireless", Some(IconDef("items/WirelessNetworkCard1"))) { + register(new WirelessNetworkCardItemPrototype.Tier1) + register(new WirelessNetworkCardItemPrototype.Tier2) + }) + }) + ItemRegistry.register(new NetworkCardItemPrototype.Recoverer) + ItemRegistry.register(new WirelessNetworkCardItemPrototype.Tier1.Recoverer) + ItemRegistry.register(new WirelessNetworkCardItemPrototype.Tier2.Recoverer) + + ItemRegistry.register(new ItemRegistry.Group("Redstone Card", Some(IconDef("items/RedstoneCard0"))) { + register(new RedstoneCardItemPrototype.Tier1) + register(new RedstoneCardItemPrototype.Tier2) + }) + ItemRegistry.register(new RedstoneCardItemPrototype.Tier1.Recoverer) + ItemRegistry.register(new RedstoneCardItemPrototype.Tier2.Recoverer) + + ItemRegistry.register(new ItemRegistry.Group("EEPROM", Some(IconDef("items/EEPROM"))) { + register(new EEPROMItemPrototype) + + register(new ItemRegistry.Group("Loot", None) { + for (key <- EEPROMItemPrototype.LootFactories.keys) { + register(new EEPROMItemPrototype(key)) + } + }) + }) + ItemRegistry.register(new EEPROMItemPrototype.Recoverer) + + ItemRegistry.register(new ItemRegistry.Group("Floppy Disk", Some(IconDef("items/FloppyDisk_dyeGray"))) { + register(new FloppyItemPrototype.Managed) + + register(new ItemRegistry.Group("Loot", Some(IconDef("items/FloppyDisk_dyeGreen"))) { + for (key <- FloppyItemPrototype.Managed.LootFactories.keys) { + register(new FloppyItemPrototype.Managed(key)) + } + }) + + register(new ItemRegistry.Group("Managed (colored)", Some(IconDef("items/FloppyDisk_dyePink"))) { + for (dye <- DyeColor.ALL if dye != DyeColor.GRAY) { + register(new FloppyItemPrototype.Managed(dye, None)) + } + }) + + register(new ItemRegistry.Group("Unmanaged", Some(IconDef("items/FloppyDisk_dyeBlack"))) { + register(new FloppyItemPrototype.Unmanaged(DyeColor.GRAY)) + + for (dye <- DyeColor.ALL if dye != DyeColor.GRAY) { + register(new FloppyItemPrototype.Unmanaged(dye)) + } + }) + }) + ItemRegistry.register(new FloppyItemPrototype.Managed.Recoverer) + ItemRegistry.register(new FloppyItemPrototype.Unmanaged.Recoverer) + } + private def setupEventHandlers(): Unit = { EventBus.subscribe[BeepEvent] { event => if (!UiHandler.audioDisabled) diff --git a/src/main/scala/ocelot/desktop/node/nodes/DiskDriveNode.scala b/src/main/scala/ocelot/desktop/node/nodes/DiskDriveNode.scala index a316075..ee691ad 100644 --- a/src/main/scala/ocelot/desktop/node/nodes/DiskDriveNode.scala +++ b/src/main/scala/ocelot/desktop/node/nodes/DiskDriveNode.scala @@ -4,28 +4,31 @@ import ocelot.desktop.OcelotDesktop import ocelot.desktop.color.IntColor import ocelot.desktop.graphics.Graphics import ocelot.desktop.node.EnvironmentNode -import ocelot.desktop.ui.widget.inventory.{InventorySlotGroup, Item} +import ocelot.desktop.ui.widget.inventory.InventorySlotGroup import ocelot.desktop.ui.widget.inventory.item.FloppyItemPrototype import ocelot.desktop.ui.widget.inventory.slot.FloppySlot import totoro.ocelot.brain.entity.FloppyDiskDrive -import totoro.ocelot.brain.entity.traits.{Environment, Floppy} +import totoro.ocelot.brain.entity.traits.Environment import totoro.ocelot.brain.nbt.{NBT, NBTTagCompound} -import totoro.ocelot.brain.util.{DyeColor, Persistable} +import totoro.ocelot.brain.util.DyeColor -class DiskDriveNode(val diskDrive: FloppyDiskDrive) extends EnvironmentNode { +class DiskDriveNode(val diskDrive: FloppyDiskDrive, initialize: Boolean = true) extends EnvironmentNode { var lastAccess = 0L OcelotDesktop.workspace.add(diskDrive) val slot = new FloppySlot(diskDrive.inventory(0), workspaceView) val slotGroup = new InventorySlotGroup(slot) - slot.item = slot.item.orElse(Some(new FloppyItemPrototype.Managed("openos").build)) + + if (initialize) { + slot.item = slot.item.orElse(Some(new FloppyItemPrototype.Managed("openos").build)) + } def this(nbt: NBTTagCompound) { this({ val address = nbt.getString("address") OcelotDesktop.workspace.entityByAddress(address).get.asInstanceOf[FloppyDiskDrive] - }) + }, false) load(nbt) } diff --git a/src/main/scala/ocelot/desktop/ui/widget/inventory/InventorySlotGroup.scala b/src/main/scala/ocelot/desktop/ui/widget/inventory/InventorySlotGroup.scala index 2aad878..0d7b35e 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/inventory/InventorySlotGroup.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/inventory/InventorySlotGroup.scala @@ -146,6 +146,8 @@ object InventorySlotGroup extends Logging { new Exception(s"Inventory ${slot.inventory.owner} stores an Entity $entity (slot index: ${slot.index}) " + s"that cannot be recovered to an Item") ).log("Could not recover an item from an Inventory") + } else { + logger.debug(s"Recovered an Item from $entity (inventory ${slot.inventory.owner}, slot ${slot.index})") } item diff --git a/src/main/scala/ocelot/desktop/ui/widget/inventory/ItemRecoverer.scala b/src/main/scala/ocelot/desktop/ui/widget/inventory/ItemRecoverer.scala index df9a080..de3c685 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/inventory/ItemRecoverer.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/inventory/ItemRecoverer.scala @@ -8,7 +8,7 @@ import scala.reflect.ClassTag trait ItemRecoverer { type Element - implicit val elementTag: ClassTag[Element] + val elementTag: ClassTag[Element] def recover(element: Element): Item[Element] } diff --git a/src/main/scala/ocelot/desktop/ui/widget/inventory/ItemRegistry.scala b/src/main/scala/ocelot/desktop/ui/widget/inventory/ItemRegistry.scala index 480eb30..6948727 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/inventory/ItemRegistry.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/inventory/ItemRegistry.scala @@ -25,8 +25,7 @@ object ItemRegistry { recovererRegistry(recoverer.elementTag.runtimeClass) = recoverer def recover[E](element: E): Option[Item[E]] = { - recovererRegistry - .get(element.getClass) + findSuperclass(Some(element.getClass))(recovererRegistry.get) .map(recoverer => { // wild type-casting ¯\_(ツ)_/¯ // (should be safe though) @@ -36,9 +35,30 @@ object ItemRegistry { def children: Iterator[Node] = nodes.iterator + private def findSuperclass[T](classes: IterableOnce[Class[_]])(filter: Class[_] => Option[T]): Option[T] = { + val visited = mutable.Set.empty[Class[_]] + val queue = mutable.ArrayDeque.from(classes) + + while (queue.nonEmpty) { + val clazz = queue.removeHead() + val filterResult = filter(clazz) + + if (filterResult.nonEmpty) { + return filterResult + } + + visited += clazz + + val superclasses = Option(clazz.getSuperclass).iterator ++ clazz.getInterfaces + queue ++= superclasses.filterNot(visited) + } + + None + } + sealed trait Node - abstract case class Group(name: String, icon: Option[IconDef]) extends Node { self => + abstract case class Group(name: String, icon: Option[IconDef]) extends Node { private val _children: ArrayBuffer[Node] = ArrayBuffer.empty final def children: Iterator[Node] = _children.iterator diff --git a/src/main/scala/ocelot/desktop/ui/widget/inventory/LmbItemSelectionSlot.scala b/src/main/scala/ocelot/desktop/ui/widget/inventory/LmbItemSelectionSlot.scala index 2f4fcf5..6e2f5a2 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/inventory/LmbItemSelectionSlot.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/inventory/LmbItemSelectionSlot.scala @@ -4,6 +4,7 @@ import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry, Cont import ocelot.desktop.ui.widget.inventory.ItemRegistry.{Group, Node} trait LmbItemSelectionSlot[E] extends SlotWidget[E] { + // FIXME: nested submenus exhibit weird behavior override def fillLmbMenu(menu: ContextMenu): Unit = { def traverse(node: Node): Option[ContextMenuEntry] = node match { case group@Group(name, icon) => diff --git a/src/main/scala/ocelot/desktop/ui/widget/inventory/item/CPUItemPrototype.scala b/src/main/scala/ocelot/desktop/ui/widget/inventory/item/CPUItemPrototype.scala index d132ef2..8ca1c65 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/inventory/item/CPUItemPrototype.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/inventory/item/CPUItemPrototype.scala @@ -1,12 +1,12 @@ package ocelot.desktop.ui.widget.inventory.item import ocelot.desktop.graphics.IconDef -import ocelot.desktop.ui.widget.inventory.ItemPrototype +import ocelot.desktop.ui.widget.inventory.{Item, ItemPrototype, ItemRecoverer} import ocelot.desktop.ui.widget.inventory.item.traits.{EnvironmentItemPrototype, PersistableItemPrototype, SlotTieredItemPrototype} import totoro.ocelot.brain.entity import totoro.ocelot.brain.entity.traits.{GenericCPU, Tiered} -import scala.reflect.ClassTag +import scala.reflect.{ClassTag, classTag} sealed abstract class CPUItemPrototype[E <: GenericCPU](implicit override val elementTag: ClassTag[E]) extends ItemPrototype.WithInstance @@ -28,7 +28,7 @@ sealed abstract class CPUItemPrototype[E <: GenericCPU](implicit override val el } object CPUItemPrototype { - class CPU(override var tier: Int) extends CPUItemPrototype[entity.CPU] { + final class CPU(override var tier: Int) extends CPUItemPrototype[entity.CPU] { override type Item = Instance override def name: String = s"CPU ($tierString)" @@ -38,7 +38,21 @@ object CPUItemPrototype { override def build: Item = new Instance(new entity.CPU(tier)) } - class APU(override var tier: Int) extends CPUItemPrototype[entity.APU] { + object CPU { + class Recoverer extends ItemRecoverer { + override type Element = entity.CPU + + override val elementTag: ClassTag[entity.CPU] = classTag[entity.CPU] + + override def recover(element: entity.CPU): Item[entity.CPU] = { + val proto = new CPU(element.tier) + + new proto.Instance(element) + } + } + } + + final class APU(override var tier: Int) extends CPUItemPrototype[entity.APU] { override type Item = Instance override def name: String = s"APU ($tierString)" @@ -55,5 +69,17 @@ object CPUItemPrototype { private val Animation = Some(Array( (0, 3f), (1, 3f), (2, 3f), (3, 3f), (4, 3f), (5, 3f), (4, 3f), (3, 3f), (2, 3f), (1, 3f), (0, 3f))) + + class Recoverer extends ItemRecoverer { + override type Element = entity.APU + + override val elementTag: ClassTag[entity.APU] = classTag[entity.APU] + + override def recover(element: entity.APU): Item[entity.APU] = { + val proto = new APU(element.tier) + + new proto.Instance(element) + } + } } } diff --git a/src/main/scala/ocelot/desktop/ui/widget/inventory/item/DataCardItemPrototype.scala b/src/main/scala/ocelot/desktop/ui/widget/inventory/item/DataCardItemPrototype.scala index 02b0dfe..bb59a20 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/inventory/item/DataCardItemPrototype.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/inventory/item/DataCardItemPrototype.scala @@ -1,12 +1,12 @@ package ocelot.desktop.ui.widget.inventory.item import ocelot.desktop.graphics.IconDef -import ocelot.desktop.ui.widget.inventory.ItemPrototype +import ocelot.desktop.ui.widget.inventory.{Item, ItemPrototype, ItemRecoverer} import ocelot.desktop.ui.widget.inventory.item.traits.{CardItemPrototype, EnvironmentItemPrototype, PersistableItemPrototype, SlotTieredItemPrototype} import totoro.ocelot.brain.entity.DataCard import totoro.ocelot.brain.util.Tier -import scala.reflect.ClassTag +import scala.reflect.{ClassTag, classTag} sealed abstract class DataCardItemPrototype[E <: DataCard](implicit override val elementTag: ClassTag[E]) extends ItemPrototype.WithInstance @@ -30,7 +30,7 @@ sealed abstract class DataCardItemPrototype[E <: DataCard](implicit override val object DataCardItemPrototype { private final val Animation = Some(Array((0, 4f), (1, 4f), (2, 4f), (3, 4f), (4, 4f), (5, 4f), (6, 4f), (7, 4f))) - class Tier1 extends DataCardItemPrototype[DataCard.Tier1] { + final class Tier1 extends DataCardItemPrototype[DataCard.Tier1] { override type Item = Instance override val slotTier: Int = Tier.One @@ -38,6 +38,20 @@ object DataCardItemPrototype { override def build: Item = new Instance(new DataCard.Tier1) } + object Tier1 { + class Recoverer extends ItemRecoverer { + override type Element = DataCard.Tier1 + + override val elementTag: ClassTag[DataCard.Tier1] = classTag[DataCard.Tier1] + + override def recover(element: DataCard.Tier1): Item[DataCard.Tier1] = { + val proto = new Tier1 + + new proto.Instance(element) + } + } + } + class Tier2 extends DataCardItemPrototype[DataCard.Tier2] { override type Item = Instance @@ -46,6 +60,20 @@ object DataCardItemPrototype { override def build: Item = new Instance(new DataCard.Tier2) } + object Tier2 { + class Recoverer extends ItemRecoverer { + override type Element = DataCard.Tier2 + + override val elementTag: ClassTag[DataCard.Tier2] = classTag[DataCard.Tier2] + + override def recover(element: DataCard.Tier2): Item[DataCard.Tier2] = { + val proto = new Tier2 + + new proto.Instance(element) + } + } + } + class Tier3 extends DataCardItemPrototype[DataCard.Tier3] { override type Item = Instance @@ -53,4 +81,18 @@ object DataCardItemPrototype { override def build: Item = new Instance(new DataCard.Tier3) } + + object Tier3 { + class Recoverer extends ItemRecoverer { + override type Element = DataCard.Tier3 + + override val elementTag: ClassTag[DataCard.Tier3] = classTag[DataCard.Tier3] + + override def recover(element: DataCard.Tier3): Item[DataCard.Tier3] = { + val proto = new Tier3 + + new proto.Instance(element) + } + } + } } diff --git a/src/main/scala/ocelot/desktop/ui/widget/inventory/item/EEPROMItemPrototype.scala b/src/main/scala/ocelot/desktop/ui/widget/inventory/item/EEPROMItemPrototype.scala index a0968b4..9c5015d 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/inventory/item/EEPROMItemPrototype.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/inventory/item/EEPROMItemPrototype.scala @@ -1,7 +1,7 @@ package ocelot.desktop.ui.widget.inventory.item import ocelot.desktop.graphics.IconDef -import ocelot.desktop.ui.widget.inventory.ItemPrototype +import ocelot.desktop.ui.widget.inventory.{Item, ItemPrototype, ItemRecoverer} import ocelot.desktop.ui.widget.inventory.item.EEPROMItemPrototype.LootFactories import ocelot.desktop.ui.widget.inventory.item.traits.{EnvironmentItemPrototype, PersistableItemPrototype} import totoro.ocelot.brain.entity.EEPROM @@ -11,7 +11,7 @@ import totoro.ocelot.brain.workspace.Workspace import scala.reflect.{ClassTag, classTag} -class EEPROMItemPrototype(private var lootFactoryKey: Option[String]) +final class EEPROMItemPrototype(private var lootFactoryKey: Option[String]) extends ItemPrototype.WithInstance with EnvironmentItemPrototype with PersistableItemPrototype { @@ -23,6 +23,10 @@ class EEPROMItemPrototype(private var lootFactoryKey: Option[String]) this(None) } + def this(lootFactoryKey: String) { + this(Some(lootFactoryKey)) + } + override type Element = EEPROM override type Item = Instance @@ -67,4 +71,17 @@ object EEPROMItemPrototype { ) private final val LootTag = "loot" + + class Recoverer extends ItemRecoverer { + override type Element = EEPROM + + override val elementTag: ClassTag[EEPROM] = classTag[EEPROM] + + override def recover(element: EEPROM): Item[EEPROM] = { + // TODO: try to recover loot factory info? (use hash codes) + val proto = new EEPROMItemPrototype + + new proto.Instance(element) + } + } } diff --git a/src/main/scala/ocelot/desktop/ui/widget/inventory/item/FloppyItemPrototype.scala b/src/main/scala/ocelot/desktop/ui/widget/inventory/item/FloppyItemPrototype.scala index 1d4e095..b0f9355 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/inventory/item/FloppyItemPrototype.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/inventory/item/FloppyItemPrototype.scala @@ -3,7 +3,7 @@ package ocelot.desktop.ui.widget.inventory.item import ocelot.desktop.graphics.IconDef import ocelot.desktop.ui.widget.inventory.item.FloppyItemPrototype.Managed.LootFactories import ocelot.desktop.ui.widget.inventory.item.traits.{EnvironmentItemPrototype, PersistableItemPrototype} -import ocelot.desktop.ui.widget.inventory.{Item, ItemPrototype} +import ocelot.desktop.ui.widget.inventory.{Item, ItemPrototype, ItemRecoverer} import totoro.ocelot.brain.entity.traits.Floppy import totoro.ocelot.brain.entity.{FloppyManaged, FloppyUnmanaged} import totoro.ocelot.brain.loot.Loot @@ -11,7 +11,7 @@ import totoro.ocelot.brain.nbt.NBTTagCompound import totoro.ocelot.brain.util.DyeColor import totoro.ocelot.brain.workspace.Workspace -import scala.reflect.ClassTag +import scala.reflect.{ClassTag, classTag} sealed abstract class FloppyItemPrototype[E <: Floppy](var color: DyeColor) (implicit override val elementTag: ClassTag[E]) @@ -42,7 +42,7 @@ sealed abstract class FloppyItemPrototype[E <: Floppy](var color: DyeColor) } object FloppyItemPrototype { - class Managed(initialColor: DyeColor, + final class Managed(initialColor: DyeColor, private var lootFactoryKey: Option[String]) extends FloppyItemPrototype[FloppyManaged](initialColor) { def this() { this(DyeColor.GRAY, None) @@ -94,9 +94,21 @@ object FloppyItemPrototype { ) private final val LootTag = "loot" + + class Recoverer extends ItemRecoverer { + override type Element = FloppyManaged + + override val elementTag: ClassTag[FloppyManaged] = classTag[FloppyManaged] + + override def recover(element: FloppyManaged): Item[FloppyManaged] = { + val proto = new Managed(element.color, None) + + new proto.Instance(element) + } + } } - class Unmanaged(initialColor: DyeColor) extends FloppyItemPrototype[FloppyUnmanaged](initialColor) { + final class Unmanaged(initialColor: DyeColor) extends FloppyItemPrototype[FloppyUnmanaged](initialColor) { def this() { this(DyeColor.GRAY) } @@ -108,5 +120,19 @@ object FloppyItemPrototype { override def build: Item = new Instance(new FloppyUnmanaged(name, color)) } + object Unmanaged { + class Recoverer extends ItemRecoverer { + override type Element = FloppyUnmanaged + + override val elementTag: ClassTag[FloppyUnmanaged] = classTag[FloppyUnmanaged] + + override def recover(element: FloppyUnmanaged): Item[FloppyUnmanaged] = { + val proto = new Unmanaged(element.color) + + new proto.Instance(element) + } + } + } + private final val ColorTag = "color" } diff --git a/src/main/scala/ocelot/desktop/ui/widget/inventory/item/GraphicsCardItemPrototype.scala b/src/main/scala/ocelot/desktop/ui/widget/inventory/item/GraphicsCardItemPrototype.scala index 7ccb07b..6ed634a 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/inventory/item/GraphicsCardItemPrototype.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/inventory/item/GraphicsCardItemPrototype.scala @@ -2,13 +2,13 @@ package ocelot.desktop.ui.widget.inventory.item import ocelot.desktop.graphics.IconDef import ocelot.desktop.ui.widget.inventory.item.traits.{CardItemPrototype, EnvironmentItemPrototype, PersistableItemPrototype} -import ocelot.desktop.ui.widget.inventory.{Item, ItemPrototype} +import ocelot.desktop.ui.widget.inventory.{Item, ItemPrototype, ItemRecoverer} import totoro.ocelot.brain.entity.GraphicsCard import totoro.ocelot.brain.entity.traits.Tiered import scala.reflect.{ClassTag, classTag} -class GraphicsCardItemPrototype(override var tier: Int) +final class GraphicsCardItemPrototype(override var tier: Int) extends ItemPrototype.WithInstance with CardItemPrototype with EnvironmentItemPrototype @@ -35,3 +35,17 @@ class GraphicsCardItemPrototype(override var tier: Int) with super[EnvironmentItemPrototype].ExtendedInstance with super[PersistableItemPrototype].ExtendedInstance } + +object GraphicsCardItemPrototype { + class Recoverer extends ItemRecoverer { + override type Element = GraphicsCard + + override val elementTag: ClassTag[GraphicsCard] = classTag[GraphicsCard] + + override def recover(element: GraphicsCard): Item[GraphicsCard] = { + val proto = new GraphicsCardItemPrototype(element.tier) + + new proto.Instance(element) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ocelot/desktop/ui/widget/inventory/item/HDDItemPrototype.scala b/src/main/scala/ocelot/desktop/ui/widget/inventory/item/HDDItemPrototype.scala index 90458f2..118b22f 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/inventory/item/HDDItemPrototype.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/inventory/item/HDDItemPrototype.scala @@ -1,12 +1,12 @@ package ocelot.desktop.ui.widget.inventory.item import ocelot.desktop.graphics.IconDef -import ocelot.desktop.ui.widget.inventory.{Item, ItemPrototype} +import ocelot.desktop.ui.widget.inventory.{Item, ItemPrototype, ItemRecoverer} import ocelot.desktop.ui.widget.inventory.item.traits.{EnvironmentItemPrototype, PersistableItemPrototype, SlotTieredItemPrototype} import totoro.ocelot.brain.entity.{HDDManaged, HDDUnmanaged} import totoro.ocelot.brain.entity.traits.{Disk, Tiered} -import scala.reflect.ClassTag +import scala.reflect.{ClassTag, classTag} sealed abstract class HDDItemPrototype[E <: Disk](implicit override val elementTag: ClassTag[E]) extends ItemPrototype.WithInstance @@ -28,7 +28,7 @@ sealed abstract class HDDItemPrototype[E <: Disk](implicit override val elementT } object HDDItemPrototype { - class Managed(override var tier: Int) extends HDDItemPrototype[HDDManaged] { + final class Managed(override var tier: Int) extends HDDItemPrototype[HDDManaged] { override type Item = Instance override def name: String = s"HDD ($tierString)" @@ -36,7 +36,21 @@ object HDDItemPrototype { override def build: Item = new Instance(new HDDManaged(tier)) } - class Unmanaged(override var tier: Int) extends HDDItemPrototype[HDDUnmanaged] { + object Managed { + class Recoverer extends ItemRecoverer { + override type Element = HDDManaged + + override val elementTag: ClassTag[HDDManaged] = classTag[HDDManaged] + + override def recover(element: HDDManaged): Item[HDDManaged] = { + val proto = new Managed(element.tier) + + new proto.Instance(element) + } + } + } + + final class Unmanaged(override var tier: Int) extends HDDItemPrototype[HDDUnmanaged] { override type Item = Instance override def name: String = s"HDD ($tierString, unmanaged)" @@ -44,4 +58,18 @@ object HDDItemPrototype { // TODO: figure out what should be fed to name override def build: Item = new Instance(new HDDUnmanaged(tier, name = null)) } + + object Unmanaged { + class Recoverer extends ItemRecoverer { + override type Element = HDDUnmanaged + + override val elementTag: ClassTag[HDDUnmanaged] = classTag[HDDUnmanaged] + + override def recover(element: HDDUnmanaged): Item[HDDUnmanaged] = { + val proto = new Unmanaged(element.tier) + + new proto.Instance(element) + } + } + } } \ No newline at end of file diff --git a/src/main/scala/ocelot/desktop/ui/widget/inventory/item/InternetCardItemPrototype.scala b/src/main/scala/ocelot/desktop/ui/widget/inventory/item/InternetCardItemPrototype.scala index 9c795da..ddb5908 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/inventory/item/InternetCardItemPrototype.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/inventory/item/InternetCardItemPrototype.scala @@ -1,14 +1,14 @@ package ocelot.desktop.ui.widget.inventory.item import ocelot.desktop.graphics.IconDef -import ocelot.desktop.ui.widget.inventory.{Item, ItemPrototype} +import ocelot.desktop.ui.widget.inventory.{Item, ItemPrototype, ItemRecoverer} import ocelot.desktop.ui.widget.inventory.item.traits.{CardItemPrototype, EnvironmentItemPrototype, PersistableItemPrototype} import totoro.ocelot.brain.entity.InternetCard import totoro.ocelot.brain.util.Tier import scala.reflect.{ClassTag, classTag} -class InternetCardItemPrototype +final class InternetCardItemPrototype extends ItemPrototype with CardItemPrototype with EnvironmentItemPrototype @@ -36,4 +36,16 @@ class InternetCardItemPrototype object InternetCardItemPrototype { private final val Animation = Some(Array((0, 2f), (1, 7f), (0, 5f), (1, 4f), (0, 7f), (1, 2f), (0, 8f), (1, 9f), (0, 6f), (1, 4f))) + + class Recoverer extends ItemRecoverer { + override type Element = InternetCard + + override val elementTag: ClassTag[InternetCard] = classTag[InternetCard] + + override def recover(element: InternetCard): Item[InternetCard] = { + val proto = new InternetCardItemPrototype + + new proto.Instance(element) + } + } } diff --git a/src/main/scala/ocelot/desktop/ui/widget/inventory/item/LinkedCardItemPrototype.scala b/src/main/scala/ocelot/desktop/ui/widget/inventory/item/LinkedCardItemPrototype.scala index d87c7b0..9d85151 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/inventory/item/LinkedCardItemPrototype.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/inventory/item/LinkedCardItemPrototype.scala @@ -1,14 +1,14 @@ package ocelot.desktop.ui.widget.inventory.item import ocelot.desktop.graphics.IconDef -import ocelot.desktop.ui.widget.inventory.{Item, ItemPrototype} +import ocelot.desktop.ui.widget.inventory.{Item, ItemPrototype, ItemRecoverer} import ocelot.desktop.ui.widget.inventory.item.traits.{CardItemPrototype, EnvironmentItemPrototype, PersistableItemPrototype} import totoro.ocelot.brain.entity.LinkedCard import totoro.ocelot.brain.util.Tier import scala.reflect.{ClassTag, classTag} -class LinkedCardItemPrototype +final class LinkedCardItemPrototype extends ItemPrototype with CardItemPrototype with EnvironmentItemPrototype @@ -35,4 +35,16 @@ class LinkedCardItemPrototype object LinkedCardItemPrototype { private final val Animation = Some(Array((0, 3f), (1, 3f), (2, 3f), (3, 3f), (4, 3f), (5, 3f))) + + class Recoverer extends ItemRecoverer { + override type Element = LinkedCard + + override val elementTag: ClassTag[LinkedCard] = classTag[LinkedCard] + + override def recover(element: LinkedCard): Item[LinkedCard] = { + val proto = new LinkedCardItemPrototype + + new proto.Instance(element) + } + } } diff --git a/src/main/scala/ocelot/desktop/ui/widget/inventory/item/MemoryItemPrototype.scala b/src/main/scala/ocelot/desktop/ui/widget/inventory/item/MemoryItemPrototype.scala index 36a94fb..b8b9d74 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/inventory/item/MemoryItemPrototype.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/inventory/item/MemoryItemPrototype.scala @@ -1,21 +1,22 @@ package ocelot.desktop.ui.widget.inventory.item import ocelot.desktop.graphics.IconDef -import ocelot.desktop.ui.widget.inventory.{Item, ItemPrototype} +import ocelot.desktop.ui.widget.inventory.{Item, ItemPrototype, ItemRecoverer} import ocelot.desktop.ui.widget.inventory.item.traits.{EnvironmentItemPrototype, PersistableItemPrototype, SlotTieredItemPrototype} import totoro.ocelot.brain.entity.Memory import totoro.ocelot.brain.entity.traits.Tiered +import totoro.ocelot.brain.util.Tier import scala.reflect.{ClassTag, classTag} -class MemoryItemPrototype(var tier: Int) +final class MemoryItemPrototype(var tier: Int) extends ItemPrototype with SlotTieredItemPrototype with EnvironmentItemPrototype with PersistableItemPrototype with Tiered { - require((1 to 6).contains(tier), s"Unsupported memory tier: $tier") + require((Tier.One to Tier.Six).contains(tier), s"Unsupported memory tier: $tier") override type Element = Memory override type Item = Instance @@ -44,4 +45,16 @@ object MemoryItemPrototype { "Tier 2", "Tier 2.5", "Tier 3", "Tier 3.5", ) + + class Recoverer extends ItemRecoverer { + override type Element = Memory + + override val elementTag: ClassTag[Memory] = classTag[Memory] + + override def recover(element: Memory): Item[Memory] = { + val proto = new MemoryItemPrototype(element.tier) + + new proto.Instance(element) + } + } } diff --git a/src/main/scala/ocelot/desktop/ui/widget/inventory/item/NetworkCardItemPrototype.scala b/src/main/scala/ocelot/desktop/ui/widget/inventory/item/NetworkCardItemPrototype.scala index 9dda4b1..49dbf23 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/inventory/item/NetworkCardItemPrototype.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/inventory/item/NetworkCardItemPrototype.scala @@ -1,14 +1,14 @@ package ocelot.desktop.ui.widget.inventory.item import ocelot.desktop.graphics.IconDef -import ocelot.desktop.ui.widget.inventory.{Item, ItemPrototype} +import ocelot.desktop.ui.widget.inventory.{Item, ItemPrototype, ItemRecoverer} import ocelot.desktop.ui.widget.inventory.item.traits.{CardItemPrototype, EnvironmentItemPrototype, PersistableItemPrototype} import totoro.ocelot.brain.entity.NetworkCard import totoro.ocelot.brain.util.Tier import scala.reflect.{ClassTag, classTag} -class NetworkCardItemPrototype +final class NetworkCardItemPrototype extends ItemPrototype with CardItemPrototype with EnvironmentItemPrototype @@ -32,3 +32,17 @@ class NetworkCardItemPrototype with super[EnvironmentItemPrototype].ExtendedInstance with super[PersistableItemPrototype].ExtendedInstance } + +object NetworkCardItemPrototype { + class Recoverer extends ItemRecoverer { + override type Element = NetworkCard + + override val elementTag: ClassTag[NetworkCard] = classTag[NetworkCard] + + override def recover(element: NetworkCard): Item[NetworkCard] = { + val proto = new NetworkCardItemPrototype + + new proto.Instance(element) + } + } +} \ No newline at end of file diff --git a/src/main/scala/ocelot/desktop/ui/widget/inventory/item/RedstoneCardItemPrototype.scala b/src/main/scala/ocelot/desktop/ui/widget/inventory/item/RedstoneCardItemPrototype.scala index 33fd37c..e21f252 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/inventory/item/RedstoneCardItemPrototype.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/inventory/item/RedstoneCardItemPrototype.scala @@ -1,13 +1,13 @@ package ocelot.desktop.ui.widget.inventory.item import ocelot.desktop.graphics.IconDef -import ocelot.desktop.ui.widget.inventory.{Item, ItemPrototype} +import ocelot.desktop.ui.widget.inventory.{Item, ItemPrototype, ItemRecoverer} import ocelot.desktop.ui.widget.inventory.item.traits.{CardItemPrototype, EnvironmentItemPrototype, PersistableItemPrototype} import totoro.ocelot.brain.entity.Redstone import totoro.ocelot.brain.entity.traits.Environment import totoro.ocelot.brain.util.{Persistable, Tier} -import scala.reflect.ClassTag +import scala.reflect.{ClassTag, classTag} sealed abstract class RedstoneCardItemPrototype[E <: Environment with Persistable](implicit override val elementTag: ClassTag[E]) extends ItemPrototype @@ -30,7 +30,7 @@ sealed abstract class RedstoneCardItemPrototype[E <: Environment with Persistabl } object RedstoneCardItemPrototype { - class Tier1 extends RedstoneCardItemPrototype[Redstone.Tier1] { + final class Tier1 extends RedstoneCardItemPrototype[Redstone.Tier1] { override type Item = Instance override val slotTier: Int = Tier.One @@ -38,11 +38,39 @@ object RedstoneCardItemPrototype { override def build: Item = new Instance(new Redstone.Tier1) } - class Tier2 extends RedstoneCardItemPrototype[Redstone.Tier2] { + object Tier1 { + class Recoverer extends ItemRecoverer { + override type Element = Redstone.Tier1 + + override val elementTag: ClassTag[Redstone.Tier1] = classTag[Redstone.Tier1] + + override def recover(element: Redstone.Tier1): Item[Redstone.Tier1] = { + val proto = new Tier1 + + new proto.Instance(element) + } + } + } + + final class Tier2 extends RedstoneCardItemPrototype[Redstone.Tier2] { override type Item = Instance override val slotTier: Int = Tier.Two override def build: Item = new Instance(new Redstone.Tier2) } + + object Tier2 { + class Recoverer extends ItemRecoverer { + override type Element = Redstone.Tier2 + + override val elementTag: ClassTag[Redstone.Tier2] = classTag[Redstone.Tier2] + + override def recover(element: Redstone.Tier2): Item[Redstone.Tier2] = { + val proto = new Tier2 + + new proto.Instance(element) + } + } + } } diff --git a/src/main/scala/ocelot/desktop/ui/widget/inventory/item/WirelessNetworkCardItemPrototype.scala b/src/main/scala/ocelot/desktop/ui/widget/inventory/item/WirelessNetworkCardItemPrototype.scala index 417e399..84df31e 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/inventory/item/WirelessNetworkCardItemPrototype.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/inventory/item/WirelessNetworkCardItemPrototype.scala @@ -1,12 +1,12 @@ package ocelot.desktop.ui.widget.inventory.item import ocelot.desktop.graphics.IconDef -import ocelot.desktop.ui.widget.inventory.ItemPrototype +import ocelot.desktop.ui.widget.inventory.{Item, ItemPrototype, ItemRecoverer} import ocelot.desktop.ui.widget.inventory.item.traits.{CardItemPrototype, EnvironmentItemPrototype, PersistableItemPrototype} import totoro.ocelot.brain.entity.WirelessNetworkCard import totoro.ocelot.brain.util.Tier -import scala.reflect.ClassTag +import scala.reflect.{ClassTag, classTag} sealed abstract class WirelessNetworkCardItemPrototype[E <: WirelessNetworkCard](implicit override val elementTag: ClassTag[E]) extends ItemPrototype @@ -27,7 +27,7 @@ sealed abstract class WirelessNetworkCardItemPrototype[E <: WirelessNetworkCard] } object WirelessNetworkCardItemPrototype { - class Tier1 extends WirelessNetworkCardItemPrototype[WirelessNetworkCard.Tier1] { + final class Tier1 extends WirelessNetworkCardItemPrototype[WirelessNetworkCard.Tier1] { override type Item = Instance override val slotTier: Int = Tier.One @@ -35,11 +35,39 @@ object WirelessNetworkCardItemPrototype { override def build: Item = new Instance(new WirelessNetworkCard.Tier1) } - class Tier2 extends WirelessNetworkCardItemPrototype[WirelessNetworkCard.Tier2] { + object Tier1 { + class Recoverer extends ItemRecoverer { + override type Element = WirelessNetworkCard.Tier1 + + override val elementTag: ClassTag[WirelessNetworkCard.Tier1] = classTag[WirelessNetworkCard.Tier1] + + override def recover(element: WirelessNetworkCard.Tier1): Item[WirelessNetworkCard.Tier1] = { + val proto = new Tier1 + + new proto.Instance(element) + } + } + } + + final class Tier2 extends WirelessNetworkCardItemPrototype[WirelessNetworkCard.Tier2] { override type Item = Instance override val slotTier: Int = Tier.Two override def build: Item = new Instance(new WirelessNetworkCard.Tier2) } + + object Tier2 { + class Recoverer extends ItemRecoverer { + override type Element = WirelessNetworkCard.Tier2 + + override val elementTag: ClassTag[WirelessNetworkCard.Tier2] = classTag[WirelessNetworkCard.Tier2] + + override def recover(element: WirelessNetworkCard.Tier2): Item[WirelessNetworkCard.Tier2] = { + val proto = new Tier2 + + new proto.Instance(element) + } + } + } } diff --git a/src/main/scala/ocelot/desktop/ui/widget/inventory/item/traits/SlotTieredItemPrototype.scala b/src/main/scala/ocelot/desktop/ui/widget/inventory/item/traits/SlotTieredItemPrototype.scala index 744fa29..61ab7ff 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/inventory/item/traits/SlotTieredItemPrototype.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/inventory/item/traits/SlotTieredItemPrototype.scala @@ -10,5 +10,5 @@ trait SlotTieredItemPrototype { protected def tierString: String = if (slotTier == Tier.Four) "Creative" - else s"Tier $slotTier" + else s"Tier ${slotTier + 1}" } diff --git a/src/main/scala/ocelot/desktop/ui/widget/inventory/slot/AnySlot.scala b/src/main/scala/ocelot/desktop/ui/widget/inventory/slot/AnySlot.scala index b9aae28..2762d94 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/inventory/slot/AnySlot.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/inventory/slot/AnySlot.scala @@ -1,8 +1,11 @@ package ocelot.desktop.ui.widget.inventory.slot import ocelot.desktop.ui.widget.WorkspaceView -import ocelot.desktop.ui.widget.inventory.{ItemPrototype, SlotWidget} +import ocelot.desktop.ui.widget.inventory.{ItemPrototype, LmbItemSelectionSlot, SlotWidget} + +class AnySlot(workspaceView: WorkspaceView) + extends SlotWidget[AnyRef](workspaceView) + with LmbItemSelectionSlot[AnyRef] { -class AnySlot(workspaceView: WorkspaceView) extends SlotWidget[AnyRef](workspaceView) { override def accepts(prototype: ItemPrototype): Boolean = true } diff --git a/src/main/scala/ocelot/desktop/ui/widget/inventory/slot/DiskSlot.scala b/src/main/scala/ocelot/desktop/ui/widget/inventory/slot/DiskSlot.scala index dab4f4f..8c6765c 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/inventory/slot/DiskSlot.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/inventory/slot/DiskSlot.scala @@ -7,6 +7,7 @@ import ocelot.desktop.ui.widget.inventory.{DecoratedSlotWidget, InventorySlotWid import totoro.ocelot.brain.entity.HDDManaged import totoro.ocelot.brain.entity.traits.Inventory +// TODO: accept unmanaged HDDs! class DiskSlot(owner: Inventory#Slot, val tier: Int, workspaceView: WorkspaceView) extends InventorySlotWidget[HDDManaged](owner, workspaceView) with DecoratedSlotWidget[HDDManaged]