Adapt code to Inventory trait reimplementation

Fixes #27, #31.
This commit is contained in:
Fingercomp 2022-05-20 22:40:07 +07:00
parent ebedd098f5
commit cb012234f4
No known key found for this signature in database
GPG Key ID: BBC71CEE45D86E37
10 changed files with 147 additions and 68 deletions

@ -1 +1 @@
Subproject commit aea345a223281e4bd8155e3b82fbbbb5b9bd1c2c
Subproject commit f326a45a0ae223904869ae02ad22ca7afdeb8b1f

View File

@ -11,12 +11,14 @@ import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry, Cont
import ocelot.desktop.ui.widget.slot._
import ocelot.desktop.util.{ResourceManager, TierColor}
import org.lwjgl.input.Keyboard
import totoro.ocelot.brain.entity.traits.{Computer, Entity, GenericCPU}
import totoro.ocelot.brain.entity.{CPU, Case, EEPROM, FloppyManaged, GraphicsCard, HDDManaged, Memory}
import totoro.ocelot.brain.entity.traits.{Computer, Entity, Floppy, GenericCPU, Inventory}
import totoro.ocelot.brain.entity.{CPU, Case, EEPROM, GraphicsCard, HDDManaged, HDDUnmanaged, Memory}
import totoro.ocelot.brain.loot.Loot
import totoro.ocelot.brain.nbt.NBTTagCompound
import totoro.ocelot.brain.util.Tier
import scala.reflect.ClassTag
class ComputerNode(val computer: Case, setup: Boolean = true) extends Node {
var lastFilesystemAccess = 0L
@ -32,12 +34,12 @@ class ComputerNode(val computer: Case, setup: Boolean = true) extends Node {
setupSlots()
if (setup) {
computer.add(new CPU(computer.tier.min(2)))
computer.add(new Memory(computer.tier.min(2) * 2 + 1))
computer.add(new Memory(computer.tier.min(2) * 2 + 1))
computer.add(new GraphicsCard(computer.tier.min(1)))
computer.add(Loot.OpenOsFloppy.create())
computer.add(Loot.OpenOsEEPROM.create())
cpuSlot.owner.put(new CPU(computer.tier.min(2)))
memorySlots(0).owner.put(new Memory(computer.tier.min(2) * 2 + 1))
memorySlots(1).owner.put(new Memory(computer.tier.min(2) * 2 + 1))
cardSlots(0).owner.put(new GraphicsCard(computer.tier.min(1)))
floppySlot.map(_.owner).foreach(_.put(Loot.OpenOsFloppy.create()))
eepromSlot.owner.put(Loot.OpenOsEEPROM.create())
// refitSlots()
OcelotDesktop.workspace.add(computer)
}
@ -118,61 +120,135 @@ class ComputerNode(val computer: Case, setup: Boolean = true) extends Node {
if (currentWindow != null) currentWindow.updateSlots()
}
private def slotAccepts(slot: Inventory#Slot, entity: Entity): Boolean = entity match {
case cpu: GenericCPU => cpuSlot.owner.index == slot.index && cpuSlot.tier >= cpu.cpuTier
case mem: Memory => memorySlots
.exists(memSlot => memSlot.owner.index == slot.index && memSlot.tier >= (mem.tier + 1) / 2 - 1)
case hdd: HDDManaged => diskSlots
.exists(diskSlot => diskSlot.owner.index == slot.index && diskSlot.tier >= hdd.tier)
case hdd: HDDUnmanaged => diskSlots
.exists(diskSlot => diskSlot.owner.index == slot.index && diskSlot.tier >= hdd.tier)
case _: EEPROM => eepromSlot.owner.index == slot.index
case _: Floppy => floppySlot.exists(_.owner.index == slot.index)
case card: Entity => cardSlots
.exists(cardSlot => cardSlot.owner.index == slot.index && cardSlot.tier >= CardRegistry.getTier(card))
}
private def isSlotValid(slot: Inventory#Slot): Boolean = slot.get.exists(slotAccepts(slot, _))
private def reloadSlots(): Unit = {
cpuSlot.reloadItem()
memorySlots.foreach(_.reloadItem())
cardSlots.foreach(_.reloadItem())
diskSlots.foreach(_.reloadItem())
eepromSlot.reloadItem()
floppySlot.foreach(_.reloadItem())
}
private def refitSlots(): Unit = {
if (computer.inventory.forall(isSlotValid)) {
reloadSlots()
return
}
val entities = computer.inventory.entities.toArray
computer.inventory.clear()
cpuSlot._item = None
for (slot <- memorySlots) slot._item = None
for (slot <- cardSlots) slot._item = None
for (slot <- diskSlots) slot._item = None
eepromSlot._item = None
floppySlot.foreach(_._item = None)
for (item <- computer.inventory) {
try {
item match {
case cpu: GenericCPU =>
if (cpuSlot.tier >= cpu.cpuTier)
cpuSlot._item = Some(cpu)
else
computer.remove(item)
case mem: Memory => memorySlots
.find(slot => slot._item.isEmpty && slot.tier >= (mem.tier + 1) / 2 - 1)
.get._item = Some(mem)
case hdd: HDDManaged => diskSlots
.find(slot => slot._item.isEmpty && slot.tier >= hdd.tier)
.get._item = Some(hdd)
case eeprom: EEPROM => eepromSlot._item = Some(eeprom)
case floppy: FloppyManaged => floppySlot.get._item = Some(floppy)
case card: Entity => cardSlots
.find(slot => slot._item.isEmpty && slot.tier >= CardRegistry.getTier(card))
.get._item = Some(card)
case _ =>
}
} catch {
case _: NoSuchElementException => computer.remove(item)
}
def findBestSlot[T <: InventorySlot[_]](entity: Entity, candidates: Array[T], tierProvider: T => Option[Int]): Option[T] = {
candidates.iterator
.filter(_.owner.isEmpty)
.filter(slot => slotAccepts(slot.owner, entity))
.minByOption(tierProvider(_).getOrElse(Int.MinValue))
}
for (entity <- entities) {
val newSlot = entity match {
case _: GenericCPU => findBestSlot[CPUSlot](entity, Array(cpuSlot), slot => Some(slot.tier))
case _: Memory => findBestSlot[MemorySlot](entity, memorySlots, slot => Some(slot.tier))
case _: HDDManaged => findBestSlot[DiskSlot](entity, diskSlots, slot => Some(slot.tier))
case _: HDDUnmanaged => findBestSlot[DiskSlot](entity, diskSlots, slot => Some(slot.tier))
case _: EEPROM => findBestSlot[EEPROMSlot](entity, Array(eepromSlot), _ => None)
case _: Floppy => findBestSlot[FloppySlot](entity, floppySlot.toArray, _ => None)
case _: Entity => findBestSlot[CardSlot](entity, cardSlots, slot => Some(slot.tier))
}
newSlot.foreach(_.owner.put(entity))
}
reloadSlots()
}
private def setupSlots(): Unit = {
eepromSlot = new EEPROMSlot(this)
cpuSlot = new CPUSlot(this, computer.tier.min(Tier.Three))
var slotIndex = 0
floppySlot = if (computer.tier >= Tier.Three) Some(new FloppySlot(computer)) else None
memorySlots = Array(
new MemorySlot(this, computer.tier.min(Tier.Three)),
new MemorySlot(this, computer.tier.min(Tier.Three)))
diskSlots = computer.tier match {
case Tier.One => Array(new DiskSlot(this, Tier.One))
case Tier.Two => Array(new DiskSlot(this, Tier.Two), new DiskSlot(this, Tier.One))
case Tier.Three => Array(new DiskSlot(this, Tier.Three), new DiskSlot(this, Tier.Two))
case _ => Array(new DiskSlot(this, Tier.Three), new DiskSlot(this, Tier.Three))
def nextSlot(): computer.Slot = {
val result = computer.inventory(slotIndex)
slotIndex += 1
result
}
cardSlots = computer.tier match {
case Tier.One => Array(new CardSlot(this, Tier.One), new CardSlot(this, Tier.One))
case Tier.Two => Array(new CardSlot(this, Tier.Two), new CardSlot(this, Tier.One))
case Tier.Three => Array(new CardSlot(this, Tier.Three), new CardSlot(this, Tier.Two), new CardSlot(this, Tier.Two))
case _ => Array(new CardSlot(this, Tier.Three), new CardSlot(this, Tier.Three), new CardSlot(this, Tier.Three))
def addSlot[T <: InventorySlot[_]](factory: computer.Slot => T): T = {
val slot = nextSlot()
val widget = factory(slot)
widget
}
def addSlots[T <: InventorySlot[_] : ClassTag](factories: (computer.Slot => T)*): Array[T] = {
val array = Array.newBuilder[T]
for (factory <- factories) {
array += addSlot(factory)
}
array.result()
}
computer.tier match {
case Tier.One =>
cardSlots = addSlots(new CardSlot(_, Tier.One), new CardSlot(_, Tier.One))
memorySlots = addSlots(new MemorySlot(_, Tier.One))
diskSlots = addSlots(new DiskSlot(_, Tier.One))
floppySlot = None
cpuSlot = addSlot(new CPUSlot(_, this, Tier.One))
// no idea why on earth the memory slots are split in two here
memorySlots :+= addSlot(new MemorySlot(_, Tier.One))
eepromSlot = addSlot(new EEPROMSlot(_))
case Tier.Two =>
cardSlots = addSlots(new CardSlot(_, Tier.Two), new CardSlot(_, Tier.One))
memorySlots = addSlots(new MemorySlot(_, Tier.Two), new MemorySlot(_, Tier.Two))
diskSlots = addSlots(new DiskSlot(_, Tier.Two), new DiskSlot(_, Tier.One))
floppySlot = None
cpuSlot = addSlot(new CPUSlot(_, this, Tier.Two))
eepromSlot = addSlot(new EEPROMSlot(_))
case _ =>
cardSlots = if (computer.tier == Tier.Three) {
addSlots(new CardSlot(_, Tier.Three), new CardSlot(_, Tier.Two), new CardSlot(_, Tier.Two))
} else {
addSlots(new CardSlot(_, Tier.Three), new CardSlot(_, Tier.Three), new CardSlot(_, Tier.Three))
}
memorySlots = addSlots(new MemorySlot(_, Tier.Three), new MemorySlot(_, Tier.Three))
diskSlots = if (computer.tier == Tier.Three) {
addSlots(new DiskSlot(_, Tier.Three), new DiskSlot(_, Tier.Two))
} else {
addSlots(new DiskSlot(_, Tier.Three), new DiskSlot(_, Tier.Three))
}
floppySlot = Some(addSlot(new FloppySlot(_)))
cpuSlot = addSlot(new CPUSlot(_, this, Tier.Three))
eepromSlot = addSlot(new EEPROMSlot(_))
}
}

View File

@ -16,7 +16,7 @@ class DiskDriveNode(val diskDrive: FloppyDiskDrive) extends Node {
OcelotDesktop.workspace.add(diskDrive)
val slot: FloppySlot = new FloppySlot(diskDrive)
val slot: FloppySlot = new FloppySlot(diskDrive.inventory(0))
slot.item = floppy.getOrElse(Loot.OpenOsFloppy.create())
def this(nbt: NBTTagCompound) {
@ -70,7 +70,7 @@ class DiskDriveNode(val diskDrive: FloppyDiskDrive) extends Node {
override val window: Option[DiskDriveWindow] = Some(new DiskDriveWindow(this))
private def floppy: Option[Floppy] = {
diskDrive.inventory.headOption match {
diskDrive.inventory(0).get match {
case Some(floppy: Floppy) => Some(floppy)
case _ => None
}

View File

@ -4,11 +4,11 @@ import ocelot.desktop.graphics.IconDef
import ocelot.desktop.node.nodes.ComputerNode
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry, ContextMenuSubmenu}
import totoro.ocelot.brain.entity.machine.MachineAPI
import totoro.ocelot.brain.entity.traits.{Entity, GenericCPU}
import totoro.ocelot.brain.entity.traits.{Entity, GenericCPU, Inventory}
import totoro.ocelot.brain.entity.{APU, CPU}
import totoro.ocelot.brain.util.Tier
class CPUSlot(node: ComputerNode, val tier: Int) extends InventorySlot[GenericCPU with Entity](node.computer) {
class CPUSlot(owner: Inventory#Slot, node: ComputerNode, val tier: Int) extends InventorySlot[GenericCPU with Entity](owner) {
private val APUAnimation = Some(Array(
(0, 3f), (1, 3f), (2, 3f), (3, 3f), (4, 3f), (5, 3f),
(4, 3f), (3, 3f), (2, 3f), (1, 3f), (0, 3f)))

View File

@ -6,10 +6,10 @@ import ocelot.desktop.ui.UiHandler
import ocelot.desktop.ui.widget.card.{Redstone1Window, Redstone2Window}
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry, ContextMenuSubmenu}
import totoro.ocelot.brain.entity.Redstone
import totoro.ocelot.brain.entity.traits.Entity
import totoro.ocelot.brain.entity.traits.{Entity, Inventory}
import totoro.ocelot.brain.util.Tier
class CardSlot(node: ComputerNode, val tier: Int) extends InventorySlot[Entity](node.computer) {
class CardSlot(owner: Inventory#Slot, val tier: Int) extends InventorySlot[Entity](owner) {
override def itemIcon: Option[IconDef] = item.flatMap(it => CardRegistry.getIcon(it))
override def icon: IconDef = new IconDef("icons/Card")

View File

@ -4,9 +4,10 @@ import ocelot.desktop.graphics.IconDef
import ocelot.desktop.node.nodes.ComputerNode
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
import totoro.ocelot.brain.entity.HDDManaged
import totoro.ocelot.brain.entity.traits.Inventory
import totoro.ocelot.brain.util.Tier
class DiskSlot(node: ComputerNode, val tier: Int) extends InventorySlot[HDDManaged](node.computer) {
class DiskSlot(owner: Inventory#Slot, val tier: Int) extends InventorySlot[HDDManaged](owner) {
override def itemIcon: Option[IconDef] = item.map(disk => new IconDef("items/HardDiskDrive" + disk.tier))
override def icon: IconDef = new IconDef("icons/HDD")

View File

@ -4,9 +4,10 @@ import ocelot.desktop.graphics.IconDef
import ocelot.desktop.node.nodes.ComputerNode
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
import totoro.ocelot.brain.entity.EEPROM
import totoro.ocelot.brain.entity.traits.Inventory
import totoro.ocelot.brain.loot.Loot
class EEPROMSlot(node: ComputerNode) extends InventorySlot[EEPROM](node.computer) {
class EEPROMSlot(owner: Inventory#Slot) extends InventorySlot[EEPROM](owner) {
override def itemIcon: Option[IconDef] = item.map(_ => new IconDef("items/EEPROM"))
override def icon: IconDef = new IconDef("icons/EEPROM")

View File

@ -8,7 +8,7 @@ import totoro.ocelot.brain.entity.traits.{Floppy, Inventory}
import totoro.ocelot.brain.loot.Loot
import totoro.ocelot.brain.util.DyeColor
class FloppySlot(inventory: Inventory) extends InventorySlot[Floppy](inventory) {
class FloppySlot(owner: Inventory#Slot) extends InventorySlot[Floppy](owner) {
private val soundFloppyInsert = new SoundSource(Audio.FloppyInsert)
private val soundFloppyEject = new SoundSource(Audio.FloppyEject)

View File

@ -4,14 +4,12 @@ import ocelot.desktop.ui.UiHandler
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
import totoro.ocelot.brain.entity.traits.{Entity, Environment, Inventory}
abstract class InventorySlot[T <: Entity](inventory: Inventory) extends SlotWidget[T] {
override def onAdded(item: T): Unit = {
inventory.add(item)
}
abstract class InventorySlot[T <: Entity](val owner: Inventory#Slot) extends SlotWidget[T] {
reloadItem()
override def onRemoved(item: T): Unit = {
inventory.remove(item)
}
override def onAdded(item: T): Unit = owner.put(item)
override def onRemoved(item: T): Unit = owner.remove()
override def fillRmbMenu(menu: ContextMenu): Unit = {
item match {
@ -23,4 +21,6 @@ abstract class InventorySlot[T <: Entity](inventory: Inventory) extends SlotWidg
}
super.fillRmbMenu(menu)
}
def reloadItem(): Unit = _item = owner.get.map(_.asInstanceOf[T])
}

View File

@ -4,9 +4,10 @@ import ocelot.desktop.graphics.IconDef
import ocelot.desktop.node.nodes.ComputerNode
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
import totoro.ocelot.brain.entity.Memory
import totoro.ocelot.brain.entity.traits.Inventory
import totoro.ocelot.brain.util.Tier
class MemorySlot(node: ComputerNode, val tier: Int) extends InventorySlot[Memory](node.computer) {
class MemorySlot(owner: Inventory#Slot, val tier: Int) extends InventorySlot[Memory](owner) {
override def itemIcon: Option[IconDef] = item.map(mem => new IconDef("items/Memory" + mem.tier))
override def icon: IconDef = new IconDef("icons/Memory")