Skip to content

Commit

Permalink
Merge branch 'master' into feat/tinkering-princess-ai
Browse files Browse the repository at this point in the history
  • Loading branch information
Scoppio authored Jan 29, 2025
2 parents f5af236 + 2614506 commit ac64281
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 74 deletions.
4 changes: 4 additions & 0 deletions megamek/docs/history.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ MEGAMEK VERSION HISTORY:
+ PR #6442: Unit Tests for WeaponAttackAction to help test megamek
+ Fix #6434: pilot rolls reported before all attacks (also #3890)
+ PR #6443: Fix for ranked path entries being overwritten
+ Fix #6299: Fix 6299 skid building damage and displaced messages out of order
+ Fix #6444: fix issue where closing window closes the unit display
+ PR #6450: Allow the print-unit-list code to run with MegaMekLab.jar
+ PR #6453: Change keys List from ArrayList to thread-safe Vector

0.50.02 (2024-12-30 2130 UTC)
+ PR #6183: New GM Commands, princess commands on map menu, graphics for some explosions
Expand Down
3 changes: 2 additions & 1 deletion megamek/i18n/megamek/client/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -1305,7 +1305,8 @@ CommonSettingsDialog.userDir.tooltip=<html>Use this directory for resources you
CommonSettingsDialog.userDir.chooser.title=Choose User Data Folder
CommonSettingsDialog.mmlPath=Path to MegaMekLab Executable:
CommonSettingsDialog.mmlPath.tooltip=<html>Used for printing unit lists.\
<br>MegaMek will try to autodetect this when the option is blank if MM and MML are installed together.</html>
<br>MegaMek will try to autodetect this when the option is blank if MM and MML are installed together.\
<br>Select MegaMekLab.exe, MegaMekLab.sh, or MegaMekLab.jar, as appropriate for your system.</html>
CommonSettingsDialog.mmlPath.chooser.title=Select MegaMekLab Executable
CommonSettingsDialog.main=Main
CommonSettingsDialog.audio=Audio
Expand Down
125 changes: 83 additions & 42 deletions megamek/src/megamek/client/ui/swing/ClientGUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import java.util.jar.JarFile;

import javax.imageio.ImageIO;
import javax.swing.*;
Expand Down Expand Up @@ -94,6 +95,7 @@
import megamek.common.util.Distractable;
import megamek.common.util.StringUtil;
import megamek.logging.MMLogger;
import org.apache.commons.lang3.SystemUtils;

public class ClientGUI extends AbstractClientGUI implements BoardViewListener,
ActionListener, IPreferenceChangeListener, MekDisplayListener, ILocalBots, IDisconnectSilently, IHasUnitDisplay, IHasBoardView, IHasMenuBar, IHasCurrentPanel {
Expand Down Expand Up @@ -2134,6 +2136,79 @@ public void saveListFile(ArrayList<Entity> unitList, String filename) {
}
}

private ProcessBuilder printToMegaMekLab(ArrayList<Entity> unitList, File mmlExecutable, boolean autodetected) {
boolean jarfile;
try (var ignored = new JarFile(mmlExecutable)) {
jarfile = true;
} catch (IOException ignored) {
jarfile = false;
}

File unitFile;
try {
unitFile = File.createTempFile("MegaMekPrint", ".mul");
EntityListFile.saveTo(unitFile, unitList);
unitFile.deleteOnExit();
} catch (IOException e) {
throw new RuntimeException(e);
}

String[] command;

if (!jarfile) {
if (!mmlExecutable.canExecute()) {
if (autodetected) {
logger.error("Could not auto-detect MegaMekLab! Please configure the path to the MegaMekLab executable in the settings.", "Error printing unit list");
} else {
logger.error("%s does not appear to be an executable! You may need to set execute permission or configure the path to the MegaMekLab executable in the settings.".formatted(mmlExecutable.getName()), "Error printing unit list");
}
return null;
}

if (mmlExecutable.getName().toLowerCase().contains("gradle")) {
// If the executable is `gradlew`/`gradelw.bat`, assume it's the gradle wrapper
// which comes in the MML git repo. Compile and run MML from source in order to print units.
command = new String[] {
mmlExecutable.getAbsolutePath(),
"run",
"--args=%s --no-startup".formatted(unitFile.getAbsolutePath())
};
} else {
// Start mml normally. "--no-startup" tells MML to exit after the user closes the
// print dialog (by printing or cancelling)
command = new String[] {
mmlExecutable.getAbsolutePath(),
unitFile.getAbsolutePath(),
"--no-startup"
};
}
} else {
if (!mmlExecutable.exists()) {
if (autodetected) {
logger.error("Could not auto-detect MegaMekLab! Please configure the path to the MegaMekLab executable in the settings.", "Error printing unit list");
} else {
logger.error("%s does not appear to exist! Please configure the path to the MegaMekLab executable in the settings.".formatted(mmlExecutable.getName()), "Error printing unit list");
}
return null;
}

// The executable is a jarfile, so let's execute it.
var javaExecutable = ProcessHandle.current().info().command().orElse("java");
command = new String[] {
javaExecutable,
"-jar",
mmlExecutable.getAbsolutePath(),
unitFile.getAbsolutePath(),
"--no-startup"
};

}

return new ProcessBuilder(command)
.directory(mmlExecutable.getAbsoluteFile().getParentFile())
.inheritIO();
}

