package sk.tomsik68.mclauncher.impl.versions.mcdownload;
import net.minidev.json.JSONObject;
import net.minidev.json.JSONStyle;
import net.minidev.json.JSONValue;
import sk.tomsik68.mclauncher.api.common.ILaunchSettings;
import sk.tomsik68.mclauncher.api.common.MCLauncherAPI;
import sk.tomsik68.mclauncher.api.common.mc.MinecraftInstance;
import sk.tomsik68.mclauncher.api.login.ISession;
import sk.tomsik68.mclauncher.api.mods.IModdingProfile;
import sk.tomsik68.mclauncher.api.servers.ServerInfo;
import sk.tomsik68.mclauncher.api.versions.IVersion;
import sk.tomsik68.mclauncher.api.versions.IVersionLauncher;
import sk.tomsik68.mclauncher.util.StringSubstitutor;
import sk.tomsik68.mclauncher.api.login.ISession.Prop;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
final class MCDownloadVersionLauncher implements IVersionLauncher {
private String[] getMinecraftArguments(MinecraftInstance mc, File assetsDir,
ISession session, ILaunchSettings settings,
MCDownloadVersion version) {
// TODO tooo lazy to finish options
String args = version.getMinecraftArgs();
StringSubstitutor subst = new StringSubstitutor("${%s}");
subst.setVariable("auth_session", session.getSessionID());
subst.setVariable("auth_access_token", session.getSessionID());
subst.setVariable("auth_player_name", session.getUsername());
subst.setVariable("auth_uuid", session.getUUID());
subst.setVariable("version_name", version.getId());
subst.setVariable("game_directory", mc.getLocation().getAbsolutePath());
subst.setVariable("game_assets", assetsDir
.getAbsolutePath());
subst.setVariable("assets_root", assetsDir
.getAbsolutePath());
subst.setVariable("assets_index_name", version.getAssetsIndexName());
subst.setVariable("user_type", session.getType().toString()
.toLowerCase());
if (session.getProperties() != null
&& !session.getProperties().isEmpty()) {
JSONObject propertiesObj = new JSONObject();
List<Prop> properties = session.getProperties();
for (Prop p : properties) {
propertiesObj.put(p.name, p.value);
}
subst.setVariable("user_properties",
propertiesObj.toJSONString(JSONStyle.NO_COMPRESS));
} else
subst.setVariable("user_properties", "{}");
args = subst.substitute(args);
return args.split(" ");
}
@Override
public List<String> getLaunchCommand(ISession session,
MinecraftInstance mc, ServerInfo server, IVersion v,
ILaunchSettings settings, IModdingProfile mods) throws Exception {
boolean moddingProfileSpecified = (mods != null);
MCDResourcesInstaller resourcesInstaller = new MCDResourcesInstaller(mc);
MCDJarManager jarManager = new MCDJarManager(mc);
LibraryProvider libraryProvider = new LibraryProvider(mc);
// get local JSON information about the version
File jsonFile = jarManager.getInfoFile(v);
MCLauncherAPI.log.fine("Looking for ".concat(jsonFile.getAbsolutePath()));
if (!jsonFile.exists()) {
throw new FileNotFoundException(
"You need to download the version at first! (JSON description file not found!)");
}
// create MCDownloadVersion based on this version
MCDownloadVersion version = (MCDownloadVersion) v;
File jarFile = jarManager.getVersionJAR(version);
// check if the version is compatible with our OS
MCLauncherAPI.log.fine("Checking version compatibility...");
if (!version.isCompatible()) {
throw new VersionIncompatibleException(version);
}
MCLauncherAPI.log.fine("Checking version inheritance...");
// check if everything's inherited
if(version.needsInheritance())
throw new VersionInheritanceException(version);
MCLauncherAPI.log.fine("Checking minecraft launcher API version...");
// check if we can launch it using the current version of MCLauncherAPI
if (version.getMinimumLauncherVersion() > MCLauncherAPI.MC_LAUNCHER_VERSION) {
throw new RuntimeException(
"You need to update MCLauncher-API to run this minecraft version! Required API version: "
+ version.getMinimumLauncherVersion());
}
MCLauncherAPI.log.fine("Building the launch command...");
// build the huge command!
ArrayList<String> command = new ArrayList<String>();
// prefix
if (settings.getCommandPrefix() != null)
command.addAll(settings.getCommandPrefix());
// java location if entered or just "java"
if (settings.getJavaLocation() != null)
command.add(settings.getJavaLocation().getAbsolutePath());
else
command.add("java");
// -Xms
if (settings.getInitHeap() != null
&& settings.getInitHeap().length() > 0)
command.add("-Xms".concat(settings.getInitHeap()));
// -Xmx
if (settings.getHeap() != null && settings.getHeap().length() > 0)
command.add("-Xmx".concat(settings.getHeap()));
// all additional java arguments
if (settings.getJavaArguments() != null) {
command.addAll(settings.getJavaArguments());
}
// find natives for this MC version
final File nativesDir = new File(jarManager.getVersionFolder(v), "natives");
command.add("-Djava.library.path=" + nativesDir.getAbsolutePath());
// build classpath
command.add("-cp");
StringBuilder librariesString = new StringBuilder();
final String LIBRARY_SEPARATOR = System.getProperty("path.separator");
//// mods can inject JARs before libraries
if(moddingProfileSpecified) {
File[] customFiles = mods.injectBeforeLibs(LIBRARY_SEPARATOR);
if(customFiles != null) {
MCLauncherAPI.log.fine("Injecting custom libraries before library list");
for (File file : customFiles) {
librariesString.append(file.getAbsolutePath()).append(LIBRARY_SEPARATOR);
}
}
}
MCLauncherAPI.log.fine("Adding library files");
//// now add library files
for (Library lib : version.getLibraries()) {
// each library has to be compatible, installed and allowed by modding profile
if (lib.isCompatible() && (!moddingProfileSpecified || mods.isLibraryAllowed(lib.getName()))) {
if (!libraryProvider.isInstalled(lib)) {
throw new FileNotFoundException("Library file wasn't found");
}
MCLauncherAPI.log.finest("Adding ".concat(lib.getName()));
librariesString = librariesString.append(libraryProvider.getLibraryFile(lib).getAbsolutePath()).append(
LIBRARY_SEPARATOR);
}
}
//// mods can inject JARs after libraries
if(moddingProfileSpecified) {
File[] customFiles = mods.injectAfterLibs(LIBRARY_SEPARATOR);
if(customFiles != null) {
MCLauncherAPI.log.fine("Injecting custom libraries after library list");
for (File file : customFiles) {
librariesString.append(file.getAbsolutePath()).append(LIBRARY_SEPARATOR);
}
}
}
// append the game JAR at the end
String jarToUse = jarFile.getAbsolutePath();
if(moddingProfileSpecified && mods.getCustomGameJar() != null) {
MCLauncherAPI.log.fine("Replacing game JAR");
jarToUse = mods.getCustomGameJar().getAbsolutePath();
}
librariesString = librariesString.append(jarToUse);
// append the whole classpath to command
command.add(librariesString.toString());
// look for the main class
String mainClass = version.getMainClass();
if(moddingProfileSpecified && mods.getMainClass() != null){
MCLauncherAPI.log.fine("Replacing main class");
mainClass = mods.getMainClass();
}
command.add(mainClass);
// create minecraft arguments
String[] arguments = getMinecraftArguments(mc, resourcesInstaller.getAssetsDirectory(), session, settings,
version);
// give mods opportunity to change minecraft arguments
if(moddingProfileSpecified){
String[] args = mods.changeMinecraftArguments(arguments);
if(args != null) {
arguments = args;
MCLauncherAPI.log.fine("Replacing minecraft arguments");
}
}
// now append all minecraft arguments to the command
for (String arg : arguments) {
command.add(arg);
}
// if server is specified, append --server and --port
if (server != null) {
command.add("--server");
command.add(server.getIP());
command.add("--port");
command.add("" + server.getPort());
}
// mods have final chance to add parameters
if(moddingProfileSpecified && mods.getLastParameters() != null){
command.addAll(mods.getLastParameters());
MCLauncherAPI.log.fine("Adding last parameters after the entire command");
}
MCLauncherAPI.log.fine("Launching command is now ready.");
return command;
}
}