package net.classicube.launcher; import java.io.File; import java.io.IOException; import java.util.NoSuchElementException; import java.util.Scanner; import java.util.logging.Level; import net.classicube.launcher.gui.DebugWindow; import net.classicube.launcher.gui.ErrorScreen; import org.apache.commons.lang3.StringUtils; // Handles launching the client process. final public class ClientLauncher { private static final String ClassPath = "client.jar" + File.pathSeparatorChar + "libs/*", ClientClassPath = "com.oyasunadev.mcraft.client.core.ClassiCubeStandalone"; public static void launchClient(final ServerJoinInfo joinInfo) { LogUtil.getLogger().info("launchClient"); if (joinInfo != null) { SessionManager.getSession().storeResumeInfo(joinInfo); }// else if joinInfo==null, then we're launching singleplayer final File java = PathUtil.getJavaPath(); final String nativePath; try { nativePath = new File(PathUtil.getClientDir(), "natives").getCanonicalPath(); } catch (final IOException | SecurityException ex) { ErrorScreen.show("Could not launch the game", "Error finding the LWJGL native library path:<br>" + ex.getMessage(), ex); return; } try { String mppass; if (joinInfo == null || joinInfo.pass == null || joinInfo.pass.length() == 0) { mppass = "none"; } else { mppass = joinInfo.pass; } final ProcessBuilder processBuilder = new ProcessBuilder( java.getAbsolutePath(), "-cp", ClassPath, "-Djava.library.path=" + nativePath, Prefs.getJavaArgs(), "-Xmx" + Prefs.getMaxMemory() + "m", ClientClassPath, (joinInfo == null ? "none" : joinInfo.address.getHostAddress()), (joinInfo == null ? "0" : Integer.toString(joinInfo.port)), (joinInfo == null ? "none" : joinInfo.playerName), mppass, SessionManager.getSession().getSkinUrl(), Boolean.toString(Prefs.getFullscreen())); processBuilder.directory(PathUtil.getClientDir()); // log the command used to launch client String cmdLineToLog = StringUtils.join(processBuilder.command(), ' '); if (joinInfo != null && joinInfo.pass != null && joinInfo.pass.length() > 16) { // sanitize mppass -- we don't want it logged. cmdLineToLog = cmdLineToLog.replace(joinInfo.pass, "########"); } LogUtil.getLogger().log(Level.INFO, cmdLineToLog); if (Prefs.getDebugMode()) { processBuilder.redirectErrorStream(true); try { final Process p = processBuilder.start(); DebugWindow.setWindowTitle("Game Running"); // capture output from the client, redirect to DebugWindow new Thread() { @Override public void run() { try { Scanner input = new Scanner(p.getInputStream()); while (true) { DebugWindow.writeLine(input.nextLine()); } } catch (NoSuchElementException ex) { DebugWindow.writeLine("(client closed)"); DebugWindow.setWindowTitle("Client Closed"); } } }.start(); } catch (IOException ex) { LogUtil.getLogger().log(Level.SEVERE, "Error launching client", ex); } } else { processBuilder.start(); if (!Prefs.getKeepOpen()) { System.exit(0); } } } catch (final Exception ex) { ErrorScreen.show("Could not launch the game", "Error launching the client:<br>" + ex.getMessage(), ex); } } private ClientLauncher() { } }