From 82dead6b9b37aac1bce33bc71c39aceb329d85fc Mon Sep 17 00:00:00 2001 From: Fingercomp Date: Sat, 10 Jun 2023 23:17:25 +0700 Subject: [PATCH] Reimplement insertItems (aka refitSlots) --- .../ocelot/desktop/inventory/Inventory.scala | 6 + .../desktop/node/nodes/ComputerNode.scala | 123 ++++++++++++------ .../ui/widget/slot/reimpl/SlotWidget.scala | 17 ++- 3 files changed, 104 insertions(+), 42 deletions(-) diff --git a/src/main/scala/ocelot/desktop/inventory/Inventory.scala b/src/main/scala/ocelot/desktop/inventory/Inventory.scala index 1d5e019..5c0256c 100644 --- a/src/main/scala/ocelot/desktop/inventory/Inventory.scala +++ b/src/main/scala/ocelot/desktop/inventory/Inventory.scala @@ -44,6 +44,12 @@ trait Inventory { def inventoryIterator: Iterator[Slot] = slotItems.keysIterator.map(Slot(_)) + def clearInventory(): Unit = { + for (slot <- slotItems.keys.toArray) { + Slot(slot).remove() + } + } + private def slotObservers(slotIndex: Int): Iterator[SlotObserver] = observers.get(slotIndex).iterator.flatMap(_.view.keys) diff --git a/src/main/scala/ocelot/desktop/node/nodes/ComputerNode.scala b/src/main/scala/ocelot/desktop/node/nodes/ComputerNode.scala index 3b678de..a194fbd 100644 --- a/src/main/scala/ocelot/desktop/node/nodes/ComputerNode.scala +++ b/src/main/scala/ocelot/desktop/node/nodes/ComputerNode.scala @@ -41,28 +41,33 @@ class ComputerNode(val computer: Case) extends Node(computer) with Logging with var eepromSlot: EepromSlotWidget = _ var cpuSlot: CpuSlotWidget = _ - var memorySlots: Array[MemorySlotWidget] = _ - var cardSlots: Array[CardSlotWidget] = _ - var diskSlots: Array[HddSlotWidget] = _ + var memorySlots: Array[MemorySlotWidget] = Array.empty + var cardSlots: Array[CardSlotWidget] = Array.empty + var diskSlots: Array[HddSlotWidget] = Array.empty var floppySlot: Option[FloppySlotWidget] = None override def brainInventory: Inventory = computer.inventory.owner private def slots: IterableOnce[SlotWidget[I]] = ( - Iterator(eepromSlot, cpuSlot) ++ + // slots may be null during initialization + Option(eepromSlot).iterator ++ + Option(cpuSlot).iterator ++ memorySlots.iterator ++ cardSlots.iterator ++ diskSlots.iterator ++ floppySlot.iterator ).map(_.asInstanceOf[SlotWidget[I]]) - private val soundComputerRunning = SoundSource.fromBuffer(SoundBuffers.MachineComputerRunning, SoundCategory.Environment, looping = true) + private val soundComputerRunning = SoundSource.fromBuffer( + SoundBuffers.MachineComputerRunning, + SoundCategory.Environment, + looping = true, + ) // TODO: Scala has lazy vals. Use them. private var soundCardStream: SoundStream = _ private var soundCardSource: SoundSource = _ setupSlots() - refitSlots() override def load(nbt: NBTTagCompound): Unit = { super[Node].load(nbt) @@ -112,8 +117,10 @@ class ComputerNode(val computer: Case) extends Node(computer) with Logging with BeepGenerator.newBeep(event.pattern, 1000, 200).play() case BrainEvent(event: FileSystemActivityEvent) if !Audio.isDisabled => - val soundFloppyAccess = SoundBuffers.MachineFloppyAccess.map(buffer => SoundSource.fromBuffer(buffer, SoundCategory.Environment)) - val soundHDDAccess = SoundBuffers.MachineHDDAccess.map(buffer => SoundSource.fromBuffer(buffer, SoundCategory.Environment)) + val soundFloppyAccess = SoundBuffers.MachineFloppyAccess + .map(buffer => SoundSource.fromBuffer(buffer, SoundCategory.Environment)) + val soundHDDAccess = SoundBuffers.MachineHDDAccess + .map(buffer => SoundSource.fromBuffer(buffer, SoundCategory.Environment)) val sound = if (event.activityType == Floppy) soundFloppyAccess else soundHDDAccess sound(Random.between(0, sound.length)).play() @@ -128,10 +135,12 @@ class ComputerNode(val computer: Case) extends Node(computer) with Logging with soundCardSource.volume = event.volume case BrainEvent(_: SelfDestructingCardBoomEvent) => - computer.workspace.runLater(() => { - SoundSources.MinecraftExplosion.play() - destroy() - }) + computer.workspace.runLater( + () => { + SoundSources.MinecraftExplosion.play() + destroy() + }, + ) } override def shouldReceiveEventsFor(address: String): Boolean = super.shouldReceiveEventsFor(address) || @@ -149,8 +158,6 @@ class ComputerNode(val computer: Case) extends Node(computer) with Logging with eepromSlot.item = new EepromItemFactory.Loot(Loot.LuaBiosEEPROM).build() - refitSlots() - this } @@ -174,21 +181,36 @@ class ComputerNode(val computer: Case) extends Node(computer) with Logging with override def setupContextMenu(menu: ContextMenu): Unit = { if (isRunning) { - menu.addEntry(new ContextMenuEntry("Turn off", () => turnOff())) - menu.addEntry(new ContextMenuEntry("Reboot", () => { - computer.turnOff() - computer.turnOn() - })) - } else - menu.addEntry(new ContextMenuEntry("Turn on", () => turnOn())) + menu.addEntry( + ContextMenuEntry("Turn off") { + turnOff() + }, + ) + menu.addEntry( + ContextMenuEntry("Reboot") { + computer.turnOff() + computer.turnOn() + }, + ) + } else { + menu.addEntry( + ContextMenuEntry("Turn on") { + turnOn() + }, + ) + } - menu.addEntry(new ContextMenuSubmenu("Set tier") { - // TODO: use multiple parameter lists - addEntry(new ContextMenuEntry("Tier 1", () => changeTier(Tier.One))) - addEntry(new ContextMenuEntry("Tier 2", () => changeTier(Tier.Two))) - addEntry(new ContextMenuEntry("Tier 3", () => changeTier(Tier.Three))) - addEntry(new ContextMenuEntry("Creative", () => changeTier(Tier.Creative))) - }) + menu.addEntry( + new ContextMenuSubmenu("Set tier") { + for (tier <- Tier.One to Tier.Creative) { + addEntry( + ContextMenuEntry(tier.label) { + changeTier(tier) + }, + ) + } + }, + ) menu.addSeparator() super.setupContextMenu(menu) @@ -197,28 +219,43 @@ class ComputerNode(val computer: Case) extends Node(computer) with Logging with override def onClick(event: ClickEvent): Unit = { event match { case ClickEvent(MouseEvent.Button.Left, _) => - if (KeyEvents.isDown(Keyboard.KEY_LSHIFT)) - if (isRunning) + if (KeyEvents.isDown(Keyboard.KEY_LSHIFT)) { + if (isRunning) { turnOff() - else + } else { turnOn() - else + } + } else { super.onClick(event) + } + case event => super.onClick(event) } } private def changeTier(tier: Tier): Unit = { computer.tier = tier + + val items = slots.iterator.flatMap(_.item).toArray + clearInventory() setupSlots() - refitSlots() - if (currentWindow != null) currentWindow.reloadWindow() + insertItems(items) + + if (currentWindow != null) { + currentWindow.reloadWindow() + } } - private def refitSlots(): Unit = { - // TODO: reimplement the sophisticated algorithm - for (slot <- slots; item <- slot.item if !slot.isItemAccepted(item.factory)) { - slot.item = None + private def insertItems(items: IterableOnce[I]): Unit = { + def findBestSlot[A <: I](item: A, candidates: IterableOnce[SlotWidget[A]]): Option[SlotWidget[A]] = { + candidates.iterator + .filter(_.item.isEmpty) + .filter(_.isItemAccepted(item.factory)) + .minByOption(_.slotTier) + } + + for (item <- items; newSlot <- findBestSlot(item, slots)) { + newSlot.item = item } } @@ -248,6 +285,10 @@ class ComputerNode(val computer: Case) extends Node(computer) with Logging with array.result() } + for (slot <- slots) { + slot.dispose() + } + computer.tier match { case Tier.One => cardSlots = addSlots(new CardSlotWidget(_, Tier.One), new CardSlotWidget(_, Tier.One)) @@ -271,7 +312,11 @@ class ComputerNode(val computer: Case) extends Node(computer) with Logging with cardSlots = if (computer.tier == Tier.Three) { addSlots(new CardSlotWidget(_, Tier.Three), new CardSlotWidget(_, Tier.Two), new CardSlotWidget(_, Tier.Two)) } else { - addSlots(new CardSlotWidget(_, Tier.Three), new CardSlotWidget(_, Tier.Three), new CardSlotWidget(_, Tier.Three)) + addSlots( + new CardSlotWidget(_, Tier.Three), + new CardSlotWidget(_, Tier.Three), + new CardSlotWidget(_, Tier.Three), + ) } memorySlots = addSlots(new MemorySlotWidget(_, Tier.Three), new MemorySlotWidget(_, Tier.Three)) diff --git a/src/main/scala/ocelot/desktop/ui/widget/slot/reimpl/SlotWidget.scala b/src/main/scala/ocelot/desktop/ui/widget/slot/reimpl/SlotWidget.scala index a8e732f..28e5ceb 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/slot/reimpl/SlotWidget.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/slot/reimpl/SlotWidget.scala @@ -42,6 +42,11 @@ class SlotWidget[I <: Item](private val slot: Inventory#Slot)(implicit slotItemT slot.addObserver(observer) + def dispose(): Unit = { + closeTooltip() + slot.removeObserver(observer) + } + def ghostIcon: Option[IconDef] = None def slotTier: Option[Tier] = None @@ -68,7 +73,7 @@ class SlotWidget[I <: Item](private val slot: Inventory#Slot)(implicit slotItemT protected def onItemAdded(): Unit = {} protected def onItemRemoved(removedItem: I, replacedBy: Option[I]): Unit = { - _tooltip.foreach(root.get.tooltipPool.closeTooltip) + closeTooltip() } protected def onItemSpecificEvent(payload: AnyRef): Unit = {} @@ -96,7 +101,7 @@ class SlotWidget[I <: Item](private val slot: Inventory#Slot)(implicit slotItemT def onHoverEnter(): Unit = { for (item <- item) { // just in case - _tooltip.foreach(root.get.tooltipPool.closeTooltip) + // closeTooltip() val tooltip = item.tooltip _tooltip = Some(tooltip) @@ -105,7 +110,13 @@ class SlotWidget[I <: Item](private val slot: Inventory#Slot)(implicit slotItemT } def onHoverLeave(): Unit = { - _tooltip.foreach(root.get.tooltipPool.closeTooltip) + closeTooltip() + } + + private def closeTooltip(): Unit = { + for (tooltip <- _tooltip) { + root.get.tooltipPool.closeTooltip(tooltip) + } } eventHandlers += {