From 2860d27c88dbe12d430dba1487790d243e2411d3 Mon Sep 17 00:00:00 2001 From: Simon Date: Thu, 7 Nov 2024 12:23:24 +0100 Subject: [PATCH 1/2] allow pausing a Princess-only game --- .../i18n/megamek/client/messages.properties | 4 + megamek/mmconf/defaultKeyBinds.xml | 167 ++++++++++-------- .../src/megamek/client/AbstractClient.java | 10 ++ .../ui/swing/StatusBarPhaseDisplay.java | 17 ++ .../client/ui/swing/util/KeyCommandBind.java | 4 +- .../common/net/enums/PacketCommand.java | 4 + megamek/src/megamek/server/Server.java | 31 +++- 7 files changed, 157 insertions(+), 80 deletions(-) diff --git a/megamek/i18n/megamek/client/messages.properties b/megamek/i18n/megamek/client/messages.properties index 4c96ba383f0..c6b459d8112 100644 --- a/megamek/i18n/megamek/client/messages.properties +++ b/megamek/i18n/megamek/client/messages.properties @@ -1972,6 +1972,10 @@ KeyBinds.cmdNames.undoSingleStep=Undo Single Step KeyBinds.cmdDesc.undoSingleStep=Undo single step in movement phase KeyBinds.cmdNames.extendTurnTimer=Activates Turn Timer Extension KeyBinds.cmdDesc.extendTurnTimer=When Turn Timer gets to 2 seconds left, reset timer. +KeyBinds.cmdNames.pause=Pause the Game +KeyBinds.cmdDesc.pause=Pauses the game. Works only when only Princess players with active units remain. +KeyBinds.cmdNames.unpause=Unpause the Game +KeyBinds.cmdDesc.unpause=Unpauses the game #Key Bindings Overlay KeyBindingsDisplay.fixedBinds=Toggle Unit Display and Minimap: Mouse Button 4\nZoom: Mouse Wheel\nTurn / Torso twist: Shift + Left-Click\nLine of Sight tool: Ctrl + Left-Click (two hexes)\nRuler tool: Alt + Left-Click (two hexes) diff --git a/megamek/mmconf/defaultKeyBinds.xml b/megamek/mmconf/defaultKeyBinds.xml index 2df36f7a237..9103c3086f8 100644 --- a/megamek/mmconf/defaultKeyBinds.xml +++ b/megamek/mmconf/defaultKeyBinds.xml @@ -1,494 +1,507 @@ - + - scrollN + scrollN 87 0 true - scrollS + scrollS 83 0 true - scrollE + scrollE 68 0 true - scrollW + scrollW 65 0 true - toggleChat + toggleChat 10 0 false - toggleChatCmd + toggleChatCmd 47 0 false - turnLeft + turnLeft 65 64 false - turnRight + turnRight 68 64 false - twistLeft + twistLeft 65 64 false - twistRight + twistRight 68 64 false - fire + fire 70 0 false - nextWeapon - 40 + nextWeapon + 521 0 false - prevWeapon - 38 + prevWeapon + 520 0 false - nextUnit + nextUnit 9 0 false - prevUnit + prevUnit 9 64 false - nextTarget + nextTarget 39 0 false - prevTarget + prevTarget 37 0 false - nextTargetValid + nextTargetValid 39 64 false - prevTargetValid + prevTargetValid 37 64 false - nextTargetNoAllies + nextTargetNoAllies 39 128 false - prevTargetNoAllies + prevTargetNoAllies 37 128 false - nextTargetValidNoAllies + nextTargetValidNoAllies 39 192 false - prevTargetValidNoAllies + prevTargetValidNoAllies 37 192 false - viewActingUnit + viewActingUnit 86 0 false - undoLastStep + undoLastStep 8 0 false - undo + undo 90 128 false - redo + redo 89 128 false - centerOnSelected + centerOnSelected 32 0 false - autoArtyDeployZone + autoArtyDeployZone 90 64 false - cancel + cancel 27 0 false - done + done 10 128 false - doneNoAction + doneNoAction 10 192 false - udGeneral + udGeneral 112 0 false - udPilot + udPilot 113 0 false - udArmor + udArmor 114 0 false - udSystems - 115 + udWeapons + 116 0 false - udWeapons - 116 + udSystems + 115 0 false - udExtras + udExtras 117 0 false - toggleJump + toggleJump 74 0 false - toggleConversion + toggleConversion 77 0 false - prevMode + prevMode 225 0 false - nextMode + nextMode 224 0 false - toggleIso + pause + 80 + 192 + false + + + + unpause + 80 + 640 + false + + + + toggleIso 84 0 false - movementEnvelope + movementEnvelope 81 128 false - fieldOfFire + fieldOfFire 82 0 false - toggleDrawLabels + toggleDrawLabels 66 128 false - toggleHexCoords + toggleHexCoords 71 128 false - toggleMinimap + toggleMinimap 77 128 false - viewLosSetting + viewLosSetting 76 640 false - toggleUnitDisplay + toggleUnitDisplay 68 128 false - toggleUnitOverview + toggleUnitOverview 85 128 false - toggleKeybinds + toggleKeybinds 75 128 false - togglePlanetaryConditions + togglePlanetaryConditions 80 128 false - toggleTurnDetails + toggleTurnDetails 84 128 false - clientSettings + clientSettings 67 512 false - incGuiScale + incGuiScale 107 128 false - decGuiScale + decGuiScale 109 128 false - roundReport + roundReport 82 128 false - zoomIn + zoomIn 107 0 false - zoomOut + zoomOut 109 0 false - quickLoad + quickLoad 76 192 false - quickSave + quickSave 83 192 false - localLoad + localLoad 76 128 false - localSave + localSave 83 128 false - replacePlayer + replacePlayer 82 192 false - viewModEnvelope + viewModEnvelope 87 128 false - sensorRange + sensorRange 67 0 false - undoSingleStep + undoSingleStep 8 128 false - toggleForceDisplay + toggleForceDisplay 70 128 false - extendTurnTimer + extendTurnTimer 115 128 false - + \ No newline at end of file diff --git a/megamek/src/megamek/client/AbstractClient.java b/megamek/src/megamek/client/AbstractClient.java index 6a30c1c5ace..4f944b39c4c 100644 --- a/megamek/src/megamek/client/AbstractClient.java +++ b/megamek/src/megamek/client/AbstractClient.java @@ -235,6 +235,16 @@ public synchronized void sendDone(boolean done) { flushConn(); } + public void sendPause() { + send(new Packet(PacketCommand.PAUSE)); + flushConn(); + } + + public void sendUnpause() { + send(new Packet(PacketCommand.UNPAUSE)); + flushConn(); + } + /** * Receives player information from the message packet. * diff --git a/megamek/src/megamek/client/ui/swing/StatusBarPhaseDisplay.java b/megamek/src/megamek/client/ui/swing/StatusBarPhaseDisplay.java index 1181c81be5a..00dfa989cd8 100644 --- a/megamek/src/megamek/client/ui/swing/StatusBarPhaseDisplay.java +++ b/megamek/src/megamek/client/ui/swing/StatusBarPhaseDisplay.java @@ -45,6 +45,7 @@ import javax.swing.ToolTipManager; import javax.swing.border.EmptyBorder; +import megamek.client.AbstractClient; import megamek.client.ui.GBC; import megamek.client.ui.Messages; import megamek.client.ui.swing.util.KeyBindReceiver; @@ -157,8 +158,24 @@ public void actionPerformed(ActionEvent e) { KeyBindParser.addPreferenceChangeListener(this); MegaMekGUI.getKeyDispatcher().registerCommandAction(KeyCommandBind.EXTEND_TURN_TIMER, this, this::extendTimer); + MegaMekGUI.getKeyDispatcher().registerCommandAction(KeyCommandBind.PAUSE.cmd, this::pauseGameWhenOnlyBotUnitsRemain); + MegaMekGUI.getKeyDispatcher().registerCommandAction(KeyCommandBind.UNPAUSE.cmd, + () -> ((AbstractClient) clientgui.getClient()).sendUnpause()); } + private void pauseGameWhenOnlyBotUnitsRemain() { + if (isIgnoringEvents() || !isVisible()) { + return; + } + IGame game = getClientgui().getClient().getGame(); + List nonBots = game.getPlayersList().stream().filter(p -> !p.isBot()).toList(); + boolean liveUnitsRemaining = nonBots.stream().anyMatch(p -> game.getEntitiesOwnedBy(p) > 0); + if (liveUnitsRemaining) { + clientgui.getClient().sendChat("Pausing the game only works when only bot units remain."); + } else { + ((AbstractClient) clientgui.getClient()).sendPause(); + } + } /** Returns the list of buttons that should be displayed. */ protected abstract List getButtonList(); diff --git a/megamek/src/megamek/client/ui/swing/util/KeyCommandBind.java b/megamek/src/megamek/client/ui/swing/util/KeyCommandBind.java index baf35a27737..2b0f54f4ac1 100644 --- a/megamek/src/megamek/client/ui/swing/util/KeyCommandBind.java +++ b/megamek/src/megamek/client/ui/swing/util/KeyCommandBind.java @@ -90,6 +90,8 @@ public enum KeyCommandBind { TOGGLE_CONVERSIONMODE("toggleConversion", VK_M), PREV_MODE("prevMode", VK_KP_DOWN), NEXT_MODE("nextMode", VK_KP_UP), + PAUSE("pause", VK_P, CTRL_DOWN_MASK | SHIFT_DOWN_MASK), + UNPAUSE("unpause", VK_P, CTRL_DOWN_MASK | ALT_DOWN_MASK), // --------- The following binds are used by the CommonMenuBar: // Toggles isometric view on/off @@ -218,4 +220,4 @@ public static String getDesc(KeyCommandBind k) { String key = getKeyText(k.key); return (mod.isEmpty() ? "" : mod + "+") + key; } -} \ No newline at end of file +} diff --git a/megamek/src/megamek/common/net/enums/PacketCommand.java b/megamek/src/megamek/common/net/enums/PacketCommand.java index 1b249ec1d58..3e37e6f71ad 100644 --- a/megamek/src/megamek/common/net/enums/PacketCommand.java +++ b/megamek/src/megamek/common/net/enums/PacketCommand.java @@ -44,6 +44,10 @@ public enum PacketCommand { /** A packet setting a Client's ready status (S -> C) or updating the Server on the Client's status (C -> S). */ PLAYER_READY, + /** A packet telling the server to pause / unpause packet handling (to interrupt a Princess-only game) */ + PAUSE, + UNPAUSE, + CHAT, ENTITY_ADD, ENTITY_REMOVE, diff --git a/megamek/src/megamek/server/Server.java b/megamek/src/megamek/server/Server.java index d62d8555e92..cc51549c8c2 100644 --- a/megamek/src/megamek/server/Server.java +++ b/megamek/src/megamek/server/Server.java @@ -209,6 +209,10 @@ public void run() { private static final String WARGAMES_RESPONSE = "Let's play global thermonuclear war."; private final ConnectionListener connectionListener = new ConnectionListener() { + + private boolean isPaused = false; + private final List pausedWaitingList = new ArrayList<>(); + /** * Called when it is sensed that a connection has terminated. */ @@ -252,11 +256,34 @@ public void packetReceived(PacketReceivedEvent e) { // Some packets should be handled immediately handle(rp.getConnectionId(), rp.getPacket()); break; - default: + case PAUSE: + if (!isPaused) { + logger.info("Pause packet received - pausing packet handling"); + sendServerChat("Game is paused."); + } + isPaused = true; + break; + case UNPAUSE: + if (isPaused) { + logger.info("Unpause packet received - resuming packet handling"); + sendServerChat("Game is resumed."); + } + isPaused = false; synchronized (packetQueue) { - packetQueue.add(rp); + packetQueue.addAll(pausedWaitingList); packetQueue.notifyAll(); } + pausedWaitingList.clear(); + break; + default: + if (isPaused) { + pausedWaitingList.add(rp); + } else { + synchronized (packetQueue) { + packetQueue.add(rp); + packetQueue.notifyAll(); + } + } break; } } From a58a77bcca3a6a5bf9d88172464b822f923bbbc4 Mon Sep 17 00:00:00 2001 From: Simon Date: Thu, 7 Nov 2024 12:46:59 +0100 Subject: [PATCH 2/2] defaultKeyBinds.xml correction, send immediate chat --- megamek/mmconf/defaultKeyBinds.xml | 181 +++++++++--------- .../ui/swing/StatusBarPhaseDisplay.java | 1 + 2 files changed, 92 insertions(+), 90 deletions(-) diff --git a/megamek/mmconf/defaultKeyBinds.xml b/megamek/mmconf/defaultKeyBinds.xml index 9103c3086f8..7b0ecbd7599 100644 --- a/megamek/mmconf/defaultKeyBinds.xml +++ b/megamek/mmconf/defaultKeyBinds.xml @@ -1,507 +1,508 @@ - + - scrollN + scrollN 87 0 true - scrollS + scrollS 83 0 true - scrollE + scrollE 68 0 true - scrollW + scrollW 65 0 true - toggleChat + toggleChat 10 0 false - toggleChatCmd + toggleChatCmd 47 0 false - turnLeft + turnLeft 65 64 false - turnRight + turnRight 68 64 false - twistLeft + twistLeft 65 64 false - twistRight + twistRight 68 64 false - fire + fire 70 0 false - nextWeapon - 521 + pause + 80 + 192 + false + + + + unpause + 80 + 640 + false + + + + nextWeapon + 40 0 false - prevWeapon - 520 + prevWeapon + 38 0 false - nextUnit + nextUnit 9 0 false - prevUnit + prevUnit 9 64 false - nextTarget + nextTarget 39 0 false - prevTarget + prevTarget 37 0 false - nextTargetValid + nextTargetValid 39 64 false - prevTargetValid + prevTargetValid 37 64 false - nextTargetNoAllies + nextTargetNoAllies 39 128 false - prevTargetNoAllies + prevTargetNoAllies 37 128 false - nextTargetValidNoAllies + nextTargetValidNoAllies 39 192 false - prevTargetValidNoAllies + prevTargetValidNoAllies 37 192 false - viewActingUnit + viewActingUnit 86 0 false - undoLastStep + undoLastStep 8 0 false - undo + undo 90 128 false - redo + redo 89 128 false - centerOnSelected + centerOnSelected 32 0 false - autoArtyDeployZone + autoArtyDeployZone 90 64 false - cancel + cancel 27 0 false - done + done 10 128 false - doneNoAction + doneNoAction 10 192 false - udGeneral + udGeneral 112 0 false - udPilot + udPilot 113 0 false - udArmor + udArmor 114 0 false - udWeapons - 116 + udSystems + 115 0 false - udSystems - 115 + udWeapons + 116 0 false - udExtras + udExtras 117 0 false - toggleJump + toggleJump 74 0 false - toggleConversion + toggleConversion 77 0 false - prevMode + prevMode 225 0 false - nextMode + nextMode 224 0 false - pause - 80 - 192 - false - - - - unpause - 80 - 640 - false - - - - toggleIso + toggleIso 84 0 false - movementEnvelope + movementEnvelope 81 128 false - fieldOfFire + fieldOfFire 82 0 false - toggleDrawLabels + toggleDrawLabels 66 128 false - toggleHexCoords + toggleHexCoords 71 128 false - toggleMinimap + toggleMinimap 77 128 false - viewLosSetting + viewLosSetting 76 640 false - toggleUnitDisplay + toggleUnitDisplay 68 128 false - toggleUnitOverview + toggleUnitOverview 85 128 false - toggleKeybinds + toggleKeybinds 75 128 false - togglePlanetaryConditions + togglePlanetaryConditions 80 128 false - toggleTurnDetails + toggleTurnDetails 84 128 false - clientSettings + clientSettings 67 512 false - incGuiScale + incGuiScale 107 128 false - decGuiScale + decGuiScale 109 128 false - roundReport + roundReport 82 128 false - zoomIn + zoomIn 107 0 false - zoomOut + zoomOut 109 0 false - quickLoad + quickLoad 76 192 false - quickSave + quickSave 83 192 false - localLoad + localLoad 76 128 false - localSave + localSave 83 128 false - replacePlayer + replacePlayer 82 192 false - viewModEnvelope + viewModEnvelope 87 128 false - sensorRange + sensorRange 67 0 false - undoSingleStep + undoSingleStep 8 128 false - toggleForceDisplay + toggleForceDisplay 70 128 false - extendTurnTimer + extendTurnTimer 115 128 false - \ No newline at end of file + diff --git a/megamek/src/megamek/client/ui/swing/StatusBarPhaseDisplay.java b/megamek/src/megamek/client/ui/swing/StatusBarPhaseDisplay.java index 00dfa989cd8..a0590743f68 100644 --- a/megamek/src/megamek/client/ui/swing/StatusBarPhaseDisplay.java +++ b/megamek/src/megamek/client/ui/swing/StatusBarPhaseDisplay.java @@ -173,6 +173,7 @@ private void pauseGameWhenOnlyBotUnitsRemain() { if (liveUnitsRemaining) { clientgui.getClient().sendChat("Pausing the game only works when only bot units remain."); } else { + clientgui.getClient().sendChat("Requesting game pause."); ((AbstractClient) clientgui.getClient()).sendPause(); } }