From 39b2c970109a276154c8c1c58adc5da866530f86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Sat, 9 Nov 2013 23:38:17 +0100 Subject: [PATCH] added analyzer tool: right click on a block show its address. for computers it also shows the last error message, if any (if the computer crashed). for multi screens it always shows the address of the origin. shift-rightclick copies the address to the clipboard. --- assets/opencomputers/lang/de_DE.lang | 2 +- assets/opencomputers/lang/en_US.lang | 1 + .../opencomputers/textures/items/analyzer.png | Bin 0 -> 244 bytes li/cil/oc/Items.scala | 4 ++ li/cil/oc/client/PacketHandler.scala | 7 +++ li/cil/oc/common/block/Delegator.scala | 7 ++- li/cil/oc/common/item/Analyzer.scala | 54 ++++++++++++++++++ li/cil/oc/common/item/Delegate.scala | 3 + li/cil/oc/common/tileentity/Computer.scala | 3 +- li/cil/oc/server/PacketSender.scala | 26 ++++++--- li/cil/oc/server/component/Computer.scala | 4 ++ 11 files changed, 97 insertions(+), 14 deletions(-) create mode 100644 assets/opencomputers/textures/items/analyzer.png create mode 100644 li/cil/oc/common/item/Analyzer.scala diff --git a/assets/opencomputers/lang/de_DE.lang b/assets/opencomputers/lang/de_DE.lang index 9e841d9ec..ff30b8b2f 100644 --- a/assets/opencomputers/lang/de_DE.lang +++ b/assets/opencomputers/lang/de_DE.lang @@ -9,8 +9,8 @@ oc.block.ScreenBasic.name=Einfacher Bildschirm oc.block.ScreenProfessional.name=Professioneller Bildschirm oc.container.Computer=Computer oc.container.DiskDrive=Diskettenlaufwerk +oc.item.Analyzer.name=Messgerät oc.item.Disk.name=Diskette -oc.item.GraphicsCard.name= oc.item.GraphicsCardAdvanced.name=Hochwertige Grafikkarte oc.item.GraphicsCardBasic.name=Einfache Grafikkarte oc.item.GraphicsCardProfessional.name=Professionelle Grafikkarte diff --git a/assets/opencomputers/lang/en_US.lang b/assets/opencomputers/lang/en_US.lang index bb260863f..595c6651a 100644 --- a/assets/opencomputers/lang/en_US.lang +++ b/assets/opencomputers/lang/en_US.lang @@ -9,6 +9,7 @@ oc.block.ScreenBasic.name=Basic Screen oc.block.ScreenProfessional.name=Professional Screen oc.container.Computer=Computer oc.container.DiskDrive=Disk Drive +oc.item.Analyzer.name=Analyzer oc.item.Disk.name=Floppy Disk oc.item.GraphicsCardAdvanced.name=Advanced Graphics Card oc.item.GraphicsCardBasic.name=Basic Graphics Card diff --git a/assets/opencomputers/textures/items/analyzer.png b/assets/opencomputers/textures/items/analyzer.png new file mode 100644 index 0000000000000000000000000000000000000000..cb308a1912f805ae7bc7e3fdb7de604da822d10f GIT binary patch literal 244 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbL!WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!fo#Q>iWR}L1T6E9y+oH$X=KXBQyWyg*kGdDLE(-GUVr|{;@ zrvLx{uiIz=vVyxL$S)Ykg#rdIf5uNh;UG^J$B>F!IsMT>2NXD%mA77~`p+CL81(zb zhsS<19Jh%75SI1~Y!cCUVeBLrFhS%uORtmd24$DI2Q~#>Wwv%c;qWx>C4cG1j1!k4 f&i(lJO(=mOJc3Q8ZHLbppy>>ru6{1-oD!M CommonPacketHandler} import li.cil.oc.server.component.Redstone +import net.minecraft.client.gui.GuiScreen import net.minecraft.entity.player.EntityPlayer import net.minecraft.tileentity.TileEntity import net.minecraftforge.common.ForgeDirection @@ -18,6 +19,7 @@ class PacketHandler extends CommonPacketHandler { override def dispatch(p: PacketParser) = p.packetType match { + case PacketType.Clipboard => onClipboard(p) case PacketType.ComputerStateResponse => onComputerStateResponse(p) case PacketType.PowerStateResponse => onPowerStateResponse(p) case PacketType.RedstoneStateResponse => onRedstoneStateResponse(p) @@ -30,6 +32,11 @@ class PacketHandler extends CommonPacketHandler { case _ => // Invalid packet. } + def onClipboard(p: PacketParser) = { + GuiScreen.setClipboardString(p.readUTF()) + p.player.asInstanceOf[EntityPlayer].addChatMessage("Copied to clipboard.") + } + def onComputerStateResponse(p: PacketParser) = p.readTileEntity[Computer]() match { case Some(t) => { diff --git a/li/cil/oc/common/block/Delegator.scala b/li/cil/oc/common/block/Delegator.scala index acf822525..868e72176 100644 --- a/li/cil/oc/common/block/Delegator.scala +++ b/li/cil/oc/common/block/Delegator.scala @@ -2,10 +2,9 @@ package li.cil.oc.common.block import cpw.mods.fml.common.registry.GameRegistry import java.util -import li.cil.oc.Config -import li.cil.oc.CreativeTab import li.cil.oc.api.network.Environment import li.cil.oc.common.tileentity.Rotatable +import li.cil.oc.{Items, Config, CreativeTab} import net.minecraft.block.Block import net.minecraft.block.material.Material import net.minecraft.client.renderer.texture.IconRegister @@ -234,6 +233,10 @@ class Delegator[Child <: Delegate](id: Int) extends Block(id, Material.iron) { } override def onBlockActivated(world: World, x: Int, y: Int, z: Int, player: EntityPlayer, side: Int, hitX: Float, hitY: Float, hitZ: Float): Boolean = { + // Do nothing if we have an analyzer in hand. + if (Items.analyzer.equals(player.getCurrentEquippedItem)) + return false + // Helper method to detect items that can be used to rotate blocks, such as // wrenches. This structural type is compatible with the BuildCraft wrench // interface. diff --git a/li/cil/oc/common/item/Analyzer.scala b/li/cil/oc/common/item/Analyzer.scala new file mode 100644 index 000000000..2fb3d100d --- /dev/null +++ b/li/cil/oc/common/item/Analyzer.scala @@ -0,0 +1,54 @@ +package li.cil.oc.common.item + +import cpw.mods.fml.common.network.Player +import li.cil.oc.Config +import li.cil.oc.api.network.Environment +import li.cil.oc.common.tileentity +import li.cil.oc.server.PacketSender +import net.minecraft.client.renderer.texture.IconRegister +import net.minecraft.entity.player.EntityPlayer +import net.minecraft.item.ItemStack +import net.minecraft.world.World + +class Analyzer(val parent: Delegator) extends Delegate { + val unlocalizedName = "Analyzer" + + override def onItemUse(item: ItemStack, player: EntityPlayer, world: World, x: Int, y: Int, z: Int, side: Int, hitX: Float, hitY: Float, hitZ: Float) = { + world.getBlockTileEntity(x, y, z) match { + case computer: tileentity.Computer => + if (!world.isRemote) { + computer.instance.lastError match { + case Some(value) => player.addChatMessage("Last error: " + value) + case _ => + } + processAddress(computer, player) + } + true + case screen: tileentity.Screen => + if (!world.isRemote) { + processAddress(screen.origin, player) + } + true + case environment: Environment => + if (!world.isRemote) { + processAddress(environment, player) + } + true + case _ => super.onItemUse(item, player, world, x, y, z, side, hitX, hitY, hitZ) + } + } + + private def processAddress(environment: Environment, player: EntityPlayer) { + val address = environment.node.address() + player.addChatMessage("Address: " + address) + if (player.isSneaking) { + PacketSender.sendClipboard(address, player.asInstanceOf[Player]) + } + } + + override def registerIcons(iconRegister: IconRegister) { + super.registerIcons(iconRegister) + + icon = iconRegister.registerIcon(Config.resourceDomain + ":analyzer") + } +} diff --git a/li/cil/oc/common/item/Delegate.scala b/li/cil/oc/common/item/Delegate.scala index b06b5d5d4..a3fc51ed4 100644 --- a/li/cil/oc/common/item/Delegate.scala +++ b/li/cil/oc/common/item/Delegate.scala @@ -30,4 +30,7 @@ trait Delegate { def onItemUse(item: ItemStack, player: EntityPlayer, world: World, x: Int, y: Int, z: Int, side: Int, hitX: Float, hitY: Float, hitZ: Float): Boolean = false def registerIcons(iconRegister: IconRegister) {} + + def equals(item: ItemStack) = + item != null && item.itemID == parent.itemID && parent.subItem(item).exists(_.itemId == itemId) } diff --git a/li/cil/oc/common/tileentity/Computer.scala b/li/cil/oc/common/tileentity/Computer.scala index 5d5baa745..481ab5a2c 100644 --- a/li/cil/oc/common/tileentity/Computer.scala +++ b/li/cil/oc/common/tileentity/Computer.scala @@ -75,8 +75,7 @@ class Computer(isClient: Boolean) extends Rotatable with ComputerEnvironment wit // otherwise loose track of its screen). instance.update() if (isRunning && !node.changeBuffer(-Config.computerBaseCost)) { - // TODO try to print to screen? sound effect? particle effect? - println("not enough power, shutting down... ") + instance.lastError = "not enough power" turnOff() } if (hasChanged) { diff --git a/li/cil/oc/server/PacketSender.scala b/li/cil/oc/server/PacketSender.scala index 8eba1c3d3..46072134a 100644 --- a/li/cil/oc/server/PacketSender.scala +++ b/li/cil/oc/server/PacketSender.scala @@ -10,7 +10,15 @@ import net.minecraftforge.common.ForgeDirection /** Centralized packet dispatcher for sending updates to the client. */ object PacketSender { - def sendComputerState(t: TileEntity, value: Boolean, player: Option[Player] = None) = { + def sendClipboard(value: String, player: Player) { + val pb = new PacketBuilder(PacketType.Clipboard) + + pb.writeUTF(value) + + pb.sendToPlayer(player) + } + + def sendComputerState(t: TileEntity, value: Boolean, player: Option[Player] = None) { val pb = new PacketBuilder(PacketType.ComputerStateResponse) pb.writeTileEntity(t) @@ -22,7 +30,7 @@ object PacketSender { } } - def sendPowerState(t: PowerDistributor, player: Option[Player] = None) = { + def sendPowerState(t: PowerDistributor, player: Option[Player] = None) { val pb = new PacketBuilder(PacketType.PowerStateResponse) pb.writeTileEntity(t) @@ -34,7 +42,7 @@ object PacketSender { } } - def sendRedstoneState(t: TileEntity with Redstone, player: Option[Player] = None) = { + def sendRedstoneState(t: TileEntity with Redstone, player: Option[Player] = None) { val pb = new PacketBuilder(PacketType.RedstoneStateResponse) pb.writeTileEntity(t) @@ -49,7 +57,7 @@ object PacketSender { } } - def sendRotatableState(t: Rotatable, player: Option[Player] = None) = { + def sendRotatableState(t: Rotatable, player: Option[Player] = None) { val pb = new PacketBuilder(PacketType.RotatableStateResponse) pb.writeTileEntity(t) @@ -62,7 +70,7 @@ object PacketSender { } } - def sendScreenBufferState(t: TileEntity, w: Int, h: Int, text: String, player: Option[Player] = None) = { + def sendScreenBufferState(t: TileEntity, w: Int, h: Int, text: String, player: Option[Player] = None) { val pb = new PacketBuilder(PacketType.ScreenBufferResponse) pb.writeTileEntity(t) @@ -76,7 +84,7 @@ object PacketSender { } } - def sendScreenCopy(t: TileEntity, col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) = { + def sendScreenCopy(t: TileEntity, col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) { val pb = new PacketBuilder(PacketType.ScreenCopy) pb.writeTileEntity(t) @@ -90,7 +98,7 @@ object PacketSender { pb.sendToAllPlayers() } - def sendScreenFill(t: TileEntity, col: Int, row: Int, w: Int, h: Int, c: Char) = { + def sendScreenFill(t: TileEntity, col: Int, row: Int, w: Int, h: Int, c: Char) { val pb = new PacketBuilder(PacketType.ScreenFill) pb.writeTileEntity(t) @@ -103,7 +111,7 @@ object PacketSender { pb.sendToAllPlayers() } - def sendScreenResolutionChange(t: TileEntity, w: Int, h: Int) = { + def sendScreenResolutionChange(t: TileEntity, w: Int, h: Int) { val pb = new PacketBuilder(PacketType.ScreenResolutionChange) pb.writeTileEntity(t) @@ -113,7 +121,7 @@ object PacketSender { pb.sendToAllPlayers() } - def sendScreenSet(t: TileEntity, col: Int, row: Int, s: String) = { + def sendScreenSet(t: TileEntity, col: Int, row: Int, s: String) { val pb = new PacketBuilder(PacketType.ScreenSet) pb.writeTileEntity(t) diff --git a/li/cil/oc/server/component/Computer.scala b/li/cil/oc/server/component/Computer.scala index bd6593eb1..7c7272fbc 100644 --- a/li/cil/oc/server/component/Computer.scala +++ b/li/cil/oc/server/component/Computer.scala @@ -77,6 +77,10 @@ class Computer(val owner: Computer.Environment) extends Persistable with Runnabl lua.setTotalMemory(kernelMemory + owner.installedMemory) }) + def lastError = message + + def lastError_=(value: String) = message = Option(value) + // ----------------------------------------------------------------------- // def start() = state.synchronized(owner.node.network != null &&