| package li.cil.oc.server.component |
| |
| import java.lang.Iterable |
| import java.util |
| |
| import li.cil.oc.Constants |
| import li.cil.oc.api.driver.DeviceInfo.DeviceAttribute |
| import li.cil.oc.api.driver.DeviceInfo.DeviceClass |
| import li.cil.oc.OpenComputers |
| import li.cil.oc.api |
| import li.cil.oc.api.Machine |
| import li.cil.oc.api.component.RackBusConnectable |
| import li.cil.oc.api.driver.DeviceInfo |
| import li.cil.oc.api.internal |
| import li.cil.oc.api.machine.MachineHost |
| import li.cil.oc.api.network.Analyzable |
| import li.cil.oc.api.network.Environment |
| import li.cil.oc.api.network.Message |
| import li.cil.oc.api.network.Node |
| import li.cil.oc.common.GuiType |
| import li.cil.oc.common.InventorySlots |
| import li.cil.oc.common.Slot |
| import li.cil.oc.common.Tier |
| import li.cil.oc.common.inventory.ComponentInventory |
| import li.cil.oc.common.inventory.ServerInventory |
| import li.cil.oc.common.item |
| import li.cil.oc.common.item.Delegator |
| import li.cil.oc.server.network.Connector |
| import li.cil.oc.util.BlockPosition |
| import li.cil.oc.util.ExtendedNBT._ |
| import net.minecraft.entity.player.EntityPlayer |
| import net.minecraft.item.ItemStack |
| import net.minecraft.nbt.NBTTagCompound |
| |
| import scala.collection.convert.WrapAsJava._ |
| |
| class Server(val rack: api.internal.Rack, val slot: Int) extends Environment with MachineHost with ServerInventory with ComponentInventory with Analyzable with internal.Server with DeviceInfo { |
| lazy val machine = Machine.create(this) |
| |
| val node = if (!rack.world.isRemote) machine.node else null |
| |
| var wasRunning = false |
| var hadErrored = false |
| var lastFileSystemAccess = 0L |
| var lastNetworkActivity = 0L |
| |
| private final lazy val deviceInfo = Map( |
| DeviceAttribute.Class -> DeviceClass.System, |
| DeviceAttribute.Description -> "Server", |
| DeviceAttribute.Vendor -> Constants.DeviceInfo.DefaultVendor, |
| DeviceAttribute.Product -> "Blader", |
| DeviceAttribute.Capacity -> getSizeInventory.toString |
| ) |
| |
| override def getDeviceInfo: util.Map[String, String] = deviceInfo |
| |
| // ----------------------------------------------------------------------- // |
| // Environment |
| |
| override def onConnect(node: Node) { |
| if (node == this.node) { |
| connectComponents() |
| } |
| } |
| |
| override def onDisconnect(node: Node) { |
| if (node == this.node) { |
| disconnectComponents() |
| } |
| } |
| |
| override def onMessage(message: Message) { |
| } |
| |
| override def load(nbt: NBTTagCompound) { |
| super.load(nbt) |
| if (!rack.world.isRemote) { |
| machine.load(nbt.getCompoundTag("machine")) |
| } |
| } |
| |
| override def save(nbt: NBTTagCompound) { |
| super.save(nbt) |
| if (!rack.world.isRemote) { |
| nbt.setNewCompoundTag("machine", machine.save) |
| } |
| } |
| |
| // ----------------------------------------------------------------------- // |
| // MachineHost |
| |
| override def internalComponents(): Iterable[ItemStack] = (0 until getSizeInventory).collect { |
| case i if getStackInSlot(i) != null && isComponentSlot(i, getStackInSlot(i)) => getStackInSlot(i) |
| } |
| |
| override def componentSlot(address: String) = components.indexWhere(_.exists(env => env.node != null && env.node.address == address)) |
| |
| override def onMachineConnect(node: Node) = onConnect(node) |
| |
| override def onMachineDisconnect(node: Node) = onDisconnect(node) |
| |
| // ----------------------------------------------------------------------- // |
| // EnvironmentHost |
| |
| override def xPosition = rack.xPosition |
| |
| override def yPosition = rack.yPosition |
| |
| override def zPosition = rack.zPosition |
| |
| override def world = rack.world |
| |
| override def markChanged() = rack.markChanged() |
| |
| // ----------------------------------------------------------------------- // |
| // ServerInventory |
| |
| override def tier = Delegator.subItem(container) match { |
| case Some(server: item.Server) => server.tier |
| case _ => 0 |
| } |
| |
| override def isUseableByPlayer(player: EntityPlayer): Boolean = rack.isUseableByPlayer(player) |
| |
| // ----------------------------------------------------------------------- // |
| // ItemStackInventory |
| |
| override def host = rack |
| |
| // ----------------------------------------------------------------------- // |
| // ComponentInventory |
| |
| override def container = rack.getStackInSlot(slot) |
| |
| override protected def connectItemNode(node: Node) { |
| if (node != null) { |
| api.Network.joinNewNetwork(machine.node) |
| machine.node.connect(node) |
| } |
| } |
| |
| override protected def onItemRemoved(slot: Int, stack: ItemStack): Unit = { |
| super.onItemRemoved(slot, stack) |
| if (!rack.world.isRemote) { |
| val slotType = InventorySlots.server(tier)(slot).slot |
| if (slotType == Slot.CPU) { |
| machine.stop() |
| } |
| } |
| } |
| |
| // ----------------------------------------------------------------------- // |
| // RackMountable |
| |
| override def getData: NBTTagCompound = { |
| val nbt = new NBTTagCompound() |
| nbt.setBoolean("isRunning", wasRunning) |
| nbt.setBoolean("hasErrored", hadErrored) |
| nbt.setLong("lastFileSystemAccess", lastFileSystemAccess) |
| nbt.setLong("lastNetworkActivity", lastNetworkActivity) |
| nbt |
| } |
| |
| override def getConnectableCount: Int = components.count { |
| case Some(_: RackBusConnectable) => true |
| case _ => false |
| } |
| |
| override def getConnectableAt(index: Int): RackBusConnectable = components.collect { |
| case Some(busConnectable: RackBusConnectable) => busConnectable |
| }.apply(index) |
| |
| override def onActivate(player: EntityPlayer, hitX: Float, hitY: Float): Boolean = { |
| if (!player.getEntityWorld.isRemote) { |
| if (player.isSneaking) { |
| if (!machine.isRunning && isUseableByPlayer(player)) { |
| wasRunning = false |
| hadErrored = false |
| machine.start() |
| } |
| } |
| else { |
| val position = BlockPosition(rack) |
| player.openGui(OpenComputers, GuiType.ServerInRack.id, world, position.x, GuiType.embedSlot(position.y, slot), position.z) |
| } |
| } |
| true |
| } |
| |
| // ----------------------------------------------------------------------- // |
| // ManagedEnvironment |
| |
| override def canUpdate: Boolean = true |
| |
| override def update(): Unit = { |
| if (!rack.world.isRemote) { |
| machine.update() |
| |
| val isRunning = machine.isRunning |
| val hasErrored = machine.lastError != null |
| if (isRunning != wasRunning || hasErrored != hadErrored) { |
| rack.markChanged(slot) |
| } |
| wasRunning = isRunning |
| hadErrored = hasErrored |
| if (tier == Tier.Four) node.asInstanceOf[Connector].changeBuffer(Double.PositiveInfinity) |
| } |
| |
| updateComponents() |
| } |
| |
| // ----------------------------------------------------------------------- // |
| // StateAware |
| |
| override def getCurrentState: util.EnumSet[api.util.StateAware.State] = { |
| if (machine.isRunning) util.EnumSet.of(api.util.StateAware.State.IsWorking) |
| else util.EnumSet.noneOf(classOf[api.util.StateAware.State]) |
| } |
| |
| // ----------------------------------------------------------------------- // |
| // Analyzable |
| |
| override def onAnalyze(player: EntityPlayer, side: Int, hitX: Float, hitY: Float, hitZ: Float) = Array(machine.node) |
| } |