Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow pausing a Princess-only game #6186

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions megamek/i18n/megamek/client/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
16 changes: 15 additions & 1 deletion megamek/mmconf/defaultKeyBinds.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<KeyBindings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="keyBindingSchema.xsd">
xsi:noNamespaceSchemaLocation="keyBindingSchema.xsd">
<KeyBind>
<command>scrollN</command> <!-- W -->
<keyCode>87</keyCode>
Expand Down Expand Up @@ -78,6 +78,20 @@
<isRepeatable>false</isRepeatable>
</KeyBind>

<KeyBind>
<command>pause</command> <!-- Ctrl+Shift-P -->
<keyCode>80</keyCode>
<modifier>192</modifier>
<isRepeatable>false</isRepeatable>
</KeyBind>

<KeyBind>
<command>unpause</command> <!-- Ctrl+Alt-P -->
<keyCode>80</keyCode>
<modifier>640</modifier>
<isRepeatable>false</isRepeatable>
</KeyBind>

<KeyBind>
<command>nextWeapon</command> <!-- Down -->
<keyCode>40</keyCode>
Expand Down
10 changes: 10 additions & 0 deletions megamek/src/megamek/client/AbstractClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
18 changes: 18 additions & 0 deletions megamek/src/megamek/client/ui/swing/StatusBarPhaseDisplay.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -157,8 +158,25 @@ 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<Player> 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 {
clientgui.getClient().sendChat("Requesting game pause.");
((AbstractClient) clientgui.getClient()).sendPause();
}
}

/** Returns the list of buttons that should be displayed. */
protected abstract List<MegaMekButton> getButtonList();
Expand Down
4 changes: 3 additions & 1 deletion megamek/src/megamek/client/ui/swing/util/KeyCommandBind.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -218,4 +220,4 @@ public static String getDesc(KeyCommandBind k) {
String key = getKeyText(k.key);
return (mod.isEmpty() ? "" : mod + "+") + key;
}
}
}
4 changes: 4 additions & 0 deletions megamek/src/megamek/common/net/enums/PacketCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
31 changes: 29 additions & 2 deletions megamek/src/megamek/server/Server.java
Original file line number Diff line number Diff line change
Expand Up @@ -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<ReceivedPacket> pausedWaitingList = new ArrayList<>();

/**
* Called when it is sensed that a connection has terminated.
*/
Expand Down Expand Up @@ -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;
}
}
Expand Down