Skip to content

Commit

Permalink
feat: update server commands for gm
Browse files Browse the repository at this point in the history
  • Loading branch information
Scoppio committed Nov 15, 2024
2 parents 36b6b37 + 02e9645 commit 1117d85
Show file tree
Hide file tree
Showing 25 changed files with 570 additions and 375 deletions.
Binary file added megamek/data/images/hexes/obinc.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
92 changes: 86 additions & 6 deletions megamek/i18n/megamek/client/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4625,16 +4625,96 @@ CMVPanel.copyText=Copy as Text
CMVPanel.MUL=Open MUL
CMVPanel.font=Font:

# Scenario Chooser
ScenarioChooser.title=Choose Scenario

# SBF Target Dialog
SBFTargetDialog.title=Targeting


#Gamemaster Menu Text
Gamemaster.Gamemaster=Gamemaster
Gamemaster.EditDamage=Edit Damage
Gamemaster.Configure=Configure
Gamemaster.Traitor=Traitor Unit
Gamemaster.SpecialCommands=Special Commands
Gamemaster.KillUnit=Kill Unit
Gamemaster.SpecialCommands=Special Commands

# Scenario Chooser
ScenarioChooser.title=Choose Scenario

# SBF Target Dialog
SBFTargetDialog.title=Targeting
#Gamemaster Chat Commands
Gamemaster.cmd.missingUnit=Specified unit is not on the board.
Gamemaster.cmd.error.integerparse=must be between the min and max values:
Gamemaster.cmd.help=Usage:
Gamemaster.cmd.params.required=Required.
Gamemaster.cmd.params.optional=Optional.
Gamemaster.cmd.x=The x coordinate of the hex.
Gamemaster.cmd.y=The y coordinate of the hex.
# Remove Smoke cmd
Gamemaster.cmd.removesmoke.help=Removes all smoke cloud hexes.
Gamemaster.cmd.removesmoke.success=The air is cleaner and the smoke is gone.
# Kill Unit cmd
Gamemaster.cmd.kill.unitID=ID of the unit to kill.
Gamemaster.cmd.kill.help=Kills a single unit.
Gamemaster.cmd.kill.success=Is going to be destroyed at the end of this phase.
Gamemaster.cmd.kill.reason=Killed by GM.
# Change ownership cmd
Gamemaster.cmd.changeownership.help=Changes the ownership of a unit from one player to another.
Gamemaster.cmd.changeownership.unitID=ID of the unit to change ownership.
Gamemaster.cmd.changeownership.playerID=ID of the player to receive the unit.
Gamemaster.cmd.changeownership.unitNotFound=No such entity.
Gamemaster.cmd.changeownership.playerNotFound=No such player.
Gamemaster.cmd.changeownership.playerUnassigned=Player must be assigned a team.
Gamemaster.cmd.changeownership.success=Ownership of unit {0} will be transferred to player {1} at the end of this round.
# Change weather cmd
Gamemaster.cmd.changeweather.help=Change any of the planetary conditions. Effects change at the next round.
Gamemaster.cmd.changeweather.fog=Fog: 0=none, 1=light, 2=heavy
Gamemaster.cmd.changeweather.light=Light: 0=daylight, 1=dusk, 2=full moon, 3=glare, 4=moonless night, 5=solar flare, 6=pitch black
Gamemaster.cmd.changeweather.wind=Wind: 0=calm, 1=light gale, 2=moderate gale, 3=strong gale, 4=storm, 5=tornado F1-F3, 6=tornado F4
Gamemaster.cmd.changeweather.winddir=Wind direction: 0=south, 1=southwest, 2=northwest, 3=north, 4=northeast, 5=southeast, 6=random
Gamemaster.cmd.changeweather.atmo=Atmosphere: 0=vacuum, 1=trace, 2=thin, 3=standard, 4=high, 5=very high
Gamemaster.cmd.changeweather.blowsand=Blowing Sand: 0=no, 1=yes
Gamemaster.cmd.changeweather.emi=EMI: 0=no, 1=yes
Gamemaster.cmd.changeweather.weather=Weather: 0=clear, 1=light rain, 2=moderate rain, 3=heavy rain, 4=gusting rain, 5=downpour, 6=light snow, 7=moderate snow, 8=snow flurries, 9=heavy snow, 10=sleet, 11=ice storm, 12=light hail, 13=heavy hail, 14=lightning storm
# Disaster cmd
Gamemaster.cmd.disaster.help=Causes a disaster on the board.
Gamemaster.cmd.disaster.type=Type of disaster. Beware, some disasters are very destructive!
Gamemaster.cmd.changeweather.fog.success=The fog has changed.
Gamemaster.cmd.changeweather.fog.error=Invalid fog value. Must be between 0 and {0}

