Showing indicator for disk activity on disk drives, cases and server racks.

This commit is contained in:
Florian Nücke 2014-10-06 17:29:13 +02:00
parent 4f95b38d02
commit 62939fd461
22 changed files with 312 additions and 130 deletions

Binary file not shown.

View File

@ -2,11 +2,13 @@ package li.cil.oc.api.event;
import cpw.mods.fml.common.eventhandler.Cancelable; import cpw.mods.fml.common.eventhandler.Cancelable;
import cpw.mods.fml.common.eventhandler.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.tileentity.TileEntity;
import net.minecraft.world.World; import net.minecraft.world.World;
/** /**
* Fired on the <em>client side only</em>, signals file system access. * Events for handling file system access and representing it on the client.
* <p/> * <p/>
* This is used to play file system access sounds and render disk activity * This is used to play file system access sounds and render disk activity
* indicators on some containers (e.g. disk drive, computer, server). * indicators on some containers (e.g. disk drive, computer, server).
@ -19,52 +21,35 @@ import net.minecraft.world.World;
*/ */
@Cancelable @Cancelable
public class FileSystemAccessEvent extends Event { public class FileSystemAccessEvent extends Event {
/** protected String sound;
* The name of the sound effect to play for the file system.
*/
public final String sound;
/** protected World world;
* The world the file system lives in.
*/
public final World world;
/** protected double x;
* The x coordinate of the file system's container.
*/
public final double x;
/** protected double y;
* The y coordinate of the file system's container.
*/
public final double y;
/** protected double z;
* The z coordinate of the file system's container.
*/
public final double z;
/** protected TileEntity tileEntity;
* The tile entity hosting the file system.
* <p/> protected NBTTagCompound data;
* <em>Important</em>: this can be <tt>null</tt>, which is usually the
* case when the container is an entity or item.
*/
public final TileEntity tileEntity;
/** /**
* Constructor for tile entity hosted file systems. * Constructor for tile entity hosted file systems.
* *
* @param sound the name of the sound effect to play. * @param sound the name of the sound effect to play.
* @param tileEntity the tile entity hosting the file system. * @param tileEntity the tile entity hosting the file system.
* @param data the additional data.
*/ */
public FileSystemAccessEvent(String sound, TileEntity tileEntity) { protected FileSystemAccessEvent(String sound, TileEntity tileEntity, NBTTagCompound data) {
this.sound = sound; this.sound = sound;
this.world = tileEntity.getWorldObj(); this.world = tileEntity.getWorldObj();
this.x = tileEntity.xCoord + 0.5; this.x = tileEntity.xCoord + 0.5;
this.y = tileEntity.yCoord + 0.5; this.y = tileEntity.yCoord + 0.5;
this.z = tileEntity.zCoord + 0.5; this.z = tileEntity.zCoord + 0.5;
this.tileEntity = tileEntity; this.tileEntity = tileEntity;
this.data = data;
} }
/** /**
@ -75,13 +60,116 @@ public class FileSystemAccessEvent extends Event {
* @param x the x coordinate of the file system's container. * @param x the x coordinate of the file system's container.
* @param y the y coordinate of the file system's container. * @param y the y coordinate of the file system's container.
* @param z the z coordinate of the file system's container. * @param z the z coordinate of the file system's container.
* @param data the additional data.
*/ */
public FileSystemAccessEvent(String sound, World world, double x, double y, double z) { protected FileSystemAccessEvent(String sound, World world, double x, double y, double z, NBTTagCompound data) {
this.sound = sound; this.sound = sound;
this.world = world; this.world = world;
this.x = x; this.x = x;
this.y = y; this.y = y;
this.z = z; this.z = z;
this.tileEntity = null; this.tileEntity = null;
this.data = data;
}
/**
* The name of the sound effect to play for the file system.
*/
public String getSound() {
return sound;
}
/**
* The world the file system lives in.
*/
public World getWorld() {
return world;
}
/**
* The x coordinate of the file system's container.
*/
public double getX() {
return x;
}
/**
* The y coordinate of the file system's container.
*/
public double getY() {
return y;
}
/**
* The z coordinate of the file system's container.
*/
public double getZ() {
return z;
}
/**
* The tile entity hosting the file system.
* <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 file system lives in, for example.
*/
public NBTTagCompound getData() {
return data;
}
public static final class Server extends FileSystemAccessEvent {
private Node node;
public Server(String sound, TileEntity tileEntity, Node node) {
super(sound, tileEntity, new NBTTagCompound());
this.node = node;
}
public Server(String sound, World world, double x, double y, double z, Node node) {
super(sound, world, x, y, z, new NBTTagCompound());
this.node = node;
}
/**
* The node of the file system that signalled activity.
*/
public Node getNode() {
return node;
}
}
public static final class Client extends FileSystemAccessEvent {
/**
* Constructor for tile entity hosted file systems.
*
* @param sound the name of the sound effect to play.
* @param tileEntity the tile entity hosting the file system.
* @param data the additional data.
*/
public Client(String sound, TileEntity tileEntity, NBTTagCompound data) {
super(sound, tileEntity, data);
}
/**
* Constructor for arbitrarily hosted file systems.
*
* @param sound the name of the sound effect to play.
* @param world the world the file system lives in.
* @param x the x coordinate of the file system's container.
* @param y the y coordinate of the file system's container.
* @param z the z coordinate of the file system's container.
* @param data the additional data.
*/
public Client(String sound, World world, double x, double y, double z, NBTTagCompound data) {
super(sound, world, x, y, z, data);
}
} }
} }

