Merge pull request #1572 from magik6k/patch-netcards

Network activity LED for servers.
This commit is contained in:
Florian "Sangar" Nücke 2015-12-17 23:13:19 +01:00
commit 99baeabdf7
14 changed files with 270 additions and 10 deletions

View File

@ -0,0 +1,158 @@
package li.cil.oc.api.event;
import cpw.mods.fml.common.eventhandler.Event;
import li.cil.oc.api.network.Node;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
/**
* Events for handling network activity and representing it on the client.
* <p/>
* This is used to render network activity
* indicators on some containers (e.g. computer, server).
* <p/>
* Use this to implement rendering of disk access indicators on you own
* containers / computers / drive bays.
* <p/>
* Canceling this event is provided to allow registering higher priority
* event handlers that override default behavior.
*/
public class NetworkActivityEvent extends Event {
protected World world;
protected double x;
protected double y;
protected double z;
protected TileEntity tileEntity;
protected NBTTagCompound data;
/**
* Constructor for tile entity hosted network cards.
*
* @param tileEntity the tile entity hosting the network card.
* @param data the additional data.
*/
protected NetworkActivityEvent(TileEntity tileEntity, NBTTagCompound data) {
this.world = tileEntity.getWorldObj();
this.x = tileEntity.xCoord + 0.5;
this.y = tileEntity.yCoord + 0.5;
this.z = tileEntity.zCoord + 0.5;
this.tileEntity = tileEntity;
this.data = data;
}
/**
* Constructor for arbitrarily hosted network cards.
*
* @param world the world the network card lives in.
* @param x the x coordinate of the network card's container.
* @param y the y coordinate of the network card's container.
* @param z the z coordinate of the network card's container.
* @param data the additional data.
*/
protected NetworkActivityEvent(World world, double x, double y, double z, NBTTagCompound data) {
this.world = world;
this.x = x;
this.y = y;
this.z = z;
this.tileEntity = null;
this.data = data;
}
/**
* The world the network card lives in.
*/
public World getWorld() {
return world;
}
/**
* The x coordinate of the network card's container.
*/
public double getX() {
return x;
}
/**
* The y coordinate of the network card's container.
*/
public double getY() {
return y;
}
/**
* The z coordinate of the network card's container.
*/
public double getZ() {
return z;
}
/**
* The tile entity hosting the network card.
* <p/>
* <em>Important</em>: this can be <tt>null</tt>, which is usually the
* case when the container is an entity or item.
*/
public TileEntity getTileEntity() {
return tileEntity;
}
/**
* Addition custom data, this is used to transmit the number of the server
* in a server rack the network card lives in, for example.
*/
public NBTTagCompound getData() {
return data;
}
public static final class Server extends NetworkActivityEvent {
private Node node;
public Server(TileEntity tileEntity, Node node) {
super(tileEntity, new NBTTagCompound());
this.node = node;
}
public Server(World world, double x, double y, double z, Node node) {
super(world, x, y, z, new NBTTagCompound());
this.node = node;
}
/**
* The node of the network card that signalled activity.
*/
public Node getNode() {
return node;
}
}
public static final class Client extends NetworkActivityEvent {
/**
* Constructor for tile entity hosted network card.
*
* @param tileEntity the tile entity hosting the network card.
* @param data the additional data.
*/
public Client(TileEntity tileEntity, NBTTagCompound data) {
super(tileEntity, data);
}
/**
* Constructor for arbitrarily hosted network card.
*
* @param world the world the file system lives in.
* @param x the x coordinate of the network card's container.
* @param y the y coordinate of the network card's container.
* @param z the z coordinate of the network card's container.
* @param data the additional data.
*/
public Client(World world, double x, double y, double z, NBTTagCompound data) {
super(world, x, y, z, data);
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 B

View File

@ -7,7 +7,7 @@ import cpw.mods.fml.common.network.FMLNetworkEvent.ClientCustomPacketEvent
import li.cil.oc.Localization
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.event.FileSystemAccessEvent
import li.cil.oc.api.event.{NetworkActivityEvent, FileSystemAccessEvent}
import li.cil.oc.client.renderer.PetRenderer
import li.cil.oc.common.Loot
import li.cil.oc.common.PacketType
@ -63,6 +63,7 @@ object PacketHandler extends CommonPacketHandler {
case PacketType.NanomachinesInputs => onNanomachinesInputs(p)
case PacketType.NanomachinesPower => onNanomachinesPower(p)
case PacketType.NetSplitterState => onNetSplitterState(p)
case PacketType.NetworkActivity => onNetworkActivity(p)
case PacketType.ParticleEffect => onParticleEffect(p)
case PacketType.PetVisibility => onPetVisibility(p)
case PacketType.PowerState => onPowerState(p)
@ -173,6 +174,23 @@ object PacketHandler extends CommonPacketHandler {
}
}
def onNetworkActivity(p: PacketParser) = {
val data = CompressedStreamTools.read(p)
if (p.readBoolean()) p.readTileEntity[net.minecraft.tileentity.TileEntity]() match {
case Some(t) =>
MinecraftForge.EVENT_BUS.post(new NetworkActivityEvent.Client(t, data))
case _ => // Invalid packet.
}
else world(p.player, p.readInt()) match {
case Some(world) =>
val x = p.readDouble()
val y = p.readDouble()
val z = p.readDouble()
MinecraftForge.EVENT_BUS.post(new NetworkActivityEvent.Client(world, x, y, z, data))
case _ => // Invalid packet.
}
}
def onFloppyChange(p: PacketParser) =
p.readTileEntity[DiskDrive]() match {
case Some(t) => t.setInventorySlotContents(0, p.readItemStack())

View File

@ -63,6 +63,7 @@ object Textures {
val blockRackServerOn = new ResourceLocation(Settings.resourceDomain, "textures/blocks/ServerFrontOn.png")
val blockRackServerError = new ResourceLocation(Settings.resourceDomain, "textures/blocks/ServerFrontError.png")
val blockRackServerActivity = new ResourceLocation(Settings.resourceDomain, "textures/blocks/ServerFrontActivity.png")
val blockRackServerNetworkActivity = new ResourceLocation(Settings.resourceDomain, "textures/blocks/ServerFrontNetworkActivity.png")
val blockRackTerminalServerOn = new ResourceLocation(Settings.resourceDomain, "textures/blocks/TerminalServerFrontOn.png")
val blockRackTerminalServerPresence = new ResourceLocation(Settings.resourceDomain, "textures/blocks/TerminalServerFrontPresence.png")

View File

@ -37,7 +37,7 @@ object CaseRenderer extends TileEntitySpecialRenderer {
if (computer.isRunning) {
renderFrontOverlay(Textures.blockCaseFrontOn)
if (System.currentTimeMillis() - computer.lastAccess < 400 && computer.world.rand.nextDouble() > 0.1) {
if (System.currentTimeMillis() - computer.lastFileSystemAccess < 400 && computer.world.rand.nextDouble() > 0.1) {
renderFrontOverlay(Textures.blockCaseFrontActivity)
}
}

View File

@ -27,6 +27,7 @@ object PacketType extends Enumeration {
NanomachinesInputs,
NanomachinesPower,
NetSplitterState,
NetworkActivity,
ParticleEffect,
PetVisibility, // Goes both ways.
PowerState,

View File

@ -20,7 +20,7 @@ object FileSystemAccessHandler {
case server: Server =>
val containsNode = server.componentSlot(e.getNode.address) >= 0
if (containsNode) {
server.lastAccess = System.currentTimeMillis()
server.lastFileSystemAccess = System.currentTimeMillis()
t.markChanged(slot)
}
case diskDrive: DiskDriveMountable =>
@ -42,7 +42,7 @@ object FileSystemAccessHandler {
e.getWorld.playSound(e.getX, e.getY, e.getZ, e.getSound, volume, 1, false)
e.getTileEntity match {
case t: DiskDrive => t.lastAccess = System.currentTimeMillis()
case t: Case => t.lastAccess = System.currentTimeMillis()
case t: Case => t.lastFileSystemAccess = System.currentTimeMillis()
case t: Raid => t.lastAccess = System.currentTimeMillis()
case _ =>
}

View File

@ -0,0 +1,36 @@
package li.cil.oc.common.event
import cpw.mods.fml.common.eventhandler.SubscribeEvent
import li.cil.oc.api.event.NetworkActivityEvent
import li.cil.oc.api.internal.Rack
import li.cil.oc.common.tileentity.Case
import li.cil.oc.server.component.Server
object NetworkActivityHandler {
@SubscribeEvent
def onNetworkActivity(e: NetworkActivityEvent.Server) {
e.getTileEntity match {
case t: Rack =>
for (slot <- 0 until t.getSizeInventory) {
t.getMountable(slot) match {
case server: Server =>
val containsNode = server.componentSlot(e.getNode.address) >= 0
if (containsNode) {
server.lastNetworkActivity = System.currentTimeMillis()
t.markChanged(slot)
}
case _ =>
}
}
case _ =>
}
}
@SubscribeEvent
def onNetworkActivity(e: NetworkActivityEvent.Client) {
e.getTileEntity match {
case t: Case => t.lastNetworkActivity = System.currentTimeMillis();
case _ =>
}
}
}

View File

@ -75,9 +75,12 @@ object RackMountableRenderHandler {
if (e.data.getBoolean("hasErrored") && RenderUtil.shouldShowErrorLight(e.rack.hashCode * (e.mountable + 1))) {
e.renderOverlay(Textures.blockRackServerError)
}
if (System.currentTimeMillis() - e.data.getLong("lastAccess") < 400 && e.rack.world.rand.nextDouble() > 0.1) {
if (System.currentTimeMillis() - e.data.getLong("lastFileSystemAccess") < 400 && e.rack.world.rand.nextDouble() > 0.1) {
e.renderOverlay(Textures.blockRackServerActivity)
}
if (!(System.currentTimeMillis() - e.data.getLong("lastNetworkActivity") < 300 && System.currentTimeMillis() % 200 > 100) && e.data.getBoolean("isRunning")) {
e.renderOverlay(Textures.blockRackServerNetworkActivity)
}
RenderState.enableLighting()
}

View File

@ -19,8 +19,9 @@ import net.minecraftforge.common.util.ForgeDirection
class Case(var tier: Int) extends traits.PowerAcceptor with traits.Computer with traits.Colored with internal.Case {
def this() = this(0)
// Used on client side to check whether to render disk activity indicators.
var lastAccess = 0L
// Used on client side to check whether to render disk activity/network indicators.
var lastFileSystemAccess = 0L
var lastNetworkActivity = 0L
color = Color.byTier(tier)

View File

@ -86,6 +86,7 @@ object ModOpenComputers extends ModProxy {
MinecraftForge.EVENT_BUS.register(HoverBootsHandler)
MinecraftForge.EVENT_BUS.register(Loot)
MinecraftForge.EVENT_BUS.register(NanomachinesHandler.Common)
MinecraftForge.EVENT_BUS.register(NetworkActivityHandler)
MinecraftForge.EVENT_BUS.register(RobotCommonHandler)
MinecraftForge.EVENT_BUS.register(SaveHandler)
MinecraftForge.EVENT_BUS.register(Tablet)

View File

@ -1,7 +1,7 @@
package li.cil.oc.server
import li.cil.oc.api
import li.cil.oc.api.event.FileSystemAccessEvent
import li.cil.oc.api.event.{NetworkActivityEvent, FileSystemAccessEvent}
import li.cil.oc.api.network.EnvironmentHost
import li.cil.oc.api.network.Node
import li.cil.oc.common._
@ -135,6 +135,34 @@ object PacketSender {
}
}
def sendNetworkActivity(node: Node, host: EnvironmentHost) = {
val event = host match {
case t: net.minecraft.tileentity.TileEntity => new NetworkActivityEvent.Server(t, node)
case _ => new NetworkActivityEvent.Server(host.world, host.xPosition, host.yPosition, host.zPosition, node)
}
MinecraftForge.EVENT_BUS.post(event)
if (!event.isCanceled) {
val pb = new SimplePacketBuilder(PacketType.NetworkActivity)
CompressedStreamTools.write(event.getData, pb)
event.getTileEntity match {
case t: net.minecraft.tileentity.TileEntity =>
pb.writeBoolean(true)
pb.writeTileEntity(t)
case _ =>
pb.writeBoolean(false)
pb.writeInt(event.getWorld.provider.dimensionId)
pb.writeDouble(event.getX)
pb.writeDouble(event.getY)
pb.writeDouble(event.getZ)
}
pb.sendToPlayersNearHost(host, Option(64))
}
}
def sendFloppyChange(t: tileentity.DiskDrive, stack: ItemStack = null) {
val pb = new SimplePacketBuilder(PacketType.FloppyChange)

View File

@ -12,6 +12,7 @@ import li.cil.oc.api.machine.Context
import li.cil.oc.api.network.EnvironmentHost
import li.cil.oc.api.network._
import li.cil.oc.api.prefab
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import net.minecraft.nbt._
import scala.collection.convert.WrapAsScala._
@ -73,6 +74,7 @@ class NetworkCard(val host: EnvironmentHost) extends prefab.ManagedEnvironment w
val port = checkPort(args.checkInteger(1))
val packet = api.Network.newPacket(node.address, address, port, args.drop(2).toArray)
doSend(packet)
networkActivity()
result(true)
}
@ -81,6 +83,7 @@ class NetworkCard(val host: EnvironmentHost) extends prefab.ManagedEnvironment w
val port = checkPort(args.checkInteger(0))
val packet = api.Network.newPacket(node.address, null, port, args.drop(1).toArray)
doBroadcast(packet)
networkActivity()
result(true)
}
@ -137,6 +140,7 @@ class NetworkCard(val host: EnvironmentHost) extends prefab.ManagedEnvironment w
if (packet.source != node.address && Option(packet.destination).forall(_ == node.address)) {
if (openPorts.contains(packet.port)) {
node.sendToReachable("computer.signal", Seq("modem_message", packet.source, Int.box(packet.port), Double.box(distance)) ++ packet.data: _*)
networkActivity()
}
// Accept wake-up messages regardless of port because we close all ports
// when our computer shuts down.
@ -184,4 +188,11 @@ class NetworkCard(val host: EnvironmentHost) extends prefab.ManagedEnvironment w
protected def checkPort(port: Int) =
if (port < 1 || port > 0xFFFF) throw new IllegalArgumentException("invalid port number")
else port
private def networkActivity() {
host match {
case (h) => ServerPacketSender.sendNetworkActivity(node, h)
case _ =>
}
}
}

View File

@ -38,7 +38,8 @@ class Server(val rack: tileentity.Rack, val slot: Int) extends Environment with
var wasRunning = false
var hadErrored = false
var lastAccess = 0L
var lastFileSystemAccess = 0L
var lastNetworkActivity = 0L
// ----------------------------------------------------------------------- //
// Environment
@ -142,7 +143,8 @@ class Server(val rack: tileentity.Rack, val slot: Int) extends Environment with
val nbt = new NBTTagCompound()
nbt.setBoolean("isRunning", wasRunning)
nbt.setBoolean("hasErrored", hadErrored)
nbt.setLong("lastAccess", lastAccess)
nbt.setLong("lastFileSystemAccess", lastFileSystemAccess)
nbt.setLong("lastNetworkActivity", lastNetworkActivity)
nbt
}