Gamemaster.cmd.changeweather.wind.success=The wind strength has changed.
Gamemaster.cmd.changeweather.wind.error=Invalid wind value. Must be between 0 and {0}

Gamemaster.cmd.changeweather.winddir.success=The wind direction has changed.
Gamemaster.cmd.changeweather.winddir.error=Invalid wind direction value. Must be between 0 and {0}

Gamemaster.cmd.changeweather.light.success=The light has changed.
Gamemaster.cmd.changeweather.light.error=Invalid light value. Must be between 0 and {0}

Gamemaster.cmd.changeweather.atmo.success0=The air has vanished, put your vac suits!
Gamemaster.cmd.changeweather.atmo.success=The air is changing.
Gamemaster.cmd.changeweather.atmo.error=Invalid atmosphere value. Must be between 0 and {0}

Gamemaster.cmd.changeweather.blowsand.success1=Sand started blowing.
Gamemaster.cmd.changeweather.blowsand.success=The sand has settled.
Gamemaster.cmd.changeweather.blowsand.error=Invalid blowsand value. Must be between 0 and {0}

Gamemaster.cmd.changeweather.weather.success=The weather has changed.
Gamemaster.cmd.changeweather.weather.error=Invalid weather value. Must be between 0 and {0}

Gamemaster.cmd.changeweather.emi.success1=EMI is active.
Gamemaster.cmd.changeweather.emi.success=EMI is inactive.
Gamemaster.cmd.changeweather.emi.error=Invalid EMI value. Must be between 0 and {0}
# Firestarter cmd
Gamemaster.cmd.fire.type=Type of fire. They are 1=Normal, 2=Inferno, 3=Inferno Bomb or 4=Inferno IV.
Gamemaster.cmd.fire.help=Starts a fire on the board.

# Firestorm cmd
Gamemaster.cmd.firestorm.help=Starts fire in the entire board.
Gamemaster.cmd.fire.failed=Failed to ignite fire.
Gamemaster.cmd.fire.percent=Percentage of the board hexes to ignite.

# Orbital bombardment cmd
Gamemaster.cmd.orbitalbombardment.help=Calls an orbital bombardment on the board. It hits after the firing phase.
Gamemaster.cmd.orbitalbombardment.dmg=Damage of the bombardment at target hex.
Gamemaster.cmd.orbitalbombardment.radius=Radius of the bombardment.
Gamemaster.cmd.orbitalbombardment.error.outofbounds=Specified hex is not on the board.
Gamemaster.cmd.orbitalbombardment.success=Orbital bombardment incoming!
1 change: 1 addition & 0 deletions megamek/i18n/megamek/common/report-messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
1300=<newline><newline><B>Orbital bombardment hit hex <data>!!!</B><newline>
1301=<span class='info'>End of orbital bombardment resolution</span>
1302=<data> has commenced an orbital bombardment, it will land at the end of the next weapons phase at hex <data>.
1303=<span class='info'>Start of orbital bombardment resolution</span>

# 1500s - ammo handling related
1500=<data> (<data>) selected <data> <data>
Expand Down
24 changes: 8 additions & 16 deletions megamek/src/megamek/client/ui/swing/MapMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -441,22 +441,14 @@ private record Tuple(String name, GamemasterServerCommand command) {}