View File

@ -52,11 +52,12 @@ local result, reason = os.execute("/bin/cp -vr /mnt/" .. boot .. "/* /mnt/" .. m
if not result then if not result then
error(reason, 0) error(reason, 0)
end end
computer.setBootAddress(choice.address) choice.setLabel("OpenOS")
print("All done! Would you like to reboot now? [Y/n]") print("All done! Set as boot device and reboot now? [Y/n]")
local result = io.read() local result = io.read()
if not result or result == "" or result:sub(1, 1):lower() == "y" then if not result or result == "" or result:sub(1, 1):lower() == "y" then
computer.setBootAddress(choice.address)
print("\nRebooting now!") print("\nRebooting now!")
computer.shutdown(true) computer.shutdown(true)
end end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 624 B

After

Width:  |  Height:  |  Size: 623 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 504 B

After

Width:  |  Height:  |  Size: 570 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 488 B

After

Width:  |  Height:  |  Size: 558 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 B

View File

@ -17,6 +17,7 @@ import li.cil.oc.util.Audio
import net.minecraft.client.Minecraft import net.minecraft.client.Minecraft
import net.minecraft.client.gui.GuiScreen import net.minecraft.client.gui.GuiScreen
import net.minecraft.entity.player.EntityPlayer import net.minecraft.entity.player.EntityPlayer
import net.minecraft.nbt.CompressedStreamTools
import net.minecraftforge.common.MinecraftForge import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.common.util.ForgeDirection import net.minecraftforge.common.util.ForgeDirection
import org.lwjgl.input.Keyboard import org.lwjgl.input.Keyboard
@ -145,9 +146,10 @@ object PacketHandler extends CommonPacketHandler {
def onFileSystemActivity(p: PacketParser) = { def onFileSystemActivity(p: PacketParser) = {
val sound = p.readUTF() val sound = p.readUTF()
val data = CompressedStreamTools.read(p)
if (p.readBoolean()) p.readTileEntity[net.minecraft.tileentity.TileEntity]() match { if (p.readBoolean()) p.readTileEntity[net.minecraft.tileentity.TileEntity]() match {
case Some(t) => case Some(t) =>
MinecraftForge.EVENT_BUS.post(new FileSystemAccessEvent(sound, t)) MinecraftForge.EVENT_BUS.post(new FileSystemAccessEvent.Client(sound, t, data))
case _ => // Invalid packet. case _ => // Invalid packet.
} }
else world(p.player, p.readInt()) match { else world(p.player, p.readInt()) match {
@ -155,7 +157,7 @@ object PacketHandler extends CommonPacketHandler {
val x = p.readDouble() val x = p.readDouble()
val y = p.readDouble() val y = p.readDouble()
val z = p.readDouble() val z = p.readDouble()
MinecraftForge.EVENT_BUS.post(new FileSystemAccessEvent(sound, world, x, y, z)) MinecraftForge.EVENT_BUS.post(new FileSystemAccessEvent.Client(sound, world, x, y, z, data))
case _ => // Invalid packet. case _ => // Invalid packet.
} }
} }

View File

@ -16,7 +16,7 @@ import li.cil.oc.client.renderer.block.BlockRenderer
import li.cil.oc.client.renderer.item.ItemRenderer import li.cil.oc.client.renderer.item.ItemRenderer
import li.cil.oc.client.renderer.tileentity._ import li.cil.oc.client.renderer.tileentity._
import li.cil.oc.common.component.TextBuffer import li.cil.oc.common.component.TextBuffer
import li.cil.oc.common.event.FileAccessHandler import li.cil.oc.common.event.FileSystemAccessHandler
import li.cil.oc.common.init.Items import li.cil.oc.common.init.Items
import li.cil.oc.common.tileentity import li.cil.oc.common.tileentity
import li.cil.oc.common.tileentity.ServerRack import li.cil.oc.common.tileentity.ServerRack
@ -61,7 +61,7 @@ private[oc] class Proxy extends CommonProxy {
ClientRegistry.registerKeyBinding(KeyBindings.materialCosts) ClientRegistry.registerKeyBinding(KeyBindings.materialCosts)
ClientRegistry.registerKeyBinding(KeyBindings.clipboardPaste) ClientRegistry.registerKeyBinding(KeyBindings.clipboardPaste)
MinecraftForge.EVENT_BUS.register(FileAccessHandler) MinecraftForge.EVENT_BUS.register(FileSystemAccessHandler)
MinecraftForge.EVENT_BUS.register(PetRenderer) MinecraftForge.EVENT_BUS.register(PetRenderer)
MinecraftForge.EVENT_BUS.register(ServerRack) MinecraftForge.EVENT_BUS.register(ServerRack)
MinecraftForge.EVENT_BUS.register(TextBuffer) MinecraftForge.EVENT_BUS.register(TextBuffer)

View File

@ -30,8 +30,11 @@ object Textures {
val guiSlot = new ResourceLocation(Settings.resourceDomain, "textures/gui/slot.png") val guiSlot = new ResourceLocation(Settings.resourceDomain, "textures/gui/slot.png")
val blockCaseFrontOn = new ResourceLocation(Settings.resourceDomain, "textures/blocks/CaseFrontOn.png") val blockCaseFrontOn = new ResourceLocation(Settings.resourceDomain, "textures/blocks/CaseFrontOn.png")
val blockCaseFrontActivity = new ResourceLocation(Settings.resourceDomain, "textures/blocks/CaseFrontActivity.png")
val blockDiskDriveFrontActivity = new ResourceLocation(Settings.resourceDomain, "textures/blocks/DiskDriveFrontActivity.png")
val blockHologram = new ResourceLocation(Settings.resourceDomain, "textures/blocks/HologramEffect.png") val blockHologram = new ResourceLocation(Settings.resourceDomain, "textures/blocks/HologramEffect.png")
val blockRackFrontOn = new ResourceLocation(Settings.resourceDomain, "textures/blocks/ServerRackFrontOn.png") val blockRackFrontOn = new ResourceLocation(Settings.resourceDomain, "textures/blocks/ServerRackFrontOn.png")
val blockRackFrontActivity = new ResourceLocation(Settings.resourceDomain, "textures/blocks/ServerRackFrontActivity.png")
val blockRobot = new ResourceLocation(Settings.resourceDomain, "textures/blocks/robot.png") val blockRobot = new ResourceLocation(Settings.resourceDomain, "textures/blocks/robot.png")
val blockScreenUpIndicator = new ResourceLocation(Settings.resourceDomain, "textures/blocks/screen/up_indicator.png") val blockScreenUpIndicator = new ResourceLocation(Settings.resourceDomain, "textures/blocks/screen/up_indicator.png")

View File

@ -14,27 +14,27 @@ object CaseRenderer extends TileEntitySpecialRenderer {
RenderState.checkError(getClass.getName + ".renderTileEntityAt: entering (aka: wasntme)") RenderState.checkError(getClass.getName + ".renderTileEntityAt: entering (aka: wasntme)")
val computer = tileEntity.asInstanceOf[Case] val computer = tileEntity.asInstanceOf[Case]
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS)
RenderState.disableLighting()
RenderState.makeItBlend()
RenderState.setBlendAlpha(1)
GL11.glPushMatrix()
GL11.glTranslated(x + 0.5, y + 0.5, z + 0.5)
computer.yaw match {
case ForgeDirection.WEST => GL11.glRotatef(-90, 0, 1, 0)
case ForgeDirection.NORTH => GL11.glRotatef(180, 0, 1, 0)
case ForgeDirection.EAST => GL11.glRotatef(90, 0, 1, 0)
case _ => // No yaw.
}
GL11.glTranslatef(-0.5f, 0.5f, 0.501f)
GL11.glScalef(1, -1, 1)
if (computer.isRunning) { if (computer.isRunning) {
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS)
RenderState.disableLighting()
RenderState.makeItBlend()
RenderState.setBlendAlpha(1)
GL11.glPushMatrix()
GL11.glTranslated(x + 0.5, y + 0.5, z + 0.5)
computer.yaw match {
case ForgeDirection.WEST => GL11.glRotatef(-90, 0, 1, 0)
case ForgeDirection.NORTH => GL11.glRotatef(180, 0, 1, 0)
case ForgeDirection.EAST => GL11.glRotatef(90, 0, 1, 0)
case _ => // No yaw.
}
GL11.glTranslatef(-0.5f, 0.5f, 0.501f)
GL11.glScalef(1, -1, 1)
bindTexture(Textures.blockCaseFrontOn) bindTexture(Textures.blockCaseFrontOn)
val t = Tessellator.instance val t = Tessellator.instance
t.startDrawingQuads() t.startDrawingQuads()
@ -44,10 +44,21 @@ object CaseRenderer extends TileEntitySpecialRenderer {
t.addVertexWithUV(0, 0, 0, 0, 0) t.addVertexWithUV(0, 0, 0, 0, 0)
t.draw() t.draw()
GL11.glPopMatrix() if (System.currentTimeMillis() - computer.lastAccess < 400 && computer.world.rand.nextDouble() > 0.1) {
GL11.glPopAttrib() bindTexture(Textures.blockCaseFrontActivity)
val t = Tessellator.instance
t.startDrawingQuads()
t.addVertexWithUV(0, 1, 0, 0, 1)
t.addVertexWithUV(1, 1, 0, 1, 1)
t.addVertexWithUV(1, 0, 0, 1, 0)
t.addVertexWithUV(0, 0, 0, 0, 0)
t.draw()
}
} }
GL11.glPopMatrix()
GL11.glPopAttrib()
RenderState.checkError(getClass.getName + ".renderTileEntityAt: leaving") RenderState.checkError(getClass.getName + ".renderTileEntityAt: leaving")
} }
} }

View File

@ -1,8 +1,10 @@
package li.cil.oc.client.renderer.tileentity package li.cil.oc.client.renderer.tileentity
import li.cil.oc.client.Textures
import li.cil.oc.common.tileentity.DiskDrive import li.cil.oc.common.tileentity.DiskDrive
import li.cil.oc.util.RenderState import li.cil.oc.util.RenderState
import net.minecraft.client.renderer.OpenGlHelper import net.minecraft.client.renderer.OpenGlHelper
import net.minecraft.client.renderer.Tessellator
import net.minecraft.client.renderer.entity.RenderItem import net.minecraft.client.renderer.entity.RenderItem
import net.minecraft.client.renderer.entity.RenderManager import net.minecraft.client.renderer.entity.RenderManager
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
@ -16,39 +18,59 @@ object DiskDriveRenderer extends TileEntitySpecialRenderer {
RenderState.checkError(getClass.getName + ".renderTileEntityAt: entering (aka: wasntme)") RenderState.checkError(getClass.getName + ".renderTileEntityAt: entering (aka: wasntme)")
val drive = tileEntity.asInstanceOf[DiskDrive] val drive = tileEntity.asInstanceOf[DiskDrive]
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS)
GL11.glPushMatrix()
GL11.glTranslated(x + 0.5, y + 0.5, z + 0.5)
drive.yaw match {
case ForgeDirection.WEST => GL11.glRotatef(-90, 0, 1, 0)
case ForgeDirection.NORTH => GL11.glRotatef(180, 0, 1, 0)
case ForgeDirection.EAST => GL11.glRotatef(90, 0, 1, 0)
case _ => // No yaw.
}
drive.items(0) match { drive.items(0) match {
case Some(stack) => case Some(stack) =>
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS) GL11.glPushMatrix()
GL11.glTranslatef(0, 3.5f / 16, 9 / 16f)
GL11.glRotatef(90, -1, 0, 0)
val brightness = drive.world.getLightBrightnessForSkyBlocks(drive.x + drive.facing.offsetX, drive.y + drive.facing.offsetY, drive.z + drive.facing.offsetZ, 0) val brightness = drive.world.getLightBrightnessForSkyBlocks(drive.x + drive.facing.offsetX, drive.y + drive.facing.offsetY, drive.z + drive.facing.offsetZ, 0)
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, brightness % 65536, brightness / 65536) OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, brightness % 65536, brightness / 65536)
GL11.glPushMatrix()
GL11.glTranslated(x + 0.5, y + 0.5, z + 0.5)
drive.yaw match {
case ForgeDirection.WEST => GL11.glRotatef(-90, 0, 1, 0)
case ForgeDirection.NORTH => GL11.glRotatef(180, 0, 1, 0)
case ForgeDirection.EAST => GL11.glRotatef(90, 0, 1, 0)
case _ => // No yaw.
}
GL11.glTranslatef(0, 3.5f / 16, 9 / 16f)
GL11.glRotatef(90, -1, 0, 0)
// This is very 'meh', but item frames do it like this, too! // This is very 'meh', but item frames do it like this, too!
val entity = new EntityItem(drive.world, 0, 0, 0, stack) val entity = new EntityItem(drive.world, 0, 0, 0, stack)
entity.hoverStart = 0 entity.hoverStart = 0
RenderItem.renderInFrame = true RenderItem.renderInFrame = true
RenderManager.instance.renderEntityWithPosYaw(entity, 0, 0, 0, 0, 0) RenderManager.instance.renderEntityWithPosYaw(entity, 0, 0, 0, 0, 0)
RenderItem.renderInFrame = false RenderItem.renderInFrame = false
GL11.glPopMatrix() GL11.glPopMatrix()
GL11.glPopAttrib()
case _ => case _ =>
} }
if (System.currentTimeMillis() - drive.lastAccess < 400 && drive.world.rand.nextDouble() > 0.1) {
GL11.glTranslatef(-0.5f, 0.5f, 0.501f)
GL11.glScalef(1, -1, 1)
RenderState.disableLighting()
RenderState.makeItBlend()
RenderState.setBlendAlpha(1)
bindTexture(Textures.blockDiskDriveFrontActivity)
val t = Tessellator.instance
t.startDrawingQuads()
t.addVertexWithUV(0, 1, 0, 0, 1)
t.addVertexWithUV(1, 1, 0, 1, 1)
t.addVertexWithUV(1, 0, 0, 1, 0)
t.addVertexWithUV(0, 0, 0, 0, 0)
t.draw()
}
GL11.glPopMatrix()
GL11.glPopAttrib()
RenderState.checkError(getClass.getName + ".renderTileEntityAt: leaving") RenderState.checkError(getClass.getName + ".renderTileEntityAt: leaving")
} }
} }

