Merge branch 'javafx' of https://github.com/huanghongxun/HMCL into javafx

This commit is contained in:
huanghongxun
2018-10-21 11:05:33 +08:00
20 changed files with 104 additions and 77 deletions

View File

@@ -26,7 +26,6 @@ import org.jackhuang.hmcl.task.Schedulers;
import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.Controllers;
import org.jackhuang.hmcl.upgrade.UpdateChecker; import org.jackhuang.hmcl.upgrade.UpdateChecker;
import org.jackhuang.hmcl.util.*; import org.jackhuang.hmcl.util.*;
import org.jackhuang.hmcl.util.io.FileUtils;
import org.jackhuang.hmcl.util.platform.OperatingSystem; import org.jackhuang.hmcl.util.platform.OperatingSystem;
import java.io.File; import java.io.File;
@@ -74,19 +73,14 @@ public final class Launcher extends Application {
public static void main(String[] args) { public static void main(String[] args) {
Thread.setDefaultUncaughtExceptionHandler(CRASH_REPORTER); Thread.setDefaultUncaughtExceptionHandler(CRASH_REPORTER);
if (!FileUtils.makeDirectory(LOG_DIRECTORY))
System.out.println("Unable to create log directory " + LOG_DIRECTORY + ", log files cannot be generated.");
try { try {
Logging.start(LOG_DIRECTORY);
LOG.info("*** " + Metadata.TITLE + " ***"); LOG.info("*** " + Metadata.TITLE + " ***");
LOG.info("Operating System: " + System.getProperty("os.name") + ' ' + OperatingSystem.SYSTEM_VERSION); LOG.info("Operating System: " + System.getProperty("os.name") + ' ' + OperatingSystem.SYSTEM_VERSION);
LOG.info("Java Version: " + System.getProperty("java.version") + ", " + System.getProperty("java.vendor")); LOG.info("Java Version: " + System.getProperty("java.version") + ", " + System.getProperty("java.vendor"));
LOG.info("Java VM Version: " + System.getProperty("java.vm.name") + " (" + System.getProperty("java.vm.info") + "), " + System.getProperty("java.vm.vendor")); LOG.info("Java VM Version: " + System.getProperty("java.vm.name") + " (" + System.getProperty("java.vm.info") + "), " + System.getProperty("java.vm.vendor"));
LOG.info("Java Home: " + System.getProperty("java.home")); LOG.info("Java Home: " + System.getProperty("java.home"));
LOG.info("Current Directory: " + Paths.get("").toAbsolutePath()); LOG.info("Current Directory: " + Paths.get("").toAbsolutePath());
LOG.info("HMCL Directory: " + HMCL_DIRECTORY); LOG.info("HMCL Directory: " + Metadata.HMCL_DIRECTORY);
LOG.info("Memory: " + Runtime.getRuntime().maxMemory() / 1024 / 1024 + "MB"); LOG.info("Memory: " + Runtime.getRuntime().maxMemory() / 1024 / 1024 + "MB");
ManagementFactory.getMemoryPoolMXBeans().stream().filter(bean -> bean.getName().equals("Metaspace")).findAny() ManagementFactory.getMemoryPoolMXBeans().stream().filter(bean -> bean.getName().equals("Metaspace")).findAny()
.ifPresent(bean -> LOG.info("Metaspace: " + bean.getUsage().getUsed() / 1024 / 1024 + "MB")); .ifPresent(bean -> LOG.info("Metaspace: " + bean.getUsage().getUsed() / 1024 / 1024 + "MB"));
@@ -143,9 +137,5 @@ public final class Launcher extends Application {
return result; return result;
} }
public static final File MINECRAFT_DIRECTORY = OperatingSystem.getWorkingDirectory("minecraft");
public static final File HMCL_DIRECTORY = OperatingSystem.getWorkingDirectory("hmcl");
public static final File LOG_DIRECTORY = new File(Launcher.HMCL_DIRECTORY, "logs");
public static final CrashReporter CRASH_REPORTER = new CrashReporter(); public static final CrashReporter CRASH_REPORTER = new CrashReporter();
} }

View File

@@ -18,6 +18,8 @@
package org.jackhuang.hmcl; package org.jackhuang.hmcl;
import org.jackhuang.hmcl.upgrade.UpdateHandler; import org.jackhuang.hmcl.upgrade.UpdateHandler;
import org.jackhuang.hmcl.util.Logging;
import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager; import javax.net.ssl.X509TrustManager;
@@ -42,6 +44,8 @@ public final class Main {
checkDirectoryPath(); checkDirectoryPath();
checkDSTRootCAX3(); checkDSTRootCAX3();
Logging.start(Metadata.HMCL_DIRECTORY.resolve("logs"));
if (UpdateHandler.processArguments(args)) { if (UpdateHandler.processArguments(args)) {
return; return;
} }

View File

@@ -17,7 +17,10 @@
*/ */
package org.jackhuang.hmcl; package org.jackhuang.hmcl;
import java.nio.file.Path;
import org.jackhuang.hmcl.util.io.JarUtils; import org.jackhuang.hmcl.util.io.JarUtils;
import org.jackhuang.hmcl.util.platform.OperatingSystem;
/** /**
* Stores metadata about this application. * Stores metadata about this application.
@@ -33,4 +36,7 @@ public final class Metadata {
public static final String CONTACT_URL = "https://hmcl.huangyuhui.net/contact"; public static final String CONTACT_URL = "https://hmcl.huangyuhui.net/contact";
public static final String HELP_URL = "https://hmcl.huangyuhui.net/help"; public static final String HELP_URL = "https://hmcl.huangyuhui.net/help";
public static final String PUBLISH_URL = "http://www.mcbbs.net/thread-142335-1-1.html"; public static final String PUBLISH_URL = "http://www.mcbbs.net/thread-142335-1-1.html";
public static final Path MINECRAFT_DIRECTORY = OperatingSystem.getWorkingDirectory("minecraft");
public static final Path HMCL_DIRECTORY = OperatingSystem.getWorkingDirectory("hmcl");
} }

View File

@@ -19,7 +19,7 @@ package org.jackhuang.hmcl.game;
import javafx.embed.swing.SwingFXUtils; import javafx.embed.swing.SwingFXUtils;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.Metadata;
import org.jackhuang.hmcl.auth.Account; import org.jackhuang.hmcl.auth.Account;
import org.jackhuang.hmcl.auth.yggdrasil.GameProfile; import org.jackhuang.hmcl.auth.yggdrasil.GameProfile;
import org.jackhuang.hmcl.auth.yggdrasil.Texture; import org.jackhuang.hmcl.auth.yggdrasil.Texture;
@@ -41,7 +41,7 @@ public final class AccountHelper {
private AccountHelper() {} private AccountHelper() {}
public static final File SKIN_DIR = new File(Launcher.HMCL_DIRECTORY, "skins"); public static final File SKIN_DIR = Metadata.HMCL_DIRECTORY.resolve("skins").toFile();
public static void loadSkins() { public static void loadSkins() {
for (Account account : Accounts.getAccounts()) { for (Account account : Accounts.getAccounts()) {

View File

@@ -23,7 +23,7 @@ import javafx.beans.property.ReadOnlyListProperty;
import javafx.beans.property.ReadOnlyListWrapper; import javafx.beans.property.ReadOnlyListWrapper;
import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.Metadata;
import org.jackhuang.hmcl.auth.Account; import org.jackhuang.hmcl.auth.Account;
import org.jackhuang.hmcl.auth.AccountFactory; import org.jackhuang.hmcl.auth.AccountFactory;
import org.jackhuang.hmcl.auth.AuthenticationException; import org.jackhuang.hmcl.auth.AuthenticationException;
@@ -61,7 +61,7 @@ public final class Accounts {
public static final OfflineAccountFactory FACTORY_OFFLINE = OfflineAccountFactory.INSTANCE; public static final OfflineAccountFactory FACTORY_OFFLINE = OfflineAccountFactory.INSTANCE;
public static final YggdrasilAccountFactory FACTORY_YGGDRASIL = new YggdrasilAccountFactory(MojangYggdrasilProvider.INSTANCE); public static final YggdrasilAccountFactory FACTORY_YGGDRASIL = new YggdrasilAccountFactory(MojangYggdrasilProvider.INSTANCE);
public static final AuthlibInjectorAccountFactory FACTORY_AUTHLIB_INJECTOR = new AuthlibInjectorAccountFactory( public static final AuthlibInjectorAccountFactory FACTORY_AUTHLIB_INJECTOR = new AuthlibInjectorAccountFactory(
new AuthlibInjectorDownloader(Launcher.HMCL_DIRECTORY.toPath(), DownloadProviders::getDownloadProvider)::getArtifactInfo, new AuthlibInjectorDownloader(Metadata.HMCL_DIRECTORY, DownloadProviders::getDownloadProvider)::getArtifactInfo,
Accounts::getOrCreateAuthlibInjectorServer); Accounts::getOrCreateAuthlibInjectorServer);
private static final String TYPE_OFFLINE = "offline"; private static final String TYPE_OFFLINE = "offline";

View File

@@ -32,7 +32,7 @@ import org.hildan.fxgson.creators.ObservableListCreator;
import org.hildan.fxgson.creators.ObservableMapCreator; import org.hildan.fxgson.creators.ObservableMapCreator;
import org.hildan.fxgson.creators.ObservableSetCreator; import org.hildan.fxgson.creators.ObservableSetCreator;
import org.hildan.fxgson.factories.JavaFxPropertyTypeAdapterFactory; import org.hildan.fxgson.factories.JavaFxPropertyTypeAdapterFactory;
import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.Metadata;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer;
import org.jackhuang.hmcl.upgrade.UpdateChannel; import org.jackhuang.hmcl.upgrade.UpdateChannel;
import org.jackhuang.hmcl.util.gson.EnumOrdinalDeserializer; import org.jackhuang.hmcl.util.gson.EnumOrdinalDeserializer;
@@ -86,7 +86,7 @@ public final class Config implements Cloneable, Observable {
private ObjectProperty<EnumCommonDirectory> commonDirType = new SimpleObjectProperty<>(EnumCommonDirectory.DEFAULT); private ObjectProperty<EnumCommonDirectory> commonDirType = new SimpleObjectProperty<>(EnumCommonDirectory.DEFAULT);
@SerializedName("commonpath") @SerializedName("commonpath")
private StringProperty commonDirectory = new SimpleStringProperty(Launcher.MINECRAFT_DIRECTORY.getAbsolutePath()); private StringProperty commonDirectory = new SimpleStringProperty(Metadata.MINECRAFT_DIRECTORY.toString());
@SerializedName("hasProxy") @SerializedName("hasProxy")
private BooleanProperty hasProxy = new SimpleBooleanProperty(); private BooleanProperty hasProxy = new SimpleBooleanProperty();

View File

@@ -22,7 +22,7 @@ import javafx.application.Platform;
import javafx.beans.Observable; import javafx.beans.Observable;
import javafx.beans.property.*; import javafx.beans.property.*;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.Metadata;
import org.jackhuang.hmcl.event.EventBus; import org.jackhuang.hmcl.event.EventBus;
import org.jackhuang.hmcl.event.RefreshedVersionsEvent; import org.jackhuang.hmcl.event.RefreshedVersionsEvent;
@@ -104,7 +104,7 @@ public final class Profiles {
private static void checkProfiles() { private static void checkProfiles() {
if (profiles.isEmpty()) { if (profiles.isEmpty()) {
Profile current = new Profile(Profiles.DEFAULT_PROFILE, new File(".minecraft"), new VersionSetting(), null, true); Profile current = new Profile(Profiles.DEFAULT_PROFILE, new File(".minecraft"), new VersionSetting(), null, true);
Profile home = new Profile(Profiles.HOME_PROFILE, Launcher.MINECRAFT_DIRECTORY); Profile home = new Profile(Profiles.HOME_PROFILE, Metadata.MINECRAFT_DIRECTORY.toFile());
Platform.runLater(() -> profiles.addAll(current, home)); Platform.runLater(() -> profiles.addAll(current, home));
} }
} }

View File

@@ -18,7 +18,7 @@
package org.jackhuang.hmcl.setting; package org.jackhuang.hmcl.setting;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.Metadata;
import org.jackhuang.hmcl.game.HMCLCacheRepository; import org.jackhuang.hmcl.game.HMCLCacheRepository;
import org.jackhuang.hmcl.util.CacheRepository; import org.jackhuang.hmcl.util.CacheRepository;
@@ -64,7 +64,7 @@ public class Settings {
} }
public static String getDefaultCommonDirectory() { public static String getDefaultCommonDirectory() {
return Launcher.MINECRAFT_DIRECTORY.getAbsolutePath(); return Metadata.MINECRAFT_DIRECTORY.toString();
} }
public String getCommonDirectory() { public String getCommonDirectory() {

View File

@@ -177,7 +177,7 @@ public final class Controllers {
HMCLGameRepository repository = profile.getRepository(); HMCLGameRepository repository = profile.getRepository();
List<Node> children = repository.getVersions().parallelStream() List<Node> children = repository.getVersions().parallelStream()
.filter(version -> !version.isHidden()) .filter(version -> !version.isHidden())
.sorted(Comparator.comparing((Version version) -> version.getReleaseTime() == null ? new Date() : version.getReleaseTime()) .sorted(Comparator.comparing((Version version) -> version.getReleaseTime() == null ? new Date(0L) : version.getReleaseTime())
.thenComparing(a -> VersionNumber.asVersion(a.getId()))) .thenComparing(a -> VersionNumber.asVersion(a.getId())))
.map(version -> { .map(version -> {
Node node = PopupMenu.wrapPopupMenuItem(new GameItem(profile, version.getId())); Node node = PopupMenu.wrapPopupMenuItem(new GameItem(profile, version.getId()));

View File

@@ -28,24 +28,35 @@ import javafx.beans.property.*;
import javafx.scene.control.ToggleGroup; import javafx.scene.control.ToggleGroup;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import javafx.scene.text.Font; import javafx.scene.text.Font;
import org.jackhuang.hmcl.Launcher;
import org.jackhuang.hmcl.Metadata; import org.jackhuang.hmcl.Metadata;
import org.jackhuang.hmcl.setting.*; import org.jackhuang.hmcl.setting.*;
import org.jackhuang.hmcl.ui.construct.MessageBox;
import org.jackhuang.hmcl.ui.construct.Validator; import org.jackhuang.hmcl.ui.construct.Validator;
import org.jackhuang.hmcl.ui.decorator.DecoratorPage; import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
import org.jackhuang.hmcl.upgrade.RemoteVersion; import org.jackhuang.hmcl.upgrade.RemoteVersion;
import org.jackhuang.hmcl.upgrade.UpdateChannel; import org.jackhuang.hmcl.upgrade.UpdateChannel;
import org.jackhuang.hmcl.upgrade.UpdateChecker; import org.jackhuang.hmcl.upgrade.UpdateChecker;
import org.jackhuang.hmcl.upgrade.UpdateHandler; import org.jackhuang.hmcl.upgrade.UpdateHandler;
import org.jackhuang.hmcl.util.Logging;
import org.jackhuang.hmcl.util.i18n.Locales; import org.jackhuang.hmcl.util.i18n.Locales;
import org.jackhuang.hmcl.util.javafx.SafeStringConverter; import org.jackhuang.hmcl.util.javafx.SafeStringConverter;
import java.awt.Desktop;
import java.io.IOException;
import java.net.Proxy; import java.net.Proxy;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Optional; import java.util.Optional;
import java.util.logging.Level;
import static org.jackhuang.hmcl.setting.ConfigHolder.config; import static org.jackhuang.hmcl.setting.ConfigHolder.config;
import static org.jackhuang.hmcl.util.Lang.thread;
import static org.jackhuang.hmcl.util.Logging.LOG;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n; import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
import static org.jackhuang.hmcl.util.javafx.ExtendedProperties.reservedSelectedPropertyFor; import static org.jackhuang.hmcl.util.javafx.ExtendedProperties.reservedSelectedPropertyFor;
import static org.jackhuang.hmcl.util.javafx.ExtendedProperties.selectedItemPropertyFor; import static org.jackhuang.hmcl.util.javafx.ExtendedProperties.selectedItemPropertyFor;
@@ -202,8 +213,29 @@ public final class SettingsPage extends SettingsView implements DecoratorPage {
} }
@Override @Override
protected void onOpenLogFolder() { protected void onExportLogs() {
FXUtils.openFolder(Launcher.LOG_DIRECTORY); // We cannot determine which file is JUL using.
// So we write all the logs to a new file.
thread(() -> {
Path logFile = Paths.get("hmcl-exported-logs-" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH-mm-ss")) + ".log").toAbsolutePath();
LOG.info("Exporting logs to " + logFile);
try {
Files.write(logFile, Logging.getRawLogs());
} catch (IOException e) {
Platform.runLater(() -> Controllers.dialog(i18n("settings.launcher.launcher_log.export.failed") + "\n" + e, null, MessageBox.ERROR_MESSAGE));
LOG.log(Level.WARNING, "Failed to export logs", e);
return;
}
Platform.runLater(() -> Controllers.dialog(i18n("settings.launcher.launcher_log.export.success", logFile)));
if (Desktop.isDesktopSupported()) {
try {
Desktop.getDesktop().open(logFile.toFile());
} catch (IOException ignored) {
}
}
});
} }
@Override @Override

View File

@@ -35,7 +35,6 @@ import org.jackhuang.hmcl.setting.EnumBackgroundImage;
import org.jackhuang.hmcl.setting.EnumCommonDirectory; import org.jackhuang.hmcl.setting.EnumCommonDirectory;
import org.jackhuang.hmcl.setting.Theme; import org.jackhuang.hmcl.setting.Theme;
import org.jackhuang.hmcl.ui.construct.*; import org.jackhuang.hmcl.ui.construct.*;
import org.jackhuang.hmcl.util.i18n.I18n;
import org.jackhuang.hmcl.util.i18n.Locales.SupportedLocale; import org.jackhuang.hmcl.util.i18n.Locales.SupportedLocale;
public abstract class SettingsView extends StackPane { public abstract class SettingsView extends StackPane {
@@ -337,8 +336,8 @@ public abstract class SettingsView extends StackPane {
logPane.setTitle(i18n("settings.launcher.log")); logPane.setTitle(i18n("settings.launcher.log"));
{ {
JFXButton logButton = new JFXButton(i18n("settings.launcher.log.dir")); JFXButton logButton = new JFXButton(i18n("settings.launcher.launcher_log.export"));
logButton.setOnMouseClicked(e -> onOpenLogFolder()); logButton.setOnMouseClicked(e -> onExportLogs());
logButton.getStyleClass().setAll("jfx-button-border"); logButton.getStyleClass().setAll("jfx-button-border");
logPane.setHeaderRight(logButton); logPane.setHeaderRight(logButton);
@@ -492,5 +491,5 @@ public abstract class SettingsView extends StackPane {
protected abstract void onUpdate(); protected abstract void onUpdate();
protected abstract void onHelp(); protected abstract void onHelp();
protected abstract void onOpenLogFolder(); protected abstract void onExportLogs();
} }

View File

@@ -21,7 +21,6 @@ import com.google.gson.Gson;
import com.google.gson.JsonParseException; import com.google.gson.JsonParseException;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.scene.layout.Region; import javafx.scene.layout.Region;
import org.jackhuang.hmcl.Launcher;
import org.jackhuang.hmcl.Main; import org.jackhuang.hmcl.Main;
import org.jackhuang.hmcl.Metadata; import org.jackhuang.hmcl.Metadata;
import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.task.Task;
@@ -231,7 +230,7 @@ public final class UpdateHandler {
private static boolean isFirstLaunchAfterUpgrade() { private static boolean isFirstLaunchAfterUpgrade() {
Optional<Path> currentPath = JarUtils.thisJar(); Optional<Path> currentPath = JarUtils.thisJar();
if (currentPath.isPresent()) { if (currentPath.isPresent()) {
Path updated = Launcher.HMCL_DIRECTORY.toPath().resolve("HMCL-" + Metadata.VERSION + ".jar"); Path updated = Metadata.HMCL_DIRECTORY.resolve("HMCL-" + Metadata.VERSION + ".jar");
if (currentPath.get().toAbsolutePath().equals(updated.toAbsolutePath())) { if (currentPath.get().toAbsolutePath().equals(updated.toAbsolutePath())) {
return true; return true;
} }
@@ -240,7 +239,7 @@ public final class UpdateHandler {
} }
private static void breakForceUpdateFeature() { private static void breakForceUpdateFeature() {
Path hmclVersionJson = Launcher.HMCL_DIRECTORY.toPath().resolve("hmclver.json"); Path hmclVersionJson = Metadata.HMCL_DIRECTORY.resolve("hmclver.json");
if (Files.isRegularFile(hmclVersionJson)) { if (Files.isRegularFile(hmclVersionJson)) {
try { try {
Map<?, ?> content = new Gson().fromJson(new String(Files.readAllBytes(hmclVersionJson), UTF_8), Map.class); Map<?, ?> content = new Gson().fromJson(new String(Files.readAllBytes(hmclVersionJson), UTF_8), Map.class);

View File

@@ -67,10 +67,12 @@
</body> </body>
<actions> <actions>
<Label fx:id="lblCreationWarning"/> <Label fx:id="lblCreationWarning"/>
<SpinnerPane fx:id="acceptPane" styleClass="small-spinner-pane"> <HBox>
<JFXButton fx:id="btnAccept" onMouseClicked="#onCreationAccept" text="%button.ok" styleClass="dialog-accept"/> <SpinnerPane fx:id="acceptPane" styleClass="small-spinner-pane">
</SpinnerPane> <JFXButton fx:id="btnAccept" onMouseClicked="#onCreationAccept" text="%button.ok" styleClass="dialog-accept"/>
<JFXButton onMouseClicked="#onCreationCancel" text="%button.cancel" styleClass="dialog-cancel"/> </SpinnerPane>
<JFXButton onMouseClicked="#onCreationCancel" text="%button.cancel" styleClass="dialog-cancel"/>
</HBox>
</actions> </actions>
</JFXDialogLayout> </JFXDialogLayout>
</fx:root> </fx:root>

View File

@@ -19,10 +19,12 @@
</body> </body>
<actions> <actions>
<Label fx:id="lblCreationWarning" /> <Label fx:id="lblCreationWarning" />
<JFXButton onMouseClicked="#onAddCancel" text="%button.cancel" styleClass="dialog-cancel" /> <HBox>
<SpinnerPane fx:id="nextPane" styleClass="small-spinner-pane"> <JFXButton onMouseClicked="#onAddCancel" text="%button.cancel" styleClass="dialog-cancel" />
<JFXButton fx:id="btnAddNext" onMouseClicked="#onAddNext" text="%wizard.next" styleClass="dialog-accept" /> <SpinnerPane fx:id="nextPane" styleClass="small-spinner-pane">
</SpinnerPane> <JFXButton fx:id="btnAddNext" onMouseClicked="#onAddNext" text="%wizard.next" styleClass="dialog-accept" />
</SpinnerPane>
</HBox>
</actions> </actions>
</JFXDialogLayout> </JFXDialogLayout>

View File

@@ -326,9 +326,11 @@ settings.launcher.common_path.tooltip=This app will save all game libraries and
settings.launcher.download_source=Download Source settings.launcher.download_source=Download Source
settings.launcher.enable_game_list=Display game list in main page settings.launcher.enable_game_list=Display game list in main page
settings.launcher.language=Language settings.launcher.language=Language
settings.launcher.launcher_log.export=Export launcher logs
settings.launcher.launcher_log.export.failed=Failed to export logs
settings.launcher.launcher_log.export.success=Logs have been exported to %s
settings.launcher.log=Log settings.launcher.log=Log
settings.launcher.log.font=Log Font settings.launcher.log.font=Log Font
settings.launcher.log.dir=Open Log Directory
settings.launcher.proxy=Proxy settings.launcher.proxy=Proxy
settings.launcher.proxy.authentication=Proxy Authentication settings.launcher.proxy.authentication=Proxy Authentication
settings.launcher.proxy.disable=Use system proxies settings.launcher.proxy.disable=Use system proxies

View File

@@ -326,9 +326,11 @@ settings.launcher.common_path.tooltip=啟動器將所有遊戲資源及依賴庫
settings.launcher.download_source=下載來源 settings.launcher.download_source=下載來源
settings.launcher.enable_game_list=在首頁內顯示遊戲列表 settings.launcher.enable_game_list=在首頁內顯示遊戲列表
settings.launcher.language=語言 settings.launcher.language=語言
settings.launcher.launcher_log.export=導出啟動器日誌
settings.launcher.launcher_log.export.failed=無法導出日誌
settings.launcher.launcher_log.export.success=日誌已保存到 %s
settings.launcher.log=記錄 settings.launcher.log=記錄
settings.launcher.log.font=記錄字體 settings.launcher.log.font=記錄字體
settings.launcher.log.dir=打開記錄資料夾
settings.launcher.proxy=代理 settings.launcher.proxy=代理
settings.launcher.proxy.authentication=身份驗證 settings.launcher.proxy.authentication=身份驗證
settings.launcher.proxy.disable=使用系統代理 settings.launcher.proxy.disable=使用系統代理

View File

@@ -326,9 +326,11 @@ settings.launcher.common_path.tooltip=启动器将所有游戏资源及依赖库
settings.launcher.download_source=下载源 settings.launcher.download_source=下载源
settings.launcher.enable_game_list=在主页内显示游戏列表 settings.launcher.enable_game_list=在主页内显示游戏列表
settings.launcher.language=语言 settings.launcher.language=语言
settings.launcher.launcher_log.export=导出启动器日志
settings.launcher.launcher_log.export.failed=无法导出日志
settings.launcher.launcher_log.export.success=日志已保存到 %s
settings.launcher.log=日志 settings.launcher.log=日志
settings.launcher.log.font=日志字体 settings.launcher.log.font=日志字体
settings.launcher.log.dir=打开日志文件夹
settings.launcher.proxy=代理 settings.launcher.proxy=代理
settings.launcher.proxy.authentication=身份验证 settings.launcher.proxy.authentication=身份验证
settings.launcher.proxy.disable=使用系统代理 settings.launcher.proxy.disable=使用系统代理

View File

@@ -43,7 +43,7 @@ public class DefaultCacheRepository extends CacheRepository {
private Index index = null; private Index index = null;
public DefaultCacheRepository() { public DefaultCacheRepository() {
this(OperatingSystem.getWorkingDirectory("minecraft").toPath()); this(OperatingSystem.getWorkingDirectory("minecraft"));
} }
public DefaultCacheRepository(Path commonDirectory) { public DefaultCacheRepository(Path commonDirectory) {

View File

@@ -18,9 +18,10 @@
package org.jackhuang.hmcl.util; package org.jackhuang.hmcl.util;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.logging.*; import java.util.logging.*;
@@ -31,20 +32,16 @@ import java.util.logging.*;
*/ */
public final class Logging { public final class Logging {
public static final Logger LOG; public static final Logger LOG = Logger.getLogger("HMCL");
private static final ByteArrayOutputStream OUTPUT_STREAM = new ByteArrayOutputStream(); private static ByteArrayOutputStream storedLogs = new ByteArrayOutputStream();
static { public static void start(Path logFolder) {
LOG = Logger.getLogger("HMCL"); LOG.setLevel(Level.ALL);
}
public static void start(File logFolder) {
LOG.setLevel(Level.FINER);
LOG.setUseParentHandlers(false); LOG.setUseParentHandlers(false);
try { try {
FileHandler fileHandler = new FileHandler(new File(logFolder, "hmcl.log").getAbsolutePath()); Files.createDirectories(logFolder);
fileHandler.setLevel(Level.FINEST); FileHandler fileHandler = new FileHandler(logFolder.resolve("hmcl.log").toAbsolutePath().toString());
fileHandler.setFormatter(DefaultFormatter.INSTANCE); fileHandler.setFormatter(DefaultFormatter.INSTANCE);
LOG.addHandler(fileHandler); LOG.addHandler(fileHandler);
} catch (IOException e) { } catch (IOException e) {
@@ -52,31 +49,28 @@ public final class Logging {
} }
ConsoleHandler consoleHandler = new ConsoleHandler(); ConsoleHandler consoleHandler = new ConsoleHandler();
consoleHandler.setLevel(Level.FINER);
consoleHandler.setFormatter(DefaultFormatter.INSTANCE); consoleHandler.setFormatter(DefaultFormatter.INSTANCE);
LOG.addHandler(consoleHandler); LOG.addHandler(consoleHandler);
StreamHandler streamHandler = new StreamHandler(OUTPUT_STREAM, DefaultFormatter.INSTANCE) { StreamHandler streamHandler = new StreamHandler(storedLogs, DefaultFormatter.INSTANCE) {
@Override @Override
public synchronized void publish(LogRecord record) { public synchronized void publish(LogRecord record) {
super.publish(record); super.publish(record);
flush(); flush();
} }
}; };
streamHandler.setLevel(Level.FINEST);
LOG.addHandler(streamHandler); LOG.addHandler(streamHandler);
} }
public static void stop() { public static byte[] getRawLogs() {
for (Handler handler : LOG.getHandlers()) return storedLogs.toByteArray();
LOG.removeHandler(handler);
} }
public static String getLogs() { public static String getLogs() {
return OUTPUT_STREAM.toString(); return storedLogs.toString();
} }
static final class DefaultFormatter extends Formatter { private static final class DefaultFormatter extends Formatter {
static final DefaultFormatter INSTANCE = new DefaultFormatter(); static final DefaultFormatter INSTANCE = new DefaultFormatter();
private final SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss"); private final SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");

View File

@@ -17,9 +17,6 @@
*/ */
package org.jackhuang.hmcl.util.platform; package org.jackhuang.hmcl.util.platform;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javax.management.JMException; import javax.management.JMException;
import javax.management.MBeanServer; import javax.management.MBeanServer;
import javax.management.ObjectName; import javax.management.ObjectName;
@@ -29,6 +26,8 @@ import org.jackhuang.hmcl.util.Lang;
import java.io.File; import java.io.File;
import java.lang.management.ManagementFactory; import java.lang.management.ManagementFactory;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Locale; import java.util.Locale;
import java.util.Optional; import java.util.Optional;
@@ -135,30 +134,24 @@ public enum OperatingSystem {
return Optional.empty(); return Optional.empty();
} }
public static void setClipboard(String string) {
ClipboardContent c = new ClipboardContent();
c.putString(string);
Clipboard.getSystemClipboard().setContent(c);
}
public static void forceGC() { public static void forceGC() {
System.gc(); System.gc();
System.runFinalization(); System.runFinalization();
System.gc(); System.gc();
} }
public static File getWorkingDirectory(String folder) { public static Path getWorkingDirectory(String folder) {
String home = System.getProperty("user.home", "."); String home = System.getProperty("user.home", ".");
switch (OperatingSystem.CURRENT_OS) { switch (OperatingSystem.CURRENT_OS) {
case LINUX: case LINUX:
return new File(home, "." + folder + "/"); return Paths.get(home, "." + folder);
case WINDOWS: case WINDOWS:
String appdata = System.getenv("APPDATA"); String appdata = System.getenv("APPDATA");
return new File(Lang.nonNull(appdata, home), "." + folder + "/"); return Paths.get(Lang.nonNull(appdata, home), "." + folder);
case OSX: case OSX:
return new File(home, "Library/Application Support/" + folder); return Paths.get(home, "Library", "Application Support", folder);
default: default:
return new File(home, folder + "/"); return Paths.get(home, folder);
} }
} }
} }