private JMenu createGMSpecialCommandsMenu() {
JMenu menu = new JMenu(Messages.getString("Gamemaster.SpecialCommands"));
var commands = List.of(
new Tuple("Kill Unit", new KillCommand(null, null)),
new Tuple("Change Ownership", new ChangeOwnershipCommand(null, null)),
new Tuple("Change Weather", new ChangeWeatherCommand(null, null)),
new Tuple("Disasters", new DisasterCommand(null, null)),
new Tuple("Orbital Bombardment", new OrbitalBombardmentCommand(null, null)),
new Tuple("Remove Smoke", new RemoveSmokeCommand(null, null)),
new Tuple("Firestarter", new FirestarterCommand(null, null)),
new Tuple("Firestorm", new FirestormCommand(null, null))
);

for (var cmd : commands) {
JMenuItem item = new JMenuItem(cmd.name());
item.addActionListener(evt -> new GamemasterCommandPanel(gui.getFrame(), gui, cmd.command()).setVisible(true));
menu.add(item);
}
Server.getServerInstance().getAllCommands().stream()
.filter(cmd -> cmd instanceof GamemasterServerCommand)
.map(cmd -> (GamemasterServerCommand) cmd)
.forEach(cmd -> {
JMenuItem item = new JMenuItem(cmd.getName());
item.addActionListener(evt -> new GamemasterCommandPanel(gui.getFrame(), gui, cmd).setVisible(true));
menu.add(item);
});

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

import megamek.client.IClient;
import megamek.client.ui.swing.ClientGUI;
import megamek.server.commands.GamemasterServerCommand;
import megamek.server.commands.arguments.Argument;
import megamek.server.commands.arguments.EnumArgument;
import megamek.server.commands.arguments.IntegerArgument;

import javax.swing.*;
import java.awt.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand All @@ -24,35 +24,42 @@ public GamemasterCommandPanel(JFrame parent, ClientGUI client, GamemasterServerC
this.client = client;
setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));

JLabel helpLabel = new JLabel(command.getHelp());
JLabel helpLabel = new JLabel(command.getHelpHtml());
add(helpLabel);

List<Argument<?>> arguments = command.defineArguments();
Map<String, JComponent> argumentComponents = new HashMap<>();

