201 lines
5.9 KiB
Scala

package ocelot.desktop.node.nodes
import ocelot.desktop.geometry.{Rect2D, Size2D, Vector2D}
import ocelot.desktop.graphics.{Graphics, IconSource}
import ocelot.desktop.inventory.Item
import ocelot.desktop.inventory.item.{DiskDriveMountableItem, RackMountableItem, ServerItem}
import ocelot.desktop.node.Node.{HighlightThickness, NoHighlightSize, Size, TexelCount}
import ocelot.desktop.node.{ComputerAwareNode, NodePort}
import ocelot.desktop.ui.event.ClickEvent
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
import ocelot.desktop.ui.widget.window.Window
import ocelot.desktop.util.DrawUtils
import ocelot.desktop.windows.RackWindow
import totoro.ocelot.brain.entity.Rack
import totoro.ocelot.brain.entity.traits.{ComponentInventory, Environment, Inventory, RackMountable}
import totoro.ocelot.brain.network
import totoro.ocelot.brain.util.Direction
class RackNode(val rack: Rack)
extends ComputerAwareNode(rack)
{
override val icon: String = "nodes/rack/Empty"
override def exposeAddress = false
override def ports: Array[NodePort] = Array(
NodePort(Some(Direction.Bottom)),
NodePort(Some(Direction.Top)),
NodePort(Some(Direction.Back)),
NodePort(Some(Direction.Right)),
NodePort(Some(Direction.Left))
)
override def getNodeByPort(port: NodePort): network.Node = rack.sidedNode(port.direction.get)
override def shouldReceiveEventsFor(address: String): Boolean =
super.shouldReceiveEventsFor(address) ||
rack.inventory.entities.exists {
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
}
override def setupContextMenu(menu: ContextMenu, event: ClickEvent): Unit = {
RackNode.addContextMenuEntriesOfMountable(menu, getMountableByClick(event))
super.setupContextMenu(menu, event)
}
override def draw(g: Graphics): Unit = {
super.draw(g)
val x = position.x + HighlightThickness
val y = position.y + HighlightThickness
var prefix: String = null
for (i <- 0 until 4) {
Slot(i).get match {
case Some(serverItem: ServerItem) =>
prefix = s"nodes/rack/server/$i/"
// Background
g.sprite(
s"${prefix}Default",
x,
y,
NoHighlightSize,
NoHighlightSize
)
// Activity overlay
DrawUtils.drawComputerNodeActivity(
g,
x,
y,
serverItem.server.machine,
prefix
)
case Some(diskDriveMountableItem: DiskDriveMountableItem) =>
prefix = s"nodes/rack/drive/$i/"
// Background
g.sprite(
s"${prefix}Default",
x,
y,
NoHighlightSize,
NoHighlightSize
)
diskDriveMountableItem.drawActivityAndFloppy(
g,
Rect2D(
x,
y,
NoHighlightSize,
NoHighlightSize
),
prefix
)
case _ =>
}
}
}
override def dispose(): Unit = {
for (i <- 0 until 4) {
Slot(i).get match {
case Some(serverItem: ServerItem) => serverItem.onRemoved()
case _=>
}
}
super.dispose()
}
// -------------------------------- Inventory --------------------------------
override type I = Item with RackMountableItem
override def brainInventory: Inventory = rack.inventory.owner
// -------------------------------- Window --------------------------------
private lazy val currentWindow = new RackWindow(this)
override def window: Option[Window] = Some(currentWindow)
// ---------------------------- ShiftClickNode ----------------------------
private def getMountableByClick(event: ClickEvent): Option[RackMountableItem] = {
val horizontalMargin = HighlightThickness + (1 / TexelCount) * Size
val verticalMargin = HighlightThickness + (2 / TexelCount) * Size
val localPosition = Vector2D(
event.mousePos.x - position.x - horizontalMargin,
event.mousePos.y - position.y - verticalMargin
)
val m = Size2D(
this.width - horizontalMargin * 2,
this.height - verticalMargin * 2
)
// Checking if click was inside mountables area
if (localPosition.x < 0 || localPosition.y < 0 || localPosition.x > m.width || localPosition.y > m.height)
return None
val mountableIndex = (localPosition.y / m.height * 4).toInt
Slot(mountableIndex).get.collect {
case item: RackMountableItem => item
}
}
override protected def onShiftClick(event: ClickEvent): Unit = {
getMountableByClick(event) match {
case Some(serverItem: ServerItem) =>
serverItem.toggleIsTurnedOn()
case Some(diskDriveMountableItem: DiskDriveMountableItem) =>
if (diskDriveMountableItem.isFloppyItemPresent)
diskDriveMountableItem.eject()
case _ =>
}
}
override protected def hoveredShiftStatusBarText: String = "Turn server on/off"
}
object RackNode {
def addContextMenuEntriesOfMountable(menu: ContextMenu, item: Option[RackMountableItem]): Unit = {
item match {
case Some(serverItem: ServerItem) =>
menu.addEntry(ContextMenuEntry("Set up", IconSource.Window) {
serverItem.window.get.open()
})
if (serverItem.isInRack) {
menu.addSeparator()
serverItem.addPowerContextMenuEntries(menu)
}
serverItem.addTierContextMenuEntries(menu)
menu.addSeparator()
case Some(diskDriveMountableItem: DiskDriveMountableItem) =>
if (diskDriveMountableItem.isFloppyItemPresent) {
diskDriveMountableItem.addDiskDriveMenuEntries(menu)
menu.addSeparator()
}
case _ =>
}
}
}