mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-11 08:27:29 -04:00
check sha1 of assets (optionally), hide all other windows, when fatal error occurred
This commit is contained in:
parent
16ef8d7b06
commit
9d12a40596
@ -34,6 +34,7 @@ import de.bixilon.minosoft.util.task.Task;
|
|||||||
import de.bixilon.minosoft.util.task.TaskImportance;
|
import de.bixilon.minosoft.util.task.TaskImportance;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.scene.control.Dialog;
|
import javafx.scene.control.Dialog;
|
||||||
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@ -85,11 +86,19 @@ public final class Minosoft {
|
|||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// hide all other gui parts
|
||||||
|
StartProgressWindow.hideDialog();
|
||||||
|
Launcher.exit();
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
Dialog<Boolean> dialog = new Dialog<>();
|
Dialog<Boolean> dialog = new Dialog<>();
|
||||||
dialog.setTitle("Critical Error");
|
dialog.setTitle("Critical Error");
|
||||||
dialog.setHeaderText("An error occurred while starting Minosoft");
|
dialog.setHeaderText("An error occurred while starting Minosoft");
|
||||||
dialog.setContentText(exception.getMessage());
|
dialog.setContentText(exception.getLocalizedMessage());
|
||||||
|
|
||||||
|
Stage stage = (Stage) dialog.getDialogPane().getScene().getWindow();
|
||||||
|
stage.setAlwaysOnTop(true);
|
||||||
|
stage.toFront();
|
||||||
|
dialog.setOnCloseRequest(dialogEvent -> System.exit(1));
|
||||||
dialog.showAndWait();
|
dialog.showAndWait();
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
});
|
});
|
||||||
@ -101,7 +110,7 @@ public final class Minosoft {
|
|||||||
|
|
||||||
taskWorker.addTask(new Task(progress -> {
|
taskWorker.addTask(new Task(progress -> {
|
||||||
progress.countUp();
|
progress.countUp();
|
||||||
LocaleManager.load(config.getString(ConfigurationPaths.LANGUAGE));
|
LocaleManager.load(config.getString(ConfigurationPaths.GENERAL_LANGUAGE));
|
||||||
progress.countDown();
|
progress.countDown();
|
||||||
|
|
||||||
}, "Minosoft Language", "", Priorities.HIGH, TaskImportance.REQUIRED));
|
}, "Minosoft Language", "", Priorities.HIGH, TaskImportance.REQUIRED));
|
||||||
@ -143,7 +152,7 @@ public final class Minosoft {
|
|||||||
|
|
||||||
taskWorker.addTask(new Task(progress -> {
|
taskWorker.addTask(new Task(progress -> {
|
||||||
progress.countUp();
|
progress.countUp();
|
||||||
MinecraftLocaleManager.load(config.getString(ConfigurationPaths.LANGUAGE));
|
MinecraftLocaleManager.load(config.getString(ConfigurationPaths.GENERAL_LANGUAGE));
|
||||||
progress.countDown();
|
progress.countDown();
|
||||||
|
|
||||||
}, "Mojang language", "", Priorities.HIGH, TaskImportance.REQUIRED, new HashSet<>(Collections.singleton("Assets"))));
|
}, "Mojang language", "", Priorities.HIGH, TaskImportance.REQUIRED, new HashSet<>(Collections.singleton("Assets"))));
|
||||||
|
@ -91,6 +91,7 @@ public class Configuration {
|
|||||||
public boolean getBoolean(ConfigurationPaths path) {
|
public boolean getBoolean(ConfigurationPaths path) {
|
||||||
return switch (path) {
|
return switch (path) {
|
||||||
case NETWORK_FAKE_CLIENT_BRAND -> config.getAsJsonObject("network").get("fake-network-brand").getAsBoolean();
|
case NETWORK_FAKE_CLIENT_BRAND -> config.getAsJsonObject("network").get("fake-network-brand").getAsBoolean();
|
||||||
|
case DEBUG_VERIFY_ASSETS -> config.getAsJsonObject("debug").get("verify-assets").getAsBoolean();
|
||||||
default -> throw new RuntimeException(String.format("Illegal boolean value: %s", path));
|
default -> throw new RuntimeException(String.format("Illegal boolean value: %s", path));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -98,6 +99,7 @@ public class Configuration {
|
|||||||
public void putBoolean(ConfigurationPaths path, boolean value) {
|
public void putBoolean(ConfigurationPaths path, boolean value) {
|
||||||
switch (path) {
|
switch (path) {
|
||||||
case NETWORK_FAKE_CLIENT_BRAND -> config.getAsJsonObject("network").addProperty("fake-network-brand", value);
|
case NETWORK_FAKE_CLIENT_BRAND -> config.getAsJsonObject("network").addProperty("fake-network-brand", value);
|
||||||
|
case DEBUG_VERIFY_ASSETS -> config.getAsJsonObject("debug").addProperty("verify-assets", value);
|
||||||
default -> throw new RuntimeException(String.format("Illegal boolean value: %s", path));
|
default -> throw new RuntimeException(String.format("Illegal boolean value: %s", path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,7 +124,7 @@ public class Configuration {
|
|||||||
return switch (path) {
|
return switch (path) {
|
||||||
case ACCOUNT_SELECTED -> config.getAsJsonObject("accounts").get("selected").getAsString();
|
case ACCOUNT_SELECTED -> config.getAsJsonObject("accounts").get("selected").getAsString();
|
||||||
case GENERAL_LOG_LEVEL -> config.getAsJsonObject("general").get("log-level").getAsString();
|
case GENERAL_LOG_LEVEL -> config.getAsJsonObject("general").get("log-level").getAsString();
|
||||||
case LANGUAGE -> config.getAsJsonObject("general").get("language").getAsString();
|
case GENERAL_LANGUAGE -> config.getAsJsonObject("general").get("language").getAsString();
|
||||||
case MAPPINGS_URL -> config.getAsJsonObject("download").getAsJsonObject("urls").get("mappings").getAsString();
|
case MAPPINGS_URL -> config.getAsJsonObject("download").getAsJsonObject("urls").get("mappings").getAsString();
|
||||||
case CLIENT_TOKEN -> config.getAsJsonObject("accounts").get("client-token").getAsString();
|
case CLIENT_TOKEN -> config.getAsJsonObject("accounts").get("client-token").getAsString();
|
||||||
default -> throw new RuntimeException(String.format("Illegal String value: %s", path));
|
default -> throw new RuntimeException(String.format("Illegal String value: %s", path));
|
||||||
@ -133,7 +135,7 @@ public class Configuration {
|
|||||||
switch (path) {
|
switch (path) {
|
||||||
case ACCOUNT_SELECTED -> config.getAsJsonObject("accounts").addProperty("selected", value);
|
case ACCOUNT_SELECTED -> config.getAsJsonObject("accounts").addProperty("selected", value);
|
||||||
case GENERAL_LOG_LEVEL -> config.getAsJsonObject("general").addProperty("log-level", value);
|
case GENERAL_LOG_LEVEL -> config.getAsJsonObject("general").addProperty("log-level", value);
|
||||||
case LANGUAGE -> config.getAsJsonObject("general").addProperty("language", value);
|
case GENERAL_LANGUAGE -> config.getAsJsonObject("general").addProperty("language", value);
|
||||||
case MAPPINGS_URL -> config.getAsJsonObject("download").getAsJsonObject("urls").addProperty("mappings", value);
|
case MAPPINGS_URL -> config.getAsJsonObject("download").getAsJsonObject("urls").addProperty("mappings", value);
|
||||||
case CLIENT_TOKEN -> config.getAsJsonObject("accounts").addProperty("client-token", value);
|
case CLIENT_TOKEN -> config.getAsJsonObject("accounts").addProperty("client-token", value);
|
||||||
default -> throw new RuntimeException(String.format("Illegal String value: %s", path));
|
default -> throw new RuntimeException(String.format("Illegal String value: %s", path));
|
||||||
|
@ -21,5 +21,6 @@ public enum ConfigurationPaths {
|
|||||||
CLIENT_TOKEN,
|
CLIENT_TOKEN,
|
||||||
MAPPINGS_URL,
|
MAPPINGS_URL,
|
||||||
ACCOUNT_SELECTED,
|
ACCOUNT_SELECTED,
|
||||||
LANGUAGE,
|
GENERAL_LANGUAGE,
|
||||||
|
DEBUG_VERIFY_ASSETS,
|
||||||
}
|
}
|
@ -19,6 +19,8 @@ import com.google.gson.JsonObject;
|
|||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
||||||
import de.bixilon.minosoft.Config;
|
import de.bixilon.minosoft.Config;
|
||||||
|
import de.bixilon.minosoft.Minosoft;
|
||||||
|
import de.bixilon.minosoft.config.ConfigurationPaths;
|
||||||
import de.bixilon.minosoft.logging.Log;
|
import de.bixilon.minosoft.logging.Log;
|
||||||
import de.bixilon.minosoft.logging.LogLevels;
|
import de.bixilon.minosoft.logging.LogLevels;
|
||||||
import de.bixilon.minosoft.util.CountUpAndDownLatch;
|
import de.bixilon.minosoft.util.CountUpAndDownLatch;
|
||||||
@ -146,7 +148,17 @@ public class AssetsManager {
|
|||||||
|
|
||||||
private static boolean verifyAssetHash(String hash) {
|
private static boolean verifyAssetHash(String hash) {
|
||||||
// file does not exist
|
// file does not exist
|
||||||
return getAssetSize(hash) != -1;// ToDo
|
if (getAssetSize(hash) == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Minosoft.config.getBoolean(ConfigurationPaths.DEBUG_VERIFY_ASSETS)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return hash.equals(Util.sha1Gzip(new File(getAssetDiskPath(hash))));
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void generateJarAssets() throws IOException {
|
public static void generateJarAssets() throws IOException {
|
||||||
|
@ -33,11 +33,16 @@ import java.io.IOException;
|
|||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
public class Launcher {
|
public class Launcher {
|
||||||
|
private static Stage stage;
|
||||||
|
private static boolean exit = false;
|
||||||
|
|
||||||
public static void start() throws Exception {
|
public static void start() throws Exception {
|
||||||
Log.info("Starting launcher...");
|
Log.info("Starting launcher...");
|
||||||
CountDownLatch latch = new CountDownLatch(1);
|
CountDownLatch latch = new CountDownLatch(1);
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
|
if (exit) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
Stage stage = new Stage();
|
Stage stage = new Stage();
|
||||||
|
|
||||||
GUITools.versionList.setCellFactory(new Callback<>() {
|
GUITools.versionList.setCellFactory(new Callback<>() {
|
||||||
@ -73,14 +78,27 @@ public class Launcher {
|
|||||||
|
|
||||||
stage.setTitle(LocaleManager.translate(Strings.MAIN_WINDOW_TITLE));
|
stage.setTitle(LocaleManager.translate(Strings.MAIN_WINDOW_TITLE));
|
||||||
stage.getIcons().add(GUITools.logo);
|
stage.getIcons().add(GUITools.logo);
|
||||||
stage.show();
|
|
||||||
stage.setOnCloseRequest(windowEvent -> System.exit(0));
|
stage.setOnCloseRequest(windowEvent -> System.exit(0));
|
||||||
if (Minosoft.getSelectedAccount() == null) {
|
if (Minosoft.getSelectedAccount() == null) {
|
||||||
MainWindow.manageAccounts();
|
MainWindow.manageAccounts();
|
||||||
}
|
}
|
||||||
|
if (exit) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
stage.show();
|
||||||
|
Launcher.stage = stage;
|
||||||
latch.countDown();
|
latch.countDown();
|
||||||
});
|
});
|
||||||
latch.await();
|
latch.await();
|
||||||
Log.info("Launcher started!");
|
Log.info("Launcher started!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void exit() {
|
||||||
|
exit = true;
|
||||||
|
if (stage == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Platform.runLater(() -> stage.close());
|
||||||
|
}
|
||||||
}
|
}
|
@ -29,26 +29,33 @@ import java.util.concurrent.atomic.AtomicReference;
|
|||||||
|
|
||||||
public class StartProgressWindow extends Application {
|
public class StartProgressWindow extends Application {
|
||||||
public static CountDownLatch toolkitLatch = new CountDownLatch(2);
|
public static CountDownLatch toolkitLatch = new CountDownLatch(2);
|
||||||
|
private static Dialog<Boolean> progressDialog;
|
||||||
|
private static boolean exit = false;
|
||||||
|
|
||||||
public static void show(CountUpAndDownLatch progress) {
|
public static void show(CountUpAndDownLatch progress) {
|
||||||
|
if (exit) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
if (progress.getCount() == 0) {
|
if (progress.getCount() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AtomicReference<ProgressBar> progressBar = new AtomicReference<>();
|
AtomicReference<ProgressBar> progressBar = new AtomicReference<>();
|
||||||
AtomicReference<Dialog<Boolean>> progressDialog = new AtomicReference<>();
|
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
progressDialog.set(new Dialog<>());
|
progressDialog = new Dialog<>();
|
||||||
progressDialog.get().setTitle(LocaleManager.translate(Strings.MINOSOFT_STILL_STARTING_TITLE));
|
progressDialog.setTitle(LocaleManager.translate(Strings.MINOSOFT_STILL_STARTING_TITLE));
|
||||||
progressDialog.get().setHeaderText(LocaleManager.translate(Strings.MINOSOFT_STILL_STARTING_HEADER));
|
progressDialog.setHeaderText(LocaleManager.translate(Strings.MINOSOFT_STILL_STARTING_HEADER));
|
||||||
GridPane grid = new GridPane();
|
GridPane grid = new GridPane();
|
||||||
progressBar.set(new ProgressBar());
|
progressBar.set(new ProgressBar());
|
||||||
progressBar.get().setProgress(1.0F - ((float) progress.getCount() / progress.getTotal()));
|
progressBar.get().setProgress(1.0F - ((float) progress.getCount() / progress.getTotal()));
|
||||||
grid.add(progressBar.get(), 0, 0);
|
grid.add(progressBar.get(), 0, 0);
|
||||||
progressDialog.get().getDialogPane().setContent(grid);
|
progressDialog.getDialogPane().setContent(grid);
|
||||||
progressDialog.get().show();
|
if (exit) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
progressDialog.show();
|
||||||
|
|
||||||
Stage stage = (Stage) progressDialog.get().getDialogPane().getScene().getWindow();
|
Stage stage = (Stage) progressDialog.getDialogPane().getScene().getWindow();
|
||||||
stage.setAlwaysOnTop(true);
|
stage.setAlwaysOnTop(true);
|
||||||
stage.toFront();
|
stage.toFront();
|
||||||
|
|
||||||
@ -61,11 +68,7 @@ public class StartProgressWindow extends Application {
|
|||||||
}
|
}
|
||||||
Platform.runLater(() -> progressBar.get().setProgress(1.0F - ((float) progress.getCount() / progress.getTotal())));
|
Platform.runLater(() -> progressBar.get().setProgress(1.0F - ((float) progress.getCount() / progress.getTotal())));
|
||||||
}
|
}
|
||||||
|
hideDialog();
|
||||||
Platform.runLater(() -> {
|
|
||||||
progressDialog.get().setResult(Boolean.TRUE);
|
|
||||||
progressDialog.get().hide();
|
|
||||||
});
|
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,6 +80,17 @@ public class StartProgressWindow extends Application {
|
|||||||
Log.debug("Initialized JavaFX Toolkit!");
|
Log.debug("Initialized JavaFX Toolkit!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void hideDialog() {
|
||||||
|
exit = true;
|
||||||
|
if (progressDialog == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
progressDialog.setResult(Boolean.TRUE);
|
||||||
|
progressDialog.hide();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(Stage stage) {
|
public void start(Stage stage) {
|
||||||
toolkitLatch.countDown();
|
toolkitLatch.countDown();
|
||||||
|
@ -102,17 +102,40 @@ public final class Util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String sha1(byte[] data) {
|
public static String sha1(byte[] data) {
|
||||||
|
ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
|
||||||
try {
|
try {
|
||||||
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
|
return sha1(inputStream);
|
||||||
crypt.reset();
|
} catch (IOException e) {
|
||||||
crypt.update(data);
|
|
||||||
return byteArrayToHexString(crypt.digest());
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String sha1(File file) throws IOException {
|
||||||
|
return sha1(new FileInputStream(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String sha1Gzip(File file) throws IOException {
|
||||||
|
return sha1(new GZIPInputStream(new FileInputStream(file)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String sha1(InputStream inputStream) throws IOException {
|
||||||
|
try {
|
||||||
|
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
|
||||||
|
crypt.reset();
|
||||||
|
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
|
int length;
|
||||||
|
while ((length = inputStream.read(buffer, 0, 4096)) != -1) {
|
||||||
|
crypt.update(buffer, 0, length);
|
||||||
|
}
|
||||||
|
return byteArrayToHexString(crypt.digest());
|
||||||
|
} catch (NoSuchAlgorithmException | FileNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static String byteArrayToHexString(byte[] b) {
|
public static String byteArrayToHexString(byte[] b) {
|
||||||
StringBuilder result = new StringBuilder();
|
StringBuilder result = new StringBuilder();
|
||||||
for (byte value : b) {
|
for (byte value : b) {
|
||||||
|
@ -23,5 +23,8 @@
|
|||||||
"urls": {
|
"urls": {
|
||||||
"mappings": "https://gitlab.com/Bixilon/minosoft/-/raw/master/data/mcdata/%s.tar.gz?inline=false"
|
"mappings": "https://gitlab.com/Bixilon/minosoft/-/raw/master/data/mcdata/%s.tar.gz?inline=false"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"debug": {
|
||||||
|
"verify-assets": true
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user