for (Argument<?> argument : arguments) {
JPanel argumentPanel = new JPanel();
argumentPanel.setLayout(new FlowLayout(FlowLayout.LEFT));

JLabel label = new JLabel(argument.getName() + ":");
add(label);
argumentPanel.add(label);

if (argument instanceof IntegerArgument intArg) {
if (argument instanceof IntegerArgument) {
IntegerArgument intArg = (IntegerArgument) argument;
JSpinner spinner = new JSpinner(new SpinnerNumberModel(
intArg.hasDefaultValue() ? intArg.getValue() : 0,
intArg.getMinValue(),
intArg.getMaxValue(),
1));
add(spinner);
argumentPanel.add(spinner);
argumentComponents.put(argument.getName(), spinner);
} else if (argument instanceof EnumArgument<?> enumArg) {
} else if (argument instanceof EnumArgument) {
EnumArgument<?> enumArg = (EnumArgument<?>) argument;
JComboBox<String> comboBox = new JComboBox<>();
for (Enum<?> constant : enumArg.getEnumType().getEnumConstants()) {
comboBox.addItem(constant.name());
}
if (enumArg.getValue() != null) {
comboBox.setSelectedItem(enumArg.getValue().name());
}
add(comboBox);
argumentPanel.add(comboBox);
argumentComponents.put(argument.getName(), comboBox);
}

add(argumentPanel);
}

JButton executeButton = new JButton("Execute Command");
Expand All @@ -63,6 +70,18 @@ public GamemasterCommandPanel(JFrame parent, ClientGUI client, GamemasterServerC
setLocationRelativeTo(parent);
}

private String wrapText(String text, int lineLength) {
StringBuilder wrappedText = new StringBuilder("<html>");
int currentIndex = 0;
while (currentIndex < text.length()) {
int endIndex = Math.min(currentIndex + lineLength, text.length());
wrappedText.append(text, currentIndex, endIndex).append("<br>");
currentIndex = endIndex;
}
wrappedText.append("</html>");
return wrappedText.toString();
}

private void executeCommand(Map<String, JComponent> argumentComponents) {
List<Argument<?>> arguments = command.defineArguments();
String[] args = new String[arguments.size()];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public class TilesetManager implements IPreferenceChangeListener {
private static final String FILENAME_ARTILLERY_ADJUSTED_IMAGE = "artyadj.gif";
private static final String FILENAME_ARTILLERY_INCOMING_IMAGE = "artyinc.gif";

private static final String FILENAME_ORBITAL_BOMBARDMENT_INCOMING_IMAGE = "obinc.gif";
public static final String FILENAME_ORBITAL_BOMBARDMENT_INCOMING_IMAGE = "obinc.gif";

public static final int ARTILLERY_AUTOHIT = 0;
public static final int ARTILLERY_ADJUSTED = 1;
Expand Down
4 changes: 3 additions & 1 deletion megamek/src/megamek/common/SpecialHexDisplay.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import megamek.common.util.ImageUtil;
import megamek.common.util.fileUtils.MegaMekFile;

import static megamek.client.ui.swing.tileset.TilesetManager.FILENAME_ORBITAL_BOMBARDMENT_INCOMING_IMAGE;

/**
* @author dirk
*/
Expand Down Expand Up @@ -101,7 +103,7 @@ public boolean drawAfter() {
return true;
}
},
ORBITAL_BOMBARDMENT(new MegaMekFile(Configuration.hexesDir(), "obinc.gif").toString());
ORBITAL_BOMBARDMENT(new MegaMekFile(Configuration.hexesDir(), FILENAME_ORBITAL_BOMBARDMENT_INCOMING_IMAGE).toString());

private transient Image defaultImage;
private final String defaultImagePath;
Expand Down
7 changes: 7 additions & 0 deletions megamek/src/megamek/server/Server.java
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,13 @@ public Collection<String> getAllCommandNames() {
return commandsHash.keySet();
}

/**
* Returns the list of all server commands
*/
public List<ServerCommand> getAllCommands() {
return new ArrayList<>(commandsHash.values());
}

/**
* Sent when a client attempts to connect.
*/
Expand Down
53 changes: 24 additions & 29 deletions megamek/src/megamek/server/commands/ChangeOwnershipCommand.java
Original file line number Diff line number Diff line change
@@ -1,73 +1,68 @@
/*
* Copyright (c) 2024 - The MegaMek Team. All Rights Reserved.
* MegaMek - Copyright (c) 2024 - The MegaMek Team. All Rights Reserved.
*
* This file is part of MegaMek.
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* MegaMek is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MegaMek is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MegaMek. If not, see <http://www.gnu.org/licenses/>.
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
package megamek.server.commands;

import megamek.client.ui.Messages;
import megamek.common.Entity;
import megamek.common.Player;
import megamek.server.Server;
import megamek.server.commands.arguments.Argument;
import megamek.server.commands.arguments.IntegerArgument;
import megamek.server.totalwarfare.TWGameManager;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
* The Server Command "/changeOwner" that will switch an entity's owner to another player.
*
* @author Luana Scoppio
* @author Luana Coppio
*/
public class ChangeOwnershipCommand extends GamemasterServerCommand {

public static final String UNIT_ID = "unitID";
public static final String PLAYER_ID = "playerID";

public ChangeOwnershipCommand(Server server, TWGameManager gameManager) {
super(server,
gameManager,
"changeOwner",
"Switches ownership of a player's entity to another player during the end phase. "
+ "Usage: /changeOwner <Unit ID> <Player ID> "
+ "The following is an example of changing unit ID 7 to player ID 2: /changeOwner 7 2 ");
Messages.getString("Gamemaster.cmd.changeownership.help"));
}

@Override
public List<Argument<?>> defineArguments() {
List<Argument<?>> arguments = new ArrayList<>();
arguments.add(new IntegerArgument("unitID", 0, Integer.MAX_VALUE));
arguments.add(new IntegerArgument("playerID", 0, Integer.MAX_VALUE));
return arguments;
return List.of(
new IntegerArgument(UNIT_ID, Messages.getString("Gamemaster.cmd.changeownership.unitID")),
new IntegerArgument(PLAYER_ID, Messages.getString("Gamemaster.cmd.changeownership.playerID")));
}

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

Entity ent = gameManager.getGame().getEntity(unitID.getValue());
Player player = server.getGame().getPlayer(playerID.getValue());
if (null == ent) {
server.sendServerChat(connId, "No such entity.");
server.sendServerChat(connId, Messages.getString("Gamemaster.cmd.changeownership.unitNotFound"));
} else if (null == player) {
server.sendServerChat(connId, "No such player.");
server.sendServerChat(connId, Messages.getString("Gamemaster.cmd.changeownership.playerNotFound"));
} else if (player.getTeam() == Player.TEAM_UNASSIGNED) {
server.sendServerChat(connId, "Player must be assigned a team.");
server.sendServerChat(connId, Messages.getString("Gamemaster.cmd.changeownership.playerUnassigned"));
} else {
server.sendServerChat(connId, ent.getDisplayName() + " will switch to " + player.getName() + "'s side at the end of this turn.");
server.sendServerChat(connId, Messages.getString("Gamemaster.cmd.changeownership.success", ent.getDisplayName(), player.getName()));
ent.setTraitorId(player.getId());
}
}
Expand Down
Loading

0 comments on commit 1117d85

Please sign in to comment.