Reimplement insertItems (aka refitSlots)

This commit is contained in:
Fingercomp 2023-06-10 23:17:25 +07:00
parent 5d645973d5
commit 82dead6b9b
No known key found for this signature in database
GPG Key ID: BBC71CEE45D86E37
3 changed files with 104 additions and 42 deletions

View File

@ -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)

View File

@ -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))

View File

@ -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 += {