mirror of
https://gitlab.com/cc-ru/ocelot/ocelot-desktop.git
synced 2025-12-20 02:59:19 +01:00
Merge branch 'refactor/entity-id' into develop
This commit is contained in:
commit
6f9558bed1
@ -1 +1 @@
|
||||
Subproject commit e1968df8a58fab83572e657d981b7263c7edd72a
|
||||
Subproject commit 648e47c42ca2ab4eb676ccc3dcddf129eac771af
|
||||
@ -2,7 +2,7 @@ package ocelot.desktop.inventory
|
||||
|
||||
import ocelot.desktop.OcelotDesktop
|
||||
import ocelot.desktop.inventory.PersistedInventory._
|
||||
import ocelot.desktop.inventory.traits.{ComponentItem, PersistableItem}
|
||||
import ocelot.desktop.inventory.traits.{EntityItem, PersistableItem}
|
||||
import ocelot.desktop.util.ReflectionUtils.findUnaryConstructor
|
||||
import ocelot.desktop.util.{Logging, Persistable}
|
||||
import totoro.ocelot.brain.nbt.ExtendedNBT.{extendNBTTagCompound, extendNBTTagList}
|
||||
@ -13,9 +13,9 @@ import scala.collection.mutable
|
||||
|
||||
/** Provides persistence for an [[Inventory]].
|
||||
*
|
||||
* [[ComponentItem]]s are treated specially: their [[ComponentItem.component component]] is persisted
|
||||
* along with the item when saving. When loading the item, it first loads the component and uses it to instantiate
|
||||
* the item (as required by [[ComponentItem]]).
|
||||
* [[EntityItem]]s are treated specially: their [[EntityItem.entity entities]] are persisted
|
||||
* along with the item when saving. When loading the item, it first loads the entity and uses it to instantiate
|
||||
* the item (as required by [[EntityItem]]).
|
||||
*/
|
||||
trait PersistedInventory extends Inventory with Logging with Persistable {
|
||||
override type I <: Item with PersistableItem
|
||||
@ -33,8 +33,8 @@ trait PersistedInventory extends Inventory with Logging with Persistable {
|
||||
val itemClass = Class.forName(slotNbt.getString(SlotItemClassTag))
|
||||
|
||||
try {
|
||||
val item = if (classOf[ComponentItem].isAssignableFrom(itemClass))
|
||||
loadComponentItem(itemClass, slotNbt)
|
||||
val item = if (classOf[EntityItem].isAssignableFrom(itemClass))
|
||||
loadEntityItem(itemClass, slotNbt)
|
||||
else
|
||||
loadPlainItem(itemClass)
|
||||
|
||||
@ -43,7 +43,7 @@ trait PersistedInventory extends Inventory with Logging with Persistable {
|
||||
} catch {
|
||||
case ItemLoadException(message) =>
|
||||
logger.error(
|
||||
s"Could not restore an item in the slot $slotIndex of " +
|
||||
s"Could not load an item in the slot $slotIndex of " +
|
||||
s"the inventory $this (class ${this.getClass.getName}): $message"
|
||||
)
|
||||
onSlotLoadFailed(slotIndex)
|
||||
@ -72,7 +72,7 @@ trait PersistedInventory extends Inventory with Logging with Persistable {
|
||||
slotNbt.setString(SlotItemClassTag, item.getClass.getName)
|
||||
|
||||
item match {
|
||||
case item: ComponentItem => saveComponentItem(slotNbt, item)
|
||||
case item: EntityItem => saveEntityItem(slotNbt, item)
|
||||
case _ =>
|
||||
}
|
||||
|
||||
@ -82,7 +82,7 @@ trait PersistedInventory extends Inventory with Logging with Persistable {
|
||||
}
|
||||
|
||||
@throws[ItemLoadException]("if the item could not be loaded")
|
||||
protected def loadComponentItem(itemClass: Class[_], slotNbt: NBTTagCompound): I = {
|
||||
protected def loadEntityItem(itemClass: Class[_], slotNbt: NBTTagCompound): I = {
|
||||
val entityNbt = slotNbt.getCompoundTag(SlotEntityTag)
|
||||
val entity = NBTPersistence.load(entityNbt, OcelotDesktop.workspace)
|
||||
|
||||
@ -107,8 +107,8 @@ trait PersistedInventory extends Inventory with Logging with Persistable {
|
||||
Slot(slotIndex).remove()
|
||||
}
|
||||
|
||||
protected def saveComponentItem(slotNbt: NBTTagCompound, item: ComponentItem): Unit = {
|
||||
slotNbt.setTag(SlotEntityTag, NBTPersistence.save(item.component))
|
||||
protected def saveEntityItem(slotNbt: NBTTagCompound, item: EntityItem): Unit = {
|
||||
slotNbt.setTag(SlotEntityTag, NBTPersistence.save(item.entity))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5,22 +5,22 @@ import ocelot.desktop.inventory.PersistedInventory.ItemLoadException
|
||||
import ocelot.desktop.inventory.SyncedInventory.SlotStatus.SlotStatus
|
||||
import ocelot.desktop.inventory.SyncedInventory.SyncDirection.SyncDirection
|
||||
import ocelot.desktop.inventory.SyncedInventory._
|
||||
import ocelot.desktop.inventory.traits.ComponentItem
|
||||
import ocelot.desktop.inventory.traits.EntityItem
|
||||
import ocelot.desktop.ui.event.{BrainEvent, EventAware}
|
||||
import ocelot.desktop.util.Logging
|
||||
import ocelot.desktop.util.ReflectionUtils.findUnaryConstructor
|
||||
import totoro.ocelot.brain.entity.traits.{Entity, Environment, Inventory => BrainInventory}
|
||||
import totoro.ocelot.brain.event.{InventoryEntityAddedEvent, InventoryEntityRemovedEvent}
|
||||
import totoro.ocelot.brain.nbt.NBTTagCompound
|
||||
import totoro.ocelot.brain.network.Network
|
||||
|
||||
import java.util.UUID
|
||||
import scala.annotation.tailrec
|
||||
|
||||
/** A [[PersistedInventory]] backed by a [[BrainInventory brain Inventory]].
|
||||
*
|
||||
* Synchronizes the contents of the two inventories, propagating changes from one to the other.
|
||||
*
|
||||
* When a new [[Item]] is added to the Desktop inventory, its [[ComponentItem.component]] is added to
|
||||
* When a new [[Item]] is added to the Desktop inventory, its [[EntityItem.entity]] is added to
|
||||
* the [[brainInventory]]. When a new [[Entity]] is added to the [[brainInventory]], an [[Item]] is recovered from it
|
||||
* by using an appropriate [[ItemRecoverer]] from [[Items the registry]].
|
||||
*
|
||||
@ -28,7 +28,7 @@ import scala.annotation.tailrec
|
||||
* by limiting the recursion depth.
|
||||
*/
|
||||
trait SyncedInventory extends PersistedInventory with EventAware with Logging {
|
||||
override type I <: Item with ComponentItem
|
||||
override type I <: EntityItem
|
||||
|
||||
// to avoid synchronization while we're loading stuff
|
||||
private var isLoading = false
|
||||
@ -54,20 +54,41 @@ trait SyncedInventory extends PersistedInventory with EventAware with Logging {
|
||||
}
|
||||
|
||||
@throws[ItemLoadException]("if the item could not be loaded")
|
||||
override protected def loadComponentItem(itemClass: Class[_], slotNbt: NBTTagCompound): I = {
|
||||
val entityAddress = slotNbt.getString(SlotEntityAddressTag)
|
||||
|
||||
// why not OcelotDesktop.workspace.entityByAddress?
|
||||
// well, that one only looks for tile entities (computers, screens, etc.), and our items are none of that...
|
||||
val matchingEntities = brainInventory.inventory.iterator
|
||||
.flatMap(_.get)
|
||||
.collect { case env: Environment if env.node.address == entityAddress => env }
|
||||
|
||||
val entity = matchingEntities.nextOption() match {
|
||||
case Some(entity) => entity
|
||||
case None => throw ItemLoadException(s"entity $entityAddress has disappeared")
|
||||
override protected def loadEntityItem(itemClass: Class[_], slotNbt: NBTTagCompound): I = {
|
||||
trait Matcher {
|
||||
def matches(entity: Entity): Boolean
|
||||
}
|
||||
|
||||
val matcher = if (slotNbt.hasKey(SlotEntityIdTag)) {
|
||||
new Matcher {
|
||||
private val entityId = UUID.fromString(slotNbt.getString(SlotEntityIdTag))
|
||||
|
||||
override def toString: String = s"entity with id `$entityId`"
|
||||
|
||||
override def matches(entity: Entity): Boolean = entity.entityId == entityId
|
||||
}
|
||||
} else {
|
||||
// migration code for older saves, which relied on entity addresses.
|
||||
new Matcher {
|
||||
private val entityAddress = slotNbt.getString(SlotEntityAddressTag)
|
||||
|
||||
override def toString: String = s"entity with address `$entityAddress"
|
||||
|
||||
override def matches(entity: Entity): Boolean = entity match {
|
||||
// why not OcelotDesktop.workspace.entityByAddress?
|
||||
// well, that one only looks for tile entities (computers, screens, etc.),
|
||||
// and our items are none of that...
|
||||
case env: Environment => env.node.address == entityAddress
|
||||
case _ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val entity = brainInventory.inventory.iterator
|
||||
.flatMap(_.get)
|
||||
.find(matcher.matches)
|
||||
.getOrElse(throw ItemLoadException(s"$matcher has disappeared"))
|
||||
|
||||
findUnaryConstructor(itemClass, entity.getClass) match {
|
||||
case Some(constructor) => constructor.newInstance(entity).asInstanceOf[I]
|
||||
|
||||
@ -83,8 +104,8 @@ trait SyncedInventory extends PersistedInventory with EventAware with Logging {
|
||||
// we'll deal with it the during synchronization
|
||||
}
|
||||
|
||||
override protected def saveComponentItem(slotNbt: NBTTagCompound, item: ComponentItem): Unit = {
|
||||
slotNbt.setString(SlotEntityAddressTag, item.component.node.address)
|
||||
override protected def saveEntityItem(slotNbt: NBTTagCompound, item: EntityItem): Unit = {
|
||||
slotNbt.setString(SlotEntityIdTag, item.entity.entityId.toString)
|
||||
}
|
||||
|
||||
eventHandlers += {
|
||||
@ -97,17 +118,6 @@ trait SyncedInventory extends PersistedInventory with EventAware with Logging {
|
||||
|
||||
override def onItemAdded(slot: Slot): Unit = {
|
||||
if (!isLoading) {
|
||||
// FIXME: the sheer scope of this atrocity is mind-blowing:
|
||||
// we strip nodes of their free will and forcefully imprint onto them an address —
|
||||
// and only because there is no other way to identify brain entities!
|
||||
// in an ideal world, persistable objects should have a stable identifier
|
||||
// which is in no way tied to environments and their addresses.
|
||||
// alas, for the time being we have to bear the burden of grave sins and war crimes.
|
||||
val component = slot.get.get.asInstanceOf[ComponentItem].component
|
||||
if (component.node.address == null) {
|
||||
Network.joinNewNetwork(component.node)
|
||||
}
|
||||
|
||||
sync(slot.index, SyncDirection.DesktopToBrain)
|
||||
}
|
||||
}
|
||||
@ -177,7 +187,7 @@ trait SyncedInventory extends PersistedInventory with EventAware with Logging {
|
||||
case SyncDirection.DesktopToBrain =>
|
||||
// the `asInstanceOf` is indeed entirely superfluous, but IntelliJ IDEA complains otherwise...
|
||||
OcelotDesktop.withTickLockAcquired {
|
||||
brainInventory.inventory(slotIndex).set(Slot(slotIndex).get.map(_.asInstanceOf[ComponentItem].component))
|
||||
brainInventory.inventory(slotIndex).set(Slot(slotIndex).get.map(_.asInstanceOf[EntityItem].entity))
|
||||
}
|
||||
|
||||
case SyncDirection.BrainToDesktop =>
|
||||
@ -248,7 +258,7 @@ trait SyncedInventory extends PersistedInventory with EventAware with Logging {
|
||||
|
||||
private def checkSlotStatus(slotIndex: Int): SlotStatus = {
|
||||
(Slot(slotIndex).get, brainInventory.inventory(slotIndex).get) match {
|
||||
case (Some(item), Some(entity)) if item.component eq entity => SlotStatus.Synchronized
|
||||
case (Some(item), Some(entity)) if item.entity eq entity => SlotStatus.Synchronized
|
||||
case (Some(_), Some(_)) => SlotStatus.Conflict
|
||||
case (Some(_), None) => SlotStatus.DesktopNonEmpty
|
||||
case (None, Some(_)) => SlotStatus.BrainNonEmpty
|
||||
@ -259,6 +269,7 @@ trait SyncedInventory extends PersistedInventory with EventAware with Logging {
|
||||
|
||||
object SyncedInventory {
|
||||
private val SlotEntityAddressTag = "entity"
|
||||
private val SlotEntityIdTag = "entity_id"
|
||||
|
||||
private val InitialSyncFuel = 5
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ import totoro.ocelot.brain.entity.traits.{Entity, GenericCPU, GenericGPU}
|
||||
import totoro.ocelot.brain.util.Tier.Tier
|
||||
|
||||
class ApuItem(val apu: APU) extends Item with ComponentItem with PersistableItem with CpuLikeItem with GpuLikeItem {
|
||||
override def component: Entity with GenericCPU with GenericGPU = apu
|
||||
override def entity: Entity with GenericCPU with GenericGPU = apu
|
||||
|
||||
override def factory: ApuItem.Factory = new ApuItem.Factory(apu.tier)
|
||||
}
|
||||
|
||||
@ -1,16 +1,14 @@
|
||||
package ocelot.desktop.inventory.item
|
||||
|
||||
import ocelot.desktop.graphics.IconSource
|
||||
import ocelot.desktop.inventory.traits.ComponentItem
|
||||
import ocelot.desktop.inventory.traits.EntityItem
|
||||
import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer}
|
||||
import ocelot.desktop.ui.widget.tooltip.ItemTooltip
|
||||
import totoro.ocelot.brain.entity.ComponentBus
|
||||
import totoro.ocelot.brain.entity.traits.{Entity, Environment}
|
||||
import totoro.ocelot.brain.util.Tier.Tier
|
||||
|
||||
class ComponentBusItem(val componentBus: ComponentBus) extends Item with ComponentItem {
|
||||
override def component: Entity with Environment = componentBus
|
||||
override def showAddress: Boolean = false
|
||||
class ComponentBusItem(val componentBus: ComponentBus) extends Item with EntityItem {
|
||||
override def entity: ComponentBus = componentBus
|
||||
override def factory: ItemFactory = new ComponentBusItem.Factory(componentBus.tier)
|
||||
|
||||
override def fillTooltip(tooltip: ItemTooltip): Unit = {
|
||||
|
||||
@ -8,7 +8,7 @@ import totoro.ocelot.brain.entity.traits.{Entity, GenericCPU}
|
||||
import totoro.ocelot.brain.util.Tier.Tier
|
||||
|
||||
class CpuItem(val cpu: CPU) extends Item with ComponentItem with PersistableItem with CpuLikeItem {
|
||||
override def component: Entity with GenericCPU = cpu
|
||||
override def entity: Entity with GenericCPU = cpu
|
||||
|
||||
override def factory: CpuItem.Factory = new CpuItem.Factory(cpu.tier)
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@ object DataCardItem {
|
||||
}
|
||||
|
||||
class Tier1(val dataCard: DataCard.Tier1) extends DataCardItem {
|
||||
override def component: Entity with Environment = dataCard
|
||||
override def entity: Entity with Environment = dataCard
|
||||
|
||||
override def factory: Factory = DataCardItem.Tier1.Factory
|
||||
}
|
||||
@ -48,7 +48,7 @@ object DataCardItem {
|
||||
}
|
||||
|
||||
class Tier2(val dataCard: DataCard.Tier2) extends DataCardItem {
|
||||
override def component: Entity with Environment = dataCard
|
||||
override def entity: Entity with Environment = dataCard
|
||||
|
||||
override def factory: Factory = DataCardItem.Tier2.Factory
|
||||
}
|
||||
@ -68,7 +68,7 @@ object DataCardItem {
|
||||
}
|
||||
|
||||
class Tier3(val dataCard: DataCard.Tier3) extends DataCardItem {
|
||||
override def component: Entity with Environment = dataCard
|
||||
override def entity: Entity with Environment = dataCard
|
||||
|
||||
override def factory: Factory = DataCardItem.Tier3.Factory
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ import totoro.ocelot.brain.util.Tier.Tier
|
||||
class DiskDriveMountableItem(val diskDriveMountable: DiskDriveMountable) extends RackMountableItem with DiskDriveAware {
|
||||
override def floppyDiskDrive: FloppyDiskDrive = diskDriveMountable
|
||||
|
||||
override def component: DiskDriveMountable = diskDriveMountable
|
||||
override def entity: DiskDriveMountable = diskDriveMountable
|
||||
override def factory: ItemFactory = DiskDriveMountableItem.Factory
|
||||
|
||||
override def fillTooltip(tooltip: ItemTooltip): Unit = {
|
||||
|
||||
@ -18,7 +18,7 @@ import javax.swing.JFileChooser
|
||||
import scala.util.Try
|
||||
|
||||
class EepromItem(val eeprom: EEPROM) extends Item with ComponentItem with PersistableItem {
|
||||
override def component: Entity with Environment = eeprom
|
||||
override def entity: Entity with Environment = eeprom
|
||||
|
||||
override def fillTooltip(tooltip: ItemTooltip): Unit = {
|
||||
super.fillTooltip(tooltip)
|
||||
|
||||
@ -12,7 +12,7 @@ import totoro.ocelot.brain.util.DyeColor
|
||||
import totoro.ocelot.brain.util.Tier.Tier
|
||||
|
||||
class FloppyItem(var floppy: Floppy) extends Item with ComponentItem with PersistableItem with DiskItem {
|
||||
override def component: Entity with Disk = floppy
|
||||
override def entity: Entity with Disk = floppy
|
||||
|
||||
override def diskKind: String = "Floppy"
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ import totoro.ocelot.brain.util.Tier.Tier
|
||||
|
||||
class GraphicsCardItem(val gpu: GraphicsCard)
|
||||
extends Item with ComponentItem with PersistableItem with CardItem with GpuLikeItem {
|
||||
override def component: Entity with GenericGPU = gpu
|
||||
override def entity: Entity with GenericGPU = gpu
|
||||
|
||||
override def factory: GraphicsCardItem.Factory = new GraphicsCardItem.Factory(gpu.tier)
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ class HddItem(var hdd: Hdd) extends Item with ComponentItem with PersistableItem
|
||||
this(Hdd.Unmanaged(hdd))
|
||||
}
|
||||
|
||||
override def component: Entity with Disk = hdd.hdd
|
||||
override def entity: Entity with Disk = hdd.hdd
|
||||
|
||||
override def diskKind: String = "HDD"
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ import totoro.ocelot.brain.util.Tier
|
||||
import totoro.ocelot.brain.util.Tier.Tier
|
||||
|
||||
class InternetCardItem(val card: InternetCard) extends Item with ComponentItem with PersistableItem with CardItem {
|
||||
override def component: Entity with Environment = card
|
||||
override def entity: Entity with Environment = card
|
||||
|
||||
override def factory: ItemFactory = InternetCardItem.Factory
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ import totoro.ocelot.brain.util.Tier
|
||||
import totoro.ocelot.brain.util.Tier.Tier
|
||||
|
||||
class LinkedCardItem(val linkedCard: LinkedCard) extends Item with ComponentItem with PersistableItem with CardItem {
|
||||
override def component: Entity with Environment = linkedCard
|
||||
override def entity: Entity with Environment = linkedCard
|
||||
|
||||
override def fillTooltip(tooltip: ItemTooltip): Unit = {
|
||||
super.fillTooltip(tooltip)
|
||||
|
||||
@ -10,7 +10,7 @@ import totoro.ocelot.brain.util.ExtendedTier.ExtendedTier
|
||||
import totoro.ocelot.brain.util.Tier.Tier
|
||||
|
||||
class MemoryItem(val memory: Memory) extends Item with ComponentItem with PersistableItem {
|
||||
override def component: Entity with Environment = memory
|
||||
override def entity: Entity with Environment = memory
|
||||
|
||||
override def factory: ItemFactory = new MemoryItem.Factory(memory.memoryTier)
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ import totoro.ocelot.brain.util.Tier
|
||||
import totoro.ocelot.brain.util.Tier.Tier
|
||||
|
||||
class NetworkCardItem(val card: NetworkCard) extends Item with ComponentItem with PersistableItem with CardItem {
|
||||
override def component: Entity with NetworkCard = card
|
||||
override def entity: Entity with NetworkCard = card
|
||||
|
||||
override def factory: ItemFactory = NetworkCardItem.Factory
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ import totoro.ocelot.brain.util.Tier.Tier
|
||||
class OcelotCardItem(val ocelotCard: OcelotCard)
|
||||
extends Item with ComponentItem with OcelotInterfaceLogStorage with PersistableItem with CardItem with Logging {
|
||||
|
||||
override def component: OcelotCard = ocelotCard
|
||||
override def entity: OcelotCard = ocelotCard
|
||||
|
||||
override def ocelotInterface: OcelotInterface = ocelotCard
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ object RedstoneCardItem {
|
||||
}
|
||||
|
||||
class Tier1(val redstoneCard: Redstone.Tier1) extends RedstoneCardItem {
|
||||
override def component: Entity with Environment = redstoneCard
|
||||
override def entity: Entity with Environment = redstoneCard
|
||||
|
||||
override def factory: Factory = RedstoneCardItem.Tier1.Factory
|
||||
|
||||
@ -80,7 +80,7 @@ object RedstoneCardItem {
|
||||
}
|
||||
|
||||
class Tier2(override val redstoneCard: Redstone.Tier2) extends RedstoneCardItem.Tier1(redstoneCard) {
|
||||
override def component: Entity with Environment = redstoneCard
|
||||
override def entity: Entity with Environment = redstoneCard
|
||||
|
||||
override def factory: Factory = RedstoneCardItem.Tier2.Factory
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ import totoro.ocelot.brain.util.Tier.Tier
|
||||
class SelfDestructingCardItem(val card: SelfDestructingCard)
|
||||
extends Item with ComponentItem with PersistableItem with CardItem {
|
||||
|
||||
override def component: Entity with Environment = card
|
||||
override def entity: Entity with Environment = card
|
||||
|
||||
override def factory: ItemFactory = SelfDestructingCardItem.Factory
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ import totoro.ocelot.brain.util.Tier
|
||||
import totoro.ocelot.brain.util.Tier.Tier
|
||||
|
||||
class ServerItem(val server: Server) extends RackMountableItem with AudibleComputerAware {
|
||||
override def component: Server = server
|
||||
override def entity: Server = server
|
||||
override def factory: ItemFactory = new ServerItem.Factory(server.tier)
|
||||
|
||||
override def onRemoved(): Unit = {
|
||||
|
||||
@ -16,7 +16,7 @@ class SoundCardItem(val soundCard: SoundCard)
|
||||
|
||||
override def createWindow(): SoundCardWindow = new SoundCardWindow(soundCard)
|
||||
|
||||
override def component: Entity with Environment = soundCard
|
||||
override def entity: Entity with Environment = soundCard
|
||||
|
||||
override def fillRmbMenu(menu: ContextMenu): Unit = {
|
||||
menu.addEntry(ContextMenuEntry("Open card interface", IconSource.Window) {
|
||||
|
||||
@ -2,7 +2,7 @@ package ocelot.desktop.inventory.item
|
||||
|
||||
import ocelot.desktop.OcelotDesktop
|
||||
import ocelot.desktop.graphics.IconSource
|
||||
import ocelot.desktop.inventory.traits.ComponentItem
|
||||
import ocelot.desktop.inventory.traits.EntityItem
|
||||
import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer}
|
||||
import ocelot.desktop.ui.widget.tooltip.ItemTooltip
|
||||
import ocelot.desktop.util.SizeFormatting.formatSize
|
||||
@ -10,12 +10,10 @@ import totoro.ocelot.brain.entity.tape.Tape
|
||||
import totoro.ocelot.brain.nbt.NBTTagCompound
|
||||
import totoro.ocelot.brain.util.Tier.Tier
|
||||
|
||||
class TapeItem(var tape: Tape) extends Item with ComponentItem {
|
||||
class TapeItem(var tape: Tape) extends Item with EntityItem {
|
||||
def this() = this(new Tape)
|
||||
|
||||
override def component: Tape = tape
|
||||
|
||||
override def showAddress: Boolean = false
|
||||
override def entity: Tape = tape
|
||||
|
||||
override def fillTooltip(tooltip: ItemTooltip): Unit = {
|
||||
super.fillTooltip(tooltip)
|
||||
|
||||
@ -1,70 +1,30 @@
|
||||
package ocelot.desktop.inventory.traits
|
||||
|
||||
import ocelot.desktop.OcelotDesktop
|
||||
import ocelot.desktop.graphics.IconSource
|
||||
import ocelot.desktop.inventory.Item
|
||||
import ocelot.desktop.ui.UiHandler
|
||||
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
|
||||
import ocelot.desktop.ui.widget.tooltip.ItemTooltip
|
||||
import totoro.ocelot.brain.entity.traits.{Entity, Environment, WorkspaceAware}
|
||||
import totoro.ocelot.brain.entity.traits.{Entity, Environment}
|
||||
|
||||
/** Implemented by [[Item]]s that wrap a component.
|
||||
*
|
||||
* @note Subclasses must provide a unary constructor that accepts the [[component]].
|
||||
*/
|
||||
trait ComponentItem extends Item with PersistableItem {
|
||||
|
||||
/** The component wrapped by this item.
|
||||
*
|
||||
* @note The value must already be available during the initialization.
|
||||
*/
|
||||
def component: Entity with Environment
|
||||
|
||||
private def setWorkspace(): Unit = component match {
|
||||
case component: WorkspaceAware => component.workspace = OcelotDesktop.workspace
|
||||
case _ =>
|
||||
}
|
||||
|
||||
override def reinserting(f: => Unit): Unit = super.reinserting {
|
||||
// removal may have set the workspace to null
|
||||
setWorkspace()
|
||||
|
||||
f
|
||||
|
||||
// since we have absolutely no idea what f does, workspace could've been set to null again
|
||||
setWorkspace()
|
||||
}
|
||||
|
||||
setWorkspace()
|
||||
|
||||
override def onInserted(): Unit = {
|
||||
super.onInserted()
|
||||
|
||||
// this one isn't strictly necessary, I believe, but I'll keep this for the sake of symmetry and safety
|
||||
setWorkspace()
|
||||
}
|
||||
|
||||
override def onRemoved(): Unit = {
|
||||
super.onRemoved()
|
||||
|
||||
// fix up ComponentInventory's zeroing out the workspace
|
||||
setWorkspace()
|
||||
}
|
||||
/** Implemented by [[Item]]s that wrap a component. */
|
||||
trait ComponentItem extends EntityItem {
|
||||
override def entity: Entity with Environment
|
||||
|
||||
override def shouldReceiveEventsFor(address: String): Boolean =
|
||||
super.shouldReceiveEventsFor(address) || Option(component.node).exists(_.address == address)
|
||||
super.shouldReceiveEventsFor(address) || Option(entity.node).exists(_.address == address)
|
||||
|
||||
override def fillTooltip(tooltip: ItemTooltip): Unit = {
|
||||
super.fillTooltip(tooltip)
|
||||
|
||||
if (showAddress) {
|
||||
tooltip.addLine(s"Address: ${component.node.address}")
|
||||
tooltip.addLine(s"Address: ${entity.node.address}")
|
||||
}
|
||||
}
|
||||
|
||||
override def fillRmbMenu(menu: ContextMenu): Unit = {
|
||||
menu.addEntry(ContextMenuEntry("Copy address", IconSource.Copy) {
|
||||
UiHandler.clipboard = component.node.address
|
||||
UiHandler.clipboard = entity.node.address
|
||||
})
|
||||
|
||||
super.fillRmbMenu(menu)
|
||||
|
||||
@ -10,19 +10,19 @@ import totoro.ocelot.brain.entity.traits.{Entity, GenericCPU}
|
||||
|
||||
/** An [[Item]] that acts as a CPU and can therefore be inserted into a CPU slot. */
|
||||
trait CpuLikeItem extends ComponentItem {
|
||||
override def component: Entity with GenericCPU
|
||||
override def entity: Entity with GenericCPU
|
||||
|
||||
override def fillRmbMenu(menu: ContextMenu): Unit = {
|
||||
menu.addEntry(new ContextMenuSubmenu("Set architecture", Some(ContextMenuIcon(IconSource.Microchip))) {
|
||||
for (arch <- component.allArchitectures) {
|
||||
for (arch <- entity.allArchitectures) {
|
||||
val name = MachineAPI.getArchitectureName(arch) +
|
||||
(if (arch == component.architecture) " (current)" else "")
|
||||
(if (arch == entity.architecture) " (current)" else "")
|
||||
val entry = ContextMenuEntry(name) {
|
||||
component.setArchitecture(arch)
|
||||
entity.setArchitecture(arch)
|
||||
notifySlot(CpuArchitectureChangedNotification)
|
||||
}
|
||||
|
||||
entry.setEnabled(arch != component.architecture)
|
||||
entry.setEnabled(arch != entity.architecture)
|
||||
addEntry(entry)
|
||||
}
|
||||
})
|
||||
@ -32,8 +32,8 @@ trait CpuLikeItem extends ComponentItem {
|
||||
|
||||
override def fillTooltip(tooltip: ItemTooltip): Unit = {
|
||||
super.fillTooltip(tooltip)
|
||||
if (component != null) {
|
||||
tooltip.addLine(s"Components: ${component.supportedComponents}")
|
||||
if (entity != null) {
|
||||
tooltip.addLine(s"Components: ${entity.supportedComponents}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,7 +15,7 @@ import scala.util.Try
|
||||
|
||||
/** A utility mixin for HDDs and floppies. */
|
||||
trait DiskItem extends ComponentItem with Windowed[DiskEditWindow] {
|
||||
override def component: Entity with Disk
|
||||
override def entity: Entity with Disk
|
||||
|
||||
def diskKind: String
|
||||
|
||||
@ -32,7 +32,7 @@ trait DiskItem extends ComponentItem with Windowed[DiskEditWindow] {
|
||||
def setManaged(managed: Boolean): Unit
|
||||
|
||||
def lock(): Unit = reinserting {
|
||||
component.setLocked(OcelotDesktop.player.nickname)
|
||||
entity.setLocked(OcelotDesktop.player.nickname)
|
||||
}
|
||||
|
||||
override def createWindow(): DiskEditWindow = new DiskEditWindow(DiskItem.this)
|
||||
@ -47,7 +47,7 @@ trait DiskItem extends ComponentItem with Windowed[DiskEditWindow] {
|
||||
override def fillRmbMenu(menu: ContextMenu): Unit = {
|
||||
if (isEditingAllowed) {
|
||||
// Real path
|
||||
component match {
|
||||
entity match {
|
||||
case diskManaged: DiskManaged =>
|
||||
DiskItem.addRealPathContextMenuEntries(menu, diskManaged,
|
||||
realPathSetter => {
|
||||
@ -86,8 +86,8 @@ trait DiskItem extends ComponentItem with Windowed[DiskEditWindow] {
|
||||
|
||||
override def fillTooltip(tooltip: ItemTooltip): Unit = {
|
||||
super.fillTooltip(tooltip)
|
||||
if (component != null) {
|
||||
tooltip.addLine(s"Capacity: ${component.capacity / 1024} kB")
|
||||
if (entity != null) {
|
||||
tooltip.addLine(s"Capacity: ${entity.capacity / 1024} kB")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
package ocelot.desktop.inventory.traits
|
||||
|
||||
import ocelot.desktop.OcelotDesktop
|
||||
import ocelot.desktop.inventory.Item
|
||||
import totoro.ocelot.brain.entity.traits.{Entity, WorkspaceAware}
|
||||
|
||||
/** Implemented by [[Item]]s that wrap an [[Entity]].
|
||||
*
|
||||
* @note Subclasses must provide a unary constructor that accepts the [[entity]].
|
||||
*/
|
||||
trait EntityItem extends Item with PersistableItem {
|
||||
/** The entity wrapped by this item.
|
||||
*
|
||||
* @note The value must already be available during the trait's initialization.
|
||||
*/
|
||||
def entity: Entity
|
||||
|
||||
private def setWorkspace(): Unit = entity match {
|
||||
case entity: WorkspaceAware => entity.workspace = OcelotDesktop.workspace
|
||||
case _ =>
|
||||
}
|
||||
|
||||
override def reinserting(f: => Unit): Unit = super.reinserting {
|
||||
// removal may have set the workspace to null
|
||||
setWorkspace()
|
||||
|
||||
f
|
||||
|
||||
// since we have absolutely no idea what f does, workspace could've been set to null again
|
||||
setWorkspace()
|
||||
}
|
||||
|
||||
setWorkspace()
|
||||
|
||||
override def onInserted(): Unit = {
|
||||
super.onInserted()
|
||||
|
||||
// this one isn't strictly necessary, I believe, but I'll keep this for the sake of symmetry and safety
|
||||
setWorkspace()
|
||||
}
|
||||
|
||||
override def onRemoved(): Unit = {
|
||||
super.onRemoved()
|
||||
|
||||
// fix up ComponentInventory's zeroing out the workspace
|
||||
setWorkspace()
|
||||
}
|
||||
}
|
||||
@ -6,20 +6,20 @@ import totoro.ocelot.brain.entity.traits.{Entity, GenericGPU}
|
||||
import totoro.ocelot.brain.util.ColorDepth
|
||||
|
||||
trait GpuLikeItem extends ComponentItem {
|
||||
override def component: Entity with GenericGPU
|
||||
override def entity: Entity with GenericGPU
|
||||
|
||||
override def fillTooltip(tooltip: ItemTooltip): Unit = {
|
||||
super.fillTooltip(tooltip)
|
||||
if (component != null) {
|
||||
val resolution = Settings.screenResolutionsByTier(component.tier.id)
|
||||
if (entity != null) {
|
||||
val resolution = Settings.screenResolutionsByTier(entity.tier.id)
|
||||
tooltip.addLine(s"Max resolution: ${resolution._1}×${resolution._2}")
|
||||
val depth = Settings.screenDepthsByTier(component.tier.id) match {
|
||||
val depth = Settings.screenDepthsByTier(entity.tier.id) match {
|
||||
case ColorDepth.OneBit => "1 bit"
|
||||
case ColorDepth.FourBit => "4 bit"
|
||||
case ColorDepth.EightBit => "8 bit"
|
||||
}
|
||||
tooltip.addLine(s"Max color depth: $depth")
|
||||
tooltip.addLine(s"VRAM: ${component.totalVRAM.toInt}")
|
||||
tooltip.addLine(s"VRAM: ${entity.totalVRAM.toInt}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ import totoro.ocelot.brain.entity.result
|
||||
import totoro.ocelot.brain.entity.traits.{Entity, RackMountable}
|
||||
|
||||
trait RackMountableItem extends Item with ComponentItem {
|
||||
override def component: Entity with RackMountable
|
||||
override def entity: Entity with RackMountable
|
||||
|
||||
def isInRack: Boolean = slot.exists(_.inventory.isInstanceOf[RackNode])
|
||||
|
||||
|
||||
@ -37,6 +37,7 @@ class RackNode(val rack: Rack) extends ComputerAwareNode(rack) with WindowedNode
|
||||
case mountable: RackMountable if mountable.node.address == address => true
|
||||
case mountable: RackMountable with ComponentInventory => mountable.inventory.entities.exists {
|
||||
case environment: Environment => environment.node.address == address
|
||||
case _ => false
|
||||
}
|
||||
case _ => false
|
||||
}
|
||||
|
||||
@ -14,23 +14,23 @@ import totoro.ocelot.brain.entity.traits.{DiskManaged, DiskUnmanaged}
|
||||
import totoro.ocelot.brain.util.DyeColor
|
||||
|
||||
class DiskEditWindow(item: DiskItem) extends PanelWindow {
|
||||
private def diskSize: Option[Long] = Some(item.component).collect { case disk: DiskManaged =>
|
||||
private def diskSize: Option[Long] = Some(item.entity).collect { case disk: DiskManaged =>
|
||||
disk.fileSystem.fileSystem.spaceUsed
|
||||
}
|
||||
|
||||
private def diskCapacity: Long = item.component.capacity
|
||||
private def diskCapacity: Long = item.entity.capacity
|
||||
|
||||
private def isWriteable: Boolean = item.component match {
|
||||
private def isWriteable: Boolean = item.entity match {
|
||||
case disk: DiskManaged => !disk.fileSystem.fileSystem.isReadOnly
|
||||
case disk: DiskUnmanaged => !disk.isLocked
|
||||
}
|
||||
|
||||
private def isManaged: Boolean = item.component match {
|
||||
private def isManaged: Boolean = item.entity match {
|
||||
case _: DiskManaged => true
|
||||
case _: DiskUnmanaged => false
|
||||
}
|
||||
|
||||
private def address: Option[String] = Option(item.component.node).flatMap(node => Option(node.address))
|
||||
private def address: Option[String] = Option(item.entity.node).flatMap(node => Option(node.address))
|
||||
|
||||
override protected def title: String = s"${item.diskKind} " + address.getOrElse("")
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user