View File

@ -14,33 +14,44 @@ object ServerRackRenderer extends TileEntitySpecialRenderer {
RenderState.checkError(getClass.getName + ".renderTileEntityAt: entering (aka: wasntme)") RenderState.checkError(getClass.getName + ".renderTileEntityAt: entering (aka: wasntme)")
val rack = tileEntity.asInstanceOf[ServerRack] val rack = tileEntity.asInstanceOf[ServerRack]
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS)
RenderState.disableLighting()
RenderState.makeItBlend()
GL11.glPushMatrix()
GL11.glTranslated(x + 0.5, y + 0.5, z + 0.5)
rack.yaw match {
case ForgeDirection.WEST => GL11.glRotatef(-90, 0, 1, 0)
case ForgeDirection.NORTH => GL11.glRotatef(180, 0, 1, 0)
case ForgeDirection.EAST => GL11.glRotatef(90, 0, 1, 0)
case _ => // No yaw.
}
GL11.glTranslatef(-0.5f, 0.5f, 0.501f)
GL11.glScalef(1, -1, 1)
if (rack.anyRunning) { if (rack.anyRunning) {
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS)
RenderState.disableLighting()
RenderState.makeItBlend()
GL11.glPushMatrix()
GL11.glTranslated(x + 0.5, y + 0.5, z + 0.5)
rack.yaw match {
case ForgeDirection.WEST => GL11.glRotatef(-90, 0, 1, 0)
case ForgeDirection.NORTH => GL11.glRotatef(180, 0, 1, 0)
case ForgeDirection.EAST => GL11.glRotatef(90, 0, 1, 0)
case _ => // No yaw.
}
GL11.glTranslatef(-0.5f, 0.5f, 0.501f)
GL11.glScalef(1, -1, 1)
bindTexture(Textures.blockRackFrontOn)
val v1 = 2 / 16f val v1 = 2 / 16f
val fs = 3 / 16f val fs = 3 / 16f
for (i <- 0 until 4 if rack.isRunning(i)) { for (i <- 0 until 4 if rack.isRunning(i)) {
val l = v1 + i * fs val l = v1 + i * fs
val h = v1 + (i + 1) * fs val h = v1 + (i + 1) * fs
bindTexture(Textures.blockRackFrontOn)
val t = Tessellator.instance
t.startDrawingQuads()
t.addVertexWithUV(0, h, 0, 0, h)
t.addVertexWithUV(1, h, 0, 1, h)
t.addVertexWithUV(1, l, 0, 1, l)
t.addVertexWithUV(0, l, 0, 0, l)
t.draw()
}
for (i <- 0 until 4 if System.currentTimeMillis() - rack.lastAccess(i) < 400 && rack.world.rand.nextDouble() > 0.1) {
val l = v1 + i * fs
val h = v1 + (i + 1) * fs
bindTexture(Textures.blockRackFrontActivity)
val t = Tessellator.instance val t = Tessellator.instance
t.startDrawingQuads() t.startDrawingQuads()
t.addVertexWithUV(0, h, 0, 0, h) t.addVertexWithUV(0, h, 0, 0, h)
@ -49,11 +60,11 @@ object ServerRackRenderer extends TileEntitySpecialRenderer {
t.addVertexWithUV(0, l, 0, 0, l) t.addVertexWithUV(0, l, 0, 0, l)
t.draw() t.draw()
} }
GL11.glPopMatrix()
GL11.glPopAttrib()
} }
GL11.glPopMatrix()
GL11.glPopAttrib()
RenderState.checkError(getClass.getName + ".renderTileEntityAt: leaving") RenderState.checkError(getClass.getName + ".renderTileEntityAt: leaving")
} }
} }

