diff --git a/LaunchServer/resources/launchserver/defaults/config.cfg b/LaunchServer/resources/launchserver/defaults/config.cfg index 3650a72..e7999a7 100644 --- a/LaunchServer/resources/launchserver/defaults/config.cfg +++ b/LaunchServer/resources/launchserver/defaults/config.cfg @@ -5,21 +5,21 @@ # Auth handler authHandler: "textFile"; authHandlerConfig: { - file: "authHandler.cfg"; - offlineUUIDs: true; + file: "authHandler.cfg"; + offlineUUIDs: true; }; # Auth provider authProvider: "reject"; authProviderConfig: { - message: "You need to change auth provider in LaunchServer.cfg"; + message: "You need to change auth provider in LaunchServer.cfg"; }; # Texture provider textureProvider: "request"; textureProviderConfig: { - skinsURL: "http://skins.minecraft.net/MinecraftSkins/%username%.png"; - cloaksURL: "http://skins.minecraft.net/MinecraftCloaks/%username%.png"; + skinsURL: "http://skins.minecraft.net/MinecraftSkins/%username%.png"; + cloaksURL: "http://skins.minecraft.net/MinecraftCloaks/%username%.png"; }; # Launch4J EXE binary building diff --git a/LaunchServer/resources/launchserver/defaults/profile1.10.2.cfg b/LaunchServer/resources/launchserver/defaults/profile1.10.2.cfg index 3aa76eb..8aeeb3a 100644 --- a/LaunchServer/resources/launchserver/defaults/profile1.10.2.cfg +++ b/LaunchServer/resources/launchserver/defaults/profile1.10.2.cfg @@ -14,11 +14,11 @@ # Updater and client watch service updateFastCheck: true; update: [ - "servers\\.dat" + "servers\\.dat" ]; updateVerify: [ - "libraries", "natives", "mods", - "minecraft\\.jar", "forge\\.jar", "liteloader\\.jar" + "libraries", "natives", "mods", + "minecraft\\.jar", "forge\\.jar", "liteloader\\.jar" ]; updateExclusions: []; @@ -26,19 +26,19 @@ mainClass: "net.minecraft.launchwrapper.Launch"; classPath: [ "forge.jar", "liteloader.jar", "minecraft.jar", "libraries" ]; jvmArgs: [ - "-Dfml.ignorePatchDiscrepancies=true", - "-Dfml.ignoreInvalidMinecraftCertificates=true", + "-Dfml.ignorePatchDiscrepancies=true", + "-Dfml.ignoreInvalidMinecraftCertificates=true", - # Some options from Mojang's launcher - "-XX:+UseConcMarkSweepGC", + # Some options from Mojang's launcher + "-XX:+UseConcMarkSweepGC", "-XX:+CMSIncrementalMode", "-XX:-UseAdaptiveSizePolicy", "-Xmn128M", - # JVM Attach protection - "-XX:+DisableAttachMechanism" + # JVM Attach protection + "-XX:+DisableAttachMechanism" ]; clientArgs: [ - "--tweakClass", "net.minecraftforge.fml.common.launcher.FMLTweaker", + "--tweakClass", "net.minecraftforge.fml.common.launcher.FMLTweaker", "--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker" ]; diff --git a/LaunchServer/resources/launchserver/defaults/profile1.11.2.cfg b/LaunchServer/resources/launchserver/defaults/profile1.11.2.cfg index 42f33b4..d224593 100644 --- a/LaunchServer/resources/launchserver/defaults/profile1.11.2.cfg +++ b/LaunchServer/resources/launchserver/defaults/profile1.11.2.cfg @@ -14,11 +14,11 @@ # Updater and client watch service updateFastCheck: true; update: [ - "servers\\.dat" + "servers\\.dat" ]; updateVerify: [ - "libraries", "natives", "mods", - "minecraft\\.jar", "forge\\.jar", "liteloader\\.jar" + "libraries", "natives", "mods", + "minecraft\\.jar", "forge\\.jar", "liteloader\\.jar" ]; updateExclusions: []; @@ -26,19 +26,19 @@ mainClass: "net.minecraft.launchwrapper.Launch"; classPath: [ "forge.jar", "liteloader.jar", "minecraft.jar", "libraries" ]; jvmArgs: [ - "-Dfml.ignorePatchDiscrepancies=true", - "-Dfml.ignoreInvalidMinecraftCertificates=true", + "-Dfml.ignorePatchDiscrepancies=true", + "-Dfml.ignoreInvalidMinecraftCertificates=true", - # Some options from Mojang's launcher - "-XX:+UseConcMarkSweepGC", + # Some options from Mojang's launcher + "-XX:+UseConcMarkSweepGC", "-XX:+CMSIncrementalMode", "-XX:-UseAdaptiveSizePolicy", "-Xmn128M", - # JVM Attach protection - "-XX:+DisableAttachMechanism" + # JVM Attach protection + "-XX:+DisableAttachMechanism" ]; clientArgs: [ - "--tweakClass", "net.minecraftforge.fml.common.launcher.FMLTweaker", + "--tweakClass", "net.minecraftforge.fml.common.launcher.FMLTweaker", "--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker" ]; diff --git a/LaunchServer/resources/launchserver/defaults/profile1.4.7.cfg b/LaunchServer/resources/launchserver/defaults/profile1.4.7.cfg index 608311d..4726cd5 100644 --- a/LaunchServer/resources/launchserver/defaults/profile1.4.7.cfg +++ b/LaunchServer/resources/launchserver/defaults/profile1.4.7.cfg @@ -14,10 +14,10 @@ # Updater and client watch service updateFastCheck: true; update: [ - "servers\\.dat" + "servers\\.dat" ]; updateVerify: [ - "libraries", "natives", "mods", "minecraft\\.jar" + "libraries", "natives", "mods", "minecraft\\.jar" ]; updateExclusions: []; @@ -25,17 +25,17 @@ mainClass: "net.minecraft.launchwrapper.Launch"; classPath: [ "minecraft.jar", "libraries" ]; jvmArgs: [ - # Some options from Mojang's launcher - "-XX:+UseConcMarkSweepGC", + # Some options from Mojang's launcher + "-XX:+UseConcMarkSweepGC", "-XX:+CMSIncrementalMode", "-XX:-UseAdaptiveSizePolicy", "-Xmn128M", - # JVM Attach protection - "-XX:+DisableAttachMechanism", + # JVM Attach protection + "-XX:+DisableAttachMechanism", - # Legacy bridge (for 1.6.4 & lower) settings - "-Dlauncher.legacy.skinsURL=http://skins.minecraft.net/MinecraftSkins/%username%.png", - "-Dlauncher.legacy.cloaksURL=http://skins.minecraft.net/MinecraftCloaks/%username%.png" + # Legacy bridge (for 1.6.4 & lower) settings + "-Dlauncher.legacy.skinsURL=http://skins.minecraft.net/MinecraftSkins/%username%.png", + "-Dlauncher.legacy.cloaksURL=http://skins.minecraft.net/MinecraftCloaks/%username%.png" ]; clientArgs: []; diff --git a/LaunchServer/resources/launchserver/defaults/profile1.5.2.cfg b/LaunchServer/resources/launchserver/defaults/profile1.5.2.cfg index 296d4c2..0e00dc9 100644 --- a/LaunchServer/resources/launchserver/defaults/profile1.5.2.cfg +++ b/LaunchServer/resources/launchserver/defaults/profile1.5.2.cfg @@ -14,10 +14,10 @@ # Updater and client watch service updateFastCheck: true; update: [ - "servers\\.dat" + "servers\\.dat" ]; updateVerify: [ - "libraries", "natives", "mods", "minecraft\\.jar" + "libraries", "natives", "mods", "minecraft\\.jar" ]; updateExclusions: []; @@ -25,17 +25,17 @@ mainClass: "net.minecraft.launchwrapper.Launch"; classPath: [ "minecraft.jar", "libraries" ]; jvmArgs: [ - # Some options from Mojang's launcher - "-XX:+UseConcMarkSweepGC", + # Some options from Mojang's launcher + "-XX:+UseConcMarkSweepGC", "-XX:+CMSIncrementalMode", "-XX:-UseAdaptiveSizePolicy", "-Xmn128M", - # JVM Attach protection - "-XX:+DisableAttachMechanism", + # JVM Attach protection + "-XX:+DisableAttachMechanism", - # Legacy bridge (for 1.6.4 & lower) settings - "-Dlauncher.legacy.skinsURL=http://skins.minecraft.net/MinecraftSkins/%username%.png", - "-Dlauncher.legacy.cloaksURL=http://skins.minecraft.net/MinecraftCloaks/%username%.png" + # Legacy bridge (for 1.6.4 & lower) settings + "-Dlauncher.legacy.skinsURL=http://skins.minecraft.net/MinecraftSkins/%username%.png", + "-Dlauncher.legacy.cloaksURL=http://skins.minecraft.net/MinecraftCloaks/%username%.png" ]; clientArgs: []; diff --git a/LaunchServer/resources/launchserver/defaults/profile1.6.4.cfg b/LaunchServer/resources/launchserver/defaults/profile1.6.4.cfg index 51b1455..1d62640 100644 --- a/LaunchServer/resources/launchserver/defaults/profile1.6.4.cfg +++ b/LaunchServer/resources/launchserver/defaults/profile1.6.4.cfg @@ -14,11 +14,11 @@ # Updater and client watch service updateFastCheck: true; update: [ - "servers\\.dat" + "servers\\.dat" ]; updateVerify: [ - "libraries", "natives", "mods", - "minecraft\\.jar", "forge\\.jar", "liteloader\\.jar" + "libraries", "natives", "mods", + "minecraft\\.jar", "forge\\.jar", "liteloader\\.jar" ]; updateExclusions: []; @@ -26,23 +26,23 @@ mainClass: "net.minecraft.launchwrapper.Launch"; classPath: [ "forge.jar", "liteloader.jar", "minecraft.jar", "libraries" ]; jvmArgs: [ - "-Dfml.ignorePatchDiscrepancies=true", - "-Dfml.ignoreInvalidMinecraftCertificates=true", + "-Dfml.ignorePatchDiscrepancies=true", + "-Dfml.ignoreInvalidMinecraftCertificates=true", - # Some options from Mojang's launcher - "-XX:+UseConcMarkSweepGC", + # Some options from Mojang's launcher + "-XX:+UseConcMarkSweepGC", "-XX:+CMSIncrementalMode", "-XX:-UseAdaptiveSizePolicy", "-Xmn128M", - # JVM Attach protection - "-XX:+DisableAttachMechanism", + # JVM Attach protection + "-XX:+DisableAttachMechanism", - # Legacy bridge (for 1.6.4 & lower) settings - "-Dlauncher.legacy.skinsURL=http://skins.minecraft.net/MinecraftSkins/%username%.png", - "-Dlauncher.legacy.cloaksURL=http://skins.minecraft.net/MinecraftCloaks/%username%.png" + # Legacy bridge (for 1.6.4 & lower) settings + "-Dlauncher.legacy.skinsURL=http://skins.minecraft.net/MinecraftSkins/%username%.png", + "-Dlauncher.legacy.cloaksURL=http://skins.minecraft.net/MinecraftCloaks/%username%.png" ]; clientArgs: [ - "--tweakClass", "cpw.mods.fml.common.launcher.FMLTweaker", - "--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker" + "--tweakClass", "cpw.mods.fml.common.launcher.FMLTweaker", + "--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker" ]; diff --git a/LaunchServer/resources/launchserver/defaults/profile1.7.10.cfg b/LaunchServer/resources/launchserver/defaults/profile1.7.10.cfg index ac3309b..62af14a 100644 --- a/LaunchServer/resources/launchserver/defaults/profile1.7.10.cfg +++ b/LaunchServer/resources/launchserver/defaults/profile1.7.10.cfg @@ -14,35 +14,35 @@ # Updater and client watch service updateFastCheck: true; update: [ - "servers\\.dat" + "servers\\.dat" ]; updateVerify: [ - "libraries", "natives", "mods", - "minecraft\\.jar", "forge\\.jar", "liteloader\\.jar" + "libraries", "natives", "mods", + "minecraft\\.jar", "forge\\.jar", "liteloader\\.jar" ]; updateExclusions: [ - # "mods/carpentersblocks", - # "mods/ic2", - # "mods/railcraft" + # "mods/carpentersblocks", + # "mods/ic2", + # "mods/railcraft" ]; # Client launcher params mainClass: "net.minecraft.launchwrapper.Launch"; classPath: [ "forge.jar", "liteloader.jar", "minecraft.jar", "libraries" ]; jvmArgs: [ - "-Dfml.ignorePatchDiscrepancies=true", - "-Dfml.ignoreInvalidMinecraftCertificates=true", + "-Dfml.ignorePatchDiscrepancies=true", + "-Dfml.ignoreInvalidMinecraftCertificates=true", - # Some options from Mojang's launcher - "-XX:+UseConcMarkSweepGC", + # Some options from Mojang's launcher + "-XX:+UseConcMarkSweepGC", "-XX:+CMSIncrementalMode", "-XX:-UseAdaptiveSizePolicy", "-Xmn128M", - # JVM Attach protection - "-XX:+DisableAttachMechanism" + # JVM Attach protection + "-XX:+DisableAttachMechanism" ]; clientArgs: [ - "--tweakClass", "cpw.mods.fml.common.launcher.FMLTweaker", - "--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker" + "--tweakClass", "cpw.mods.fml.common.launcher.FMLTweaker", + "--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker" ]; diff --git a/LaunchServer/resources/launchserver/defaults/profile1.7.2.cfg b/LaunchServer/resources/launchserver/defaults/profile1.7.2.cfg index 6811f57..a9d73e0 100644 --- a/LaunchServer/resources/launchserver/defaults/profile1.7.2.cfg +++ b/LaunchServer/resources/launchserver/defaults/profile1.7.2.cfg @@ -14,11 +14,11 @@ # Updater and client watch service updateFastCheck: true; update: [ - "servers\\.dat" + "servers\\.dat" ]; updateVerify: [ - "libraries", "natives", "mods", - "minecraft\\.jar", "forge\\.jar", "liteloader\\.jar" + "libraries", "natives", "mods", + "minecraft\\.jar", "forge\\.jar", "liteloader\\.jar" ]; updateExclusions: []; @@ -26,19 +26,19 @@ mainClass: "net.minecraft.launchwrapper.Launch"; classPath: [ "forge.jar", "liteloader.jar", "minecraft.jar", "libraries" ]; jvmArgs: [ - "-Dfml.ignorePatchDiscrepancies=true", - "-Dfml.ignoreInvalidMinecraftCertificates=true", + "-Dfml.ignorePatchDiscrepancies=true", + "-Dfml.ignoreInvalidMinecraftCertificates=true", - # Some options from Mojang's launcher - "-XX:+UseConcMarkSweepGC", + # Some options from Mojang's launcher + "-XX:+UseConcMarkSweepGC", "-XX:+CMSIncrementalMode", "-XX:-UseAdaptiveSizePolicy", "-Xmn128M", - # JVM Attach protection - "-XX:+DisableAttachMechanism" + # JVM Attach protection + "-XX:+DisableAttachMechanism" ]; clientArgs: [ - "--tweakClass", "cpw.mods.fml.common.launcher.FMLTweaker", - "--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker" + "--tweakClass", "cpw.mods.fml.common.launcher.FMLTweaker", + "--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker" ]; diff --git a/LaunchServer/resources/launchserver/defaults/profile1.8.9.cfg b/LaunchServer/resources/launchserver/defaults/profile1.8.9.cfg index 2869cff..5e93176 100644 --- a/LaunchServer/resources/launchserver/defaults/profile1.8.9.cfg +++ b/LaunchServer/resources/launchserver/defaults/profile1.8.9.cfg @@ -14,11 +14,11 @@ # Updater and client watch service updateFastCheck: true; update: [ - "servers\\.dat" + "servers\\.dat" ]; updateVerify: [ - "libraries", "natives", "mods", - "minecraft\\.jar", "forge\\.jar", "liteloader\\.jar" + "libraries", "natives", "mods", + "minecraft\\.jar", "forge\\.jar", "liteloader\\.jar" ]; updateExclusions: []; @@ -26,19 +26,19 @@ mainClass: "net.minecraft.launchwrapper.Launch"; classPath: [ "forge.jar", "liteloader.jar", "minecraft.jar", "libraries" ]; jvmArgs: [ - "-Dfml.ignorePatchDiscrepancies=true", - "-Dfml.ignoreInvalidMinecraftCertificates=true", + "-Dfml.ignorePatchDiscrepancies=true", + "-Dfml.ignoreInvalidMinecraftCertificates=true", - # Some options from Mojang's launcher - "-XX:+UseConcMarkSweepGC", + # Some options from Mojang's launcher + "-XX:+UseConcMarkSweepGC", "-XX:+CMSIncrementalMode", "-XX:-UseAdaptiveSizePolicy", "-Xmn128M", - # JVM Attach protection - "-XX:+DisableAttachMechanism" + # JVM Attach protection + "-XX:+DisableAttachMechanism" ]; clientArgs: [ - "--tweakClass", "net.minecraftforge.fml.common.launcher.FMLTweaker", + "--tweakClass", "net.minecraftforge.fml.common.launcher.FMLTweaker", "--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker" ]; diff --git a/LaunchServer/resources/launchserver/defaults/profile1.9.4.cfg b/LaunchServer/resources/launchserver/defaults/profile1.9.4.cfg index 2653508..cfdeefa 100644 --- a/LaunchServer/resources/launchserver/defaults/profile1.9.4.cfg +++ b/LaunchServer/resources/launchserver/defaults/profile1.9.4.cfg @@ -14,11 +14,11 @@ # Updater and client watch service updateFastCheck: true; update: [ - "servers\\.dat" + "servers\\.dat" ]; updateVerify: [ - "libraries", "natives", "mods", - "minecraft\\.jar", "forge\\.jar", "liteloader\\.jar" + "libraries", "natives", "mods", + "minecraft\\.jar", "forge\\.jar", "liteloader\\.jar" ]; updateExclusions: []; @@ -26,19 +26,19 @@ mainClass: "net.minecraft.launchwrapper.Launch"; classPath: [ "forge.jar", "liteloader.jar", "minecraft.jar", "libraries" ]; jvmArgs: [ - "-Dfml.ignorePatchDiscrepancies=true", - "-Dfml.ignoreInvalidMinecraftCertificates=true", + "-Dfml.ignorePatchDiscrepancies=true", + "-Dfml.ignoreInvalidMinecraftCertificates=true", - # Some options from Mojang's launcher - "-XX:+UseConcMarkSweepGC", + # Some options from Mojang's launcher + "-XX:+UseConcMarkSweepGC", "-XX:+CMSIncrementalMode", "-XX:-UseAdaptiveSizePolicy", "-Xmn128M", - # JVM Attach protection - "-XX:+DisableAttachMechanism" + # JVM Attach protection + "-XX:+DisableAttachMechanism" ]; clientArgs: [ - "--tweakClass", "net.minecraftforge.fml.common.launcher.FMLTweaker", + "--tweakClass", "net.minecraftforge.fml.common.launcher.FMLTweaker", "--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker" ]; diff --git a/LaunchServer/source/LaunchServer.java b/LaunchServer/source/LaunchServer.java index f89ae6d..528ce8d 100644 --- a/LaunchServer/source/LaunchServer.java +++ b/LaunchServer/source/LaunchServer.java @@ -284,7 +284,7 @@ // Sync and sign update dir LogHelper.subInfo("Syncing '%s' update dir", name); - HashedDir updateHDir = new HashedDir(updateDir, null, true); + HashedDir updateHDir = new HashedDir(updateDir, null, true, true); newUpdatesDirMap.put(name, new SignedObjectHolder<>(updateHDir, privateKey)); } } diff --git a/Launcher/runtime/dialog/dialog.js b/Launcher/runtime/dialog/dialog.js index d98074a..78ec989 100644 --- a/Launcher/runtime/dialog/dialog.js +++ b/Launcher/runtime/dialog/dialog.js @@ -7,352 +7,355 @@ var pingers = {}; function initDialog() { - // Lookup news WebView - news = rootPane.lookup("#news"); - var newsEngine = news.getEngine(); - newsEngine.setUserDataDirectory(dir.resolve("webview").toFile()); - newsEngine.load(config.newsURL); + // Lookup news WebView + news = rootPane.lookup("#news"); + var newsEngine = news.getEngine(); + newsEngine.setUserDataDirectory(dir.resolve("webview").toFile()); + newsEngine.load(config.newsURL); - // Lookup auth pane and dim - initAuthPane(rootPane.lookup("#authPane")); - dimPane = rootPane.lookup("#dim"); - - // Init overlays - debug.initOverlay(); - processing.initOverlay(); - settings.initOverlay(); - update.initOverlay(); + // Lookup auth pane and dim + initAuthPane(rootPane.lookup("#authPane")); + dimPane = rootPane.lookup("#dim"); - // Verify launcher & make request - verifyLauncher(); + // Init overlays + debug.initOverlay(); + processing.initOverlay(); + settings.initOverlay(); + update.initOverlay(); + + // Verify launcher & make request + verifyLauncher(); } function initAuthPane(pane) { - authPane = pane; - - // Lookup login field - loginField = pane.lookup("#login"); - loginField.setOnAction(goAuth); - if (settings.login !== null) { - loginField.setText(settings.login); - } + authPane = pane; - // Lookup password field - passwordField = pane.lookup("#password"); - passwordField.setOnAction(goAuth); - if (settings.rsaPassword !== null) { - passwordField.getStyleClass().add("hasSaved"); - passwordField.setPromptText("*** Сохранённый ***"); - } + // Lookup login field + loginField = pane.lookup("#login"); + loginField.setOnAction(goAuth); + if (settings.login !== null) { + loginField.setText(settings.login); + } - // Lookup profiles combobox - profilesBox = pane.lookup("#profiles"); - profilesBox.setCellFactory(newProfileCell); - profilesBox.setButtonCell(newProfileCell(null)); + // Lookup password field + passwordField = pane.lookup("#password"); + passwordField.setOnAction(goAuth); + if (settings.rsaPassword !== null) { + passwordField.getStyleClass().add("hasSaved"); + passwordField.setPromptText("*** Сохранённый ***"); + } - // Lookup save password box - savePasswordBox = pane.lookup("#savePassword"); - savePasswordBox.setSelected(settings.login === null || settings.rsaPassword !== null); - - // Lookup hyperlink text and actions - var link = pane.lookup("#link"); - link.setText(config.linkText); - link.setOnAction(function(event) app.getHostServices().showDocument(config.linkURL.toURI())); + // Lookup profiles combobox + profilesBox = pane.lookup("#profiles"); + profilesBox.setCellFactory(newProfileCell); + profilesBox.setButtonCell(newProfileCell(null)); - // Lookup action buttons - pane.lookup("#goAuth").setOnAction(goAuth); - pane.lookup("#goSettings").setOnAction(goSettings); + // Lookup save password box + savePasswordBox = pane.lookup("#savePassword"); + savePasswordBox.setSelected(settings.login === null || settings.rsaPassword !== null); + + // Lookup hyperlink text and actions + var link = pane.lookup("#link"); + link.setText(config.linkText); + link.setOnAction(function(event) app.getHostServices().showDocument(config.linkURL.toURI())); + + // Lookup action buttons + pane.lookup("#goAuth").setOnAction(goAuth); + pane.lookup("#goSettings").setOnAction(goSettings); } function initOffline() { - // Update title - stage.setTitle(config.title + " [Offline]"); - - // Set login field as username field - loginField.setPromptText("Имя пользователя"); - if (!VerifyHelper.isValidUsername(settings.login)) { - loginField.setText(""); // Reset if not valid - } - - // Disable password field - passwordField.setDisable(true); - passwordField.setPromptText("Недоступно"); - passwordField.setText(""); - - // Switch news view to offline page - var offlineURL = Launcher.getResourceURL("dialog/offline/offline.html"); - news.getEngine().load(offlineURL.toString()); + // Update title + stage.setTitle(config.title + " [Offline]"); + + // Set login field as username field + loginField.setPromptText("Имя пользователя"); + if (!VerifyHelper.isValidUsername(settings.login)) { + loginField.setText(""); // Reset if not valid + } + + // Disable password field + passwordField.setDisable(true); + passwordField.setPromptText("Недоступно"); + passwordField.setText(""); + + // Switch news view to offline page + var offlineURL = Launcher.getResourceURL("dialog/offline/offline.html"); + news.getEngine().load(offlineURL.toString()); } /* ======== Handler functions ======== */ function goAuth(event) { - // Verify there's no other overlays - if (overlay.current !== null) { - return; - } + // Verify there's no other overlays + if (overlay.current !== null) { + return; + } - // Get profile - var profile = profilesBox.getSelectionModel().getSelectedItem(); - if (profile === null) { - return; // No profile selected - } + // Get profile + var profile = profilesBox.getSelectionModel().getSelectedItem(); + if (profile === null) { + return; // No profile selected + } - // Get login - var login = loginField.getText(); - if (login.isEmpty()) { - return; // Maybe throw exception?) - } + // Get login + var login = loginField.getText(); + if (login.isEmpty()) { + return; // Maybe throw exception?) + } - // Get password if online-mode - var rsaPassword = null; - if (!passwordField.isDisable()) { - var password = passwordField.getText(); - if (!password.isEmpty()) { - rsaPassword = settings.setPassword(password); - } else if (settings.rsaPassword !== null) { - rsaPassword = settings.rsaPassword; - } else { - return; // No password - no auth, sorry :C - } + // Get password if online-mode + var rsaPassword = null; + if (!passwordField.isDisable()) { + var password = passwordField.getText(); + if (!password.isEmpty()) { + rsaPassword = settings.setPassword(password); + } else if (settings.rsaPassword !== null) { + rsaPassword = settings.rsaPassword; + } else { + return; // No password - no auth, sorry :C + } - // Remember or reset password - settings.rsaPassword = savePasswordBox.isSelected() ? rsaPassword : null; - } + // Remember or reset password + settings.rsaPassword = savePasswordBox.isSelected() ? rsaPassword : null; + } - // Show auth overlay - settings.login = login; - doAuth(profile, login, rsaPassword); + // Show auth overlay + settings.login = login; + doAuth(profile, login, rsaPassword); } function goSettings(event) { - // Verify there's no other overlays - if (overlay.current !== null) { - return; - } + // Verify there's no other overlays + if (overlay.current !== null) { + return; + } - // Show settings overlay - overlay.show(settings.overlay, null); + // Show settings overlay + overlay.show(settings.overlay, null); } /* ======== Processing functions ======== */ function verifyLauncher(e) { - processing.resetOverlay(); - overlay.show(processing.overlay, function(event) makeLauncherRequest(function(result) { - settings.lastSign = result.sign; - settings.lastProfiles = result.profiles; - - // Init offline if set - if (settings.offline) { - initOffline(); - } + processing.resetOverlay(); + overlay.show(processing.overlay, function(event) makeLauncherRequest(function(result) { + settings.lastSign = result.sign; + settings.lastProfiles = result.profiles; - // Update profiles list and hide overlay - updateProfilesList(result.profiles); - overlay.hide(0, function() { - if (cliParams.autoLogin) { - goAuth(null); - } - }); - })); + // Init offline if set + if (settings.offline) { + initOffline(); + } + + // Update profiles list and hide overlay + updateProfilesList(result.profiles); + overlay.hide(0, function() { + if (cliParams.autoLogin) { + goAuth(null); + } + }); + })); } function doAuth(profile, login, rsaPassword) { - processing.resetOverlay(); - overlay.show(processing.overlay, function(event) makeAuthRequest(login, rsaPassword, function(result) - doUpdate(profile, result.pp, result.accessToken) - )); + processing.resetOverlay(); + overlay.show(processing.overlay, function(event) makeAuthRequest(login, rsaPassword, function(result) + doUpdate(profile, result.pp, result.accessToken) + )); } function doUpdate(profile, pp, accessToken) { - update.resetOverlay("Обновление файлов JVM"); - overlay.swap(0, update.overlay, function(event) { - var jvmDir = settings.updatesDir.resolve(jvmDirName); - makeUpdateRequest(jvmDirName, jvmDir, null, function(jvmHDir) { - settings.lastHDirs.put(jvmDirName, jvmHDir); - - // Update asset dir - update.resetOverlay("Обновление файлов ресурсов"); - var assetDirName = profile.object.block.getEntryValue("assetDir", StringConfigEntryClass); - var assetDir = settings.updatesDir.resolve(assetDirName); - var assetMatcher = profile.object.getAssetUpdateMatcher(); - makeUpdateRequest(assetDirName, assetDir, assetMatcher, function(assetHDir) { - settings.lastHDirs.put(assetDirName, assetHDir); - - // Update client dir - update.resetOverlay("Обновление файлов клиента"); - var clientDirName = profile.object.block.getEntryValue("dir", StringConfigEntryClass); - var clientDir = settings.updatesDir.resolve(clientDirName); - var clientMatcher = profile.object.getClientUpdateMatcher(); - makeUpdateRequest(clientDirName, clientDir, clientMatcher, function(clientHDir) { - settings.lastHDirs.put(clientDirName, clientHDir); - doLaunchClient(jvmDir, jvmHDir, assetDir, assetHDir, clientDir, clientHDir, profile, pp, accessToken); - }); - }); - }); - }); + var digest = profile.object.isUpdateFastCheck(); + + // Update JVM dir + update.resetOverlay("Обновление файлов JVM"); + overlay.swap(0, update.overlay, function(event) { + var jvmDir = settings.updatesDir.resolve(jvmDirName); + makeUpdateRequest(jvmDirName, jvmDir, null, digest, function(jvmHDir) { + settings.lastHDirs.put(jvmDirName, jvmHDir); + + // Update asset dir + update.resetOverlay("Обновление файлов ресурсов"); + var assetDirName = profile.object.block.getEntryValue("assetDir", StringConfigEntryClass); + var assetDir = settings.updatesDir.resolve(assetDirName); + var assetMatcher = profile.object.getAssetUpdateMatcher(); + makeUpdateRequest(assetDirName, assetDir, assetMatcher, digest, function(assetHDir) { + settings.lastHDirs.put(assetDirName, assetHDir); + + // Update client dir + update.resetOverlay("Обновление файлов клиента"); + var clientDirName = profile.object.block.getEntryValue("dir", StringConfigEntryClass); + var clientDir = settings.updatesDir.resolve(clientDirName); + var clientMatcher = profile.object.getClientUpdateMatcher(); + makeUpdateRequest(clientDirName, clientDir, clientMatcher, digest, function(clientHDir) { + settings.lastHDirs.put(clientDirName, clientHDir); + doLaunchClient(jvmDir, jvmHDir, assetDir, assetHDir, clientDir, clientHDir, profile, pp, accessToken); + }); + }); + }); + }); } function doLaunchClient(jvmDir, jvmHDir, assetDir, assetHDir, clientDir, clientHDir, profile, pp, accessToken) { - processing.resetOverlay(); - overlay.swap(0, processing.overlay, function(event) - launchClient(jvmDir, jvmHDir, assetHDir, clientHDir, profile, new ClientLauncherParams(settings.lastSign, - assetDir, clientDir, pp, accessToken, settings.autoEnter, settings.fullScreen, settings.ram, 0, 0), doDebugClient) - ); + processing.resetOverlay(); + overlay.swap(0, processing.overlay, function(event) + launchClient(jvmDir, jvmHDir, assetHDir, clientHDir, profile, new ClientLauncherParams(settings.lastSign, + assetDir, clientDir, pp, accessToken, settings.autoEnter, settings.fullScreen, settings.ram, 0, 0), doDebugClient) + ); } function doDebugClient(process) { - if (!LogHelper.isDebugEnabled()) { - javafx.application.Platform.exit(); - return; - } - - // Switch to debug overlay - debug.resetOverlay(); - overlay.swap(0, debug.overlay, function(event) debugProcess(process)); + if (!LogHelper.isDebugEnabled()) { + javafx.application.Platform.exit(); + return; + } + + // Switch to debug overlay + debug.resetOverlay(); + overlay.swap(0, debug.overlay, function(event) debugProcess(process)); } /* ======== Server handler functions ======== */ function updateProfilesList(profiles) { - // Set profiles items - profilesBox.setItems(javafx.collections.FXCollections.observableList(profiles)); - for each (var profile in profiles) { - pingers[profile.object] = new ServerPinger(profile.object.getServerSocketAddress(), profile.object.getVersion()); - } + // Set profiles items + profilesBox.setItems(javafx.collections.FXCollections.observableList(profiles)); + for each (var profile in profiles) { + pingers[profile.object] = new ServerPinger(profile.object.getServerSocketAddress(), profile.object.getVersion()); + } - // Set profiles selection model - var sm = profilesBox.getSelectionModel(); - sm.selectedIndexProperty()["addListener(javafx.beans.value.ChangeListener)"]( - function(o, ov, nv) settings.profile = nv); // Store selected profile index + // Set profiles selection model + var sm = profilesBox.getSelectionModel(); + sm.selectedIndexProperty()["addListener(javafx.beans.value.ChangeListener)"]( + function(o, ov, nv) settings.profile = nv); // Store selected profile index - // Restore selected item - var i = settings.profile; - sm.select(i < profiles.size() ? i : 0); + // Restore selected item + var i = settings.profile; + sm.select(i < profiles.size() ? i : 0); } function newProfileCell(listView) { - var statusBox = loadFXML("dialog/profileCell.fxml"); + var statusBox = loadFXML("dialog/profileCell.fxml"); - // Lookup labels - var title = statusBox.lookup("#profileTitle"); - var status = statusBox.lookup("#serverStatus"); - var statusCircle = title.getGraphic(); + // Lookup labels + var title = statusBox.lookup("#profileTitle"); + var status = statusBox.lookup("#serverStatus"); + var statusCircle = title.getGraphic(); - // Create and return new cell - var cell = new (Java.extend(javafx.scene.control.ListCell))() { - updateItem: function(item, empty) { - Java.super(cell).updateItem(item, empty); - cell.setGraphic(empty ? null : statusBox); - if (empty) { // No need to update state - return; - } + // Create and return new cell + var cell = new (Java.extend(javafx.scene.control.ListCell))() { + updateItem: function(item, empty) { + Java.super(cell).updateItem(item, empty); + cell.setGraphic(empty ? null : statusBox); + if (empty) { // No need to update state + return; + } - // Update title and server status - title.setText(item.object.getTitle()); - pingServer(status, statusCircle, item); - } - }; - cell.setText(null); - return cell; + // Update title and server status + title.setText(item.object.getTitle()); + pingServer(status, statusCircle, item); + } + }; + cell.setText(null); + return cell; } function pingServer(status, statusCircle, profile) { - setServerStatus(status, statusCircle, javafx.scene.paint.Color.GREY, "..."); - var task = newTask(function() pingers[profile.object].ping()); - task.setOnSucceeded(function(event) { - var result = task.getValue(); - var color = result.isOverfilled() ? javafx.scene.paint.Color.YELLOW : javafx.scene.paint.Color.GREEN; - setServerStatus(status, statusCircle, color, java.lang.String.format("%d из %d", result.onlinePlayers, result.maxPlayers)); - }); - task.setOnFailed(function(event) setServerStatus(status, statusCircle, javafx.scene.paint.Color.RED, "Недоступен")); - startTask(task); + setServerStatus(status, statusCircle, javafx.scene.paint.Color.GREY, "..."); + var task = newTask(function() pingers[profile.object].ping()); + task.setOnSucceeded(function(event) { + var result = task.getValue(); + var color = result.isOverfilled() ? javafx.scene.paint.Color.YELLOW : javafx.scene.paint.Color.GREEN; + setServerStatus(status, statusCircle, color, java.lang.String.format("%d из %d", result.onlinePlayers, result.maxPlayers)); + }); + task.setOnFailed(function(event) setServerStatus(status, statusCircle, javafx.scene.paint.Color.RED, "Недоступен")); + startTask(task); } function setServerStatus(status, statusCircle, color, description) { - status.setText(description); - statusCircle.setFill(color); + status.setText(description); + statusCircle.setFill(color); } /* ======== Overlay helper functions ======== */ function fade(region, delay, from, to, onFinished) { - var transition = new javafx.animation.FadeTransition(javafx.util.Duration.millis(100), region); - if (onFinished !== null) { - transition.setOnFinished(onFinished); - } + var transition = new javafx.animation.FadeTransition(javafx.util.Duration.millis(100), region); + if (onFinished !== null) { + transition.setOnFinished(onFinished); + } - // Launch transition - transition.setDelay(javafx.util.Duration.millis(delay)); - transition.setFromValue(from); - transition.setToValue(to); - transition.play(); + // Launch transition + transition.setDelay(javafx.util.Duration.millis(delay)); + transition.setFromValue(from); + transition.setToValue(to); + transition.play(); } var overlay = { - current: null, + current: null, - show: function(newOverlay, onFinished) { - // Freeze root pane - news.setDisable(true); - authPane.setDisable(true); - overlay.current = newOverlay; - - // Show dim pane - dimPane.setVisible(true); - dimPane.toFront(); - - // Fade dim pane - fade(dimPane, 0.0, 0.0, 1.0, function(event) { - dimPane.requestFocus(); - dimPane.getChildren().add(newOverlay); - - // Fix overlay position - newOverlay.setLayoutX((dimPane.getPrefWidth() - newOverlay.getPrefWidth()) / 2.0); - newOverlay.setLayoutY((dimPane.getPrefHeight() - newOverlay.getPrefHeight()) / 2.0); - - // Fade in - fade(newOverlay, 0.0, 0.0, 1.0, onFinished); - }); - }, + show: function(newOverlay, onFinished) { + // Freeze root pane + news.setDisable(true); + authPane.setDisable(true); + overlay.current = newOverlay; - hide: function(delay, onFinished) { - fade(overlay.current, delay, 1.0, 0.0, function(event) { - dimPane.getChildren().remove(overlay.current); - fade(dimPane, 0.0, 1.0, 0.0, function(event) { - dimPane.setVisible(false); - - // Unfreeze root pane - news.setDisable(false); - authPane.setDisable(false); - rootPane.requestFocus(); - - // Reset overlay state - overlay.current = null; - if (onFinished !== null) { - onFinished(); - } - }); - }); - }, + // Show dim pane + dimPane.setVisible(true); + dimPane.toFront(); - swap: function(delay, newOverlay, onFinished) { - dimPane.toFront(); - fade(overlay.current, delay, 1.0, 0.0, function(event) { - dimPane.requestFocus(); + // Fade dim pane + fade(dimPane, 0.0, 0.0, 1.0, function(event) { + dimPane.requestFocus(); + dimPane.getChildren().add(newOverlay); - // Hide old overlay - if (overlay.current !== newOverlay) { - var child = dimPane.getChildren(); - child.set(child.indexOf(overlay.current), newOverlay); - } - - // Fix overlay position - newOverlay.setLayoutX((dimPane.getPrefWidth() - newOverlay.getPrefWidth()) / 2.0); - newOverlay.setLayoutY((dimPane.getPrefHeight() - newOverlay.getPrefHeight()) / 2.0); + // Fix overlay position + newOverlay.setLayoutX((dimPane.getPrefWidth() - newOverlay.getPrefWidth()) / 2.0); + newOverlay.setLayoutY((dimPane.getPrefHeight() - newOverlay.getPrefHeight()) / 2.0); - // Show new overlay - overlay.current = newOverlay; - fade(newOverlay, 0.0, 0.0, 1.0, onFinished); - }); - } + // Fade in + fade(newOverlay, 0.0, 0.0, 1.0, onFinished); + }); + }, + + hide: function(delay, onFinished) { + fade(overlay.current, delay, 1.0, 0.0, function(event) { + dimPane.getChildren().remove(overlay.current); + fade(dimPane, 0.0, 1.0, 0.0, function(event) { + dimPane.setVisible(false); + + // Unfreeze root pane + news.setDisable(false); + authPane.setDisable(false); + rootPane.requestFocus(); + + // Reset overlay state + overlay.current = null; + if (onFinished !== null) { + onFinished(); + } + }); + }); + }, + + swap: function(delay, newOverlay, onFinished) { + dimPane.toFront(); + fade(overlay.current, delay, 1.0, 0.0, function(event) { + dimPane.requestFocus(); + + // Hide old overlay + if (overlay.current !== newOverlay) { + var child = dimPane.getChildren(); + child.set(child.indexOf(overlay.current), newOverlay); + } + + // Fix overlay position + newOverlay.setLayoutX((dimPane.getPrefWidth() - newOverlay.getPrefWidth()) / 2.0); + newOverlay.setLayoutY((dimPane.getPrefHeight() - newOverlay.getPrefHeight()) / 2.0); + + // Show new overlay + overlay.current = newOverlay; + fade(newOverlay, 0.0, 0.0, 1.0, onFinished); + }); + } }; /* ======== Overlay scripts ======== */ diff --git a/Launcher/runtime/dialog/overlay/update/update.js b/Launcher/runtime/dialog/overlay/update/update.js index dced45d..9cf5723 100644 --- a/Launcher/runtime/dialog/overlay/update/update.js +++ b/Launcher/runtime/dialog/overlay/update/update.js @@ -1,100 +1,100 @@ var update = { - overlay: null, title: null, description: null, progress: null, + overlay: null, title: null, description: null, progress: null, - /* State and overlay functions */ - initOverlay: function() { - update.overlay = loadFXML("dialog/overlay/update/update.fxml"); + /* State and overlay functions */ + initOverlay: function() { + update.overlay = loadFXML("dialog/overlay/update/update.fxml"); - // Lookup nodes - update.title = update.overlay.lookup("#utitle"); - update.description = update.overlay.lookup("#description"); - update.progress = update.overlay.lookup("#progress"); - }, + // Lookup nodes + update.title = update.overlay.lookup("#utitle"); + update.description = update.overlay.lookup("#description"); + update.progress = update.overlay.lookup("#progress"); + }, - resetOverlay: function(title) { - update.title.setText(title); - update.description.getStyleClass().remove("error"); - update.description.setText("..."); - update.progress.setProgress(-1.0); - }, + resetOverlay: function(title) { + update.title.setText(title); + update.description.getStyleClass().remove("error"); + update.description.setText("..."); + update.progress.setProgress(-1.0); + }, - setError: function(e) { - LogHelper.error(e); + setError: function(e) { + LogHelper.error(e); - // Set error description - update.description.getStyleClass().add("error"); - update.description.setText(e.toString()); - }, + // Set error description + update.description.getStyleClass().add("error"); + update.description.setText(e.toString()); + }, - stateCallback: function(task, state) { - var bps = state.getBps(); - var estimated = state.getEstimatedTime(); - var estimatedSeconds = estimated === null ? 0 : estimated.getSeconds(); - var estimatedHH = (estimatedSeconds / 3600) | 0; - var estimatedMM = ((estimatedSeconds % 3600) / 60) | 0; - var estimatedSS = (estimatedSeconds % 60) | 0; - task.updateMessage(java.lang.String.format( - "Файл: %s%n" + // File line - "Загружено (Файл): %.2f / %.2f MiB.%n" + // File downloaded line - "Загружено (Всего): %.2f / %.2f MiB.%n" + // Total downloaded line - "%n" + - "Средняя скорость: %.1f Kbps%n" + // Speed line - "Примерно осталось: %d:%02d:%02d%n", // Estimated line + stateCallback: function(task, state) { + var bps = state.getBps(); + var estimated = state.getEstimatedTime(); + var estimatedSeconds = estimated === null ? 0 : estimated.getSeconds(); + var estimatedHH = (estimatedSeconds / 3600) | 0; + var estimatedMM = ((estimatedSeconds % 3600) / 60) | 0; + var estimatedSS = (estimatedSeconds % 60) | 0; + task.updateMessage(java.lang.String.format( + "Файл: %s%n" + // File line + "Загружено (Файл): %.2f / %.2f MiB.%n" + // File downloaded line + "Загружено (Всего): %.2f / %.2f MiB.%n" + // Total downloaded line + "%n" + + "Средняя скорость: %.1f Kbps%n" + // Speed line + "Примерно осталось: %d:%02d:%02d%n", // Estimated line - // Formatting - state.filePath, // File path - state.getFileDownloadedMiB(), state.getFileSizeMiB(), // File downloaded - state.getTotalDownloadedMiB(), state.getTotalSizeMiB(), // Total downloaded - bps <= 0.0 ? 0.0 : bps / 1024.0, // Speed - estimatedHH, estimatedMM, estimatedSS // Estimated (hh:mm:ss) - )); - task.updateProgress(state.totalDownloaded, state.totalSize); - }, + // Formatting + state.filePath, // File path + state.getFileDownloadedMiB(), state.getFileSizeMiB(), // File downloaded + state.getTotalDownloadedMiB(), state.getTotalSizeMiB(), // Total downloaded + bps <= 0.0 ? 0.0 : bps / 1024.0, // Speed + estimatedHH, estimatedMM, estimatedSS // Estimated (hh:mm:ss) + )); + task.updateProgress(state.totalDownloaded, state.totalSize); + }, - setTaskProperties: function(task, request, callback) { - update.description.textProperty().bind(task.messageProperty()); - update.progress.progressProperty().bind(task.progressProperty()); - request.setStateCallback(function(state) update.stateCallback(task, state)); - task.setOnFailed(function(event) { - update.description.textProperty().unbind(); - update.progress.progressProperty().unbind(); - update.setError(task.getException()); - overlay.hide(2500, null); - }); - task.setOnSucceeded(function(event) { - update.description.textProperty().unbind(); - update.progress.progressProperty().unbind(); - if (callback !== null) { - callback(task.getValue()); - } - }); - } + setTaskProperties: function(task, request, callback) { + update.description.textProperty().bind(task.messageProperty()); + update.progress.progressProperty().bind(task.progressProperty()); + request.setStateCallback(function(state) update.stateCallback(task, state)); + task.setOnFailed(function(event) { + update.description.textProperty().unbind(); + update.progress.progressProperty().unbind(); + update.setError(task.getException()); + overlay.hide(2500, null); + }); + task.setOnSucceeded(function(event) { + update.description.textProperty().unbind(); + update.progress.progressProperty().unbind(); + if (callback !== null) { + callback(task.getValue()); + } + }); + } }; function offlineUpdateRequest(dirName, dir, matcher) { - return function() { - var hdir = settings.lastHDirs.get(dirName); - if (hdir === null) { - Request.requestError(java.lang.String.format("Директории '%s' нет в кэше", dirName)); - return; - } - - // Verify dir with matcher using ClientLauncher's API - ClientLauncher.verifyHDir(dir, hdir.object, matcher); - return hdir; - }; + return function() { + var hdir = settings.lastHDirs.get(dirName); + if (hdir === null) { + Request.requestError(java.lang.String.format("Директории '%s' нет в кэше", dirName)); + return; + } + + // Verify dir with matcher using ClientLauncher's API + ClientLauncher.verifyHDir(dir, hdir.object, matcher); + return hdir; + }; } /* Export functions */ -function makeUpdateRequest(dirName, dir, matcher, callback) { - var request = settings.offline ? { setStateCallback: function(stateCallback) { /* Ignored */ } } : - new UpdateRequest(dirName, dir, matcher); - var task = settings.offline ? newTask(offlineUpdateRequest(dirName, dir, matcher)) : - newRequestTask(request); - - // Set task properties and start - update.setTaskProperties(task, request, callback); - task.updateMessage("Состояние: Хеширование"); - task.updateProgress(-1, -1); - startTask(task); +function makeUpdateRequest(dirName, dir, matcher, digest, callback) { + var request = settings.offline ? { setStateCallback: function(stateCallback) { /* Ignored */ } } : + new UpdateRequest(dirName, dir, matcher, digest); + var task = settings.offline ? newTask(offlineUpdateRequest(dirName, dir, matcher)) : + newRequestTask(request); + + // Set task properties and start + update.setTaskProperties(task, request, callback); + task.updateMessage("Состояние: Хеширование"); + task.updateProgress(-1, -1); + startTask(task); } diff --git a/Launcher/source-authlib/yggdrasil/YggdrasilMinecraftSessionService.java b/Launcher/source-authlib/yggdrasil/YggdrasilMinecraftSessionService.java index 8342dc9..99c3356 100644 --- a/Launcher/source-authlib/yggdrasil/YggdrasilMinecraftSessionService.java +++ b/Launcher/source-authlib/yggdrasil/YggdrasilMinecraftSessionService.java @@ -24,6 +24,8 @@ import launcher.request.uuid.ProfileByUUIDRequest; public final class YggdrasilMinecraftSessionService extends BaseMinecraftSessionService { + public static final boolean NO_TEXTURES = Boolean.parseBoolean("launcher.authlib.noTextures"); + public YggdrasilMinecraftSessionService(AuthenticationService service) { super(service); LogHelper.debug("Patched MinecraftSessionService created"); @@ -64,22 +66,25 @@ LogHelper.debug("getTextures, Username: '%s'", profile.getName()); Map textures = new EnumMap<>(Type.class); - // Add skin URL to textures map - Iterator skinURL = profile.getProperties().get(ClientLauncher.SKIN_URL_PROPERTY).iterator(); - Iterator skinHash = profile.getProperties().get(ClientLauncher.SKIN_DIGEST_PROPERTY).iterator(); - if (skinURL.hasNext() && skinHash.hasNext()) { - String urlValue = skinURL.next().getValue(); - String hashValue = skinHash.next().getValue(); - textures.put(Type.SKIN, new MinecraftProfileTexture(urlValue, hashValue)); - } + // Add textures + if (!NO_TEXTURES) { + // Add skin URL to textures map + Iterator skinURL = profile.getProperties().get(ClientLauncher.SKIN_URL_PROPERTY).iterator(); + Iterator skinHash = profile.getProperties().get(ClientLauncher.SKIN_DIGEST_PROPERTY).iterator(); + if (skinURL.hasNext() && skinHash.hasNext()) { + String urlValue = skinURL.next().getValue(); + String hashValue = skinHash.next().getValue(); + textures.put(Type.SKIN, new MinecraftProfileTexture(urlValue, hashValue)); + } - // Add cloak URL to textures map - Iterator cloakURL = profile.getProperties().get(ClientLauncher.CLOAK_URL_PROPERTY).iterator(); - Iterator cloakHash = profile.getProperties().get(ClientLauncher.CLOAK_DIGEST_PROPERTY).iterator(); - if (cloakURL.hasNext() && cloakHash.hasNext()) { - String urlValue = cloakURL.next().getValue(); - String hashValue = cloakHash.next().getValue(); - textures.put(Type.CAPE, new MinecraftProfileTexture(urlValue, hashValue)); + // Add cloak URL to textures map + Iterator cloakURL = profile.getProperties().get(ClientLauncher.CLOAK_URL_PROPERTY).iterator(); + Iterator cloakHash = profile.getProperties().get(ClientLauncher.CLOAK_DIGEST_PROPERTY).iterator(); + if (cloakURL.hasNext() && cloakHash.hasNext()) { + String urlValue = cloakURL.next().getValue(); + String hashValue = cloakHash.next().getValue(); + textures.put(Type.CAPE, new MinecraftProfileTexture(urlValue, hashValue)); + } } // Return filled textures @@ -134,14 +139,22 @@ } public static void fillTextureProperties(GameProfile profile, PlayerProfile pp) { + LogHelper.debug("fillTextureProperties, Username: '%s'", profile.getName()); + if (NO_TEXTURES) { + return; + } + + // Fill textures map PropertyMap properties = profile.getProperties(); if (pp.skin != null) { properties.put(ClientLauncher.SKIN_URL_PROPERTY, new Property(ClientLauncher.SKIN_URL_PROPERTY, pp.skin.url, "")); properties.put(ClientLauncher.SKIN_DIGEST_PROPERTY, new Property(ClientLauncher.SKIN_DIGEST_PROPERTY, SecurityHelper.toHex(pp.skin.digest), "")); + LogHelper.debug("fillTextureProperties, Has skin texture for username '%s'", profile.getName()); } if (pp.cloak != null) { properties.put(ClientLauncher.CLOAK_URL_PROPERTY, new Property(ClientLauncher.CLOAK_URL_PROPERTY, pp.cloak.url, "")); properties.put(ClientLauncher.CLOAK_DIGEST_PROPERTY, new Property(ClientLauncher.CLOAK_DIGEST_PROPERTY, SecurityHelper.toHex(pp.cloak.digest), "")); + LogHelper.debug("fillTextureProperties, Has cloak texture for username '%s'", profile.getName()); } } diff --git a/Launcher/source/client/ClientLauncher.java b/Launcher/source/client/ClientLauncher.java index b165bdd..498bc39 100644 --- a/Launcher/source/client/ClientLauncher.java +++ b/Launcher/source/client/ClientLauncher.java @@ -13,7 +13,6 @@ import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.PosixFilePermission; import java.security.interfaces.RSAPublicKey; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.EnumSet; @@ -185,16 +184,17 @@ } // Start client with WatchService monitoring + boolean digest = !profile.object.isUpdateFastCheck(); LogHelper.debug("Starting JVM and client WatchService"); FileNameMatcher assetMatcher = profile.object.getAssetUpdateMatcher(); FileNameMatcher clientMatcher = profile.object.getClientUpdateMatcher(); - try (DirWatcher jvmWatcher = new DirWatcher(IOHelper.JVM_DIR, jvmHDir.object, null); // JVM Watcher - DirWatcher assetWatcher = new DirWatcher(params.assetDir, assetHDir.object, assetMatcher); - DirWatcher clientWatcher = new DirWatcher(params.clientDir, clientHDir.object, clientMatcher)) { + try (DirWatcher jvmWatcher = new DirWatcher(IOHelper.JVM_DIR, jvmHDir.object, null, digest); // JVM Watcher + DirWatcher assetWatcher = new DirWatcher(params.assetDir, assetHDir.object, assetMatcher, digest); + DirWatcher clientWatcher = new DirWatcher(params.clientDir, clientHDir.object, clientMatcher, digest)) { // Verify current state of all dirs - verifyHDir(IOHelper.JVM_DIR, jvmHDir.object, null); - verifyHDir(params.assetDir, assetHDir.object, assetMatcher); - verifyHDir(params.clientDir, clientHDir.object, clientMatcher); + verifyHDir(IOHelper.JVM_DIR, jvmHDir.object, null, digest); + verifyHDir(params.assetDir, assetHDir.object, assetMatcher, digest); + verifyHDir(params.clientDir, clientHDir.object, clientMatcher, digest); // Start WatchService, and only then client CommonHelper.newThread("JVM Directory Watcher", true, jvmWatcher).start(); @@ -210,13 +210,13 @@ } @LauncherAPI - public static void verifyHDir(Path dir, HashedDir hdir, FileNameMatcher matcher) throws IOException { + public static void verifyHDir(Path dir, HashedDir hdir, FileNameMatcher matcher, boolean digest) throws IOException { if (matcher != null) { matcher = matcher.verifyOnly(); } // Hash directory and compare (ignore update-only matcher entries, it will break offline-mode) - HashedDir currentHDir = new HashedDir(dir, matcher, false); + HashedDir currentHDir = new HashedDir(dir, matcher, false, digest); if (!hdir.diff(currentHDir, matcher).isSame()) { throw new SecurityException(String.format("Forbidden modification: '%s'", IOHelper.getFileName(dir))); } @@ -355,7 +355,7 @@ @LauncherAPI public Params(byte[] launcherSign, Path assetDir, Path clientDir, PlayerProfile pp, String accessToken, boolean autoEnter, boolean fullScreen, int ram, int width, int height) { - this.launcherSign = Arrays.copyOf(launcherSign, launcherSign.length); + this.launcherSign = launcherSign.clone(); // Client paths this.assetDir = assetDir; diff --git a/Launcher/source/hasher/DirWatcher.java b/Launcher/source/hasher/DirWatcher.java index 5f3c1b5..ef0d9e5 100644 --- a/Launcher/source/hasher/DirWatcher.java +++ b/Launcher/source/hasher/DirWatcher.java @@ -44,12 +44,14 @@ private final HashedDir hdir; private final FileNameMatcher matcher; private final WatchService service; + private final boolean digest; @LauncherAPI - public DirWatcher(Path dir, HashedDir hdir, FileNameMatcher matcher) throws IOException { + public DirWatcher(Path dir, HashedDir hdir, FileNameMatcher matcher, boolean digest) throws IOException { this.dir = Objects.requireNonNull(dir, "dir"); this.hdir = Objects.requireNonNull(hdir, "hdir"); this.matcher = matcher; + this.digest = digest; service = dir.getFileSystem().newWatchService(); // Use FILE_TREE if supported @@ -101,7 +103,7 @@ // Verify is REALLY modified (not just attributes) if (kind.equals(StandardWatchEventKinds.ENTRY_MODIFY)) { HashedEntry entry = hdir.resolve(stringPath); - if (entry != null && (entry.getType() != Type.FILE || ((HashedFile) entry).isSame(path))) { + if (entry != null && (entry.getType() != Type.FILE || ((HashedFile) entry).isSame(path, digest))) { continue; // Modified attributes, not need to worry :D } } diff --git a/Launcher/source/hasher/HashedDir.java b/Launcher/source/hasher/HashedDir.java index 6c989af..db47235 100644 --- a/Launcher/source/hasher/HashedDir.java +++ b/Launcher/source/hasher/HashedDir.java @@ -28,8 +28,8 @@ } @LauncherAPI - public HashedDir(Path dir, FileNameMatcher matcher, boolean allowSymlinks) throws IOException { - IOHelper.walk(dir, new HashFileVisitor(dir, matcher, allowSymlinks), true); + public HashedDir(Path dir, FileNameMatcher matcher, boolean allowSymlinks, boolean digest) throws IOException { + IOHelper.walk(dir, new HashFileVisitor(dir, matcher, allowSymlinks, digest), true); } @LauncherAPI @@ -175,16 +175,18 @@ private final Path dir; private final FileNameMatcher matcher; private final boolean allowSymlinks; + private final boolean digest; // State private HashedDir current = HashedDir.this; private final Deque path = new LinkedList<>(); private final Deque stack = new LinkedList<>(); - private HashFileVisitor(Path dir, FileNameMatcher matcher, boolean allowSymlinks) { + private HashFileVisitor(Path dir, FileNameMatcher matcher, boolean allowSymlinks, boolean digest) { this.dir = dir; this.matcher = matcher; this.allowSymlinks = allowSymlinks; + this.digest = digest; } @Override @@ -234,8 +236,8 @@ // Add file (may be unhashed, if exclusion) path.add(IOHelper.getFileName(file)); - boolean hash = matcher == null || matcher.shouldUpdate(path); - current.map.put(path.removeLast(), new HashedFile(file, attrs.size(), hash)); + boolean doDigest = digest && (matcher == null || matcher.shouldUpdate(path)); + current.map.put(path.removeLast(), new HashedFile(file, attrs.size(), doDigest)); return super.visitFile(file, attrs); } } diff --git a/Launcher/source/hasher/HashedFile.java b/Launcher/source/hasher/HashedFile.java index d9f5b85..306cbd1 100644 --- a/Launcher/source/hasher/HashedFile.java +++ b/Launcher/source/hasher/HashedFile.java @@ -13,7 +13,7 @@ import launcher.serialize.HOutput; public final class HashedFile extends HashedEntry { - private static final byte[] DUMMY_HASH = new byte[0]; + public static final DigestAlgorithm DIGEST_ALGO = DigestAlgorithm.MD5; // Instance @LauncherAPI public final long size; @@ -22,17 +22,17 @@ @LauncherAPI public HashedFile(long size, byte[] digest) { this.size = VerifyHelper.verifyLong(size, VerifyHelper.L_NOT_NEGATIVE, "Illegal size: " + size); - this.digest = Arrays.copyOf(digest, digest.length); + this.digest = DIGEST_ALGO.verify(digest).clone(); } @LauncherAPI - public HashedFile(Path file, long size, boolean hash) throws IOException { - this(size, hash ? SecurityHelper.digest(DigestAlgorithm.MD5, file) : DUMMY_HASH); + public HashedFile(Path file, long size, boolean digest) throws IOException { + this(size, digest ? SecurityHelper.digest(DIGEST_ALGO, file) : null); } @LauncherAPI public HashedFile(HInput input) throws IOException { - this(input.readVarLong(), input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH)); + this(input.readVarLong(), input.readBoolean() ? input.readByteArray(-DIGEST_ALGO.bytes) : null); } @Override @@ -48,21 +48,33 @@ @Override public void write(HOutput output) throws IOException { output.writeVarLong(size); - output.writeByteArray(digest, SecurityHelper.CRYPTO_MAX_LENGTH); + output.writeBoolean(digest != null); + if (digest != null) { + output.writeByteArray(digest, -DIGEST_ALGO.bytes); + } } @LauncherAPI public boolean isSame(HashedFile o) { - return size == o.size && Arrays.equals(digest, o.digest); + return size == o.size && (digest == null || o.digest == null || Arrays.equals(digest, o.digest)); } @LauncherAPI - public boolean isSame(Path file) throws IOException { - return isSame(new HashedFile(file, IOHelper.readAttributes(file).size(), true)); + public boolean isSame(Path file, boolean digest) throws IOException { + if (size != IOHelper.readAttributes(file).size()) { + return false; + } + if (!digest || this.digest == null) { + return true; + } + + // Create digest + byte[] actualDigest = SecurityHelper.digest(DIGEST_ALGO, file); + return Arrays.equals(this.digest, actualDigest); } @LauncherAPI public boolean isSameDigest(byte[] digest) { - return Arrays.equals(this.digest, digest); + return this.digest == null || digest == null || Arrays.equals(this.digest, digest); } } diff --git a/Launcher/source/helper/IOHelper.java b/Launcher/source/helper/IOHelper.java index aa96c0b..1196938 100644 --- a/Launcher/source/helper/IOHelper.java +++ b/Launcher/source/helper/IOHelper.java @@ -499,8 +499,8 @@ socket.setSoTimeout(SOCKET_TIMEOUT); socket.setTrafficClass(0b11100); // Allow OS to adjust buffer sizes - // socket.setSendBufferSize(0x100000); - // socket.setReceiveBufferSize(0x100000); + // socket.setSendBufferSize(0x100000); + // socket.setReceiveBufferSize(0x100000); socket.setPerformancePreferences(1, 0, 2); } diff --git a/Launcher/source/request/auth/AuthRequest.java b/Launcher/source/request/auth/AuthRequest.java index 79924f0..e3ba2c7 100644 --- a/Launcher/source/request/auth/AuthRequest.java +++ b/Launcher/source/request/auth/AuthRequest.java @@ -1,9 +1,7 @@ package launcher.request.auth; import java.io.IOException; -import java.util.Arrays; -import launcher.Launcher; import launcher.Launcher.Config; import launcher.LauncherAPI; import launcher.client.PlayerProfile; @@ -22,7 +20,7 @@ public AuthRequest(Config config, String login, byte[] encryptedPassword) { super(config); this.login = VerifyHelper.verify(login, VerifyHelper.NOT_EMPTY, "Login can't be empty"); - this.encryptedPassword = Arrays.copyOf(encryptedPassword, encryptedPassword.length); + this.encryptedPassword = encryptedPassword.clone(); } @LauncherAPI diff --git a/Launcher/source/request/update/LauncherRequest.java b/Launcher/source/request/update/LauncherRequest.java index 0a88482..cb68630 100644 --- a/Launcher/source/request/update/LauncherRequest.java +++ b/Launcher/source/request/update/LauncherRequest.java @@ -3,7 +3,6 @@ import java.nio.file.Path; import java.security.interfaces.RSAPublicKey; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -99,13 +98,13 @@ private final byte[] sign; private Result(byte[] sign, List> profiles) { - this.sign = Arrays.copyOf(sign, sign.length); + this.sign = sign.clone(); this.profiles = Collections.unmodifiableList(profiles); } @LauncherAPI public byte[] getSign() { - return Arrays.copyOf(sign, sign.length); + return sign.clone(); } } } diff --git a/Launcher/source/request/update/UpdateRequest.java b/Launcher/source/request/update/UpdateRequest.java index 9b4ec3a..3741fe1 100644 --- a/Launcher/source/request/update/UpdateRequest.java +++ b/Launcher/source/request/update/UpdateRequest.java @@ -40,6 +40,7 @@ private final String dirName; private final Path dir; private final FileNameMatcher matcher; + private final boolean digest; private volatile Callback stateCallback; // State @@ -49,16 +50,17 @@ private Instant startTime; @LauncherAPI - public UpdateRequest(Config config, String dirName, Path dir, FileNameMatcher matcher) { + public UpdateRequest(Config config, String dirName, Path dir, FileNameMatcher matcher, boolean digest) { super(config); this.dirName = IOHelper.verifyFileName(dirName); this.dir = Objects.requireNonNull(dir, "dir"); this.matcher = matcher; + this.digest = digest; } @LauncherAPI - public UpdateRequest(String dirName, Path dir, FileNameMatcher matcher) { - this(null, dirName, dir, matcher); + public UpdateRequest(String dirName, Path dir, FileNameMatcher matcher, boolean digest) { + this(null, dirName, dir, matcher, digest); } @Override @@ -69,7 +71,7 @@ @Override public SignedObjectHolder request() throws Exception { Files.createDirectories(dir); - localDir = new HashedDir(dir, matcher, false); + localDir = new HashedDir(dir, matcher, false, digest); // Start request return super.request(); diff --git a/Launcher/source/request/uuid/BatchProfileByUsernameRequest.java b/Launcher/source/request/uuid/BatchProfileByUsernameRequest.java index 1f13ac0..b8d7a05 100644 --- a/Launcher/source/request/uuid/BatchProfileByUsernameRequest.java +++ b/Launcher/source/request/uuid/BatchProfileByUsernameRequest.java @@ -1,9 +1,7 @@ package launcher.request.uuid; import java.io.IOException; -import java.util.Arrays; -import launcher.Launcher; import launcher.Launcher.Config; import launcher.LauncherAPI; import launcher.client.PlayerProfile; @@ -20,7 +18,7 @@ @LauncherAPI public BatchProfileByUsernameRequest(Config config, String... usernames) throws IOException { super(config); - this.usernames = Arrays.copyOf(usernames, usernames.length); + this.usernames = usernames.clone(); IOHelper.verifyLength(this.usernames.length, MAX_BATCH_SIZE); for (String username : this.usernames) { VerifyHelper.verifyUsername(username); diff --git a/Launcher/source/serialize/signed/SignedBytesHolder.java b/Launcher/source/serialize/signed/SignedBytesHolder.java index 19b6729..dec3594 100644 --- a/Launcher/source/serialize/signed/SignedBytesHolder.java +++ b/Launcher/source/serialize/signed/SignedBytesHolder.java @@ -4,7 +4,6 @@ import java.security.SignatureException; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; -import java.util.Arrays; import launcher.LauncherAPI; import launcher.helper.SecurityHelper; @@ -24,13 +23,13 @@ @LauncherAPI public SignedBytesHolder(byte[] bytes, byte[] sign, RSAPublicKey publicKey) throws SignatureException { SecurityHelper.verifySign(bytes, sign, publicKey); - this.bytes = Arrays.copyOf(bytes, bytes.length); - this.sign = Arrays.copyOf(sign, sign.length); + this.bytes = bytes.clone(); + this.sign = sign.clone(); } @LauncherAPI public SignedBytesHolder(byte[] bytes, RSAPrivateKey privateKey) { - this.bytes = Arrays.copyOf(bytes, bytes.length); + this.bytes = bytes.clone(); sign = SecurityHelper.sign(bytes, privateKey); } @@ -42,11 +41,11 @@ @LauncherAPI public final byte[] getBytes() { - return Arrays.copyOf(bytes, bytes.length); + return bytes.clone(); } @LauncherAPI public final byte[] getSign() { - return Arrays.copyOf(sign, sign.length); + return sign.clone(); } }