/* * This file is part of The Technic Launcher Version 3. * Copyright ©2015 Syndicate, LLC * * The Technic Launcher is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The Technic Launcher is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with the Technic Launcher. If not, see <http://www.gnu.org/licenses/>. */ package net.technicpack.launcher; import com.beust.jcommander.JCommander; import net.technicpack.autoupdate.IBuildNumber; import net.technicpack.autoupdate.Relauncher; import net.technicpack.autoupdate.http.HttpUpdateStream; import net.technicpack.discord.CacheDiscordApi; import net.technicpack.discord.HttpDiscordApi; import net.technicpack.discord.IDiscordApi; import net.technicpack.launcher.autoupdate.CommandLineBuildNumber; import net.technicpack.launcher.autoupdate.TechnicRelauncher; import net.technicpack.launcher.autoupdate.VersionFileBuildNumber; import net.technicpack.launcher.io.*; import net.technicpack.launcher.settings.migration.IMigrator; import net.technicpack.launcher.settings.migration.InitialV3Migrator; import net.technicpack.launcher.ui.InstallerFrame; import net.technicpack.launcher.ui.components.discover.DiscoverInfoPanel; import net.technicpack.launcher.ui.components.modpacks.ModpackSelector; import net.technicpack.launchercore.auth.IAuthListener; import net.technicpack.launchercore.auth.IUserStore; import net.technicpack.launchercore.exception.DownloadException; import net.technicpack.launchercore.image.face.CrafatarFaceImageStore; import net.technicpack.launchercore.launch.java.JavaVersionRepository; import net.technicpack.launchercore.launch.java.source.FileJavaSource; import net.technicpack.launchercore.launch.java.source.InstalledJavaSource; import net.technicpack.launchercore.logging.BuildLogFormatter; import net.technicpack.launchercore.logging.RotatingFileHandler; import net.technicpack.launchercore.modpacks.PackLoader; import net.technicpack.launchercore.modpacks.sources.IAuthoritativePackSource; import net.technicpack.minecraftcore.mojang.auth.MojangUser; import net.technicpack.platform.IPlatformSearchApi; import net.technicpack.platform.cache.ModpackCachePlatformApi; import net.technicpack.platform.http.HttpPlatformSearchApi; import net.technicpack.solder.cache.CachedSolderApi; import net.technicpack.ui.components.Console; import net.technicpack.ui.components.ConsoleFrame; import net.technicpack.ui.components.ConsoleHandler; import net.technicpack.ui.components.LoggerOutputStream; import net.technicpack.ui.controls.installation.SplashScreen; import net.technicpack.ui.lang.ResourceLoader; import net.technicpack.launcher.launch.Installer; import net.technicpack.launcher.settings.SettingsFactory; import net.technicpack.launcher.settings.StartupParameters; import net.technicpack.launcher.settings.TechnicSettings; import net.technicpack.launcher.ui.LauncherFrame; import net.technicpack.launcher.ui.LoginFrame; import net.technicpack.launchercore.auth.IUserType; import net.technicpack.minecraftcore.mojang.auth.AuthenticationService; import net.technicpack.launchercore.auth.UserModel; import net.technicpack.launchercore.image.ImageRepository; import net.technicpack.launchercore.image.face.WebAvatarImageStore; import net.technicpack.launchercore.install.ModpackInstaller; import net.technicpack.minecraftcore.launch.MinecraftLauncher; import net.technicpack.launchercore.modpacks.ModpackModel; import net.technicpack.launchercore.modpacks.resources.PackImageStore; import net.technicpack.launchercore.modpacks.resources.PackResourceMapper; import net.technicpack.launchercore.modpacks.resources.resourcetype.BackgroundResourceType; import net.technicpack.launchercore.modpacks.resources.resourcetype.IModpackResourceType; import net.technicpack.launchercore.modpacks.resources.resourcetype.IconResourceType; import net.technicpack.launchercore.modpacks.resources.resourcetype.LogoResourceType; import net.technicpack.launchercore.modpacks.sources.IInstalledPackRepository; import net.technicpack.launchercore.install.LauncherDirectories; import net.technicpack.launchercore.mirror.MirrorStore; import net.technicpack.launchercore.mirror.secure.rest.JsonWebSecureMirror; import net.technicpack.platform.IPlatformApi; import net.technicpack.platform.PlatformPackInfoRepository; import net.technicpack.platform.http.HttpPlatformApi; import net.technicpack.platform.io.AuthorshipInfo; import net.technicpack.solder.ISolderApi; import net.technicpack.solder.SolderPackSource; import net.technicpack.solder.http.HttpSolderApi; import net.technicpack.utilslib.OperatingSystem; import net.technicpack.utilslib.Utils; import org.apache.commons.io.FileUtils; import org.joda.time.DateTime; import sun.misc.ClassLoaderUtil; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.IOException; import java.io.PrintStream; import java.io.UnsupportedEncodingException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Iterator; import java.util.Locale; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.Logger; public class LauncherMain { public static ConsoleFrame consoleFrame; public static Locale[] supportedLanguages = new Locale[] { Locale.ENGLISH, new Locale("pt","BR"), new Locale("pt","PT"), new Locale("cs"), Locale.GERMAN, Locale.FRENCH, Locale.ITALIAN, new Locale("hu"), new Locale("pl"), Locale.CHINA, Locale.TAIWAN }; public static void main(String[] args) { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception ex) { Utils.getLogger().log(Level.SEVERE, ex.getMessage(), ex); } ToolTipManager.sharedInstance().setDismissDelay(Integer.MAX_VALUE); StartupParameters params = new StartupParameters(args); try { new JCommander(params, args); } catch (Exception ex) { ex.printStackTrace(); } TechnicSettings settings = null; try { settings = SettingsFactory.buildSettingsObject(Relauncher.getRunningPath(LauncherMain.class), params.isMover()); } catch (UnsupportedEncodingException ex) { ex.printStackTrace(); } if (settings == null) { ResourceLoader installerResources = new ResourceLoader(null, "net","technicpack","launcher","resources"); installerResources.setSupportedLanguages(supportedLanguages); installerResources.setLocale(ResourceLoader.DEFAULT_LOCALE); InstallerFrame dialog = new InstallerFrame(installerResources, params); dialog.setVisible(true); return; } LauncherDirectories directories = new TechnicLauncherDirectories(settings.getTechnicRoot()); ResourceLoader resources = new ResourceLoader(directories, "net","technicpack","launcher","resources"); resources.setSupportedLanguages(supportedLanguages); resources.setLocale(settings.getLanguageCode()); IBuildNumber buildNumber = null; if (params.getBuildNumber() != null && !params.getBuildNumber().isEmpty()) buildNumber = new CommandLineBuildNumber(params); else buildNumber = new VersionFileBuildNumber(resources); setupLogging(directories, resources, buildNumber); String launcherBuild = buildNumber.getBuildNumber(); int build = -1; try { build = Integer.parseInt((new VersionFileBuildNumber(resources)).getBuildNumber()); } catch (NumberFormatException ex) { //This is probably a debug build or something, build number is invalid } Relauncher launcher = new TechnicRelauncher(new HttpUpdateStream("http://api.technicpack.net/launcher/"), settings.getBuildStream()+"4", build, directories, resources, params); try { if (launcher.runAutoUpdater()) startLauncher(settings, params, directories, resources, buildNumber); } catch (InterruptedException e) { //Canceled by user } catch (DownloadException e) { //JOptionPane.showMessageDialog(null, resources.getString("launcher.updateerror.download", pack.getDisplayName(), e.getMessage()), resources.getString("launcher.installerror.title"), JOptionPane.WARNING_MESSAGE); } catch (IOException e) { e.printStackTrace(); } } private static void setupLogging(LauncherDirectories directories, ResourceLoader resources, IBuildNumber buildNumber) { System.out.println("Setting up logging"); final Logger logger = Utils.getLogger(); File logDirectory = new File(directories.getLauncherDirectory(), "logs"); if (!logDirectory.exists()) { logDirectory.mkdir(); } File logs = new File(logDirectory, "techniclauncher_%D.log"); RotatingFileHandler fileHandler = new RotatingFileHandler(logs.getPath()); fileHandler.setFormatter(new BuildLogFormatter(buildNumber.getBuildNumber())); for (Handler h : logger.getHandlers()) { logger.removeHandler(h); } logger.addHandler(fileHandler); logger.setUseParentHandlers(false); LauncherMain.consoleFrame = new ConsoleFrame(2500, resources.getImage("icon.png")); Console console = new Console(LauncherMain.consoleFrame, buildNumber.getBuildNumber()); logger.addHandler(new ConsoleHandler(console)); System.setOut(new PrintStream(new LoggerOutputStream(console, Level.INFO, logger), true)); System.setErr(new PrintStream(new LoggerOutputStream(console, Level.SEVERE, logger), true)); Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { @Override public void uncaughtException(Thread t, Throwable e) { e.printStackTrace(); logger.log(Level.SEVERE, "Unhandled Exception in " + t, e); // if (errorDialog == null) { // LauncherFrame frame = null; // // try { // frame = Launcher.getFrame(); // } catch (Exception ex) { // //This can happen if we have a very early crash- before Launcher initializes // } // // errorDialog = new ErrorDialog(frame, e); // errorDialog.setVisible(true); // } } }); } private static void startLauncher(final TechnicSettings settings, StartupParameters startupParameters, final LauncherDirectories directories, ResourceLoader resources, IBuildNumber buildNumber) { UIManager.put( "ComboBox.disabledBackground", LauncherFrame.COLOR_FORMELEMENT_INTERNAL ); UIManager.put( "ComboBox.disabledForeground", LauncherFrame.COLOR_GREY_TEXT ); System.setProperty("xr.load.xml-reader", "org.ccil.cowan.tagsoup.Parser"); //Remove all log files older than a week new Thread(new Runnable() { @Override public void run() { Iterator<File> files = FileUtils.iterateFiles(new File(directories.getLauncherDirectory(), "logs"), new String[] {"log"}, false); while (files.hasNext()) { File logFile = files.next(); if (logFile.exists() && (new DateTime(logFile.lastModified())).isBefore(DateTime.now().minusWeeks(1))) { logFile.delete(); } } } }).start(); Utils.getLogger().info("OS: " + System.getProperty("os.name").toLowerCase(Locale.ENGLISH)); Utils.getLogger().info("Identified as "+ OperatingSystem.getOperatingSystem().getName()); final SplashScreen splash = new SplashScreen(resources.getImage("launch_splash.png"), 0); Color bg = LauncherFrame.COLOR_FORMELEMENT_INTERNAL; splash.getContentPane().setBackground(new Color (bg.getRed(),bg.getGreen(),bg.getBlue(),255)); splash.pack(); splash.setLocationRelativeTo(null); splash.setVisible(true); boolean loadedAether = false; try { if (Class.forName("org.apache.maven.repository.internal.MavenRepositorySystemUtils", false, ClassLoader.getSystemClassLoader()) != null) { loadedAether = true; } } catch (ClassNotFoundException ex) { //Aether is not loaded } if (!loadedAether) { File launcherAssets = new File(directories.getAssetsDirectory(), "launcher"); File aether = new File(launcherAssets, "aether-dep.jar"); try { Method m = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); m.setAccessible(true); m.invoke(ClassLoader.getSystemClassLoader(), aether.toURI().toURL()); } catch (NoSuchMethodException ex) { ex.printStackTrace(); } catch (InvocationTargetException ex) { ex.printStackTrace(); } catch (IllegalAccessException ex) { ex.printStackTrace(); } catch (MalformedURLException ex) { ex.printStackTrace(); } } JavaVersionRepository javaVersions = new JavaVersionRepository(); (new InstalledJavaSource()).enumerateVersions(javaVersions); FileJavaSource javaVersionFile = FileJavaSource.load(new File(settings.getTechnicRoot(), "javaVersions.json")); javaVersionFile.enumerateVersions(javaVersions); javaVersions.selectVersion(settings.getJavaVersion(), settings.getJavaBitness()); IUserStore<MojangUser> users = TechnicUserStore.load(new File(directories.getLauncherDirectory(),"users.json")); UserModel userModel = new UserModel(users, new AuthenticationService()); MirrorStore mirrorStore = new MirrorStore(userModel); mirrorStore.addSecureMirror("mirror.technicpack.net", new JsonWebSecureMirror("http://mirror.technicpack.net/", "mirror.technicpack.net")); IModpackResourceType iconType = new IconResourceType(); IModpackResourceType logoType = new LogoResourceType(); IModpackResourceType backgroundType = new BackgroundResourceType(); PackResourceMapper iconMapper = new PackResourceMapper(directories, resources.getImage("icon.png"), iconType); ImageRepository<ModpackModel> iconRepo = new ImageRepository<ModpackModel>(iconMapper, new PackImageStore(iconType, mirrorStore, userModel)); ImageRepository<ModpackModel> logoRepo = new ImageRepository<ModpackModel>(new PackResourceMapper(directories, resources.getImage("modpack/ModImageFiller.png"), logoType), new PackImageStore(logoType, mirrorStore, userModel)); ImageRepository<ModpackModel> backgroundRepo = new ImageRepository<ModpackModel>(new PackResourceMapper(directories, null, backgroundType), new PackImageStore(backgroundType, mirrorStore, userModel)); ImageRepository<IUserType> skinRepo = new ImageRepository<IUserType>(new TechnicFaceMapper(directories, resources), new CrafatarFaceImageStore("http://crafatar.com/", mirrorStore)); ImageRepository<AuthorshipInfo> avatarRepo = new ImageRepository<AuthorshipInfo>(new TechnicAvatarMapper(directories, resources), new WebAvatarImageStore(mirrorStore)); HttpSolderApi httpSolder = new HttpSolderApi(settings.getClientId(), userModel); ISolderApi solder = new CachedSolderApi(directories, httpSolder, 60 * 60); HttpPlatformApi httpPlatform = new HttpPlatformApi("http://api.technicpack.net/", mirrorStore, buildNumber.getBuildNumber()); IPlatformApi platform = new ModpackCachePlatformApi(httpPlatform, 60 * 60, directories); IPlatformSearchApi platformSearch = new HttpPlatformSearchApi("http://api.technicpack.net/", buildNumber.getBuildNumber()); IInstalledPackRepository packStore = TechnicInstalledPackStore.load(new File(directories.getLauncherDirectory(), "installedPacks")); IAuthoritativePackSource packInfoRepository = new PlatformPackInfoRepository(platform, solder); ArrayList<IMigrator> migrators = new ArrayList<IMigrator>(1); migrators.add(new InitialV3Migrator(platform)); SettingsFactory.migrateSettings(settings, packStore, directories, users, migrators); PackLoader packList = new PackLoader(directories, packStore, packInfoRepository); ModpackSelector selector = new ModpackSelector(resources, packList, new SolderPackSource("http://solder.technicpack.net/api/", solder), solder, platform, platformSearch, iconRepo); selector.setBorder(BorderFactory.createEmptyBorder()); userModel.addAuthListener(selector); resources.registerResource(selector); DiscoverInfoPanel discoverInfoPanel = new DiscoverInfoPanel(resources, startupParameters.getDiscoverUrl(), platform, directories, selector); MinecraftLauncher launcher = new MinecraftLauncher(platform, directories, userModel, javaVersions); ModpackInstaller modpackInstaller = new ModpackInstaller(platform, settings.getClientId()); Installer installer = new Installer(startupParameters, mirrorStore, directories, modpackInstaller, launcher, settings, iconMapper); IDiscordApi discordApi = new HttpDiscordApi("https://discordapp.com/api/"); discordApi = new CacheDiscordApi(discordApi, 600, 60); final LauncherFrame frame = new LauncherFrame(resources, skinRepo, userModel, settings, selector, iconRepo, logoRepo, backgroundRepo, installer, avatarRepo, platform, directories, packStore, startupParameters, discoverInfoPanel, javaVersions, javaVersionFile, buildNumber, discordApi); userModel.addAuthListener(frame); ActionListener listener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { splash.dispose(); if (settings.getLaunchToModpacks()) frame.selectTab("modpacks"); } }; discoverInfoPanel.setLoadListener(listener); LoginFrame login = new LoginFrame(resources, settings, userModel, skinRepo); userModel.addAuthListener(login); userModel.addAuthListener(new IAuthListener() { @Override public void userChanged(Object user) { if (user == null) splash.dispose(); } }); userModel.initAuth(); Utils.sendTracking("runLauncher", "run", buildNumber.getBuildNumber(), settings.getClientId()); } }