Package net.ftb.minecraft

Source Code of net.ftb.minecraft.MCLauncher

/*
* This file is part of FTB Launcher.
*
* Copyright © 2012-2014, FTB Launcher Contributors <https://github.com/Slowpoke101/FTBLaunch/>
* FTB Launcher is licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.ftb.minecraft;

import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.Map.Entry;

import com.google.common.collect.Lists;
import net.feed_the_beast.launcher.json.JsonFactory;
import net.feed_the_beast.launcher.json.OldPropertyMapSerializer;
import net.feed_the_beast.launcher.json.assets.AssetIndex;
import net.feed_the_beast.launcher.json.assets.AssetIndex.Asset;
import net.ftb.data.ModPack;
import net.ftb.data.Settings;
import net.ftb.download.Locations;
import net.ftb.log.Logger;
import net.ftb.util.*;

import com.google.gson.GsonBuilder;
import com.google.gson.JsonIOException;
import com.google.gson.JsonSyntaxException;
import com.mojang.authlib.UserAuthentication;
import com.mojang.authlib.UserType;
import com.mojang.authlib.properties.PropertyMap;
import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication;
import com.mojang.util.UUIDTypeAdapter;

import javax.swing.*;

public class MCLauncher {
    public static boolean isLegacy = false;
    private static String separator = File.separator;
    private static String gameDirectory;
    private static StringBuilder cpb;

    public static Process launchMinecraft (String javaPath, String gameFolder, File assetDir, File nativesDir, List<File> classpath, String mainClass, String args, String assetIndex, String rmax,
            String maxPermSize, String version, UserAuthentication authentication, boolean legacy) throws IOException {

        cpb = new StringBuilder("");
        isLegacy = legacy;
        gameDirectory = gameFolder;
        File gameDir = new File(gameFolder);
        assetDir = syncAssets(assetDir, assetIndex);

        for (File f : classpath) {
            cpb.append(OSUtils.getJavaDelimiter());
            cpb.append(f.getAbsolutePath());
        }
        if (isLegacy) {
            setupLegacyStuff(gameDirectory, Locations.FORGENAME);
        }
        //Logger.logInfo("ClassPath: " + cpb.toString());

        List<String> arguments = Lists.newArrayList();

        Logger.logInfo("Java Path: " + javaPath);
        Logger.logInfo("Pack: " + ModPack.getSelectedPack().getName() + " " + version);
        arguments.add(javaPath);

        setMemory(arguments, rmax);

        if (OSUtils.getCurrentOS().equals(OSUtils.OS.WINDOWS)) {
            if (!OSUtils.is64BitWindows()) {
                if (maxPermSize == null || maxPermSize.isEmpty()) {
                    if (OSUtils.getOSTotalMemory() > 2046) {
                        maxPermSize = "192m";
                        Logger.logInfo("Defaulting PermSize to 192m");
                    } else {
                        maxPermSize = "128m";
                        Logger.logInfo("Defaulting PermSize to 128m");
                    }
                }
            }
        }

        if (maxPermSize == null || maxPermSize.isEmpty()) {
            // 64-bit or Non-Windows
            maxPermSize = "256m";
            Logger.logInfo("Defaulting PermSize to 256m");
        }

        arguments.add("-XX:PermSize=" + maxPermSize);
        arguments.add("-Djava.library.path=" + nativesDir.getAbsolutePath());
        arguments.add("-Dorg.lwjgl.librarypath=" + nativesDir.getAbsolutePath());
        arguments.add("-Dnet.java.games.input.librarypath=" + nativesDir.getAbsolutePath());
        arguments.add("-Duser.home=" + gameDir.getParentFile().getAbsolutePath());

        if (OSUtils.getCurrentOS() == OSUtils.OS.WINDOWS) {
            arguments.add("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump");
        }

        // Use IPv4 when possible, only use IPv6 when connecting to IPv6 only addresses
        arguments.add("-Djava.net.preferIPv4Stack=true");

        if (Settings.getSettings().getUseSystemProxy()) {
            arguments.add("-Djava.net.useSystemProxies=true");
        }

        arguments.add("-cp");
        arguments.add(cpb.toString());

        String additionalOptions = Settings.getSettings().getAdditionalJavaOptions();
        if (!additionalOptions.isEmpty()) {
            Logger.logInfo("Additional java parameters: " + additionalOptions);
            for (String s : additionalOptions.split("\\s+")) {
                if (s.equalsIgnoreCase("-Dfml.ignoreInvalidMinecraftCertificates=true") && !isLegacy) {
                    String curVersion = (Settings.getSettings().getPackVer().equalsIgnoreCase("recommended version") ? ModPack.getSelectedPack().getVersion() :
                            Settings.getSettings().getPackVer()).replace(".", "_");
                    TrackerUtils.sendPageView("JarmodAttempt", "JarmodAttempt / " + ModPack.getSelectedPack().getName() + " / " + curVersion.replace('_', '.'));
                    ErrorUtils.tossError("JARMODDING DETECTED in 1.6.4+ " + s, "FTB Does not support jarmodding in MC 1.6+ ");
                } else {
                    arguments.add(s);
                }
            }
        }
        if (Settings.getSettings().getOptJavaArgs()) {
            Logger.logInfo("Adding Optimization Arguments");
            Collections.addAll(arguments, "-XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CICompilerCountPerCPU -XX:+TieredCompilation".split("\\s+"));
        }

        //Undocumented environment variable to control JVM
        String additionalEnvVar = System.getenv("_JAVA_OPTIONS");
        if (additionalEnvVar != null && !additionalEnvVar.isEmpty()) {
            Logger.logDebug("_JAVA_OPTIONS has following arguments: " + additionalEnvVar + " Arguments will  be ignored at MC startup");
        }
        //Documented environment variable to control JVM
        additionalEnvVar = System.getenv("JAVA_TOOL_OPTIONS");
        if (additionalEnvVar != null && !additionalEnvVar.isEmpty()) {
            Logger.logDebug("JAVA_TOOL_OPTIONS has following arguments: " + additionalEnvVar + " Arguments will  be ignored at MC startup");
        }
        //Documented environment variable to control JVM
        additionalEnvVar = System.getenv("JAVA_OPTIONS");
        if (additionalEnvVar != null && !additionalEnvVar.isEmpty()) {
            Logger.logDebug("JAVA_OPTIONS has following arguments: " + additionalEnvVar + " Arguments will  be ignored at MC startup");
        }

        arguments.add(mainClass);
        for (String s : args.split(" ")) {
            boolean done = false;
            if (authentication.getSelectedProfile() != null) {
                if (s.equals("${auth_player_name}")) {
                    arguments.add(authentication.getSelectedProfile().getName());
                    done = true;
                } else if (s.equals("${auth_uuid}")) {
                    arguments.add(UUIDTypeAdapter.fromUUID(authentication.getSelectedProfile().getId()));
                    done = true;
                } else if (s.equals("${user_type}")) {
                    arguments.add(authentication.getUserType().getName());
                    done = true;
                }
            } else {
                if (s.equals("${auth_player_name}")) {
                    arguments.add("Player");
                    done = true;
                } else if (s.equals("${auth_uuid}")) {
                    arguments.add(new UUID(0L, 0L).toString());
                    done = true;
                } else if (s.equals("${user_type}")) {
                    arguments.add(UserType.LEGACY.getName());
                    done = true;
                }
            }
            if (!done) {
                if (s.equals("${auth_session}")) {
                    if (authentication.isLoggedIn() && authentication.canPlayOnline()) {
                        if (authentication instanceof YggdrasilUserAuthentication && !isLegacy) {
                            arguments.add(String.format("token:%s:%s", authentication.getAuthenticatedToken(), UUIDTypeAdapter.fromUUID(authentication.getSelectedProfile().getId())));
                        } else {
                            arguments.add(authentication.getAuthenticatedToken());
                        }
                    } else {
                        arguments.add("-");
                    }
                } else if (s.equals("${auth_access_token}")) {
                    arguments.add(authentication.getAuthenticatedToken());
                } else if (s.equals("${version_name}")) {
                    arguments.add(version);
                } else if (s.equals("${game_directory}")) {
                    arguments.add(gameDir.getAbsolutePath());
                } else if (s.equals("${game_assets}") || s.equals("${assets_root}")) {
                    arguments.add(assetDir.getAbsolutePath());
                } else if (s.equals("${assets_index_name}")) {
                    arguments.add(assetIndex == null ? "legacy" : assetIndex);
                } else if (s.equals("${user_properties}")) {
                    arguments.add(new GsonBuilder().registerTypeAdapter(PropertyMap.class, new OldPropertyMapSerializer()).create().toJson(authentication.getUserProperties()));
                } else if (s.equals("${user_properties_map}")) {
                    arguments.add(new GsonBuilder().registerTypeAdapter(PropertyMap.class, new PropertyMap.Serializer()).create().toJson(authentication.getUserProperties()));
                } else if (isLegacy) {
                    arguments.add(parseLegacyArgs(s));
                } else {
                    arguments.add(s);
                }
            }
        }
        if (!isLegacy) {//legacy is handled separately
            boolean fullscreen = false;
            if (Settings.getSettings().getLastExtendedState() == JFrame.MAXIMIZED_BOTH) {
                GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
                Rectangle bounds = env.getMaximumWindowBounds();
                arguments.add("--width");
                arguments.add(String.valueOf((int) bounds.getWidth()));
                arguments.add("--height");
                arguments.add(String.valueOf((int) bounds.getHeight()));
                fullscreen = true;
            }
            Dimension def = new Dimension(854, 480);
            if (Settings.getSettings().getLastDimension().getWidth() != def.getWidth() && !fullscreen) {
                arguments.add("--width");
                arguments.add(String.valueOf(Math.abs((int) Settings.getSettings().getLastDimension().getWidth())));
            }
            if (Settings.getSettings().getLastDimension().getHeight() != def.getHeight() && !fullscreen) {
                arguments.add("--height");
                arguments.add(String.valueOf(Math.abs((int) Settings.getSettings().getLastDimension().getHeight())));
            }
        }

        ProcessBuilder builder = new ProcessBuilder(arguments);
        /*StringBuilder tmp = new StringBuilder();
        for (String a : builder.command())
            tmp.append(a).append(' ');
        Logger.logInfo("Launching: " + tmp.toString());*/
        builder.directory(gameDir);
        builder.redirectErrorStream(true);
        OSUtils.cleanEnvVars(builder.environment());
        return builder.start();
    }

    private static void setMemory (List<String> arguments, String rmax) {
        boolean memorySet = false;
        try {
            int min = 256;
            if (rmax != null && Integer.parseInt(rmax) > 0) {
                arguments.add("-Xms" + min + "M");
                Logger.logInfo("Setting MinMemory to " + min);
                arguments.add("-Xmx" + rmax + "M");
                Logger.logInfo("Setting MaxMemory to " + rmax);
                memorySet = true;
            }
        } catch (Exception e) {
            Logger.logError("Error parsing memory settings", e);
        }
        if (!memorySet) {
            arguments.add("-Xms" + 256 + "M");
            Logger.logInfo("Defaulting MinMemory to " + 256);
            arguments.add("-Xmx" + 1024 + "M");
            Logger.logInfo("Defaulting MaxMemory to " + 1024);
        }
    }

    private static File syncAssets (File assetDir, String indexName) throws JsonSyntaxException, JsonIOException, IOException {
        Logger.logInfo("Syncing Assets:");
        final File objects = new File(assetDir, "objects");
        AssetIndex index = JsonFactory.loadAssetIndex(new File(assetDir, "indexes/{INDEX}.json".replace("{INDEX}", indexName)));

        if (!index.virtual) {
            return assetDir;
        }

        final File targetDir = new File(assetDir, "virtual/" + indexName);

        final ConcurrentSkipListSet<File> old = new ConcurrentSkipListSet();
        old.addAll(FTBFileUtils.listFiles(targetDir));

        Benchmark.reset("threading");
        Parallel.TaskHandler th = new Parallel.ForEach(index.objects.entrySet())
                .withFixedThreads(2 * OSUtils.getNumCores())
                        //.configurePoolSize(2*2*OSUtils.getNumCores(), 10)
                .apply(new Parallel.F<Entry<String, Asset>, Void>() {
                    public Void apply (Entry<String, Asset> e) {
                        Asset asset = e.getValue();
                        File local = new File(targetDir, e.getKey());
                        File object = new File(objects, asset.hash.substring(0, 2) + "/" + asset.hash);

                        old.remove(local);

                        try {
                            if (local.exists() && !DownloadUtils.fileSHA(local).equals(asset.hash)) {
                                Logger.logInfo("  Changed: " + e.getKey());
                                FTBFileUtils.copyFile(object, local, true);
                            } else if (!local.exists()) {
                                Logger.logInfo("  Added: " + e.getKey());
                                FTBFileUtils.copyFile(object, local);
                            }
                        } catch (Exception ex) {
                            Logger.logError("Asset checking failed: ", ex);
                        }
                        return null;
                    }
                });
        try {
            th.shutdown();
            th.wait(60, TimeUnit.SECONDS);
        } catch (Exception ex) {
            Logger.logError("Asset checking failed: ", ex);
        }
        Benchmark.logBenchAs("threading", "parallel asset(virtual) check");

        for (File f : old) {
            String name = f.getAbsolutePath().replace(targetDir.getAbsolutePath(), "");
            Logger.logInfo("  Removed: " + name.substring(1));
            f.delete();
        }

        return targetDir;
    }

    public static String parseLegacyArgs (String s) {
        if (s.equals("${animation_name}")) {
            return (((!ModPack.getSelectedPack().getAnimation().equalsIgnoreCase("empty")) ? OSUtils.getCacheStorageLocation() + "ModPacks" + separator + ModPack.getSelectedPack().getDir()
                    + separator + ModPack.getSelectedPack().getAnimation() : "empty"));
        } else if (s.equals("${forge_name}")) {
            return Locations.FORGENAME;
        } else if (s.equals("${pack_name}")) {
            return (ModPack.getSelectedPack().getName() + " v"
                            + (Settings.getSettings().getPackVer().equalsIgnoreCase("recommended version") ? ModPack.getSelectedPack().getVersion() : Settings.getSettings().getPackVer()));
        } else if (s.equals("${pack_image}")) {
            return (OSUtils.getCacheStorageLocation() + "ModPacks" + separator + ModPack.getSelectedPack().getDir() + separator + ModPack.getSelectedPack().getLogoName());
        } else if (s.equals("${extended_state}")) {
            return (String.valueOf(Settings.getSettings().getLastExtendedState()));
        } else if (s.equals("${width}")) {
            return (String.valueOf(Settings.getSettings().getLastDimension().getWidth()));
        } else if (s.equals("${height}")) {
            return (String.valueOf(Settings.getSettings().getLastDimension().getHeight()));
        } else if (s.equals("${minecraft_jar}")) {
            return (gameDirectory + File.separator + "bin" + File.separator + Locations.OLDMCJARNAME);
        } else {
            return s;
        }
    }

    public static void setupLegacyStuff (String workingDir, String forgename) {
        File instModsDir = new File(new File(workingDir).getParentFile(), "instMods/");
        //jarmods are added inside the wrapper

        cpb.append(OSUtils.getJavaDelimiter());
        cpb.append(new File(instModsDir, forgename).getAbsolutePath());
        cpb.append(new File(new File(workingDir, "bin"), Locations.OLDMCJARNAME).getAbsolutePath());
        File libsDir = new File(workingDir, "lib/");
        if (libsDir.isDirectory()) {
            String[] files = libsDir.list();
            Arrays.sort(files);
            for (String name : files) {
                if ((name.toLowerCase().endsWith(".zip") || name.toLowerCase().endsWith(".jar"))) {
                    cpb.append(OSUtils.getJavaDelimiter());
                    cpb.append(new File(libsDir, name).getAbsolutePath());
                }
            }
        } else {
            Logger.logInfo("Not loading any FML libs, as the directory does not exist.");
        }
    }
}
TOP

Related Classes of net.ftb.minecraft.MCLauncher

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.