Search in sources :

Example 1 with Version

use of kml.game.version.Version in project Krothium-Launcher by DarkLBP.

the class GameLauncher method launch.

/**
 * Prepares and launcher the game
 * @throws GameLauncherException If an error has been thrown
 */
public final void launch(final MainFX mainFX) throws GameLauncherException {
    console.print("Game launch work has started.");
    Profile p = kernel.getProfiles().getSelectedProfile();
    if (isRunning()) {
        throw new GameLauncherException("Game is already started!");
    }
    Versions versions = kernel.getVersions();
    VersionMeta verID;
    switch(p.getType()) {
        case CUSTOM:
            verID = p.hasVersion() ? p.getVersionID() : versions.getLatestRelease();
            break;
        case RELEASE:
            verID = versions.getLatestRelease();
            break;
        default:
            verID = versions.getLatestSnapshot();
            break;
    }
    if (verID == null) {
        throw new GameLauncherException("Version ID is null.");
    }
    Version ver = versions.getVersion(verID);
    if (ver == null) {
        throw new GameLauncherException("Version info could not be obtained.");
    }
    File workingDir = Kernel.APPLICATION_WORKING_DIR;
    console.print("Deleting old natives.");
    File nativesRoot = new File(workingDir + File.separator + "versions" + File.separator + ver.getID());
    if (nativesRoot.isDirectory()) {
        File[] files = nativesRoot.listFiles();
        if (files != null) {
            for (File f : files) {
                if (f.isDirectory() && f.getName().contains("natives")) {
                    Utils.deleteDirectory(f);
                }
            }
        }
    }
    final File nativesDir = new File(workingDir, "versions" + File.separator + ver.getID() + File.separator + ver.getID() + "-natives-" + System.nanoTime());
    if (!nativesDir.isDirectory()) {
        nativesDir.mkdirs();
    }
    console.print("Launching Minecraft " + ver.getID() + " on " + workingDir.getAbsolutePath());
    console.print("Using natives dir: " + nativesDir);
    console.print("Extracting natives.");
    List<String> gameArgs = new ArrayList<>();
    if (p.hasJavaDir()) {
        gameArgs.add(p.getJavaDir().getAbsolutePath());
    } else {
        gameArgs.add(Utils.getJavaDir());
    }
    if (!p.hasJavaArgs()) {
        if (Utils.getOSArch() == OSArch.OLD) {
            gameArgs.add("-Xmx1G");
        } else {
            gameArgs.add("-Xmx2G");
        }
        gameArgs.add("-Xmn128M");
    } else {
        String javaArgs = p.getJavaArgs();
        String[] args = javaArgs.split(" ");
        Collections.addAll(gameArgs, args);
    }
    gameArgs.add("-Djava.library.path=" + nativesDir.getAbsolutePath());
    gameArgs.add("-cp");
    StringBuilder libraries = new StringBuilder();
    List<Library> libs = ver.getLibraries();
    String separator = System.getProperty("path.separator");
    Authentication a = kernel.getAuthentication();
    User u = a.getSelectedUser();
    if (u.getType() == UserType.KROTHIUM) {
        try {
            File launchPath = new File(GameLauncher.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
            libraries.append(launchPath.getAbsolutePath()).append(separator);
        } catch (URISyntaxException ex) {
            console.print("Failed to load GameStarter.");
        }
    }
    for (Library lib : libs) {
        if (!lib.isCompatible()) {
            continue;
        }
        if (lib.isNative()) {
            try {
                File completePath = new File(Kernel.APPLICATION_WORKING_DIR + File.separator + lib.getRelativeNativePath());
                FileInputStream input = new FileInputStream(completePath);
                Utils.decompressZIP(input, nativesDir, lib.getExtractExclusions());
            } catch (IOException ex) {
                console.print("Failed to extract native: " + lib.getName());
                ex.printStackTrace(console.getWriter());
            }
        } else {
            File completePath = new File(Kernel.APPLICATION_WORKING_DIR + File.separator + lib.getRelativePath());
            libraries.append(completePath.getAbsolutePath()).append(separator);
        }
    }
    console.print("Preparing game args.");
    File verPath = new File(Kernel.APPLICATION_WORKING_DIR + File.separator + ver.getRelativeJar());
    libraries.append(verPath.getAbsolutePath());
    File assetsDir;
    AssetIndex index = ver.getAssetIndex();
    File assetsRoot = new File(workingDir, "assets");
    if ("legacy".equals(index.getID())) {
        assetsDir = new File(assetsRoot, "virtual" + File.separator + "legacy");
        if (!assetsDir.isDirectory()) {
            assetsDir.mkdirs();
        }
        console.print("Building virtual asset folder.");
        File indexJSON = new File(assetsRoot, "indexes" + File.separator + index.getID() + ".json");
        try {
            JSONObject o = new JSONObject(new String(Files.readAllBytes(indexJSON.toPath()), "ISO-8859-1"));
            JSONObject objects = o.getJSONObject("objects");
            Set s = objects.keySet();
            for (Object value : s) {
                String name = value.toString();
                File assetFile = new File(assetsDir, name);
                JSONObject asset = objects.getJSONObject(name);
                String sha = asset.getString("hash");
                if (!Utils.verifyChecksum(assetFile, sha, "SHA-1")) {
                    File objectFile = new File(assetsRoot, "objects" + File.separator + sha.substring(0, 2) + File.separator + sha);
                    if (assetFile.getParentFile() != null) {
                        assetFile.getParentFile().mkdirs();
                    }
                    Files.copy(objectFile.toPath(), assetFile.toPath());
                }
            }
        } catch (Exception ex) {
            console.print("Failed to create virtual asset folder.");
            ex.printStackTrace(console.getWriter());
        }
    } else {
        assetsDir = assetsRoot;
    }
    gameArgs.add(libraries.toString());
    if (u.getType() == UserType.KROTHIUM) {
        gameArgs.add("kml.game.GameStarter");
    }
    gameArgs.add(ver.getMainClass());
    console.print("Full game launcher parameters: ");
    String[] versionArgs = ver.getMinecraftArguments().split(" ");
    for (int i = 0; i < versionArgs.length; i++) {
        if (versionArgs[i].startsWith("$")) {
            switch(versionArgs[i]) {
                case "${auth_player_name}":
                    versionArgs[i] = versionArgs[i].replace("${auth_player_name}", u.getDisplayName());
                    break;
                case "${version_name}":
                    versionArgs[i] = versionArgs[i].replace("${version_name}", ver.getID());
                    break;
                case "${game_directory}":
                    if (p.hasGameDir()) {
                        File gameDir = p.getGameDir();
                        if (!gameDir.isDirectory()) {
                            gameDir.mkdirs();
                        }
                        versionArgs[i] = versionArgs[i].replace("${game_directory}", gameDir.getAbsolutePath());
                    } else {
                        versionArgs[i] = versionArgs[i].replace("${game_directory}", workingDir.getAbsolutePath());
                    }
                    break;
                case "${assets_root}":
                    versionArgs[i] = versionArgs[i].replace("${assets_root}", assetsDir.getAbsolutePath());
                    break;
                case "${game_assets}":
                    versionArgs[i] = versionArgs[i].replace("${game_assets}", assetsDir.getAbsolutePath());
                    break;
                case "${assets_index_name}":
                    versionArgs[i] = versionArgs[i].replace("${assets_index_name}", index.getID());
                    break;
                case "${auth_uuid}":
                    versionArgs[i] = versionArgs[i].replace("${auth_uuid}", u.getSelectedProfile());
                    break;
                case "${auth_access_token}":
                    versionArgs[i] = versionArgs[i].replace("${auth_access_token}", u.getAccessToken());
                    break;
                case "${version_type}":
                    versionArgs[i] = versionArgs[i].replace("${version_type}", ver.getType().name());
                    break;
                case "${user_properties}":
                    versionArgs[i] = versionArgs[i].replace("${user_properties}", "{}");
                    break;
                case "${user_type}":
                    versionArgs[i] = versionArgs[i].replace("${user_type}", "mojang");
                    break;
                case "${auth_session}":
                    versionArgs[i] = versionArgs[i].replace("${auth_session}", "token:" + u.getAccessToken() + ':' + u.getSelectedProfile().replace("-", ""));
                    break;
            }
        }
    }
    Collections.addAll(gameArgs, versionArgs);
    if (p.hasResolution()) {
        gameArgs.add("--width");
        gameArgs.add(String.valueOf(p.getResolutionWidth()));
        gameArgs.add("--height");
        gameArgs.add(String.valueOf(p.getResolutionHeight()));
    }
    for (String arg : gameArgs) {
        console.print(arg);
    }
    ProcessBuilder pb = new ProcessBuilder(gameArgs);
    pb.directory(workingDir);
    try {
        process = pb.start();
        if (kernel.getSettings().getShowGameLog()) {
            Platform.runLater(new Runnable() {

                @Override
                public void run() {
                    FXMLLoader loader = new FXMLLoader();
                    loader.setLocation(GameLauncher.this.getClass().getResource("/kml/gui/fxml/Output.fxml"));
                    Parent parent;
                    try {
                        parent = loader.load();
                    } catch (IOException e) {
                        parent = null;
                        console.print("Failed to initialize Output GUI!");
                        e.printStackTrace(console.getWriter());
                    }
                    Stage stage = new Stage();
                    stage.getIcons().add(Kernel.APPLICATION_ICON);
                    stage.setTitle("Krothium Minecraft Launcher - " + Language.get(69));
                    stage.setScene(new Scene(parent));
                    stage.setResizable(true);
                    stage.setMaximized(false);
                    stage.show();
                    output = loader.getController();
                    outputGUI = stage;
                }
            });
        }
        Thread log_info = new Thread(new Runnable() {

            @Override
            public void run() {
                GameLauncher.this.pipeOutput(process.getInputStream());
            }
        });
        log_info.start();
        Thread log_error = new Thread(new Runnable() {

            @Override
            public void run() {
                GameLauncher.this.pipeOutput(process.getErrorStream());
            }
        });
        log_error.start();
        final Timer timer = new Timer();
        TimerTask process_status = new TimerTask() {

            @Override
            public void run() {
                if (!GameLauncher.this.isRunning()) {
                    boolean error;
                    if (GameLauncher.this.process.exitValue() != 0) {
                        error = true;
                        GameLauncher.this.console.print("Game stopped unexpectedly.");
                    } else {
                        error = false;
                    }
                    GameLauncher.this.console.print("Deleteting natives dir.");
                    Utils.deleteDirectory(nativesDir);
                    timer.cancel();
                    timer.purge();
                    mainFX.gameEnded(error);
                }
            }
        };
        timer.schedule(process_status, 0, 25);
    } catch (IOException ex) {
        ex.printStackTrace(console.getWriter());
        throw new GameLauncherException("Game returned an error code.");
    }
}
Also used : User(kml.auth.user.User) Parent(javafx.scene.Parent) URISyntaxException(java.net.URISyntaxException) FXMLLoader(javafx.fxml.FXMLLoader) Profile(kml.game.profile.Profile) Version(kml.game.version.Version) Stage(javafx.stage.Stage) VersionMeta(kml.game.version.VersionMeta) AssetIndex(kml.game.version.asset.AssetIndex) Scene(javafx.scene.Scene) URISyntaxException(java.net.URISyntaxException) GameLauncherException(kml.exceptions.GameLauncherException) Versions(kml.game.version.Versions) JSONObject(org.json.JSONObject) Authentication(kml.auth.Authentication) JSONObject(org.json.JSONObject) GameLauncherException(kml.exceptions.GameLauncherException) Library(kml.game.version.library.Library)

Example 2 with Version

use of kml.game.version.Version in project Krothium-Launcher by DarkLBP.

the class Downloader method download.

/**
 * Downloads all requires game files
 * @throws DownloaderException If the download fails
 */
public final void download() throws DownloaderException {
    // Initial values
    downloading = true;
    downloaded = 0;
    validated = 0;
    total = 0;
    int tries;
    console.print("Download work has started.");
    if (Kernel.USE_LOCAL) {
        console.print("You are in offline mode.");
        downloading = false;
        return;
    }
    // Fetch version used by profile
    Profile p = kernel.getProfiles().getSelectedProfile();
    Versions versions = kernel.getVersions();
    VersionMeta verID;
    switch(p.getType()) {
        case CUSTOM:
            verID = p.hasVersion() ? p.getVersionID() : versions.getLatestRelease();
            break;
        case RELEASE:
            verID = versions.getLatestRelease();
            break;
        default:
            verID = versions.getLatestSnapshot();
            break;
    }
    if (verID == null) {
        downloading = false;
        throw new DownloaderException("Version ID is null.");
    }
    console.print("Using version ID: " + verID);
    Version v = versions.getVersion(verID);
    if (v == null) {
        downloading = false;
        throw new DownloaderException("Version info could not be obtained.");
    }
    // Get required files to be downloaded
    Set<Downloadable> urls = new HashSet<>();
    // Fetch assets
    console.print("Fetching asset urls..");
    AssetIndex index = v.getAssetIndex();
    File indexJSON = new File(Kernel.APPLICATION_WORKING_DIR, "assets" + File.separator + "indexes" + File.separator + index.getID() + ".json");
    tries = 0;
    if (!Utils.verifyChecksum(indexJSON, index.getSHA1(), "SHA-1")) {
        while (tries < DOWNLOAD_TRIES) {
            try {
                Utils.downloadFile(index.getURL(), indexJSON);
                break;
            } catch (IOException ex) {
                console.print("Failed to download file " + indexJSON.getName() + " (try " + tries + ')');
                ex.printStackTrace(console.getWriter());
                tries++;
            }
        }
    }
    if (tries == DOWNLOAD_TRIES) {
        console.print("Failed to download asset index for version " + index.getID());
    } else {
        // Load assets
        try {
            JSONObject root;
            try {
                root = new JSONObject(new String(Files.readAllBytes(indexJSON.toPath()), StandardCharsets.UTF_8));
            } catch (JSONException | IOException ex) {
                downloading = false;
                throw new DownloaderException("Failed to read asset index json file.");
            }
            JSONObject objects = root.getJSONObject("objects");
            Set<String> keys = objects.keySet();
            Collection<String> processedHashes = new ArrayList<>();
            File objectsRoot = new File("assets" + File.separator + "objects");
            for (String key : keys) {
                JSONObject o = objects.getJSONObject(key);
                String hash = o.getString("hash");
                long size = o.getLong("size");
                String downloadURL = "http://resources.download.minecraft.net/" + hash.substring(0, 2) + '/' + hash;
                File relPath = new File(objectsRoot, hash.substring(0, 2) + File.separator + hash);
                File fullPath = new File(Kernel.APPLICATION_WORKING_DIR + File.separator + relPath);
                if (!processedHashes.contains(hash)) {
                    total += size;
                    processedHashes.add(hash);
                    if (!Utils.verifyChecksum(fullPath, hash, "SHA-1")) {
                        Downloadable d = new Downloadable(downloadURL, size, relPath, hash, key);
                        urls.add(d);
                    } else {
                        validated += size;
                    }
                }
            }
        } catch (JSONException ex) {
            console.print("Failed to parse asset index.");
        }
    }
    // Fetch version
    console.print("Fetching version urls..");
    Map<String, Downloadable> downloads = v.getDownloads();
    if (downloads.containsKey("client")) {
        Downloadable d = downloads.get("client");
        if (d.hasURL()) {
            long jarSize = d.getSize();
            String jarSHA1 = d.getHash();
            total += d.getSize();
            File destPath = new File(Kernel.APPLICATION_WORKING_DIR + File.separator + v.getRelativeJar());
            File jsonFile = new File(Kernel.APPLICATION_WORKING_DIR + File.separator + v.getRelativeJSON());
            tries = 0;
            while (tries < DOWNLOAD_TRIES) {
                try {
                    Utils.downloadFile(v.getJSONURL(), jsonFile);
                    break;
                } catch (IOException ex) {
                    console.print("Failed to download file " + jsonFile.getName() + " (try " + tries + ')');
                    ex.printStackTrace(console.getWriter());
                    tries++;
                }
            }
            if (tries == DOWNLOAD_TRIES) {
                console.print("Failed to download version index " + destPath.getName());
            }
            if (!Utils.verifyChecksum(destPath, jarSHA1, "SHA-1")) {
                urls.add(d);
            } else {
                validated += jarSize;
            }
        } else {
            console.print("Incompatible version downloadable.");
        }
    } else if (v.hasJar()) {
        String jar = v.getJar();
        File relPath = v.getRelativeJar();
        console.print("Found legacy version " + jar);
        if (!relPath.exists()) {
            Downloadable d = new Downloadable("https://s3.amazonaws.com/Minecraft.Download/versions/" + jar + "/" + jar + ".jar", -1, v.getRelativeJar(), null, null);
            urls.add(d);
        } else {
            console.print("Legacy version file found. Assuming is valid.");
        }
    } else {
        console.print("Version file from " + v.getID() + " has no compatible downloadable objects.");
    }
    // Fetch libraries and natives
    console.print("Fetching library and native urls..");
    List<Library> libs = v.getLibraries();
    for (Library lib : libs) {
        if (lib.isCompatible()) {
            // Standard download
            if (lib.hasArtifactDownload()) {
                Downloadable a = lib.getArtifactDownload();
                File completePath = new File(Kernel.APPLICATION_WORKING_DIR + File.separator + a.getRelativePath());
                if (completePath.isFile() && a.getHash() == null) {
                    console.print("File " + completePath + " has no hash. So let's assume the local one is valid.");
                } else {
                    total += a.getSize();
                    if (Utils.verifyChecksum(completePath, a.getHash(), "SHA-1")) {
                        validated += a.getSize();
                    } else {
                        urls.add(a);
                    }
                }
            }
            // Native download
            if (lib.hasClassifierDownload()) {
                Downloadable c = lib.getClassifierDownload();
                File completePath = new File(Kernel.APPLICATION_WORKING_DIR + File.separator + c.getRelativePath());
                total += c.getSize();
                if (completePath.isFile() && c.getHash() == null) {
                    console.print("File " + completePath + " has no hash. So let's assume the local one is valid.");
                } else {
                    if (Utils.verifyChecksum(completePath, c.getHash(), "SHA-1")) {
                        validated += c.getSize();
                    } else {
                        urls.add(c);
                    }
                }
            }
        }
    }
    console.print("Downloading required game files...");
    if (urls.isEmpty()) {
        console.print("Nothing to download.");
    } else {
        // Download required files
        downloadFiles(urls);
    }
    downloading = false;
}
Also used : VersionMeta(kml.game.version.VersionMeta) DownloaderException(kml.exceptions.DownloaderException) AssetIndex(kml.game.version.asset.AssetIndex) JSONException(org.json.JSONException) Profile(kml.game.profile.Profile) Versions(kml.game.version.Versions) JSONObject(org.json.JSONObject) Version(kml.game.version.Version) Library(kml.game.version.library.Library)

Aggregations

Profile (kml.game.profile.Profile)2 Version (kml.game.version.Version)2 VersionMeta (kml.game.version.VersionMeta)2 Versions (kml.game.version.Versions)2 AssetIndex (kml.game.version.asset.AssetIndex)2 Library (kml.game.version.library.Library)2 JSONObject (org.json.JSONObject)2 URISyntaxException (java.net.URISyntaxException)1 FXMLLoader (javafx.fxml.FXMLLoader)1 Parent (javafx.scene.Parent)1 Scene (javafx.scene.Scene)1 Stage (javafx.stage.Stage)1 Authentication (kml.auth.Authentication)1 User (kml.auth.user.User)1 DownloaderException (kml.exceptions.DownloaderException)1 GameLauncherException (kml.exceptions.GameLauncherException)1 JSONException (org.json.JSONException)1