Crash and upgrade
This commit is contained in:
@@ -23,10 +23,14 @@ import javafx.application.Platform;
|
||||
import javafx.stage.Stage;
|
||||
import org.jackhuang.hmcl.setting.Settings;
|
||||
import org.jackhuang.hmcl.task.Schedulers;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.ui.Controllers;
|
||||
import org.jackhuang.hmcl.upgrade.IUpgrader;
|
||||
import org.jackhuang.hmcl.upgrade.UpdateChecker;
|
||||
import org.jackhuang.hmcl.util.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.logging.Level;
|
||||
|
||||
@@ -44,8 +48,17 @@ public final class Main extends Application {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
NetworkUtils.setUserAgentSupplier(() -> "Hello Minecraft! Launcher");
|
||||
Thread.setDefaultUncaughtExceptionHandler(new CrashReporter());
|
||||
|
||||
// NetworkUtils.setUserAgentSupplier(() -> "Hello Minecraft! Launcher");
|
||||
Constants.UI_THREAD_SCHEDULER = Constants.JAVAFX_UI_THREAD_SCHEDULER;
|
||||
IUpgrader.NOW_UPGRADER.parseArguments(VersionNumber.asVersion(VERSION), Arrays.asList(args));
|
||||
|
||||
Logging.LOG.info("*** " + TITLE + " ***");
|
||||
|
||||
UPDATE_CHECKER.process(false)
|
||||
.then(Task.of(Controllers::showUpdate))
|
||||
.start();
|
||||
|
||||
launch(args);
|
||||
}
|
||||
@@ -99,4 +112,8 @@ public final class Main extends Application {
|
||||
public static final String TITLE = NAME + " " + VERSION;
|
||||
public static final File APPDATA = getWorkingDirectory("hmcl");
|
||||
public static final ResourceBundle RESOURCE_BUNDLE = Settings.INSTANCE.getLocale().getResourceBundle();
|
||||
public static final UpdateChecker UPDATE_CHECKER = new UpdateChecker(VersionNumber.asVersion(VERSION), "hmcl");
|
||||
|
||||
public static final String CONTACT = "http://huangyuhui.duapp.com/hmcl.php";
|
||||
public static final String PUBLISH = "http://www.mcbbs.net/thread-142335-1-1.html";
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ public final class Locales {
|
||||
}
|
||||
|
||||
public static SupportedLocale getLocaleByName(String name) {
|
||||
if (name == null) return DEFAULT;
|
||||
switch (name.toLowerCase()) {
|
||||
case "en": return EN;
|
||||
case "zh": return ZH;
|
||||
|
||||
@@ -68,6 +68,7 @@ public final class AccountsPage extends StackPane implements DecoratorPage {
|
||||
FXUtils.setValidateWhileTextChanged(txtUsername);
|
||||
FXUtils.setValidateWhileTextChanged(txtPassword);
|
||||
|
||||
cboType.getItems().setAll(Main.i18n("account.methods.offline"), Main.i18n("account.methods.yggdrasil"));
|
||||
cboType.getSelectionModel().selectedIndexProperty().addListener((a, b, newValue) -> {
|
||||
txtPassword.setVisible(newValue.intValue() != 0);
|
||||
});
|
||||
|
||||
@@ -139,4 +139,8 @@ public final class Controllers {
|
||||
public static void navigate(Node node) {
|
||||
decorator.showPage(node);
|
||||
}
|
||||
|
||||
public static void showUpdate() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
72
HMCL/src/main/java/org/jackhuang/hmcl/ui/CrashWindow.java
Normal file
72
HMCL/src/main/java/org/jackhuang/hmcl/ui/CrashWindow.java
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher.
|
||||
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
*/
|
||||
package org.jackhuang.hmcl.ui;
|
||||
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TextArea;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.layout.BorderPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.stage.Stage;
|
||||
import org.jackhuang.hmcl.Main;
|
||||
|
||||
/**
|
||||
* @author huangyuhui
|
||||
*/
|
||||
public class CrashWindow extends Stage {
|
||||
|
||||
private Label lblCrash = new Label();
|
||||
private Button btnContact = new Button();
|
||||
private TextArea textArea = new TextArea();
|
||||
|
||||
public CrashWindow(String text) {
|
||||
if (Main.UPDATE_CHECKER.isOutOfDate())
|
||||
lblCrash.setText(Main.i18n("launcher.crash_out_dated"));
|
||||
else
|
||||
lblCrash.setText(Main.i18n("launcher.crash"));
|
||||
lblCrash.setWrapText(true);
|
||||
|
||||
textArea.setText(text);
|
||||
textArea.setEditable(false);
|
||||
|
||||
btnContact.setText(Main.i18n("launcher.contact"));
|
||||
btnContact.setOnMouseClicked(event -> FXUtils.openLink(Main.CONTACT));
|
||||
HBox box = new HBox();
|
||||
box.setStyle("-fx-padding: 8px;");
|
||||
box.getChildren().add(btnContact);
|
||||
box.setAlignment(Pos.CENTER_RIGHT);
|
||||
|
||||
BorderPane pane = new BorderPane();
|
||||
StackPane stackPane = new StackPane();
|
||||
stackPane.setStyle("-fx-padding: 8px;");
|
||||
stackPane.getChildren().add(lblCrash);
|
||||
pane.setTop(stackPane);
|
||||
pane.setCenter(textArea);
|
||||
pane.setBottom(box);
|
||||
|
||||
Scene scene = new Scene(pane, 800, 480);
|
||||
setScene(scene);
|
||||
getIcons().add(new Image("/assets/img/icon.png"));
|
||||
setTitle(Main.i18n("message.error"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -118,6 +118,8 @@ public final class Decorator extends StackPane implements TaskExecutorDialogWiza
|
||||
private JFXButton btnMax;
|
||||
@FXML
|
||||
private JFXButton btnClose;
|
||||
@FXML
|
||||
private HBox updatePane;
|
||||
|
||||
public Decorator(Stage primaryStage, Node mainPage, String title) {
|
||||
this(primaryStage, mainPage, title, true, true);
|
||||
@@ -131,6 +133,9 @@ public final class Decorator extends StackPane implements TaskExecutorDialogWiza
|
||||
|
||||
FXUtils.loadFXML(this, "/assets/fxml/decorator.fxml");
|
||||
|
||||
updatePane.setCursor(Cursor.HAND);
|
||||
updatePane.setOnMouseClicked(event -> Main.UPDATE_CHECKER.checkOutdate());
|
||||
|
||||
primaryStage.initStyle(StageStyle.UNDECORATED);
|
||||
btnClose.setGraphic(close);
|
||||
btnMin.setGraphic(minus);
|
||||
@@ -374,6 +379,10 @@ public final class Decorator extends StackPane implements TaskExecutorDialogWiza
|
||||
}
|
||||
}
|
||||
|
||||
public void showUpdate() {
|
||||
updatePane.setVisible(true);
|
||||
}
|
||||
|
||||
private void setContent(Node content, AnimationProducer animation) {
|
||||
animationHandler.setContent(content, animation);
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ import org.jackhuang.hmcl.util.OperatingSystem;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
@@ -203,6 +204,27 @@ public final class FXUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open URL by java.awt.Desktop
|
||||
*
|
||||
* @param link null is allowed but will be ignored
|
||||
*/
|
||||
public static void openLink(String link) {
|
||||
if (link == null)
|
||||
return;
|
||||
try {
|
||||
java.awt.Desktop.getDesktop().browse(new URI(link));
|
||||
} catch (Throwable e) {
|
||||
if (OperatingSystem.CURRENT_OS == OperatingSystem.OSX)
|
||||
try {
|
||||
Runtime.getRuntime().exec(new String[] { "/usr/bin/open", link });
|
||||
} catch (IOException ex) {
|
||||
Logging.LOG.log(Level.WARNING, "Unable to open link: " + link, ex);
|
||||
}
|
||||
Logging.LOG.log(Level.WARNING, "Failed to open link: " + link, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void bindInt(JFXTextField textField, Property<?> property) {
|
||||
textField.textProperty().unbind();
|
||||
textField.textProperty().bindBidirectional((Property<Integer>) property, SafeIntStringConverter.INSTANCE);
|
||||
|
||||
@@ -40,7 +40,7 @@ import java.util.Objects;
|
||||
public final class LeftPaneController {
|
||||
private final AdvancedListBox leftPane;
|
||||
private final VBox profilePane = new VBox();
|
||||
private final VersionListItem accountItem = new VersionListItem("No Account", "unknown");
|
||||
private final VersionListItem accountItem = new VersionListItem("", "");
|
||||
|
||||
public LeftPaneController(AdvancedListBox leftPane) {
|
||||
this.leftPane = leftPane;
|
||||
@@ -67,8 +67,8 @@ public final class LeftPaneController {
|
||||
|
||||
FXUtils.onChangeAndOperate(Settings.INSTANCE.selectedAccountProperty(), it -> {
|
||||
if (it == null) {
|
||||
accountItem.setVersionName("mojang@mojang.com");
|
||||
accountItem.setGameVersion("Yggdrasil");
|
||||
accountItem.setVersionName(Main.i18n("account.missing"));
|
||||
accountItem.setGameVersion(Main.i18n("message.unknown"));
|
||||
} else {
|
||||
accountItem.setVersionName(it.getUsername());
|
||||
accountItem.setGameVersion(AccountsPage.accountType(it));
|
||||
|
||||
@@ -48,7 +48,6 @@ import org.jackhuang.hmcl.task.Schedulers;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.task.TaskExecutor;
|
||||
import org.jackhuang.hmcl.ui.construct.MessageBox;
|
||||
import org.jackhuang.hmcl.ui.construct.MessageDialogPane;
|
||||
import org.jackhuang.hmcl.ui.construct.TaskExecutorDialogPane;
|
||||
import org.jackhuang.hmcl.ui.download.DownloadWizardProvider;
|
||||
import org.jackhuang.hmcl.ui.wizard.DecoratorPage;
|
||||
@@ -104,13 +103,13 @@ public final class MainPage extends StackPane implements DecoratorPage {
|
||||
item.setVersionName(version);
|
||||
item.setOnLaunchButtonClicked(e -> {
|
||||
if (Settings.INSTANCE.getSelectedAccount() == null)
|
||||
Controllers.dialog(Main.i18n("login.no_Player007"));
|
||||
Controllers.dialog(Main.i18n("login.empty_username"));
|
||||
else
|
||||
LauncherHelper.INSTANCE.launch(version, null);
|
||||
});
|
||||
item.setOnScriptButtonClicked(e -> {
|
||||
if (Settings.INSTANCE.getSelectedAccount() == null)
|
||||
Controllers.dialog(Main.i18n("login.no_Player007"));
|
||||
Controllers.dialog(Main.i18n("login.empty_username"));
|
||||
else {
|
||||
FileChooser chooser = new FileChooser();
|
||||
chooser.setInitialDirectory(profile.getRepository().getRunDirectory(version));
|
||||
|
||||
@@ -106,7 +106,7 @@ public class AppDataUpgrader extends IUpgrader {
|
||||
String hash = null;
|
||||
if (map.containsKey("jarsha1"))
|
||||
hash = map.get("jarsha1");
|
||||
Controllers.dialog(Main.i18n("ui.message.downloading"));
|
||||
Controllers.dialog(Main.i18n("message.downloading"));
|
||||
if (new AppDataUpgraderJarTask(NetworkUtils.toURL(map.get("jar")), version.toString(), hash).test()) {
|
||||
new ProcessBuilder(JavaVersion.fromCurrentEnvironment().getBinary().getAbsolutePath(), "-jar", AppDataUpgraderJarTask.getSelf(version.toString()).getAbsolutePath())
|
||||
.directory(new File("").getAbsoluteFile()).start();
|
||||
@@ -121,7 +121,7 @@ public class AppDataUpgrader extends IUpgrader {
|
||||
String hash = null;
|
||||
if (map.containsKey("packsha1"))
|
||||
hash = map.get("packsha1");
|
||||
Controllers.dialog(Main.i18n("ui.message.downloading"));
|
||||
Controllers.dialog(Main.i18n("message.downloading"));
|
||||
if (new AppDataUpgraderPackGzTask(NetworkUtils.toURL(map.get("pack")), version.toString(), hash).test()) {
|
||||
new ProcessBuilder(JavaVersion.fromCurrentEnvironment().getBinary().getAbsolutePath(), "-jar", AppDataUpgraderPackGzTask.getSelf(version.toString()).getAbsolutePath())
|
||||
.directory(new File("").getAbsoluteFile()).start();
|
||||
@@ -132,14 +132,14 @@ public class AppDataUpgrader extends IUpgrader {
|
||||
Logging.LOG.log(Level.SEVERE, "Failed to create upgrader", ex);
|
||||
}
|
||||
else {
|
||||
String url = URL_PUBLISH;
|
||||
String url = Main.PUBLISH;
|
||||
if (map != null)
|
||||
if (map.containsKey(OperatingSystem.CURRENT_OS.getCheckedName()))
|
||||
url = map.get(OperatingSystem.CURRENT_OS.getCheckedName());
|
||||
else if (map.containsKey(OperatingSystem.UNKNOWN.getCheckedName()))
|
||||
url = map.get(OperatingSystem.UNKNOWN.getCheckedName());
|
||||
if (url == null)
|
||||
url = URL_PUBLISH;
|
||||
url = Main.PUBLISH;
|
||||
try {
|
||||
java.awt.Desktop.getDesktop().browse(new URI(url));
|
||||
} catch (URISyntaxException | IOException e) {
|
||||
@@ -240,7 +240,4 @@ public class AppDataUpgrader extends IUpgrader {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static final String URL_PUBLISH = "http://www.mcbbs.net/thread-142335-1-1.html";
|
||||
public static final String URL_CONTACT = "http://huangyuhui.duapp.com/hmcl.php";
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public class NewFileUpgrader extends IUpgrader {
|
||||
URL url = requestDownloadLink();
|
||||
if (url == null) return;
|
||||
File newf = new File(url.getFile());
|
||||
Controllers.dialog(Main.i18n("ui.message.downloading"));
|
||||
Controllers.dialog(Main.i18n("message.downloading"));
|
||||
if (new FileDownloadTask(url, newf).test()) {
|
||||
try {
|
||||
new ProcessBuilder(newf.getCanonicalPath(), "--removeOldLauncher", getRealPath())
|
||||
|
||||
@@ -75,7 +75,7 @@ public final class UpdateChecker {
|
||||
}
|
||||
|
||||
if (value == null) {
|
||||
Logging.LOG.warning("Failed to check update...");
|
||||
Logging.LOG.warning("Unable to check update...");
|
||||
if (showMessage)
|
||||
MessageBox.show(Main.i18n("update.failed"));
|
||||
} else if (base.compareTo(value) < 0)
|
||||
|
||||
121
HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java
Normal file
121
HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher.
|
||||
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
*/
|
||||
package org.jackhuang.hmcl.util;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import org.jackhuang.hmcl.Main;
|
||||
import org.jackhuang.hmcl.ui.CrashWindow;
|
||||
import org.jackhuang.hmcl.ui.construct.MessageBox;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* @author huangyuhui
|
||||
*/
|
||||
public class CrashReporter implements Thread.UncaughtExceptionHandler {
|
||||
|
||||
private static final HashMap<String, String> SOURCE = new HashMap<String, String>() {
|
||||
{
|
||||
put("UnsatisfiedLinkError", Main.i18n("crash.user_fault"));
|
||||
put("java.lang.NoClassDefFoundError", Main.i18n("crash.NoClassDefFound"));
|
||||
put("java.lang.VerifyError", Main.i18n("crash.NoClassDefFound"));
|
||||
put("java.lang.NoSuchMethodError", Main.i18n("crash.NoClassDefFound"));
|
||||
put("java.lang.IncompatibleClassChangeError", Main.i18n("crash.NoClassDefFound"));
|
||||
put("java.lang.ClassFormatError", Main.i18n("crash.NoClassDefFound"));
|
||||
put("java.lang.OutOfMemoryError", "FUCKING MEMORY LIMIT!");
|
||||
put("Trampoline", Main.i18n("launcher.update_java"));
|
||||
put("NoSuchAlgorithmException", "Has your operating system been installed completely or is a ghost system?");
|
||||
}
|
||||
};
|
||||
|
||||
private boolean checkThrowable(Throwable e) {
|
||||
String s = StringUtils.getStackTrace(e);
|
||||
for (HashMap.Entry<String, String> entry : SOURCE.entrySet())
|
||||
if (s.contains(entry.getKey())) {
|
||||
if (StringUtils.isNotBlank(entry.getValue())) {
|
||||
String info = entry.getValue();
|
||||
Logging.LOG.severe(info);
|
||||
try {
|
||||
MessageBox.show(info);
|
||||
} catch (Throwable t) {
|
||||
Logging.LOG.log(Level.SEVERE, "Unable to show message", t);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e) {
|
||||
String s = StringUtils.getStackTrace(e);
|
||||
if (!s.contains("org.jackhuang"))
|
||||
return;
|
||||
|
||||
try {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("---- Hello Minecraft! Crash Report ----\n");
|
||||
builder.append(" Version: " + Main.VERSION + "\n");
|
||||
builder.append(" Time: ").append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())).append("\n");
|
||||
builder.append(" Thread: ").append(t.toString()).append("\n");
|
||||
builder.append("\n Content: \n ");
|
||||
builder.append(s).append("\n\n");
|
||||
builder.append("-- System Details --\n");
|
||||
builder.append(" Operating System: ").append(OperatingSystem.SYSTEM_VERSION).append("\n");
|
||||
builder.append(" Java Version: ").append(System.getProperty("java.version")).append(", ").append(System.getProperty("java.vendor")).append("\n");
|
||||
builder.append(" Java VM Version: ").append(System.getProperty("java.vm.name")).append(" (").append(System.getProperty("java.vm.info")).append("), ").append(System.getProperty("java.vm.vendor")).append("\n");
|
||||
String text = builder.toString();
|
||||
|
||||
Logging.LOG.log(Level.SEVERE, text);
|
||||
|
||||
if (checkThrowable(e) && !System.getProperty("java.vm.name").contains("OpenJDK")) {
|
||||
Platform.runLater(() -> new CrashWindow(text).show());
|
||||
if (!Main.UPDATE_CHECKER.isOutOfDate())
|
||||
reportToServer(text, s);
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
Logging.LOG.log(Level.SEVERE, "Unable to caught exception", ex);
|
||||
Logging.LOG.log(Level.SEVERE, "There is the original exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static final HashSet<String> THROWABLE_SET = new HashSet<>();
|
||||
|
||||
private void reportToServer(final String text, String stacktrace) {
|
||||
if (THROWABLE_SET.contains(stacktrace) || stacktrace.contains("Font") || stacktrace.contains("InternalError"))
|
||||
return;
|
||||
THROWABLE_SET.add(stacktrace);
|
||||
Thread t = new Thread(() -> {
|
||||
HashMap<String, String> map = new HashMap<>();
|
||||
map.put("crash_report", text);
|
||||
map.put("version", Main.VERSION);
|
||||
try {
|
||||
NetworkUtils.doPost(NetworkUtils.toURL("http://huangyuhui.duapp.com/hmcl/crash.php"), map);
|
||||
} catch (IOException ex) {
|
||||
Logging.LOG.log(Level.SEVERE, "Unable to post HMCL server.", ex);
|
||||
}
|
||||
});
|
||||
t.setDaemon(true);
|
||||
t.start();
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@
|
||||
<StackPane>
|
||||
<JFXDialogLayout>
|
||||
<heading>
|
||||
<Label>Create a new account</Label>
|
||||
<Label text="%account.create" />
|
||||
</heading>
|
||||
<body>
|
||||
<GridPane vgap="15" hgap="15" style="-fx-padding: 15 0 0 0;">
|
||||
@@ -34,24 +34,17 @@
|
||||
<ColumnConstraints maxWidth="100" />
|
||||
<ColumnConstraints />
|
||||
</columnConstraints>
|
||||
<Label text="Type" GridPane.halignment="RIGHT" GridPane.columnIndex="0" GridPane.rowIndex="0" />
|
||||
<Label text="%account.methods" GridPane.halignment="RIGHT" GridPane.columnIndex="0" GridPane.rowIndex="0" />
|
||||
|
||||
<JFXComboBox fx:id="cboType" GridPane.columnIndex="1" GridPane.rowIndex="0">
|
||||
<items>
|
||||
<FXCollections fx:factory="observableArrayList">
|
||||
<String fx:value="Offline Account"/>
|
||||
<String fx:value="Online Account" />
|
||||
</FXCollections>
|
||||
</items>
|
||||
</JFXComboBox>
|
||||
<JFXComboBox fx:id="cboType" GridPane.columnIndex="1" GridPane.rowIndex="0" />
|
||||
|
||||
<JFXTextField fx:id="txtUsername" promptText="Username" labelFloat="true" GridPane.columnIndex="0" GridPane.rowIndex="1" GridPane.columnSpan="2">
|
||||
<JFXTextField fx:id="txtUsername" promptText="%account.username" labelFloat="true" GridPane.columnIndex="0" GridPane.rowIndex="1" GridPane.columnSpan="2">
|
||||
<validators>
|
||||
<RequiredFieldValidator message="%input.not_empty">
|
||||
</RequiredFieldValidator>
|
||||
</validators>
|
||||
</JFXTextField>
|
||||
<JFXPasswordField fx:id="txtPassword" promptText="%login.password" labelFloat="true" GridPane.columnIndex="0" GridPane.rowIndex="2" GridPane.columnSpan="2">
|
||||
<JFXPasswordField fx:id="txtPassword" promptText="%account.password" labelFloat="true" GridPane.columnIndex="0" GridPane.rowIndex="2" GridPane.columnSpan="2">
|
||||
<validators>
|
||||
<RequiredFieldValidator message="%input.not_empty">
|
||||
</RequiredFieldValidator>
|
||||
|
||||
@@ -29,6 +29,11 @@
|
||||
</center>
|
||||
<bottom>
|
||||
<BorderPane fx:id="menuBottomBar">
|
||||
<left>
|
||||
<HBox fx:id="updatePane" visible="false" style="-fx-background-color: red;" alignment="CENTER_LEFT">
|
||||
<Label text="%update.found" style="-fx-text-fill: white; -fx-font-size: 16px;" />
|
||||
</HBox>
|
||||
</left>
|
||||
<right>
|
||||
<JFXButton fx:id="addMenuButton" styleClass="toggle-icon4">
|
||||
<graphic>
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
|
||||
<BorderPane>
|
||||
<left>
|
||||
<Label text="%mainwindow.show_log"/>
|
||||
<Label text="%settings.show_log"/>
|
||||
</left>
|
||||
<right>
|
||||
<JFXToggleButton fx:id="chkShowLogs" size="7"/>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<body>
|
||||
<VBox spacing="15" style="-fx-padding: 15 0 0 0;">
|
||||
<Label fx:id="lblUsername" />
|
||||
<JFXPasswordField fx:id="txtPassword" promptText="%login.password" labelFloat="true">
|
||||
<JFXPasswordField fx:id="txtPassword" promptText="%account.password" labelFloat="true">
|
||||
<validators>
|
||||
<RequiredFieldValidator message="Input Required!">
|
||||
</RequiredFieldValidator>
|
||||
|
||||
@@ -50,7 +50,7 @@ crash.minecraft=Minecraft has crashed!
|
||||
login.choose_charactor=Please choose the character you want
|
||||
account.failed.no_charactor=No character in this account.
|
||||
login.failed=Failed to login
|
||||
login.no_Player007=You have not set a username!
|
||||
login.empty_username=You have not set a username!
|
||||
account.failed.wrong_password=Incorrect password or username
|
||||
login.invalid_username=Invalid username
|
||||
login.invalid_uuid_and_username=Invalid UUID and username
|
||||
@@ -58,9 +58,9 @@ account.failed.invalid_password=Invalid password
|
||||
account.failed.invalid_access_token=Invalid Access Token
|
||||
login.changed_client_token=The server response has changed the client token.
|
||||
input.email=The username must be an e-mail.
|
||||
account.methods=Login
|
||||
account.methods=Login Type
|
||||
account.username=Name
|
||||
login.account=Email
|
||||
account.email=Email
|
||||
account.failed.invalid_token=Please log out and re-input your password to log in.
|
||||
login.no_valid_character=No valid character, please visit skinme.cc and create your own character.
|
||||
|
||||
@@ -101,9 +101,6 @@ crash.headless=If your OS is Linux, please use Oracle JDK instead of OpenJDK, or
|
||||
crash.NoClassDefFound=Please check "HMCL" software is complete.
|
||||
|
||||
crash.error=Minecraft has crashed.
|
||||
crash.main_class_not_found=Main Class is not found, may be your mc has been broken.
|
||||
crash.class_path_wrong=Maybe the launch script is malformed.
|
||||
|
||||
profile.new_name=New Profile Name:
|
||||
profile.copy_from=Copy From:
|
||||
profile.new=New Config
|
||||
@@ -130,12 +127,12 @@ button.ok=OK
|
||||
button.yes=Yes
|
||||
button.no=No
|
||||
|
||||
login.password=Password
|
||||
account.password=Password
|
||||
profile=Profile
|
||||
|
||||
login.enter_username=Please enter your name.
|
||||
login.enter_password=Please enter your password.
|
||||
ui.message.downloading=Downloading...
|
||||
message.downloading=Downloading...
|
||||
profile.remove=Sure to remove profile %s?
|
||||
launcher.update_java=Please upgrade your Java.
|
||||
launcher.open_jdk=We have found that you started this application using OpenJDK, which will cause so many troubles drawing the UI. We suggest you using Oracle JDK instead.
|
||||
@@ -263,13 +260,11 @@ advancedsettings.precall_command=Precalling command(will be executed before game
|
||||
advancedsettings.server_ip=Server Host
|
||||
advancedsettings.dont_check_game_completeness=Don't check game completeness
|
||||
|
||||
mainwindow.show_log=Show Logs
|
||||
settings.show_log=Show Logs
|
||||
version.launch_script=Make Launching Script.
|
||||
version.launch_script.failed=Failed to make script.
|
||||
version.launch_script.save=Save the launch script
|
||||
version.launch_script.success=Finished script creation, %s.
|
||||
mainwindow.no_version=No version found. Switch to Game Downloads Tab?
|
||||
|
||||
launcher.about=About Author\nMinecraft Forum ID: klkl6523\nCopyright (c) 2013 huangyuhui\nOpened source under GPL v3 license:http://github.com/huanghongxun/HMCL/\nThis software used project Gson which is under Apache License 2.0, thanks contributors.
|
||||
launcher_settings.download_source=Download Source
|
||||
launcher.background_location=Background Location
|
||||
@@ -285,7 +280,6 @@ launcher.background_tooltip=The laucher uses a default background.\nIf you use c
|
||||
launcher.update_launcher=Check for update
|
||||
launcher_settings.theme=Theme
|
||||
launcher_settings.proxy=Proxy
|
||||
launcher_settings.decorated=Enable system window border(in order to fix the problem that the ui become all gray in Linux OS)
|
||||
launcher.modpack=Documentations for modpacks.
|
||||
launcher_settings.language=Language
|
||||
launcher.restart=Options will be in operations only if restart this app.
|
||||
@@ -337,11 +331,11 @@ update.no_browser=Cannot open any browser. The link has been copied to the clipb
|
||||
update.should_open_link=Are you willing to update the launcher?
|
||||
update.newest_version=Newest version:
|
||||
update.failed=Failed to check for updates.
|
||||
update.found=(Found Update!)
|
||||
update.found=Found Update!
|
||||
|
||||
logwindow.terminate_game=Terminate Game
|
||||
logwindow.title=Log
|
||||
logwindow.contact=Contact Us
|
||||
launcher.contact=Contact Us
|
||||
logwindow.show_lines=Show Lines
|
||||
logwindow.search=Search
|
||||
|
||||
@@ -373,7 +367,7 @@ wizard.steps=Steps
|
||||
|
||||
lang=English
|
||||
lang.default=Belong to OS language.
|
||||
account.create=
|
||||
account.create=Create a new account
|
||||
input.not_empty=Input Requrired!
|
||||
account=Accounts
|
||||
install.new_game=Install a New Game
|
||||
@@ -412,3 +406,5 @@ modpack.invalid=Invalid modpack file.
|
||||
modpack.update=Upgrading game
|
||||
message.confirm=Confirm
|
||||
version.forbidden_name=Forbidden name, do not use this.
|
||||
account.missing=Missing account
|
||||
message.unknown=Unknown
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
# along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
#
|
||||
#author: huangyuhui
|
||||
message.downloading=正在下载...
|
||||
launch.failed=启动失败
|
||||
launch.failed_creating_process=启动失败,在创建新进程时发生错误,可能是Java路径错误。
|
||||
launch.failed.sh_permission=为启动文件添加权限时发生错误
|
||||
@@ -50,7 +51,7 @@ crash.minecraft=Minecraft崩溃了!请认真阅读建议。
|
||||
login.choose_charactor=请选择您要使用的角色
|
||||
account.failed.no_charactor=该帐号没有角色
|
||||
login.failed=登录失败:
|
||||
login.no_Player007=你还未设置用户名!
|
||||
login.empty_username=你还未设置用户名!
|
||||
account.failed.wrong_password=可能是您的用户名或密码错误
|
||||
login.invalid_username=无效的用户名
|
||||
login.invalid_uuid_and_username=无效的UUID和用户名
|
||||
@@ -58,9 +59,9 @@ account.failed.invalid_password=无效的密码
|
||||
account.failed.invalid_access_token=无效的访问令牌
|
||||
login.changed_client_token=服务器回应已经修改客户端令牌
|
||||
input.email=用户名必须是邮箱
|
||||
account.methods=登录
|
||||
account.methods=登录方式
|
||||
account.username=用户名
|
||||
login.account=邮箱
|
||||
account.email=邮箱
|
||||
account.failed.invalid_token=请尝试登出并重新输入密码登录
|
||||
login.no_valid_character=无有效的角色,自行到skinme.cc登陆并创建角色
|
||||
|
||||
@@ -101,9 +102,6 @@ crash.headless=如果您的操作系统是Linux,请注意不要使用OpenJDK
|
||||
crash.NoClassDefFound=请确认HMCL本体是否完整
|
||||
|
||||
crash.error=您的Minecraft崩溃了。
|
||||
crash.main_class_not_found=找不到主类,可能是您的JSON文件填写错误。无法启动游戏。可以通过下载整合包解决问题。
|
||||
crash.class_path_wrong=解析Class Path时出现错误,此错误本不应该发生。可能是启动脚本错误,请仔细检查启动脚本。
|
||||
|
||||
profile.new_name=新配置名:
|
||||
profile.copy_from=复制配置:
|
||||
profile.new=新建配置
|
||||
@@ -130,7 +128,7 @@ button.ok=确定
|
||||
button.yes=是
|
||||
button.no=否
|
||||
|
||||
login.password=密码
|
||||
account.password=密码
|
||||
profile=配置
|
||||
|
||||
login.enter_username=请输入您的账号
|
||||
@@ -263,13 +261,11 @@ advancedsettings.precall_command=启动前执行命令(不必填写,将在游
|
||||
advancedsettings.server_ip=直入服务器ip地址(不必填写,启动游戏后直接进入对应服务器)
|
||||
advancedsettings.dont_check_game_completeness=不检查游戏完整性
|
||||
|
||||
mainwindow.show_log=查看日志
|
||||
settings.show_log=查看日志
|
||||
version.launch_script=生成启动脚本
|
||||
version.launch_script.failed=生成启动脚本失败
|
||||
version.launch_script.save=保存启动脚本
|
||||
version.launch_script.success=启动脚本已生成完毕: %s.
|
||||
mainwindow.no_version=未找到任何版本,是否进入游戏下载?
|
||||
|
||||
launcher.about=默认背景图感谢gamerteam提供。\n关于作者:\n百度ID:huanghongxun20\nmcbbs:huanghongxun\nMinecraft Forum ID: klkl6523\n欢迎提交Bug哦\nCopyright (c) 2013-2017 huangyuhui.\n免责声明:Minecraft软件版权归Mojang AB所有,使用本软件产生的版权问题本软件制作方概不负责。\n本启动器在GPLv3协议下开源:https://github.com/huanghongxun/HMCL/ ,感谢issues和pull requests贡献者\n本软件使用了基于Apache License 2.0的Gson项目,感谢贡献者。
|
||||
launcher_settings.download_source=下载源
|
||||
launcher.background_location=背景地址
|
||||
@@ -285,7 +281,6 @@ launcher.background_tooltip=启动器默认使用自带的背景\n如果当前
|
||||
launcher.update_launcher=检查更新
|
||||
launcher_settings.theme=主题
|
||||
launcher_settings.proxy=代理
|
||||
launcher_settings.decorated=启用窗口边框(Linux下可解决程序界面全灰问题)
|
||||
launcher.modpack=整合包作者帮助
|
||||
launcher_settings.language=语言
|
||||
launcher.restart=本界面选项需要重启本启动器生效
|
||||
@@ -337,11 +332,11 @@ update.no_browser=无法打开浏览器,网址已经复制到剪贴板了,
|
||||
update.should_open_link=是否更新?
|
||||
update.newest_version=最新版本为:
|
||||
update.failed=检查更新失败
|
||||
update.found=(发现更新!)
|
||||
update.found=发现更新
|
||||
|
||||
logwindow.terminate_game=结束游戏进程
|
||||
logwindow.title=日志
|
||||
logwindow.contact=联系我们
|
||||
launcher.contact=联系我们
|
||||
logwindow.show_lines=显示行数
|
||||
logwindow.search=查找
|
||||
|
||||
@@ -412,3 +407,5 @@ modpack.invalid=无效的整合包升级文件,可能是下载时出现问题
|
||||
modpack.update=正在升级整合包
|
||||
message.confirm=提示
|
||||
version.forbidden_name=此版本名称不受支持,请换一个名字
|
||||
account.missing=没有账户
|
||||
message.unknown=未知
|
||||
|
||||
@@ -283,6 +283,7 @@ public final class Lang {
|
||||
|
||||
public static Integer toIntOrNull(Object string) {
|
||||
try {
|
||||
if (string == null) return null;
|
||||
return Integer.parseInt(string.toString());
|
||||
} catch (NumberFormatException e) {
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user