View File

@ -1,13 +0,0 @@
package li.cil.oc.common.event
import cpw.mods.fml.common.eventhandler.SubscribeEvent
import li.cil.oc.Settings
import li.cil.oc.api.event.FileSystemAccessEvent
object FileAccessHandler {
@SubscribeEvent
def onFileSystemAccess(e: FileSystemAccessEvent) {
val volume = Settings.get.soundVolume
e.world.playSound(e.x, e.y, e.z, e.sound, volume, 1, false)
}
}

View File

@ -0,0 +1,36 @@
package li.cil.oc.common.event
import cpw.mods.fml.common.eventhandler.SubscribeEvent
import li.cil.oc.Settings
import li.cil.oc.api.event.FileSystemAccessEvent
import li.cil.oc.common.tileentity.Case
import li.cil.oc.common.tileentity.DiskDrive
import li.cil.oc.common.tileentity.ServerRack
object FileSystemAccessHandler {
@SubscribeEvent
def onFileSystemAccess(e: FileSystemAccessEvent.Server) {
e.getTileEntity match {
case t: ServerRack =>
val serverSlot = t.servers.indexWhere {
case Some(server) => server.componentSlot(e.getNode.address) >= 0
case _ => false
}
if (serverSlot < 0) e.setCanceled(true)
else e.getData.setInteger("server", serverSlot)
case _ =>
}
}
@SubscribeEvent
def onFileSystemAccess(e: FileSystemAccessEvent.Client) {
val volume = Settings.get.soundVolume
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: ServerRack => t.lastAccess(e.getData.getInteger("server")) = System.currentTimeMillis()
case _ =>
}
}
}

