Skip to content

Commit

Permalink
feat: new GM commands and client commands
Browse files Browse the repository at this point in the history
  • Loading branch information
Scoppio committed Dec 4, 2024
1 parent 65a4651 commit 40186e2
Show file tree
Hide file tree
Showing 34 changed files with 994 additions and 280 deletions.
19 changes: 19 additions & 0 deletions megamek/i18n/megamek/client/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4755,10 +4755,29 @@ Gamemaster.cmd.orbitalbombardment.success=Orbital bombardment incoming!
Gamemaster.cmd.firefight.longName=Firefight
Gamemaster.cmd.firefight.reason=Fire extinguished
Gamemaster.cmd.firefight.help=Extinguishes a fire on the board.

# No Fire
Gamemaster.cmd.nofire.longName=No Fires
Gamemaster.cmd.nofire.help=Extinguishes all fires on the board.

# Change player team
Gamemaster.cmd.changeteam.help=Changes the team of a player.
Gamemaster.cmd.changeteam.longName=Change Player Team
Gamemaster.cmd.changeteam.playerNotFound=No such player.
Gamemaster.cmd.changeteam.success=Player {0} has been moved to team {1}.
Gamemaster.cmd.changeteam.playerID=ID of the player to change team.
Gamemaster.cmd.changeteam.teamID=ID of the team to move the player to.
Gamemaster.cmd.changeteam.playerCantJoinUnassigned=Player must have no more units to join the unassigned team!

# End game
Gamemaster.cmd.endgame.success=This is the end of the game
Gamemaster.cmd.endgame.force=Force the game to finish before the end of the round
Gamemaster.cmd.endgame.help=Ends the game, declaring one player the winner. If the player is part of a team then their team wins.
Gamemaster.cmd.endgame.playerID=ID of the player to win the game, or whose team is to be declared winner.
Gamemaster.cmd.endgame.longName=End Game
Gamemaster.cmd.endgame.playerNotFound=No such player.


