diff --git a/src/main/resources/assets/opencomputers/lang/de_DE.lang b/src/main/resources/assets/opencomputers/lang/de_DE.lang index 9b02842bf..7d9e90687 100644 --- a/src/main/resources/assets/opencomputers/lang/de_DE.lang +++ b/src/main/resources/assets/opencomputers/lang/de_DE.lang @@ -146,6 +146,8 @@ oc:gui.ServerRack.Bottom=Unten oc:gui.ServerRack.Left=Links oc:gui.ServerRack.Right=Rechts oc:gui.ServerRack.Top=Oben +oc:gui.ServerRack.SwitchExternal=Extern +oc:gui.ServerRack.SwitchInternal=Intern oc:gui.ServerRack.WirelessRange=Reichweite oc:gui.Switch.TransferRate=Taktung oc:gui.Switch.PacketsPerCycle=Pakete / Zyklus diff --git a/src/main/resources/assets/opencomputers/lang/en_US.lang b/src/main/resources/assets/opencomputers/lang/en_US.lang index 1e402f0b5..8fbd9d6be 100644 --- a/src/main/resources/assets/opencomputers/lang/en_US.lang +++ b/src/main/resources/assets/opencomputers/lang/en_US.lang @@ -147,6 +147,8 @@ oc:gui.ServerRack.Bottom=Bottom oc:gui.ServerRack.Left=Left oc:gui.ServerRack.Right=Right oc:gui.ServerRack.Top=Top +oc:gui.ServerRack.SwitchExternal=External +oc:gui.ServerRack.SwitchInternal=Internal oc:gui.ServerRack.WirelessRange=Range oc:gui.Switch.TransferRate=Cycle rate oc:gui.Switch.PacketsPerCycle=Packets / cycle diff --git a/src/main/resources/assets/opencomputers/textures/gui/button_switch.png b/src/main/resources/assets/opencomputers/textures/gui/button_switch.png new file mode 100644 index 000000000..4b88de9f7 Binary files /dev/null and b/src/main/resources/assets/opencomputers/textures/gui/button_switch.png differ diff --git a/src/main/scala/li/cil/oc/Localization.scala b/src/main/scala/li/cil/oc/Localization.scala index ac003ea40..0787b0d59 100644 --- a/src/main/scala/li/cil/oc/Localization.scala +++ b/src/main/scala/li/cil/oc/Localization.scala @@ -93,6 +93,10 @@ object Localization { def None = localizeImmediately("gui.ServerRack.None") + def SwitchExternal = localizeImmediately("gui.ServerRack.SwitchExternal") + + def SwitchInternal = localizeImmediately("gui.ServerRack.SwitchInternal") + def WirelessRange = localizeImmediately("gui.ServerRack.WirelessRange") } diff --git a/src/main/scala/li/cil/oc/client/PacketSender.scala b/src/main/scala/li/cil/oc/client/PacketSender.scala index 4e777a4a8..a6153667a 100644 --- a/src/main/scala/li/cil/oc/client/PacketSender.scala +++ b/src/main/scala/li/cil/oc/client/PacketSender.scala @@ -154,4 +154,13 @@ object PacketSender { pb.sendToServer() } + + def sendServerSwitchMode(t: ServerRack, internal: Boolean) { + val pb = new PacketBuilder(PacketType.ServerSwitchMode) + + pb.writeTileEntity(t) + pb.writeBoolean(internal) + + pb.sendToServer() + } } \ No newline at end of file diff --git a/src/main/scala/li/cil/oc/client/Textures.scala b/src/main/scala/li/cil/oc/client/Textures.scala index 8301d72b0..5e0ea01d0 100644 --- a/src/main/scala/li/cil/oc/client/Textures.scala +++ b/src/main/scala/li/cil/oc/client/Textures.scala @@ -16,6 +16,7 @@ object Textures extends ResourceManagerReloadListener { val guiButtonRun = new ResourceLocation(Settings.resourceDomain, "textures/gui/button_run.png") val guiButtonScroll = new ResourceLocation(Settings.resourceDomain, "textures/gui/button_scroll.png") val guiButtonSide = new ResourceLocation(Settings.resourceDomain, "textures/gui/button_side.png") + val guiButtonSwitch = new ResourceLocation(Settings.resourceDomain, "textures/gui/button_switch.png") val guiComputer = new ResourceLocation(Settings.resourceDomain, "textures/gui/computer.png") val guiDisassembler = new ResourceLocation(Settings.resourceDomain, "textures/gui/disassembler.png") val guiKeyboardMissing = new ResourceLocation(Settings.resourceDomain, "textures/gui/keyboard_missing.png") diff --git a/src/main/scala/li/cil/oc/client/gui/ImageButton.scala b/src/main/scala/li/cil/oc/client/gui/ImageButton.scala index a6de183be..8f5d9c705 100644 --- a/src/main/scala/li/cil/oc/client/gui/ImageButton.scala +++ b/src/main/scala/li/cil/oc/client/gui/ImageButton.scala @@ -13,7 +13,8 @@ class ImageButton(id: Int, x: Int, y: Int, w: Int, h: Int, val canToggle: Boolean = false, val textColor: Int = 0xE0E0E0, val textDisabledColor: Int = 0xA0A0A0, - val textHoverColor: Int = 0xFFFFA0) extends GuiButton(id, x, y, w, h, text) { + val textHoverColor: Int = 0xFFFFA0, + val textIndent: Int = -1) extends GuiButton(id, x, y, w, h, text) { var toggled = false @@ -48,7 +49,8 @@ class ImageButton(id: Int, x: Int, y: Int, w: Int, h: Int, if (!enabled) textDisabledColor else if (hoverOverride || field_82253_i) textHoverColor else textColor - drawCenteredString(mc.fontRenderer, displayString, xPosition + width / 2, yPosition + (height - 8) / 2, color) + if (textIndent >= 0) drawString(mc.fontRenderer, displayString, textIndent + xPosition, yPosition + (height - 8) / 2, color) + else drawCenteredString(mc.fontRenderer, displayString, xPosition + width / 2, yPosition + (height - 8) / 2, color) } } } diff --git a/src/main/scala/li/cil/oc/client/gui/ServerRack.scala b/src/main/scala/li/cil/oc/client/gui/ServerRack.scala index 060dab34e..627f3d77e 100644 --- a/src/main/scala/li/cil/oc/client/gui/ServerRack.scala +++ b/src/main/scala/li/cil/oc/client/gui/ServerRack.scala @@ -13,6 +13,8 @@ import net.minecraftforge.common.ForgeDirection import org.lwjgl.opengl.GL11 class ServerRack(playerInventory: InventoryPlayer, val rack: tileentity.ServerRack) extends DynamicGuiContainer(new container.ServerRack(playerInventory, rack)) { + protected var switchButton: ImageButton = _ + protected var powerButtons = new Array[ImageButton](4) protected var sideButtons = new Array[GuiButton](4) @@ -57,6 +59,9 @@ class ServerRack(playerInventory: InventoryPlayer, val rack: tileentity.ServerRa ClientPacketSender.sendServerRange(rack, range) } } + if (button.id == 10) { + ClientPacketSender.sendServerSwitchMode(rack, !rack.internalSwitch) + } } override def drawScreen(mouseX: Int, mouseY: Int, dt: Float) { @@ -64,6 +69,7 @@ class ServerRack(playerInventory: InventoryPlayer, val rack: tileentity.ServerRa powerButtons(i).toggled = rack.isRunning(i) sideButtons(i).displayString = sideName(i) } + switchButton.displayString = if (rack.internalSwitch) Localization.ServerRack.SwitchInternal else Localization.ServerRack.SwitchExternal super.drawScreen(mouseX, mouseY, dt) } @@ -78,9 +84,11 @@ class ServerRack(playerInventory: InventoryPlayer, val rack: tileentity.ServerRa add(buttonList, sideButtons(i)) } for (i <- 0 to 1) { - rangeButtons(i) = new ImageButton(8 + i, guiLeft + 8 + i * 48, guiTop + 43, 16, 18, Textures.guiButtonRange, if (i == 0) "-" else "+") + rangeButtons(i) = new ImageButton(8 + i, guiLeft + 8 + i * 48, guiTop + 50, 16, 18, Textures.guiButtonRange, if (i == 0) "-" else "+") add(buttonList, rangeButtons(i)) } + switchButton = new ImageButton(10, guiLeft + 8, guiTop + 17, 64, 18, Textures.guiButtonSwitch, Localization.ServerRack.SwitchExternal, textIndent = 18) + add(buttonList, switchButton) } override def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) = { @@ -91,12 +99,13 @@ class ServerRack(playerInventory: InventoryPlayer, val rack: tileentity.ServerRa StatCollector.translateToLocal(rack.getInvName), 8, 6, 0x404040) - fontRenderer.drawString(Localization.ServerRack.WirelessRange, 8, 31, 0x404040) + val rangeY = 39 + fontRenderer.drawString(Localization.ServerRack.WirelessRange, 8, rangeY, 0x404040) { // Background for range value. val tx = 25 - val ty = 43 + val ty = 50 val w = 30 val h = 18 val t = Tessellator.instance @@ -114,7 +123,7 @@ class ServerRack(playerInventory: InventoryPlayer, val rack: tileentity.ServerRa drawCenteredString(fontRenderer, rack.range.toString, - 40, 48, 0xFFFFFF) + 40, 56, 0xFFFFFF) for (i <- 0 to 3 if powerButtons(i).func_82252_a) { val tooltip = new java.util.ArrayList[String] diff --git a/src/main/scala/li/cil/oc/common/PacketType.scala b/src/main/scala/li/cil/oc/common/PacketType.scala index 80f5c9ec5..7e4589d57 100644 --- a/src/main/scala/li/cil/oc/common/PacketType.scala +++ b/src/main/scala/li/cil/oc/common/PacketType.scala @@ -49,6 +49,9 @@ object PacketType extends Enumeration { MultiPartPlace, RobotAssemblerStart, RobotStateRequest, + ServerRange, ServerSide, - ServerRange = Value + ServerSwitchMode, + + EndOfList = Value } \ No newline at end of file diff --git a/src/main/scala/li/cil/oc/common/container/ServerRack.scala b/src/main/scala/li/cil/oc/common/container/ServerRack.scala index b3ed24129..3608533ef 100644 --- a/src/main/scala/li/cil/oc/common/container/ServerRack.scala +++ b/src/main/scala/li/cil/oc/common/container/ServerRack.scala @@ -1,6 +1,8 @@ package li.cil.oc.common.container +import cpw.mods.fml.relauncher.{Side, SideOnly} import li.cil.oc.common.tileentity +import li.cil.oc.util.SideTracker import net.minecraft.entity.player.InventoryPlayer class ServerRack(playerInventory: InventoryPlayer, rack: tileentity.ServerRack) extends Player(playerInventory, rack) { @@ -9,4 +11,23 @@ class ServerRack(playerInventory: InventoryPlayer, rack: tileentity.ServerRack) addSlotToContainer(106, 44) addSlotToContainer(106, 62) addPlayerInventorySlots(8, 84) + + var lastSentSwitchMode = !rack.internalSwitch + + @SideOnly(Side.CLIENT) + override def updateProgressBar(id: Int, value: Int) { + if (id == 0) { + rack.internalSwitch = value == 1 + } + } + + override def detectAndSendChanges() { + super.detectAndSendChanges() + if (SideTracker.isServer) { + if (lastSentSwitchMode != rack.internalSwitch) { + lastSentSwitchMode = rack.internalSwitch + sendProgressBarUpdate(0, if (lastSentSwitchMode) 1 else 0) + } + } + } } diff --git a/src/main/scala/li/cil/oc/common/tileentity/ServerRack.scala b/src/main/scala/li/cil/oc/common/tileentity/ServerRack.scala index 55249bc1c..97691a38c 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/ServerRack.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/ServerRack.scala @@ -7,7 +7,7 @@ import cpw.mods.fml.common.Optional.Method import cpw.mods.fml.relauncher.{Side, SideOnly} import li.cil.oc._ import li.cil.oc.api.Network -import li.cil.oc.api.network.{Analyzable, Connector, Node, Visibility} +import li.cil.oc.api.network._ import li.cil.oc.client.Sound import li.cil.oc.server.{component, driver, PacketSender => ServerPacketSender} import li.cil.oc.util.ExtendedNBT._ @@ -39,6 +39,8 @@ class ServerRack extends traits.PowerAcceptor with traits.Hub with traits.PowerB private var hasChanged = false + var internalSwitch = false + // For client side rendering. var isPresent = Array.fill[Option[String]](getSizeInventory)(None) @@ -143,6 +145,33 @@ class ServerRack extends traits.PowerAcceptor with traits.Hub with traits.PowerB // ----------------------------------------------------------------------- // + override protected def relayPacket(sourceSide: ForgeDirection, packet: Packet) { + if (internalSwitch) { + for (slot <- 0 until servers.length) { + val side = sides(slot) + if (side != sourceSide) { + servers(slot) match { + case Some(server) => server.node.sendToNeighbors("network.message", packet) + case _ => + } + } + } + } + else super.relayPacket(sourceSide, packet) + } + + override protected def onPlugMessage(plug: Plug, message: Message) { + // This check is a little hacky. Basically what we test here is whether + // the message was relayed internally, because only internally relayed + // network messages originate from the actual server nodes themselves. + // The otherwise come from the network card. + if (message.name != "network.message" || !(servers collect { + case Some(server) => server.node + }).contains(message.source)) super.onPlugMessage(plug, message) + } + + // ----------------------------------------------------------------------- // + override def getSizeInventory = 4 override def getInventoryStackLimit = 1 @@ -260,6 +289,7 @@ class ServerRack extends traits.PowerAcceptor with traits.Hub with traits.PowerB } } range = nbt.getInteger(Settings.namespace + "range") + internalSwitch = nbt.getBoolean(Settings.namespace + "internalSwitch") } // Side check for Waila (and other mods that may call this client side). @@ -285,6 +315,7 @@ class ServerRack extends traits.PowerAcceptor with traits.Hub with traits.PowerB terminalNbt })) nbt.setInteger(Settings.namespace + "range", range) + nbt.setBoolean(Settings.namespace + "internalSwitch", internalSwitch) } @SideOnly(Side.CLIENT) diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/Hub.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/Hub.scala index d1d807a9e..85b279baa 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/traits/Hub.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/traits/Hub.scala @@ -78,7 +78,7 @@ trait Hub extends traits.Environment with SidedEnvironment { } protected def tryEnqueuePacket(sourceSide: ForgeDirection, packet: Packet) = queue.synchronized { - if (packet.ttl > 0 && queue.size < maxQueueSize && !plugs.exists(_.node.address == packet.source)) { + if (packet.ttl > 0 && queue.size < maxQueueSize) { queue += sourceSide -> packet.hop() if (relayCooldown < 0) { relayCooldown = relayDelay @@ -156,7 +156,7 @@ trait Hub extends traits.Environment with SidedEnvironment { protected def onPlugDisconnect(plug: Plug, node: Node) {} protected def onPlugMessage(plug: Plug, message: Message) { - if (message.name == "network.message") message.data match { + if (message.name == "network.message" && !plugs.exists(_.node == message.source)) message.data match { case Array(packet: Packet) => tryEnqueuePacket(plug.side, packet) case _ => } diff --git a/src/main/scala/li/cil/oc/server/PacketHandler.scala b/src/main/scala/li/cil/oc/server/PacketHandler.scala index 2ba677956..9029d3172 100644 --- a/src/main/scala/li/cil/oc/server/PacketHandler.scala +++ b/src/main/scala/li/cil/oc/server/PacketHandler.scala @@ -30,6 +30,7 @@ class PacketHandler extends CommonPacketHandler { case PacketType.RobotStateRequest => onRobotStateRequest(p) case PacketType.ServerRange => onServerRange(p) case PacketType.ServerSide => onServerSide(p) + case PacketType.ServerSwitchMode => onServerSwitchMode(p) case _ => // Invalid packet. } @@ -177,4 +178,14 @@ class PacketHandler extends CommonPacketHandler { } case _ => // Invalid packet. } + + def onServerSwitchMode(p: PacketParser) = + p.readTileEntity[ServerRack]() match { + case Some(rack) => p.player match { + case player: EntityPlayerMP if rack.isUseableByPlayer(player) => + rack.internalSwitch = p.readBoolean() + case _ => + } + case _ => // Invalid packet. + } } \ No newline at end of file