View File

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

View File

@ -18,6 +18,9 @@ import net.minecraft.nbt.NBTTagCompound
class DiskDrive extends traits.Environment with traits.ComponentInventory with traits.Rotatable with Analyzable { class DiskDrive extends traits.Environment with traits.ComponentInventory with traits.Rotatable with Analyzable {
val node = api.Network.newNode(this, Visibility.None).create() val node = api.Network.newNode(this, Visibility.None).create()
// Used on client side to check whether to render disk activity indicators.
var lastAccess = 0L
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
override def onAnalyze(player: EntityPlayer, side: Int, hitX: Float, hitY: Float, hitZ: Float) = override def onAnalyze(player: EntityPlayer, side: Int, hitX: Float, hitY: Float, hitZ: Float) =

View File

@ -51,6 +51,9 @@ class ServerRack extends traits.PowerAcceptor with traits.Hub with traits.PowerB
// For client side rendering. // For client side rendering.
var isPresent = Array.fill[Option[String]](getSizeInventory)(None) var isPresent = Array.fill[Option[String]](getSizeInventory)(None)
// Used on client side to check whether to render disk activity indicators.
var lastAccess = Array.fill(4)(0L)
@SideOnly(Side.CLIENT) @SideOnly(Side.CLIENT)
override protected def hasConnector(side: ForgeDirection) = side != facing override protected def hasConnector(side: ForgeDirection) = side != facing

View File

@ -2,13 +2,17 @@ package li.cil.oc.server
import li.cil.oc.api.component.TextBuffer.ColorDepth import li.cil.oc.api.component.TextBuffer.ColorDepth
import li.cil.oc.api.driver.EnvironmentHost import li.cil.oc.api.driver.EnvironmentHost
import li.cil.oc.api.event.FileSystemAccessEvent
import li.cil.oc.api.network.Node
import li.cil.oc.common._ import li.cil.oc.common._
import li.cil.oc.common.tileentity.traits._ import li.cil.oc.common.tileentity.traits._
import li.cil.oc.util.PackedColor import li.cil.oc.util.PackedColor
import net.minecraft.entity.player.EntityPlayerMP import net.minecraft.entity.player.EntityPlayerMP
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.CompressedStreamTools
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
import net.minecraft.world.World import net.minecraft.world.World
import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.common.util.ForgeDirection import net.minecraftforge.common.util.ForgeDirection
import scala.collection.mutable import scala.collection.mutable
@ -81,28 +85,36 @@ object PacketSender {
// Avoid spamming the network with disk activity notices. // Avoid spamming the network with disk activity notices.
val fileSystemAccessTimeouts = mutable.WeakHashMap.empty[EnvironmentHost, mutable.Map[String, Long]] val fileSystemAccessTimeouts = mutable.WeakHashMap.empty[EnvironmentHost, mutable.Map[String, Long]]
def sendFileSystemActivity(host: EnvironmentHost, name: String) = fileSystemAccessTimeouts.synchronized { def sendFileSystemActivity(node: Node, host: EnvironmentHost, name: String) = fileSystemAccessTimeouts.synchronized {
fileSystemAccessTimeouts.get(host) match { fileSystemAccessTimeouts.get(host) match {
case Some(hostTimeouts) if hostTimeouts.getOrElse(name, 0L) > System.currentTimeMillis() => // Cooldown. case Some(hostTimeouts) if hostTimeouts.getOrElse(name, 0L) > System.currentTimeMillis() => // Cooldown.
case _ => case _ =>
fileSystemAccessTimeouts.getOrElseUpdate(host, mutable.Map.empty) += name -> (System.currentTimeMillis() + 500) val event = host match {
case t: net.minecraft.tileentity.TileEntity => new FileSystemAccessEvent.Server(name, t, node)
val pb = new SimplePacketBuilder(PacketType.FileSystemActivity) case _ => new FileSystemAccessEvent.Server(name, host.world, host.xPosition, host.yPosition, host.zPosition, node)
pb.writeUTF(name)
host match {
case t: net.minecraft.tileentity.TileEntity =>
pb.writeBoolean(true)
pb.writeTileEntity(t)
case _ =>
pb.writeBoolean(false)
pb.writeInt(host.world.provider.dimensionId)
pb.writeDouble(host.xPosition)
pb.writeDouble(host.yPosition)
pb.writeDouble(host.zPosition)
} }
MinecraftForge.EVENT_BUS.post(event)
if (!event.isCanceled) {
fileSystemAccessTimeouts.getOrElseUpdate(host, mutable.Map.empty) += name -> (System.currentTimeMillis() + 500)
pb.sendToPlayersNearHost(host, 64) val pb = new SimplePacketBuilder(PacketType.FileSystemActivity)
pb.writeUTF(event.getSound)
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, 64)
}
} }
} }

View File

@ -313,7 +313,7 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label, val host: Option
private def diskActivity() { private def diskActivity() {
(sound, host) match { (sound, host) match {
case (Some(s), Some(h)) => ServerPacketSender.sendFileSystemActivity(h, s) case (Some(s), Some(h)) => ServerPacketSender.sendFileSystemActivity(node, h, s)
case _ => case _ =>
} }
} }