/**
* Request MegaMekLab to print out record sheets for the current player's selected units.
* The method will try to find MML either automatically or based on a configured client setting.
Expand All @@ -2154,58 +2229,23 @@ public void printList(ArrayList<Entity> unitList, JButton button) {
var autodetect = false;
if (null == mmlPath || mmlPath.isBlank()) {
autodetect = true;
if (System.getProperty("os.name").toLowerCase().contains("win")) {
mmlPath = "MegaMekLab.exe";
} else {
mmlPath = "MegaMekLab.sh";
}
mmlPath = "MegaMekLab.jar";
}

var mml = new File(mmlPath);

if (!mml.canExecute()) {
if (autodetect) {
logger.error("Could not auto-detect MegaMekLab! Please configure the path to the MegaMekLab executable in the settings.", "Error printing unit list");
} else {
logger.error("%s does not appear to be an executable! Please configure the path to the MegaMekLab executable in the settings.".formatted(mml.getName()), "Error printing unit list");
}
var pb = printToMegaMekLab(unitList, new File(mmlPath), autodetect);
if (pb == null) {
return;
}

try {
// Save unit list to a temporary file
var unitFile = File.createTempFile("MegaMekPrint", ".mul");
EntityListFile.saveTo(unitFile, unitList);

String[] command;
if (mml.getName().toLowerCase().contains("gradle")) {
// If the executable is `gradlew`/`gradelw.bat`, assume it's the gradle wrapper
// which comes in the MML git repo. Compile and run MML from source in order to print units.
command = new String[] {
mml.getAbsolutePath(),
"run",
"--args=%s --no-startup".formatted(unitFile.getAbsolutePath())
};
} else {
// Start mml normally. "--no-startup" tells MML to exit after the user closes the
// print dialog (by printing or cancelling)
command = new String[] {
mml.getAbsolutePath(),
unitFile.getAbsolutePath(),
"--no-startup"
};
}
// It takes a while for MML to start, so we change the text of the button
// It sometimes takes a while for MML to start, so we change the text of the button
// to let the user know that something is happening
button.setText(Messages.getString("ChatLounge.butPrintList.printing"));

logger.info("Running command: {}", String.join(" ", command));
logger.info("Running command: {}", String.join(" ", pb.command()));


var p = new ProcessBuilder(command)
.directory(mml.getAbsoluteFile().getParentFile())
.inheritIO()
.start();
var p = pb.start();

// This thread's only purpose is to wait for the MML process to finish and change the button's text back to
// its original value.
Expand All @@ -2222,8 +2262,9 @@ public void printList(ArrayList<Entity> unitList, JButton button) {
} catch (Exception e) {
// If something goes wrong, probably ProcessBuild.start if anything,
// Make sure to set the button text back to what it started as no matter what.
logger.error(e, "Operation failed", "Error printing unit list");
button.setText(Messages.getString("ChatLounge.butPrintList"));
logger.error(e, "Operation failed", "Error printing unit list");

}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public ForceDisplayDialog(final JFrame frame, final ClientGUI clientGUI) {
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent evt) {
GUIP.setUnitDisplayEnabled(false);
GUIP.setForceDisplayEnabled(false);
}
});
}
Expand Down
9 changes: 2 additions & 7 deletions megamek/src/megamek/common/battlevalue/BVCalculator.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,7 @@
import static megamek.common.AmmoType.T_AMS;
import static megamek.common.AmmoType.T_APDS;

import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.*;
import java.util.function.Predicate;

import megamek.client.ui.swing.calculationReport.CalculationReport;
Expand Down Expand Up @@ -61,7 +56,7 @@ public abstract class BVCalculator {
protected boolean ignoreC3;
protected boolean ignoreSkill;
protected Map<String, Double> ammoMap = new HashMap<>();
protected List<String> keys = new ArrayList<>();
protected List<String> keys = new Vector<>();
protected Map<String, String> names = new HashMap<>();
protected Map<String, Double> weaponsForExcessiveAmmo = new HashMap<>();
protected int runMP;
Expand Down
Loading

0 comments on commit ac64281

Please sign in to comment.