package magic;
import java.awt.SplashScreen;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.SwingUtilities;
import magic.ai.MagicAI;
import magic.data.DeckGenerators;
import magic.data.DuelConfig;
import magic.exception.InvalidDeckException;
import magic.game.state.GameLoader;
import magic.model.DuelPlayerConfig;
import magic.model.MagicDeck;
import magic.model.player.AiProfile;
import magic.test.TestGameBuilder;
import magic.ui.ScreenController;
import magic.ui.SplashProgressReporter;
import magic.ui.UiExceptionHandler;
import magic.ui.WikiPage;
import magic.ui.helpers.LaFHelper;
import magic.ui.widget.duel.animation.MagicAnimations;
import magic.utility.DeckUtils;
import magic.utility.MagicFileSystem;
import magic.utility.MagicFileSystem.DataPath;
import magic.utility.MagicSystem;
import magic.utility.ProgressReporter;
public class MagicMain {
private static final Logger LOGGER = Logger.getLogger(MagicMain.class.getName());
private static SplashScreen splash;
private static ProgressReporter reporter = new ProgressReporter();
public static void main(final String[] args) {
Thread.setDefaultUncaughtExceptionHandler(new UiExceptionHandler());
setSplashScreen();
System.out.println(MagicSystem.getRuntimeParameters());
final CommandLineArgs cmdline = new CommandLineArgs(args);
parseCommandLine(cmdline);
// show the data folder being used
System.out.println("Data folder : "+ MagicFileSystem.getDataPath());
// init subsystems
final long start_time = System.currentTimeMillis();
reporter.setMessage("Initializing game engine...");
MagicSystem.initialize(reporter);
if (MagicSystem.showStartupStats()) {
final double duration = (double)(System.currentTimeMillis() - start_time) / 1000;
System.err.println("Initalization of engine took " + duration + "s");
}
LaFHelper.setDefaultLookAndFeel();
reporter.setMessage("Starting UI...");
SwingUtilities.invokeLater(() -> { startUI(cmdline); });
}
private static void parseCommandLine(CommandLineArgs cmdline) {
if (cmdline.showHelp()) {
System.err.println("--help specified - opening wiki page and exit...\n" + WikiPage.COMMAND_LINE.getUrl());
WikiPage.show(WikiPage.COMMAND_LINE);
System.exit(0);
}
MagicAnimations.setEnabled(cmdline.isAnimationsEnabled());
MagicAI.setMaxThreads(cmdline.getMaxThreads());
MagicSystem.setIsDevMode(cmdline.isDevMode());
}
/**
* Sets splash screen as defined in JAR manifest or via "-splash" command line.
* <p>
* Can override with custom splash by placing "splash.png" in mods folder.
*/
private static void setSplashScreen() {
splash = SplashScreen.getSplashScreen();
if (splash == null) {
System.err.println("Error: no splash image specified on the command line");
} else {
reporter = new SplashProgressReporter(splash);
try {
final File splashFile = MagicFileSystem.getDataPath(DataPath.MODS).resolve("splash.png").toFile();
if (splashFile.exists()) {
splash.setImageURL(splashFile.toURI().toURL());
}
} catch (IOException ex) {
// A problem occurred trying to set custom splash.
// Log error and use default splash screen.
System.err.println(ex);
}
}
}
private static void setPlayerDeck(String deckArg, DuelPlayerConfig player) {
if (deckArg.isEmpty()) {
player.setDeckProfile("Random;***");
DeckGenerators.setRandomDeck(player);
return;
} else if (deckArg.equals("@")) { // random deck file.
player.setDeckProfile("Random;@");
DeckGenerators.setRandomDeck(player);
return;
} else if (deckArg.equals("#")) { // random single color deck.
player.setDeckProfile("Random;*");
DeckGenerators.setRandomDeck(player);
return;
} else if (deckArg.equals("##")) { //random two-color deck.
player.setDeckProfile("Random;**");
DeckGenerators.setRandomDeck(player);
return;
} else if (deckArg.equals("###")) { // random three-color deck.
player.setDeckProfile("Random;***");
DeckGenerators.setRandomDeck(player);
return;
} else if (!deckArg.isEmpty()) { // search for deck file.
File deckFile = DeckUtils.findDeckFile(deckArg);
if (deckFile != null) {
MagicDeck deck = DeckUtils.loadDeckFromFile(deckFile.toPath());
if (deck.isValid()) {
player.setDeck(deck);
return;
}
}
}
throw new InvalidDeckException("Invalid deck specified in command line : " + deckArg);
}
private static void runAivsAiGame(CommandLineArgs cmdline) {
System.out.println("");
System.err.println("=== AI vs AI ===");
final DuelConfig config = DuelConfig.getInstance();
config.load();
config.setPlayerProfile(0, AiProfile.create(cmdline.getAi1(), cmdline.getAi1Level()));
config.setPlayerProfile(1, AiProfile.create(cmdline.getAi2(), cmdline.getAi2Level()));
setPlayerDeck(cmdline.getDeck1(), config.getPlayerConfig(0));
setPlayerDeck(cmdline.getDeck2(), config.getPlayerConfig(1));
config.setNrOfGames(cmdline.getGames());
config.setStartLife(cmdline.getLife());
System.out.println("P1 : " + config.getPlayerProfile(0).getPlayerLabel());
System.out.println(" " + config.getPlayerConfig(0).getDeck().getQualifiedName());
System.out.println("P2 : " + config.getPlayerProfile(1).getPlayerLabel());
System.out.println(" " + config.getPlayerConfig(1).getDeck().getQualifiedName());
System.out.println("Threads : " + MagicAI.getMaxThreads());
ScreenController.getFrame().newDuel(config);
}
private static void startUI(CommandLineArgs cmdline) {
// -DtestGame=X, where X is one of the classes (without the .java) in "magic.test".
final String testGame = System.getProperty("testGame");
if (testGame != null) {
ScreenController.showDuelGameScreen(TestGameBuilder.buildGame(testGame));
return;
}
// -DsaveGame=X, where X is the path to a snapshot.game
final String saveGame = System.getProperty("saveGame");
if (saveGame != null) {
final File f = new File(saveGame);
ScreenController.showDuelGameScreen(GameLoader.loadSavedGame(f));
return;
}
// AI vs AI game.
if (MagicSystem.isAiVersusAi()) {
try {
runAivsAiGame(cmdline);
} catch (InvalidDeckException ex) {
System.err.println(ex);
} catch (RuntimeException ex) {
LOGGER.log(Level.SEVERE, null, ex);
}
return;
}
// normal UI startup.
ScreenController.showStartScreen();
}
}