# Orbital Bombardment text
OrbitalBombardment.source=Unknown warship in orbit
OrbitalBombardment.hitOnRound=Orbital bombardment incoming, hit on round {0}
Expand Down
27 changes: 19 additions & 8 deletions megamek/src/megamek/client/ui/swing/MapMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import megamek.client.bot.princess.CardinalEdge;
import megamek.client.event.BoardViewEvent;
import megamek.client.ui.Messages;
import megamek.client.ui.swing.gmCommands.GamemasterCommandPanel;
import megamek.client.ui.swing.commands.ClientCommandPanel;
import megamek.client.ui.swing.lobby.LobbyUtility;
import megamek.common.*;
import megamek.common.Building.DemolitionCharge;
Expand Down Expand Up @@ -630,7 +630,7 @@ JMenuItem createTargetHexMenuItem(Player bot) {
/**
* Create various menus related to GameMaster (GM) mode
*
* @return
* @return JMenu
*/
private JMenu createGamemasterMenu() {
JMenu menu = new JMenu(Messages.getString("Gamemaster.Gamemaster"));
Expand Down Expand Up @@ -679,21 +679,32 @@ private JMenu createGamemasterMenu() {
*/
private JMenu createGMSpecialCommandsMenu() {
JMenu menu = new JMenu(Messages.getString("Gamemaster.SpecialCommands"));

var nukesAllowed = client.getGame().getOptions().booleanOption(OptionsConstants.ALLOWED_REALLY_ALLOW_NUKES)
&& client.getGame().getOptions().booleanOption(OptionsConstants.ALLOWED_ALLOW_NUKES);

List.of(
new ChangeOwnershipCommand(null, null),
new ChangeWeatherCommand(null, null),
new DisasterCommand(null, null),
new ChangeTeamCommand(null, null),
new ChangeOwnershipCommand(null, null),
new KillCommand(null, null),
new FirefightCommand(null, null),
new RescueCommand(null, null),
new FirestarterCommand(null, null),
new FirestormCommand(null, null),
new FirefightCommand(null, null),
new NoFiresCommand(null, null),
new OrbitalBombardmentCommand(null, null),
new RemoveSmokeCommand(null, null),
new RescueCommand(null, null)
new OrbitalBombardmentCommand(null, null),
new DisasterCommand(null, null),
new NukeCommand(null, null),
new EndGameCommand(null, null)
).forEach(cmd -> {
JMenuItem item = new JMenuItem(cmd.getLongName());
item.addActionListener(evt -> new GamemasterCommandPanel(gui.getFrame(), gui, cmd, coords).setVisible(true));
if (cmd instanceof NukeCommand) {
item.setEnabled(nukesAllowed);
}
item.addActionListener(evt -> new ClientCommandPanel(gui.getFrame(), gui, cmd, coords).setVisible(true));

menu.add(item);
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
package megamek.client.ui.swing.gmCommands;
package megamek.client.ui.swing.commands;

import megamek.client.ui.swing.ClientGUI;
import megamek.common.Coords;
import megamek.common.annotations.Nullable;
import megamek.server.commands.GamemasterServerCommand;
import megamek.server.commands.arguments.Argument;
import megamek.server.commands.arguments.EnumArgument;
import megamek.server.commands.arguments.IntegerArgument;
import megamek.server.commands.arguments.OptionalEnumArgument;
import megamek.server.commands.ClientServerCommand;
import megamek.server.commands.arguments.*;

import javax.swing.*;
import java.awt.*;
Expand All @@ -17,21 +14,21 @@
import java.util.Objects;

/**
* Dialog for executing a gamemaster command.
* Dialog for executing a client command.
*/
public class GamemasterCommandPanel extends JDialog {
private final GamemasterServerCommand command;
public class ClientCommandPanel extends JDialog {
private final ClientServerCommand command;
private final ClientGUI client;
private final Coords coords;

/**
* Constructor for the dialog for executing a gamemaster command.
* Constructor for the dialog for executing a client command.
*
* @param parent The parent frame.
* @param client The client GUI.
* @param command The command to render.
*/
public GamemasterCommandPanel(JFrame parent, ClientGUI client, GamemasterServerCommand command, @Nullable Coords coords) {
public ClientCommandPanel(JFrame parent, ClientGUI client, ClientServerCommand command, @Nullable Coords coords) {
super(parent, command.getName(), true);
this.command = command;
this.client = client;
Expand Down Expand Up @@ -88,6 +85,10 @@ private JComponent getArgumentComponent(Argument<?> argument, JPanel argumentPan
JSpinner spinner = createSpinner(intArg);
argumentPanel.add(spinner);
return spinner;
} else if (argument instanceof OptionalIntegerArgument intArg) {
JSpinner spinner = createSpinner(intArg);
argumentPanel.add(spinner);
return spinner;
} else if (argument instanceof OptionalEnumArgument<?> enumArg) {
JComboBox<String> comboBox = createOptionalEnumComboBox(enumArg);
argumentPanel.add(comboBox);
Expand All @@ -96,6 +97,31 @@ private JComponent getArgumentComponent(Argument<?> argument, JPanel argumentPan
JComboBox<String> comboBox = createEnumComboBox(enumArg);
argumentPanel.add(comboBox);
return comboBox;
} else if (argument instanceof OptionalPasswordArgument) {
JPasswordField passwordField = new JPasswordField();
argumentPanel.add(passwordField);
return passwordField;
} else if (argument instanceof StringArgument stringArg) {
JTextField textField = new JTextField();
if (stringArg.hasDefaultValue()) {
textField.setText(stringArg.getValue());
}
argumentPanel.add(textField);
return textField;
} else if (argument instanceof OptionalStringArgument stringArg) {
JTextField textField = new JTextField();
if (stringArg.getValue().isPresent()) {
textField.setText(stringArg.getValue().get());
}
argumentPanel.add(textField);
return textField;
} else if (argument instanceof BooleanArgument boolArg) {
JCheckBox checkBox = new JCheckBox();
if (boolArg.hasDefaultValue()) {
checkBox.setSelected(boolArg.getValue());
}
argumentPanel.add(checkBox);
return checkBox;
}
return null;
}
Expand All @@ -113,6 +139,14 @@ private int getIntArgumentDefaultValue(IntegerArgument intArg) {
isArgumentY(intArg) ? coords.getY()+1 : 0;
}

private JSpinner createSpinner(OptionalIntegerArgument intArg) {
return new JSpinner(new SpinnerNumberModel(
(int) intArg.getValue().orElse(0),
intArg.getMinValue(),
intArg.getMaxValue(),
1));
}

private JSpinner createSpinner(IntegerArgument intArg) {
return new JSpinner(new SpinnerNumberModel(
getIntArgumentDefaultValue(intArg),
Expand Down Expand Up @@ -184,6 +218,12 @@ private void executeCommand(Map<String, JComponent> argumentComponents) {

if (component instanceof JSpinner) {
args[i] = argument.getName() + "=" + ((JSpinner) component).getValue().toString();
} else if (component instanceof JPasswordField) {
args[i] = argument.getName() + "=" + new String(((JPasswordField) component).getPassword());
} else if (component instanceof JTextField) {
args[i] = argument.getName() + "=" + ((JTextField) component).getText();
} else if (component instanceof JCheckBox) {
args[i] = argument.getName() + "=" + (((JCheckBox) component).isSelected() ? "true" : "false");
} else if (component instanceof JComboBox) {
if (argument instanceof OptionalEnumArgument<?>) {
String selectedItem = (String) ((JComboBox<?>) component).getSelectedItem();
Expand Down
44 changes: 37 additions & 7 deletions megamek/src/megamek/common/Game.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ public final class Game extends AbstractGame implements Serializable, PlanetaryC
private final GameReports gameReports = new GameReports();

private boolean forceVictory = false;
private boolean endImmediately = false;
private boolean ignorePlayerDefeatVotes = false;
private int victoryPlayerId = Player.PLAYER_NONE;
private int victoryTeam = Player.TEAM_NONE;

Expand Down Expand Up @@ -2528,13 +2530,6 @@ public void setRoundCount(int roundCount) {
setCurrentRound(roundCount);
}

/**
* Increments the round counter
*/
public void incrementRoundCount() {
incrementCurrentRound();
}

/**
* Getter for property forceVictory. This tells us that there is an active claim
* for victory.
Expand All @@ -2546,6 +2541,24 @@ public boolean isForceVictory() {
return forceVictory;
}

/**
* Getter for property ignorePlayerDefeatVotes.
* @return Value of property ignorePlayerDefeatVotes.
*/
public boolean isIgnorePlayerDefeatVotes() {
return ignorePlayerDefeatVotes;
}

/**
* Getter for property endImmediately. This tells us that the game should end even if it is not the end of the round in a
* forced victory
*
* @return Value of property endImmediately.
*/
public boolean isEndImmediately() {
return endImmediately;
}

/**
* Setter for property forceVictory.
*
Expand All @@ -2555,6 +2568,23 @@ public void setForceVictory(boolean forceVictory) {
this.forceVictory = forceVictory;
}

/**
* Setter for property endImmediately.
*
* @param endImmediately New value of property endImmediately.
*/
public void setEndImmediately(boolean endImmediately) {
this.endImmediately = endImmediately;
}

/**
* Setter for property ignorePlayerDefeatVotes.
* @param ignorePlayerDefeatVotes New value of property ignorePlayerDefeatVotes.
*/
public void setIgnorePlayerDefeatVotes(boolean ignorePlayerDefeatVotes) {
this.ignorePlayerDefeatVotes = ignorePlayerDefeatVotes;
}

/**
* Adds the given reports vector to the GameReport collection.
*
Expand Down
2 changes: 2 additions & 0 deletions megamek/src/megamek/server/IGameManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ default void saveGame(String fileName) {

void requestTeamChange(int teamId, Player player);

void requestTeamChangeForPlayer(int teamID, Player player);

List<ServerCommand> getCommandList(Server server);

void addReport(ReportEntry r);
Expand Down
15 changes: 15 additions & 0 deletions megamek/src/megamek/server/Server.java
Original file line number Diff line number Diff line change
Expand Up @@ -1183,10 +1183,25 @@ private void transmitAllPlayerUpdates() {
}
}

/**
* Player can request its own change of team
* @param teamId target team id
* @param player player requesting the change
* @deprecated Planned to be removed. Use {@link #requestTeamChangeForPlayer(int, Player)} instead.
*/
public void requestTeamChange(int teamId, Player player) {
gameManager.requestTeamChange(teamId, player);
}

/**
* Player can request its own change of team
* @param teamID target team id
* @param player player requesting the change
*/
public void requestTeamChangeForPlayer(int teamID, Player player) {
gameManager.requestTeamChangeForPlayer(teamID, player);
}

public void requestGameMaster(Player player) {
gameManager.requestGameMaster(player);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import megamek.common.Player;
import megamek.server.Server;
import megamek.server.commands.arguments.Argument;
import megamek.server.commands.arguments.Arguments;
import megamek.server.commands.arguments.IntegerArgument;
import megamek.server.totalwarfare.TWGameManager;

Expand Down Expand Up @@ -50,7 +51,7 @@ public List<Argument<?>> defineArguments() {
}

@Override
protected void runAsGM(int connId, Map<String, Argument<?>> args) {
protected void runCommand(int connId, Arguments args) {
IntegerArgument unitID = (IntegerArgument) args.get(UNIT_ID);
IntegerArgument playerID = (IntegerArgument) args.get(PLAYER_ID);

Expand Down
Loading

0 comments on commit 40186e2

Please sign in to comment.