2015-02-11 19:30:27 -08:00
|
|
|
package magic.utility;
|
2014-02-19 18:12:00 -08:00
|
|
|
|
2015-02-17 17:51:51 -08:00
|
|
|
import java.io.File;
|
2015-06-30 12:18:41 -07:00
|
|
|
import java.io.IOException;
|
2015-06-30 12:35:25 -07:00
|
|
|
import java.lang.management.ManagementFactory;
|
|
|
|
import java.lang.management.RuntimeMXBean;
|
2015-06-30 12:18:41 -07:00
|
|
|
import java.net.URISyntaxException;
|
2015-07-08 23:12:39 -07:00
|
|
|
import java.nio.file.Files;
|
2015-06-30 12:18:41 -07:00
|
|
|
import java.security.CodeSource;
|
2015-07-01 09:55:33 -07:00
|
|
|
import java.util.ArrayList;
|
2015-06-30 12:35:25 -07:00
|
|
|
import java.util.List;
|
2016-10-26 19:04:39 -07:00
|
|
|
import java.util.Locale;
|
2015-06-30 12:35:25 -07:00
|
|
|
import java.util.concurrent.ExecutionException;
|
|
|
|
import java.util.concurrent.ExecutorService;
|
|
|
|
import java.util.concurrent.Executors;
|
|
|
|
import java.util.concurrent.FutureTask;
|
|
|
|
import magic.data.CardDefinitions;
|
|
|
|
import magic.data.DeckGenerators;
|
|
|
|
import magic.data.GeneralConfig;
|
|
|
|
import magic.data.MagicCustomFormat;
|
|
|
|
import magic.data.UnimplementedParser;
|
|
|
|
import magic.model.MagicGameLog;
|
|
|
|
import magic.utility.MagicFileSystem.DataPath;
|
2015-02-16 03:06:10 -08:00
|
|
|
|
2015-02-11 19:37:00 -08:00
|
|
|
final public class MagicSystem {
|
|
|
|
private MagicSystem() {}
|
2014-02-19 18:12:00 -08:00
|
|
|
|
2019-12-28 19:16:33 -08:00
|
|
|
public static final String VERSION = "1.96";
|
2016-02-01 02:05:25 -08:00
|
|
|
static {
|
2017-05-16 02:12:43 -07:00
|
|
|
System.setProperty("http.agent", "Magarena " + VERSION);
|
2016-02-01 02:05:25 -08:00
|
|
|
}
|
|
|
|
|
2016-10-26 19:04:39 -07:00
|
|
|
public static final boolean IS_WINDOWS_OS = System.getProperty("os.name").toLowerCase(Locale.ENGLISH).startsWith("windows");
|
2015-03-25 07:56:31 -07:00
|
|
|
private static final ProgressReporter reporter = new ProgressReporter();
|
2015-05-04 07:49:20 -07:00
|
|
|
|
2015-05-04 08:16:53 -07:00
|
|
|
// Load card definitions in the background so that it does not delay the
|
|
|
|
// loading of the UI. Override done() to ensure exceptions not suppressed.
|
2018-04-07 17:59:14 -07:00
|
|
|
public static final FutureTask<Void> loadPlayable = new FutureTask<Void>(
|
|
|
|
() -> initializeEngine(reporter), null
|
|
|
|
) {
|
2015-05-04 08:16:53 -07:00
|
|
|
@Override
|
|
|
|
protected void done() {
|
|
|
|
try {
|
|
|
|
if (!isCancelled()) {
|
|
|
|
get();
|
|
|
|
}
|
|
|
|
} catch (ExecutionException ex) {
|
|
|
|
throw new RuntimeException(ex.getCause());
|
|
|
|
} catch (InterruptedException ex) {
|
|
|
|
// Shouldn't happen, we're invoked when computation is finished
|
|
|
|
throw new AssertionError(ex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2014-02-19 18:12:00 -08:00
|
|
|
|
2018-04-07 17:59:14 -07:00
|
|
|
public static final FutureTask<Void> loadMissing = new FutureTask<Void>(
|
|
|
|
() -> CardDefinitions.loadMissingCards(), null
|
|
|
|
) {
|
2016-12-20 03:47:09 -08:00
|
|
|
@Override
|
|
|
|
protected void done() {
|
|
|
|
try {
|
|
|
|
if (!isCancelled()) {
|
|
|
|
get();
|
|
|
|
}
|
|
|
|
} catch (ExecutionException ex) {
|
|
|
|
throw new RuntimeException(ex.getCause());
|
|
|
|
} catch (InterruptedException ex) {
|
|
|
|
// Shouldn't happen, we're invoked when computation is finished
|
|
|
|
throw new AssertionError(ex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-05-16 02:12:43 -07:00
|
|
|
public static String getVersionTitle() {
|
|
|
|
return "Magarena " + VERSION + (isDevMode() ? " [DEV MODE]" : "");
|
|
|
|
}
|
|
|
|
|
2015-12-15 03:17:48 -08:00
|
|
|
public static void setIsTestGame(boolean b) {
|
|
|
|
System.setProperty("testGame", b ? "Y" : "");
|
|
|
|
}
|
|
|
|
|
2014-03-06 01:45:19 -08:00
|
|
|
public static boolean isTestGame() {
|
2017-02-21 07:26:08 -08:00
|
|
|
return !System.getProperty("testGame", "").isEmpty()
|
|
|
|
|| !System.getProperty("saveGame", "").isEmpty();
|
2014-03-06 01:45:19 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
public static boolean isDevMode() {
|
2017-05-10 01:46:50 -07:00
|
|
|
return Boolean.getBoolean("devMode") || Boolean.getBoolean("debug");
|
|
|
|
}
|
2017-05-16 02:12:43 -07:00
|
|
|
|
2017-05-10 01:46:50 -07:00
|
|
|
public static void setIsDevMode(boolean b) {
|
|
|
|
System.setProperty("devMode", String.valueOf(b));
|
2014-03-06 01:45:19 -08:00
|
|
|
}
|
|
|
|
|
2014-05-11 12:11:06 -07:00
|
|
|
public static boolean isDebugMode() {
|
|
|
|
return Boolean.getBoolean("debug");
|
|
|
|
}
|
2015-12-19 15:58:39 -08:00
|
|
|
|
2014-09-18 10:35:09 -07:00
|
|
|
/**
|
|
|
|
* add "-DparseMissing=true" VM argument for parsing scripts_missing folder.
|
|
|
|
*/
|
|
|
|
public static boolean isParseMissing() {
|
|
|
|
return Boolean.getBoolean("parseMissing");
|
|
|
|
}
|
2014-05-11 12:11:06 -07:00
|
|
|
|
2014-03-06 01:45:19 -08:00
|
|
|
/**
|
|
|
|
* add "-DselfMode=true" VM argument for AI vs AI mode.
|
|
|
|
*/
|
|
|
|
public static boolean isAiVersusAi() {
|
|
|
|
return Boolean.getBoolean("selfMode");
|
|
|
|
}
|
|
|
|
|
2017-05-09 14:03:51 -07:00
|
|
|
public static void setAiVersusAi(boolean b) {
|
|
|
|
System.setProperty("selfMode", String.valueOf(b));
|
|
|
|
}
|
|
|
|
|
2014-08-29 03:45:40 -07:00
|
|
|
/**
|
|
|
|
* add "-DshowStats=true" to output startup statistics to console.
|
|
|
|
*/
|
|
|
|
public static boolean showStartupStats() {
|
|
|
|
return Boolean.getBoolean("showStats");
|
|
|
|
}
|
|
|
|
|
2015-02-16 03:06:10 -08:00
|
|
|
public static String getHeapUtilizationStats() {
|
2017-01-29 23:33:37 -08:00
|
|
|
final int mb = 1024*1024;
|
2015-02-16 03:06:10 -08:00
|
|
|
final Runtime runtime = Runtime.getRuntime();
|
2017-01-29 23:33:37 -08:00
|
|
|
return "Used Memory: " + (runtime.totalMemory() - runtime.freeMemory()) / mb + "M" +
|
|
|
|
"\nFree Memory: " + runtime.freeMemory() / mb + "M" +
|
|
|
|
"\nTotal Memory: " + runtime.totalMemory() / mb + "M" +
|
|
|
|
"\nMax Memory: " + runtime.maxMemory() / mb + "M";
|
2015-02-16 03:06:10 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets VM arguments.
|
|
|
|
*/
|
|
|
|
public static String getRuntimeParameters() {
|
|
|
|
RuntimeMXBean bean = ManagementFactory.getRuntimeMXBean();
|
2018-04-07 17:59:14 -07:00
|
|
|
StringBuilder params = new StringBuilder();
|
|
|
|
for (String param : bean.getInputArguments()) {
|
|
|
|
params.append(param).append("\n");
|
2015-02-16 03:06:10 -08:00
|
|
|
}
|
2018-04-07 17:59:14 -07:00
|
|
|
return params.toString();
|
2015-02-16 03:06:10 -08:00
|
|
|
}
|
2015-03-24 18:57:49 -07:00
|
|
|
|
2015-03-25 07:56:31 -07:00
|
|
|
public static String getLoadingProgress() {
|
|
|
|
return reporter.getMessage();
|
2015-03-24 18:57:49 -07:00
|
|
|
}
|
2015-02-16 03:06:10 -08:00
|
|
|
|
2016-12-20 03:47:09 -08:00
|
|
|
public static void waitForMissingCards() {
|
|
|
|
if (loadMissing.isDone()) {
|
|
|
|
return;
|
2018-04-07 17:59:14 -07:00
|
|
|
}
|
|
|
|
try {
|
|
|
|
loadMissing.get();
|
|
|
|
} catch (final InterruptedException|ExecutionException ex) {
|
|
|
|
throw new RuntimeException(ex);
|
2016-12-20 03:47:09 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-09 01:30:02 -07:00
|
|
|
public static void waitForPlayableCards() {
|
2017-07-09 01:28:20 -07:00
|
|
|
if (loadPlayable.isDone()) {
|
2015-03-25 07:56:31 -07:00
|
|
|
return;
|
2018-04-07 17:59:14 -07:00
|
|
|
}
|
|
|
|
try {
|
|
|
|
loadPlayable.get();
|
|
|
|
} catch (final InterruptedException|ExecutionException ex) {
|
|
|
|
throw new RuntimeException(ex);
|
2015-03-25 07:56:31 -07:00
|
|
|
}
|
|
|
|
}
|
2015-12-19 15:58:39 -08:00
|
|
|
|
2015-03-24 18:57:49 -07:00
|
|
|
private static void initializeEngine(final ProgressReporter reporter) {
|
2015-03-24 18:44:09 -07:00
|
|
|
if (isParseMissing()) {
|
2015-02-17 17:51:51 -08:00
|
|
|
UnimplementedParser.parseScriptsMissing(reporter);
|
|
|
|
reporter.setMessage("Parsing card abilities...");
|
|
|
|
UnimplementedParser.parseCardAbilities();
|
2015-03-25 07:56:31 -07:00
|
|
|
|
2015-02-17 17:51:51 -08:00
|
|
|
}
|
|
|
|
CardDefinitions.loadCardDefinitions(reporter);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void initialize(final ProgressReporter reporter) {
|
2015-03-24 11:14:35 -07:00
|
|
|
|
2018-04-07 17:59:14 -07:00
|
|
|
// must load config here otherwise annotated card image theme-specific
|
2015-02-17 17:51:51 -08:00
|
|
|
// icons are not loaded before the AbilityIcon class is initialized
|
|
|
|
// and you end up with the default icons instead.
|
|
|
|
GeneralConfig.getInstance().load();
|
2015-12-19 15:58:39 -08:00
|
|
|
|
2015-02-17 17:51:51 -08:00
|
|
|
final File gamePathFile = MagicFileSystem.getDataPath().toFile();
|
|
|
|
if (!gamePathFile.exists() && !gamePathFile.mkdir()) {
|
|
|
|
System.err.println("Unable to create directory " + gamePathFile.toString());
|
|
|
|
}
|
|
|
|
|
|
|
|
final File modsPathFile = MagicFileSystem.getDataPath(DataPath.MODS).toFile();
|
|
|
|
if (!modsPathFile.exists() && !modsPathFile.mkdir()) {
|
|
|
|
System.err.println("Unable to create directory " + modsPathFile.toString());
|
|
|
|
}
|
|
|
|
|
|
|
|
DeckUtils.createDeckFolder();
|
2015-03-24 11:14:35 -07:00
|
|
|
|
|
|
|
// setup the game log
|
|
|
|
reporter.setMessage("Initializing log...");
|
|
|
|
MagicGameLog.initialize();
|
2015-12-19 15:58:39 -08:00
|
|
|
|
2017-02-01 04:44:59 -08:00
|
|
|
// Queue up tasks to run synchronously on a single background thread.
|
2015-03-28 18:12:40 -07:00
|
|
|
final ExecutorService background = Executors.newSingleThreadExecutor();
|
2017-07-09 01:28:20 -07:00
|
|
|
background.execute(loadPlayable);
|
2018-04-07 17:59:14 -07:00
|
|
|
background.execute(() -> CardDefinitions.postCardDefinitions());
|
2016-12-20 03:47:09 -08:00
|
|
|
background.execute(loadMissing);
|
2015-03-28 18:12:40 -07:00
|
|
|
background.shutdown();
|
2015-03-25 07:56:31 -07:00
|
|
|
|
|
|
|
// if parse scripts missing or pre-load abilities then load cards synchronously
|
2015-03-24 18:44:09 -07:00
|
|
|
if (isParseMissing() || isDebugMode()) {
|
2017-07-09 01:30:02 -07:00
|
|
|
waitForPlayableCards();
|
2015-03-24 11:14:35 -07:00
|
|
|
}
|
2015-12-19 15:58:39 -08:00
|
|
|
|
2015-03-26 04:28:35 -07:00
|
|
|
if (isDebugMode()) {
|
|
|
|
reporter.setMessage("Loading card abilities...");
|
|
|
|
CardDefinitions.loadCardAbilities();
|
|
|
|
}
|
2015-03-24 11:14:35 -07:00
|
|
|
|
2015-06-22 18:41:43 -07:00
|
|
|
reporter.setMessage("Loading cube definitions...");
|
|
|
|
MagicCustomFormat.loadCustomFormats();
|
2015-03-24 18:44:09 -07:00
|
|
|
reporter.setMessage("Loading deck generators...");
|
|
|
|
DeckGenerators.getInstance().loadDeckGenerators();
|
2015-08-04 04:16:00 -07:00
|
|
|
|
2015-02-17 17:51:51 -08:00
|
|
|
}
|
2015-06-30 12:18:41 -07:00
|
|
|
|
|
|
|
public static File getJarFile() throws URISyntaxException {
|
2015-12-19 15:58:39 -08:00
|
|
|
|
2015-08-06 02:02:25 -07:00
|
|
|
CodeSource codeSource = MagicSystem.class.getProtectionDomain().getCodeSource();
|
2015-07-01 09:55:33 -07:00
|
|
|
File jarFile = new File(codeSource.getLocation().toURI());
|
2015-06-30 12:18:41 -07:00
|
|
|
|
2015-07-01 16:05:53 -07:00
|
|
|
if (jarFile.isFile() && jarFile.exists()) {
|
2015-06-30 12:18:41 -07:00
|
|
|
return jarFile;
|
|
|
|
} else if (System.getProperty("jarFile") != null) {
|
|
|
|
jarFile = new File(System.getProperty("jarFile"));
|
|
|
|
return jarFile;
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Restart the current Java application.
|
|
|
|
* <p>
|
2015-07-01 09:55:33 -07:00
|
|
|
* Should also work when JAR is not available (eg. when running from IDE).
|
2015-06-30 12:18:41 -07:00
|
|
|
*/
|
2018-04-07 17:59:14 -07:00
|
|
|
public static void restart() throws URISyntaxException {
|
2015-06-30 12:18:41 -07:00
|
|
|
|
2015-07-01 09:55:33 -07:00
|
|
|
final List<String> command = new ArrayList<>();
|
2015-06-30 12:18:41 -07:00
|
|
|
|
2015-07-01 09:55:33 -07:00
|
|
|
final String javaBin = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java";
|
|
|
|
command.add(javaBin);
|
2015-12-19 15:58:39 -08:00
|
|
|
|
2015-07-01 09:55:33 -07:00
|
|
|
// vm arguments
|
|
|
|
final List<String> vmArguments = ManagementFactory.getRuntimeMXBean().getInputArguments();
|
|
|
|
for (final String arg : vmArguments) {
|
|
|
|
// if it's the agent argument : we ignore it otherwise the
|
|
|
|
// address of the old application and the new one will be in conflict
|
|
|
|
if (!arg.contains("-agentlib")) {
|
|
|
|
command.add(arg);
|
2015-06-30 12:18:41 -07:00
|
|
|
}
|
2015-07-01 09:55:33 -07:00
|
|
|
}
|
2015-06-30 12:18:41 -07:00
|
|
|
|
2015-07-01 09:55:33 -07:00
|
|
|
final File jarFile = getJarFile();
|
|
|
|
if (jarFile != null) {
|
|
|
|
command.add("-jar");
|
|
|
|
command.add(jarFile.getPath());
|
|
|
|
} else {
|
2015-12-23 20:45:50 -08:00
|
|
|
// Sun property pointing to the main class and its arguments.
|
|
|
|
// Might not be defined on non Hotspot VM implementations.
|
2015-07-01 09:55:33 -07:00
|
|
|
command.add("-cp \"");
|
|
|
|
command.add(System.getProperty("java.class.path"));
|
|
|
|
command.add("\" ");
|
|
|
|
command.add(System.getProperty("sun.java.command").split(" ")[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// execute the command in a shutdown hook, to be sure that all the
|
|
|
|
// resources have been disposed before restarting the application
|
2018-04-07 17:59:14 -07:00
|
|
|
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
|
|
|
try {
|
|
|
|
final ProcessBuilder builder = new ProcessBuilder(command);
|
|
|
|
builder.start();
|
|
|
|
} catch (final IOException ex) {
|
|
|
|
System.err.println(ex);
|
2015-06-30 12:18:41 -07:00
|
|
|
}
|
2018-04-07 17:59:14 -07:00
|
|
|
}));
|
2015-07-01 09:55:33 -07:00
|
|
|
|
|
|
|
System.exit(0);
|
2015-12-19 15:58:39 -08:00
|
|
|
|
2015-06-30 12:18:41 -07:00
|
|
|
}
|
|
|
|
|
2015-07-08 23:12:39 -07:00
|
|
|
public static boolean isNewInstall() {
|
2018-04-07 17:59:14 -07:00
|
|
|
return !Files.exists(MagicFileSystem.getDataPath().resolve(GeneralConfig.CONFIG_FILENAME));
|
2015-07-08 23:12:39 -07:00
|
|
|
}
|
|
|
|
|
2017-05-24 04:02:29 -07:00
|
|
|
public static boolean isNotNormalGame() {
|
|
|
|
return MagicSystem.isAiVersusAi()
|
|
|
|
|| MagicSystem.isDevMode()
|
|
|
|
|| MagicSystem.isTestGame();
|
|
|
|
}
|
|
|
|
|
2014-02-19 18:12:00 -08:00
|
|
|
}
|