diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/AccountHelper.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/AccountHelper.java index 7bc572bd2..d60284fa0 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/AccountHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/AccountHelper.java @@ -33,7 +33,6 @@ import org.jackhuang.hmcl.ui.DialogController; import org.jackhuang.hmcl.util.NetworkUtils; import java.io.File; -import java.net.Proxy; import java.util.*; public final class AccountHelper { @@ -43,31 +42,19 @@ public final class AccountHelper { public static final File SKIN_DIR = new File(Launcher.HMCL_DIRECTORY, "skins"); public static void loadSkins() { - loadSkins(Proxy.NO_PROXY); - } - - public static void loadSkins(Proxy proxy) { for (Account account : Settings.INSTANCE.getAccounts()) { if (account instanceof YggdrasilAccount) { - new SkinLoadTask((YggdrasilAccount) account, proxy, false).start(); + new SkinLoadTask((YggdrasilAccount) account, false).start(); } } } public static Task loadSkinAsync(YggdrasilAccount account) { - return loadSkinAsync(account, Settings.INSTANCE.getProxy()); - } - - public static Task loadSkinAsync(YggdrasilAccount account, Proxy proxy) { - return new SkinLoadTask(account, proxy, false); + return new SkinLoadTask(account, false); } public static Task refreshSkinAsync(YggdrasilAccount account) { - return refreshSkinAsync(account, Settings.INSTANCE.getProxy()); - } - - public static Task refreshSkinAsync(YggdrasilAccount account, Proxy proxy) { - return new SkinLoadTask(account, proxy, true); + return new SkinLoadTask(account, true); } private static File getSkinFile(UUID uuid) { @@ -94,9 +81,9 @@ public final class AccountHelper { return getDefaultSkin(uuid, scaleRatio); } - public static Image getSkinImmediately(YggdrasilAccount account, GameProfile profile, double scaleRatio, Proxy proxy) throws Exception { + public static Image getSkinImmediately(YggdrasilAccount account, GameProfile profile, double scaleRatio) throws Exception { File file = getSkinFile(profile.getId()); - downloadSkin(account, profile, true, proxy); + downloadSkin(account, profile, true); if (!file.exists()) return getDefaultSkin(profile.getId(), scaleRatio); @@ -111,17 +98,15 @@ public final class AccountHelper { private static class SkinLoadTask extends Task { private final YggdrasilAccount account; - private final Proxy proxy; private final boolean refresh; private final List dependencies = new LinkedList<>(); - public SkinLoadTask(YggdrasilAccount account, Proxy proxy) { - this(account, proxy, false); + public SkinLoadTask(YggdrasilAccount account) { + this(account, false); } - public SkinLoadTask(YggdrasilAccount account, Proxy proxy, boolean refresh) { + public SkinLoadTask(YggdrasilAccount account, boolean refresh) { this.account = account; - this.proxy = proxy; this.refresh = refresh; } @@ -140,11 +125,11 @@ public final class AccountHelper { if (!account.isLoggedIn() && (account.getCharacter() == null || refresh)) DialogController.logIn(account); - downloadSkin(account, refresh, proxy); + downloadSkin(account, refresh); } } - private static void downloadSkin(YggdrasilAccount account, GameProfile profile, boolean refresh, Proxy proxy) throws Exception { + private static void downloadSkin(YggdrasilAccount account, GameProfile profile, boolean refresh) throws Exception { account.clearCache(); Optional texture = account.getSkin(profile); @@ -153,10 +138,10 @@ public final class AccountHelper { File file = getSkinFile(profile.getId()); if (!refresh && file.exists()) return; - new FileDownloadTask(NetworkUtils.toURL(url), file, proxy).run(); + new FileDownloadTask(NetworkUtils.toURL(url), file).run(); } - private static void downloadSkin(YggdrasilAccount account, boolean refresh, Proxy proxy) throws Exception { + private static void downloadSkin(YggdrasilAccount account, boolean refresh) throws Exception { account.clearCache(); if (account.getCharacter() == null) return; @@ -166,7 +151,7 @@ public final class AccountHelper { File file = getSkinFile(account.getUUID()); if (!refresh && file.exists()) return; - new FileDownloadTask(NetworkUtils.toURL(url), file, proxy).run(); + new FileDownloadTask(NetworkUtils.toURL(url), file).run(); } public static Image scale(String url, double scaleRatio) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLDependencyManager.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLDependencyManager.java index 5c3e2093b..7c81dabd8 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLDependencyManager.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLDependencyManager.java @@ -22,8 +22,6 @@ import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.GameBuilder; import org.jackhuang.hmcl.setting.Profile; -import java.net.Proxy; - /** * @author huangyuhui */ @@ -31,11 +29,7 @@ public class HMCLDependencyManager extends DefaultDependencyManager { private final Profile profile; public HMCLDependencyManager(Profile profile, DownloadProvider downloadProvider) { - this(profile, downloadProvider, Proxy.NO_PROXY); - } - - public HMCLDependencyManager(Profile profile, DownloadProvider downloadProvider, Proxy proxy) { - super(profile.getRepository(), downloadProvider, proxy); + super(profile.getRepository(), downloadProvider); this.profile = profile; } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameDownloadTask.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameDownloadTask.java index e1402d55e..ce34357a3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameDownloadTask.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameDownloadTask.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.game; import org.jackhuang.hmcl.setting.Profile; -import org.jackhuang.hmcl.setting.Settings; import org.jackhuang.hmcl.task.FileDownloadTask; import org.jackhuang.hmcl.task.FileDownloadTask.IntegrityCheck; import org.jackhuang.hmcl.task.Task; @@ -32,6 +31,8 @@ import java.util.LinkedList; import java.util.List; import java.util.logging.Level; +import static org.jackhuang.hmcl.setting.ConfigHolder.CONFIG; + /** * @author huangyuhui */ @@ -58,7 +59,7 @@ public class HMCLGameDownloadTask extends Task { public void execute() { File jar = profile.getRepository().getVersionJar(version); - File cache = new File(Settings.INSTANCE.getCommonPath(), "jars/" + gameVersion + ".jar"); + File cache = new File(CONFIG.getCommonDirectory(), "jars/" + gameVersion + ".jar"); if (cache.exists()) try { FileUtils.copyFile(cache, jar); @@ -70,7 +71,6 @@ public class HMCLGameDownloadTask extends Task { dependencies.add(new FileDownloadTask( NetworkUtils.toURL(profile.getDependency().getDownloadProvider().injectURL(version.getDownloadInfo().getUrl())), cache, - profile.getDependency().getProxy(), new IntegrityCheck("SHA-1", version.getDownloadInfo().getSha1()) ).then(Task.of(v -> FileUtils.copyFile(cache, jar)))); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java index 2b242795e..2aff2a527 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java @@ -24,7 +24,6 @@ import org.jackhuang.hmcl.event.RefreshedVersionsEvent; import org.jackhuang.hmcl.event.RefreshingVersionsEvent; import org.jackhuang.hmcl.setting.EnumGameDirectory; import org.jackhuang.hmcl.setting.Profile; -import org.jackhuang.hmcl.setting.Settings; import org.jackhuang.hmcl.setting.VersionSetting; import org.jackhuang.hmcl.util.FileUtils; import org.jackhuang.hmcl.util.Logging; @@ -34,6 +33,8 @@ import java.io.IOException; import java.util.*; import java.util.logging.Level; +import static org.jackhuang.hmcl.setting.ConfigHolder.CONFIG; + public class HMCLGameRepository extends DefaultGameRepository { private final Profile profile; private final Map versionSettings = new HashMap<>(); @@ -60,7 +61,7 @@ public class HMCLGameRepository extends DefaultGameRepository { if (useSelf(version, assetId)) return super.getAssetDirectory(version, assetId); else - return new File(Settings.INSTANCE.getCommonPath(), "assets"); + return new File(CONFIG.getCommonDirectory(), "assets"); } @Override @@ -85,7 +86,7 @@ public class HMCLGameRepository extends DefaultGameRepository { if (self.exists() || vs.isNoCommon()) return self; else - return new File(Settings.INSTANCE.getCommonPath(), "libraries/" + lib.getPath()); + return new File(CONFIG.getCommonDirectory(), "libraries/" + lib.getPath()); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java index 453306eb2..427b8de49 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java @@ -33,6 +33,7 @@ import java.io.IOException; import java.util.Map; import java.util.logging.Level; +import static org.jackhuang.hmcl.setting.ConfigHolder.CONFIG; import static org.jackhuang.hmcl.util.Lang.mapOf; import static org.jackhuang.hmcl.util.Logging.LOG; import static org.jackhuang.hmcl.util.Pair.pair; @@ -71,7 +72,7 @@ public final class Accounts { } private static AuthlibInjectorServer getOrCreateAuthlibInjectorServer(String url) { - return ConfigHolder.CONFIG.authlibInjectorServers.stream() + return CONFIG.getAuthlibInjectorServers().stream() .filter(server -> url.equals(server.getUrl())) .findFirst() .orElseGet(() -> { @@ -85,7 +86,7 @@ public final class Accounts { LOG.log(Level.WARNING, "Failed to migrate authlib injector server " + url, e); } - ConfigHolder.CONFIG.authlibInjectorServers.add(server); + CONFIG.getAuthlibInjectorServers().add(server); return server; }); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java index 3e2727be6..6c0b60e8d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java @@ -18,8 +18,11 @@ package org.jackhuang.hmcl.setting; import java.io.File; +import java.lang.reflect.Modifier; +import java.net.Proxy; import java.util.Map; import java.util.TreeMap; +import java.util.stream.Stream; import org.hildan.fxgson.creators.ObservableListCreator; import org.hildan.fxgson.creators.ObservableMapCreator; @@ -27,19 +30,25 @@ import org.hildan.fxgson.creators.ObservableSetCreator; import org.hildan.fxgson.factories.JavaFxPropertyTypeAdapterFactory; import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer; +import org.jackhuang.hmcl.util.EnumOrdinalDeserializer; import org.jackhuang.hmcl.util.FileTypeAdapter; +import org.jackhuang.hmcl.util.ObservableHelper; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonParseException; import com.google.gson.annotations.SerializedName; +import javafx.beans.InvalidationListener; +import javafx.beans.Observable; import javafx.beans.property.BooleanProperty; import javafx.beans.property.DoubleProperty; import javafx.beans.property.IntegerProperty; +import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleDoubleProperty; import javafx.beans.property.SimpleIntegerProperty; +import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.collections.FXCollections; @@ -47,7 +56,7 @@ import javafx.collections.ObservableList; import javafx.collections.ObservableMap; import javafx.collections.ObservableSet; -public final class Config implements Cloneable { +public final class Config implements Cloneable, Observable { private static final Gson CONFIG_GSON = new GsonBuilder() .registerTypeAdapter(VersionSetting.class, VersionSetting.Serializer.INSTANCE) @@ -57,77 +66,117 @@ public final class Config implements Cloneable { .registerTypeAdapter(ObservableSet.class, new ObservableSetCreator()) .registerTypeAdapter(ObservableMap.class, new ObservableMapCreator()) .registerTypeAdapterFactory(new JavaFxPropertyTypeAdapterFactory(true, true)) + .registerTypeAdapter(EnumBackgroundImage.class, new EnumOrdinalDeserializer<>(EnumBackgroundImage.class)) // backward compatibility for backgroundType + .registerTypeAdapter(Proxy.Type.class, new EnumOrdinalDeserializer<>(Proxy.Type.class)) // backward compatibility for hasProxy .setPrettyPrinting() .create(); public static Config fromJson(String json) throws JsonParseException { - return CONFIG_GSON.fromJson(json, Config.class); + Config instance = CONFIG_GSON.fromJson(json, Config.class); + // Gson will replace the property fields (even they are final!) + // So we have to add the listeners again after deserialization + instance.addListenerToProperties(); + return instance; } @SerializedName("last") - public final StringProperty selectedProfile = new SimpleStringProperty(""); + private StringProperty selectedProfile = new SimpleStringProperty(""); @SerializedName("backgroundType") - public final IntegerProperty backgroundImageType = new SimpleIntegerProperty(0); + private ObjectProperty backgroundImageType = new SimpleObjectProperty<>(EnumBackgroundImage.DEFAULT); @SerializedName("bgpath") - public final StringProperty backgroundImage = new SimpleStringProperty(); + private StringProperty backgroundImage = new SimpleStringProperty(); @SerializedName("commonpath") - public final StringProperty commonDirectory = new SimpleStringProperty(Launcher.MINECRAFT_DIRECTORY.getAbsolutePath()); + private StringProperty commonDirectory = new SimpleStringProperty(Launcher.MINECRAFT_DIRECTORY.getAbsolutePath()); @SerializedName("hasProxy") - public final BooleanProperty hasProxy = new SimpleBooleanProperty(); + private BooleanProperty hasProxy = new SimpleBooleanProperty(); @SerializedName("hasProxyAuth") - public final BooleanProperty hasProxyAuth = new SimpleBooleanProperty(); + private BooleanProperty hasProxyAuth = new SimpleBooleanProperty(); @SerializedName("proxyType") - public final IntegerProperty proxyType = new SimpleIntegerProperty(); + private ObjectProperty proxyType = new SimpleObjectProperty<>(Proxy.Type.DIRECT); @SerializedName("proxyHost") - public final StringProperty proxyHost = new SimpleStringProperty(); + private StringProperty proxyHost = new SimpleStringProperty(); @SerializedName("proxyPort") - public final StringProperty proxyPort = new SimpleStringProperty(); + private StringProperty proxyPort = new SimpleStringProperty(); @SerializedName("proxyUserName") - public final StringProperty proxyUser = new SimpleStringProperty(); + private StringProperty proxyUser = new SimpleStringProperty(); @SerializedName("proxyPassword") - public final StringProperty proxyPass = new SimpleStringProperty(); + private StringProperty proxyPass = new SimpleStringProperty(); @SerializedName("theme") - public final StringProperty theme = new SimpleStringProperty(); + private StringProperty theme = new SimpleStringProperty(); @SerializedName("localization") - public final StringProperty localization = new SimpleStringProperty(); + private StringProperty localization = new SimpleStringProperty(); @SerializedName("downloadtype") - public final IntegerProperty downloadType = new SimpleIntegerProperty(1); + private IntegerProperty downloadType = new SimpleIntegerProperty(1); @SerializedName("configurations") - public final ObservableMap configurations = FXCollections.observableMap(new TreeMap<>()); + private ObservableMap configurations = FXCollections.observableMap(new TreeMap<>()); @SerializedName("accounts") - public final ObservableList> accounts = FXCollections.observableArrayList(); + private ObservableList> accounts = FXCollections.observableArrayList(); @SerializedName("selectedAccount") - public final StringProperty selectedAccount = new SimpleStringProperty(""); + private StringProperty selectedAccount = new SimpleStringProperty(""); @SerializedName("fontFamily") - public final StringProperty fontFamily = new SimpleStringProperty("Consolas"); + private StringProperty fontFamily = new SimpleStringProperty("Consolas"); @SerializedName("fontSize") - public final DoubleProperty fontSize = new SimpleDoubleProperty(12); + private DoubleProperty fontSize = new SimpleDoubleProperty(12); @SerializedName("logLines") - public final IntegerProperty logLines = new SimpleIntegerProperty(100); + private IntegerProperty logLines = new SimpleIntegerProperty(100); @SerializedName("firstLaunch") - public final BooleanProperty firstLaunch = new SimpleBooleanProperty(true); + private BooleanProperty firstLaunch = new SimpleBooleanProperty(true); - public final ObservableList authlibInjectorServers = FXCollections.observableArrayList(); + @SerializedName("authlibInjectorServers") + private ObservableList authlibInjectorServers = FXCollections.observableArrayList(); + + private transient ObservableHelper helper = new ObservableHelper(this); + + public Config() { + addListenerToProperties(); + } + + private void addListenerToProperties() { + Stream.of(getClass().getDeclaredFields()) + .filter(it -> { + int modifiers = it.getModifiers(); + return !Modifier.isTransient(modifiers) && !Modifier.isStatic(modifiers); + }) + .filter(it -> Observable.class.isAssignableFrom(it.getType())) + .map(it -> { + try { + return (Observable) it.get(this); + } catch (IllegalAccessException e) { + throw new IllegalStateException("Failed to get my own properties"); + } + }) + .forEach(helper::receiveUpdatesFrom); + } + + @Override + public void addListener(InvalidationListener listener) { + helper.addListener(listener); + } + + @Override + public void removeListener(InvalidationListener listener) { + helper.removeListener(listener); + } public String toJson() { return CONFIG_GSON.toJson(this); @@ -137,4 +186,246 @@ public final class Config implements Cloneable { public Config clone() { return fromJson(this.toJson()); } + + // Getters & Setters & Properties + public String getSelectedProfile() { + return selectedProfile.get(); + } + + public void setSelectedProfile(String selectedProfile) { + this.selectedProfile.set(selectedProfile); + } + + public StringProperty selectedProfileProperty() { + return selectedProfile; + } + + public EnumBackgroundImage getBackgroundImageType() { + return backgroundImageType.get(); + } + + public void setBackgroundImageType(EnumBackgroundImage backgroundImageType) { + this.backgroundImageType.set(backgroundImageType); + } + + public ObjectProperty backgroundImageTypeProperty() { + return backgroundImageType; + } + + public String getBackgroundImage() { + return backgroundImage.get(); + } + + public void setBackgroundImage(String backgroundImage) { + this.backgroundImage.set(backgroundImage); + } + + public StringProperty backgroundImageProperty() { + return backgroundImage; + } + + public String getCommonDirectory() { + return commonDirectory.get(); + } + + public void setCommonDirectory(String commonDirectory) { + this.commonDirectory.set(commonDirectory); + } + + public StringProperty commonDirectoryProperty() { + return commonDirectory; + } + + public boolean hasProxy() { + return hasProxy.get(); + } + + public void setHasProxy(boolean hasProxy) { + this.hasProxy.set(hasProxy); + } + + public BooleanProperty hasProxyProperty() { + return hasProxy; + } + + public boolean hasProxyAuth() { + return hasProxyAuth.get(); + } + + public void setHasProxyAuth(boolean hasProxyAuth) { + this.hasProxyAuth.set(hasProxyAuth); + } + + public BooleanProperty hasProxyAuthProperty() { + return hasProxyAuth; + } + + public Proxy.Type getProxyType() { + return proxyType.get(); + } + + public void setProxyType(Proxy.Type proxyType) { + this.proxyType.set(proxyType); + } + + public ObjectProperty proxyTypeProperty() { + return proxyType; + } + + public String getProxyHost() { + return proxyHost.get(); + } + + public void setProxyHost(String proxyHost) { + this.proxyHost.set(proxyHost); + } + + public StringProperty proxyHostProperty() { + return proxyHost; + } + + public String getProxyPort() { + return proxyPort.get(); + } + + public void setProxyPort(String proxyPort) { + this.proxyPort.set(proxyPort); + } + + public StringProperty proxyPortProperty() { + return proxyPort; + } + + public String getProxyUser() { + return proxyUser.get(); + } + + public void setProxyUser(String proxyUser) { + this.proxyUser.set(proxyUser); + } + + public StringProperty proxyUserProperty() { + return proxyUser; + } + + public String getProxyPass() { + return proxyPass.get(); + } + + public void setProxyPass(String proxyPass) { + this.proxyPass.set(proxyPass); + } + + public StringProperty proxyPassProperty() { + return proxyPass; + } + + public String getTheme() { + return theme.get(); + } + + public void setTheme(String theme) { + this.theme.set(theme); + } + + public StringProperty themeProperty() { + return theme; + } + + public String getLocalization() { + return localization.get(); + } + + public void setLocalization(String localization) { + this.localization.set(localization); + } + + public StringProperty localizationProperty() { + return localization; + } + + public int getDownloadType() { + return downloadType.get(); + } + + public void setDownloadType(int downloadType) { + this.downloadType.set(downloadType); + } + + public IntegerProperty downloadTypeProperty() { + return downloadType; + } + + public ObservableMap getConfigurations() { + return configurations; + } + + public ObservableList> getAccounts() { + return accounts; + } + + public String getSelectedAccount() { + return selectedAccount.get(); + } + + public void setSelectedAccount(String selectedAccount) { + this.selectedAccount.set(selectedAccount); + } + + public StringProperty selectedAccountProperty() { + return selectedAccount; + } + + public String getFontFamily() { + return fontFamily.get(); + } + + public void setFontFamily(String fontFamily) { + this.fontFamily.set(fontFamily); + } + + public StringProperty fontFamilyProperty() { + return fontFamily; + } + + public double getFontSize() { + return fontSize.get(); + } + + public void setFontSize(double fontSize) { + this.fontSize.set(fontSize); + } + + public DoubleProperty fontSizeProperty() { + return fontSize; + } + + public int getLogLines() { + return logLines.get(); + } + + public void setLogLines(int logLines) { + this.logLines.set(logLines); + } + + public IntegerProperty logLinesProperty() { + return logLines; + } + + public boolean isFirstLaunch() { + return firstLaunch.get(); + } + + public void setFirstLaunch(boolean firstLaunch) { + this.firstLaunch.set(firstLaunch); + } + + public BooleanProperty firstLaunchProperty() { + return firstLaunch; + } + + public ObservableList getAuthlibInjectorServers() { + return authlibInjectorServers; + } + } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profile.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profile.java index 0c44eb222..e6b134098 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profile.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profile.java @@ -122,7 +122,7 @@ public final class Profile { } public HMCLDependencyManager getDependency() { - return new HMCLDependencyManager(this, Settings.INSTANCE.getDownloadProvider(), Settings.INSTANCE.getProxy()); + return new HMCLDependencyManager(this, Settings.INSTANCE.getDownloadProvider()); } public VersionSetting getVersionSetting(String id) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Proxies.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Proxies.java deleted file mode 100644 index 919351d30..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Proxies.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2018 huangyuhui - * - * 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.setting; - -import org.jackhuang.hmcl.util.Lang; - -import java.net.Proxy; -import java.util.List; - -/** - * @author huangyuhui - */ -public final class Proxies { - private Proxies() {} - - public static final List PROXIES = Lang.immutableListOf(Proxy.Type.DIRECT, Proxy.Type.HTTP, Proxy.Type.SOCKS); - - public static Proxy.Type getProxyType(int index) { - return Lang.get(PROXIES, index).orElse(null); - } -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/ProxyManager.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/ProxyManager.java new file mode 100644 index 000000000..8f8972ff5 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/ProxyManager.java @@ -0,0 +1,117 @@ +/* + * Hello Minecraft! Launcher. + * Copyright (C) 2018 huangyuhui + * + * 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.setting; + +import static org.jackhuang.hmcl.setting.ConfigHolder.CONFIG; + +import java.net.Authenticator; +import java.net.InetSocketAddress; +import java.net.PasswordAuthentication; +import java.net.Proxy; +import java.net.Proxy.Type; + +import org.jackhuang.hmcl.util.Lang; +import org.jackhuang.hmcl.util.StringUtils; + +import javafx.beans.binding.Bindings; +import javafx.beans.binding.ObjectBinding; +import javafx.beans.value.ObservableObjectValue; + +public final class ProxyManager { + private ProxyManager() { + } + + private static final ObjectBinding proxyProperty = Bindings.createObjectBinding( + () -> { + String host = CONFIG.getProxyHost(); + Integer port = Lang.toIntOrNull(CONFIG.getProxyPort()); + if (!CONFIG.hasProxy() || StringUtils.isBlank(host) || port == null || CONFIG.getProxyType() == Proxy.Type.DIRECT) { + return Proxy.NO_PROXY; + } else { + return new Proxy(CONFIG.getProxyType(), new InetSocketAddress(host, port)); + } + }, + CONFIG.proxyTypeProperty(), + CONFIG.proxyHostProperty(), + CONFIG.proxyPortProperty(), + CONFIG.hasProxyProperty()); + + public static Proxy getProxy() { + return proxyProperty.get(); + } + + public static ObservableObjectValue proxyProperty() { + return proxyProperty; + } + + static { + initProxy(); + } + + private static void initProxy() { + proxyProperty.addListener(observable -> updateSystemProxy()); + + updateSystemProxy(); + + Authenticator.setDefault(new Authenticator() { + + @Override + protected PasswordAuthentication getPasswordAuthentication() { + if (CONFIG.hasProxyAuth()) { + String username = CONFIG.getProxyUser(); + String password = CONFIG.getProxyPass(); + if (username != null && password != null) { + return new PasswordAuthentication(username, password.toCharArray()); + } + } + return null; + } + }); + } + + private static void updateSystemProxy() { + Proxy proxy = proxyProperty.get(); + if (proxy.type() == Proxy.Type.DIRECT) { + System.clearProperty("http.proxyHost"); + System.clearProperty("http.proxyPort"); + System.clearProperty("https.proxyHost"); + System.clearProperty("https.proxyPort"); + System.clearProperty("socksProxyHost"); + System.clearProperty("socksProxyPort"); + } else { + InetSocketAddress address = (InetSocketAddress) proxy.address(); + String host = address.getHostString(); + String port = String.valueOf(address.getPort()); + if (proxy.type() == Type.HTTP) { + System.clearProperty("socksProxyHost"); + System.clearProperty("socksProxyPort"); + System.setProperty("http.proxyHost", host); + System.setProperty("http.proxyPort", port); + System.setProperty("https.proxyHost", host); + System.setProperty("https.proxyPort", port); + } else if (proxy.type() == Type.SOCKS) { + System.clearProperty("http.proxyHost"); + System.clearProperty("http.proxyPort"); + System.clearProperty("https.proxyHost"); + System.clearProperty("https.proxyPort"); + System.setProperty("socksProxyHost", host); + System.setProperty("socksProxyPort", port); + } + } + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java index 378f25ade..c5d73164c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java @@ -17,8 +17,8 @@ */ package org.jackhuang.hmcl.setting; +import javafx.beans.InvalidationListener; import javafx.beans.property.ObjectProperty; -import javafx.beans.property.StringProperty; import javafx.beans.value.ObservableValue; import javafx.scene.text.Font; @@ -33,16 +33,13 @@ import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.util.*; import org.jackhuang.hmcl.util.i18n.Locales; -import java.net.Authenticator; -import java.net.InetSocketAddress; -import java.net.PasswordAuthentication; -import java.net.Proxy; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.stream.Collectors; import static java.util.stream.Collectors.toList; +import static org.jackhuang.hmcl.setting.ConfigHolder.CONFIG; import static org.jackhuang.hmcl.ui.FXUtils.onInvalidating; import static org.jackhuang.hmcl.util.Lang.tryCast; import static org.jackhuang.hmcl.util.Logging.LOG; @@ -55,13 +52,23 @@ public class Settings { private final boolean firstLaunch; + private InvalidationListener accountChangeListener = + source -> CONFIG.getAccounts().setAll( + accounts.values().stream() + .map(account -> { + Map storage = account.toStorage(); + storage.put("type", Accounts.getAccountType(account)); + return storage; + }) + .collect(toList())); + private Settings() { - firstLaunch = ConfigHolder.CONFIG.firstLaunch.get(); - ConfigHolder.CONFIG.firstLaunch.set(false); + firstLaunch = CONFIG.isFirstLaunch(); + CONFIG.setFirstLaunch(false); - loadProxy(); + ProxyManager.getProxy(); // init ProxyManager - for (Iterator> iterator = ConfigHolder.CONFIG.accounts.iterator(); iterator.hasNext();) { + for (Iterator> iterator = CONFIG.getAccounts().iterator(); iterator.hasNext();) { Map settings = iterator.next(); AccountFactory factory = Accounts.ACCOUNT_FACTORY.get(tryCast(settings.get("type"), String.class).orElse("")); if (factory == null) { @@ -72,7 +79,7 @@ public class Settings { Account account; try { - account = factory.fromStorage(settings, getProxy()); + account = factory.fromStorage(settings); } catch (Exception e) { LOG.log(Level.WARNING, "Malformed account storage, removing: " + settings, e); iterator.remove(); @@ -80,62 +87,37 @@ public class Settings { } accounts.put(Accounts.getAccountId(account), account); + account.addListener(accountChangeListener); } - ConfigHolder.CONFIG.authlibInjectorServers.addListener(onInvalidating(this::removeDanglingAuthlibInjectorAccounts)); + CONFIG.getAuthlibInjectorServers().addListener(onInvalidating(this::removeDanglingAuthlibInjectorAccounts)); - this.selectedAccount.set(accounts.get(ConfigHolder.CONFIG.selectedAccount.get())); + this.selectedAccount.set(accounts.get(CONFIG.getSelectedAccount())); checkProfileMap(); save(); - for (Map.Entry entry2 : getProfileMap().entrySet()) { - entry2.getValue().setName(entry2.getKey()); - entry2.getValue().nameProperty().setChangedListener(this::profileNameChanged); - entry2.getValue().addPropertyChangedListener(e -> save()); + for (Map.Entry profileEntry : getProfileMap().entrySet()) { + profileEntry.getValue().setName(profileEntry.getKey()); + profileEntry.getValue().nameProperty().setChangedListener(this::profileNameChanged); + profileEntry.getValue().addPropertyChangedListener(e -> save()); } Lang.ignoringException(() -> Runtime.getRuntime().addShutdownHook(new Thread(this::save))); + + CONFIG.addListener(source -> save()); } - public void save() { - ConfigHolder.CONFIG.accounts.clear(); - for (Account account : accounts.values()) { - Map storage = account.toStorage(); - storage.put("type", Accounts.getAccountType(account)); - ConfigHolder.CONFIG.accounts.add(storage); - } - ConfigHolder.saveConfig(ConfigHolder.CONFIG); + private void save() { + ConfigHolder.saveConfig(CONFIG); } public boolean isFirstLaunch() { return firstLaunch; } - private final StringProperty commonPath = new ImmediateStringProperty(this, "commonPath", ConfigHolder.CONFIG.commonDirectory.get()) { - @Override - public void invalidated() { - super.invalidated(); - - ConfigHolder.CONFIG.commonDirectory.set(get()); - save(); - } - }; - - public String getCommonPath() { - return commonPath.get(); - } - - public StringProperty commonPathProperty() { - return commonPath; - } - - public void setCommonPath(String commonPath) { - this.commonPath.set(commonPath); - } - - private Locales.SupportedLocale locale = Locales.getLocaleByName(ConfigHolder.CONFIG.localization.get()); + private Locales.SupportedLocale locale = Locales.getLocaleByName(CONFIG.getLocalization()); public Locales.SupportedLocale getLocale() { return locale; @@ -143,126 +125,24 @@ public class Settings { public void setLocale(Locales.SupportedLocale locale) { this.locale = locale; - ConfigHolder.CONFIG.localization.set(Locales.getNameByLocale(locale)); - save(); - } - - private Proxy proxy = Proxy.NO_PROXY; - - public Proxy getProxy() { - return proxy; - } - - private Proxy.Type proxyType = Proxies.getProxyType(ConfigHolder.CONFIG.proxyType.get()); - - public Proxy.Type getProxyType() { - return proxyType; - } - - public void setProxyType(Proxy.Type proxyType) { - this.proxyType = proxyType; - ConfigHolder.CONFIG.proxyType.set(Proxies.PROXIES.indexOf(proxyType)); - save(); - loadProxy(); - } - - public String getProxyHost() { - return ConfigHolder.CONFIG.proxyHost.get(); - } - - public void setProxyHost(String proxyHost) { - ConfigHolder.CONFIG.proxyHost.set(proxyHost); - save(); - } - - public String getProxyPort() { - return ConfigHolder.CONFIG.proxyPort.get(); - } - - public void setProxyPort(String proxyPort) { - ConfigHolder.CONFIG.proxyPort.set(proxyPort); - save(); - } - - public String getProxyUser() { - return ConfigHolder.CONFIG.proxyUser.get(); - } - - public void setProxyUser(String proxyUser) { - ConfigHolder.CONFIG.proxyUser.set(proxyUser); - save(); - } - - public String getProxyPass() { - return ConfigHolder.CONFIG.proxyPass.get(); - } - - public void setProxyPass(String proxyPass) { - ConfigHolder.CONFIG.proxyPass.set(proxyPass); - save(); - } - - public boolean hasProxy() { - return ConfigHolder.CONFIG.hasProxy.get(); - } - - public void setHasProxy(boolean hasProxy) { - ConfigHolder.CONFIG.hasProxy.set(hasProxy); - save(); - } - - public boolean hasProxyAuth() { - return ConfigHolder.CONFIG.hasProxyAuth.get(); - } - - public void setHasProxyAuth(boolean hasProxyAuth) { - ConfigHolder.CONFIG.hasProxyAuth.set(hasProxyAuth); - save(); - } - - private void loadProxy() { - String host = getProxyHost(); - Integer port = Lang.toIntOrNull(getProxyPort()); - if (!hasProxy() || StringUtils.isBlank(host) || port == null || getProxyType() == Proxy.Type.DIRECT) - proxy = Proxy.NO_PROXY; - else { - System.setProperty("http.proxyHost", getProxyHost()); - System.setProperty("http.proxyPort", getProxyPort()); - proxy = new Proxy(proxyType, new InetSocketAddress(host, port)); - - String user = getProxyUser(); - String pass = getProxyPass(); - if (hasProxyAuth() && StringUtils.isNotBlank(user) && StringUtils.isNotBlank(pass)) { - System.setProperty("http.proxyUser", user); - System.setProperty("http.proxyPassword", pass); - - Authenticator.setDefault(new Authenticator() { - @Override - public PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(user, pass.toCharArray()); - } - }); - } - } + CONFIG.setLocalization(Locales.getNameByLocale(locale)); } public Font getFont() { - return Font.font(ConfigHolder.CONFIG.fontFamily.get(), ConfigHolder.CONFIG.fontSize.get()); + return Font.font(CONFIG.getFontFamily(), CONFIG.getFontSize()); } public void setFont(Font font) { - ConfigHolder.CONFIG.fontFamily.set(font.getFamily()); - ConfigHolder.CONFIG.fontSize.set(font.getSize()); - save(); + CONFIG.setFontFamily(font.getFamily()); + CONFIG.setFontSize(font.getSize()); } public int getLogLines() { - return Math.max(ConfigHolder.CONFIG.logLines.get(), 100); + return Math.max(CONFIG.getLogLines(), 100); } public void setLogLines(int logLines) { - ConfigHolder.CONFIG.logLines.set(logLines); - save(); + CONFIG.setLogLines(logLines); } /**************************************** @@ -277,7 +157,7 @@ public class Settings { private void removeDanglingAuthlibInjectorAccounts() { accounts.values().stream() .filter(AuthlibInjectorAccount.class::isInstance) - .filter(it -> !ConfigHolder.CONFIG.authlibInjectorServers.contains(((AuthlibInjectorAccount) it).getServer())) + .filter(it -> !CONFIG.getAuthlibInjectorServers().contains(((AuthlibInjectorAccount) it).getServer())) .collect(toList()) .forEach(this::deleteAccount); } @@ -287,15 +167,14 @@ public class Settings { ****************************************/ public DownloadProvider getDownloadProvider() { - return DownloadProviders.getDownloadProvider(ConfigHolder.CONFIG.downloadType.get()); + return DownloadProviders.getDownloadProvider(CONFIG.getDownloadType()); } public void setDownloadProvider(DownloadProvider downloadProvider) { int index = DownloadProviders.DOWNLOAD_PROVIDERS.indexOf(downloadProvider); if (index == -1) throw new IllegalArgumentException("Unknown download provider: " + downloadProvider); - ConfigHolder.CONFIG.downloadType.set(index); - save(); + CONFIG.setDownloadType(index); } /**************************************** @@ -324,8 +203,7 @@ public class Settings { public void invalidated() { super.invalidated(); - ConfigHolder.CONFIG.selectedAccount.set(getValue() == null ? "" : Accounts.getAccountId(getValue())); - save(); + CONFIG.setSelectedAccount(getValue() == null ? "" : Accounts.getAccountId(getValue())); } }; @@ -343,6 +221,9 @@ public class Settings { public void addAccount(Account account) { accounts.put(Accounts.getAccountId(account), account); + account.addListener(accountChangeListener); + accountChangeListener.invalidated(account); + onAccountLoading(); EventBus.EVENT_BUS.fireEvent(new AccountAddedEvent(this, account)); @@ -357,78 +238,35 @@ public class Settings { } public void deleteAccount(String name, String character) { - accounts.remove(Accounts.getAccountId(name, character)); + Account removed = accounts.remove(Accounts.getAccountId(name, character)); + if (removed != null) { + removed.removeListener(accountChangeListener); + accountChangeListener.invalidated(removed); - onAccountLoading(); - selectedAccount.get(); + onAccountLoading(); + selectedAccount.get(); + } } public void deleteAccount(Account account) { accounts.remove(Accounts.getAccountId(account)); + account.removeListener(accountChangeListener); + accountChangeListener.invalidated(account); onAccountLoading(); selectedAccount.get(); } - /**************************************** - * BACKGROUND * - ****************************************/ - - private final ImmediateStringProperty backgroundImage = new ImmediateStringProperty(this, "backgroundImage", ConfigHolder.CONFIG.backgroundImage.get()) { - @Override - public void invalidated() { - super.invalidated(); - - ConfigHolder.CONFIG.backgroundImage.set(get()); - save(); - } - }; - - public String getBackgroundImage() { - return backgroundImage.get(); - } - - public ImmediateStringProperty backgroundImageProperty() { - return backgroundImage; - } - - public void setBackgroundImage(String backgroundImage) { - this.backgroundImage.set(backgroundImage); - } - - private final ImmediateObjectProperty backgroundImageType = new ImmediateObjectProperty(this, "backgroundImageType", EnumBackgroundImage.indexOf(ConfigHolder.CONFIG.backgroundImageType.get())) { - @Override - public void invalidated() { - super.invalidated(); - - ConfigHolder.CONFIG.backgroundImageType.set(get().ordinal()); - save(); - } - }; - - public EnumBackgroundImage getBackgroundImageType() { - return backgroundImageType.get(); - } - - public ImmediateObjectProperty backgroundImageTypeProperty() { - return backgroundImageType; - } - - public void setBackgroundImageType(EnumBackgroundImage backgroundImageType) { - this.backgroundImageType.set(backgroundImageType); - } - /**************************************** * THEME * ****************************************/ - private final ImmediateObjectProperty theme = new ImmediateObjectProperty(this, "theme", Theme.getTheme(ConfigHolder.CONFIG.theme.get()).orElse(Theme.BLUE)) { + private final ImmediateObjectProperty theme = new ImmediateObjectProperty(this, "theme", Theme.getTheme(CONFIG.getTheme()).orElse(Theme.BLUE)) { @Override public void invalidated() { super.invalidated(); - ConfigHolder.CONFIG.theme.set(get().getName().toLowerCase()); - save(); + CONFIG.setTheme(get().getName().toLowerCase()); } }; @@ -451,20 +289,18 @@ public class Settings { public Profile getSelectedProfile() { checkProfileMap(); - if (!hasProfile(ConfigHolder.CONFIG.selectedProfile.get())) { + if (!hasProfile(CONFIG.getSelectedProfile())) { getProfileMap().keySet().stream().findFirst().ifPresent(selectedProfile -> { - ConfigHolder.CONFIG.selectedProfile.set(selectedProfile); - save(); + CONFIG.setSelectedProfile(selectedProfile); }); Schedulers.computation().schedule(this::onProfileChanged); } - return getProfile(ConfigHolder.CONFIG.selectedProfile.get()); + return getProfile(CONFIG.getSelectedProfile()); } public void setSelectedProfile(Profile selectedProfile) { - if (hasProfile(selectedProfile.getName()) && !Objects.equals(selectedProfile.getName(), ConfigHolder.CONFIG.selectedProfile.get())) { - ConfigHolder.CONFIG.selectedProfile.set(selectedProfile.getName()); - save(); + if (hasProfile(selectedProfile.getName()) && !Objects.equals(selectedProfile.getName(), CONFIG.getSelectedProfile())) { + CONFIG.setSelectedProfile(selectedProfile.getName()); Schedulers.computation().schedule(this::onProfileChanged); } } @@ -481,7 +317,7 @@ public class Settings { } public Map getProfileMap() { - return ConfigHolder.CONFIG.configurations; + return CONFIG.getConfigurations(); } public Collection getProfiles() { @@ -496,8 +332,6 @@ public class Settings { Schedulers.computation().schedule(this::onProfileLoading); ver.nameProperty().setChangedListener(this::profileNameChanged); - - save(); } public void deleteProfile(Profile profile) { @@ -542,8 +376,4 @@ public class Settings { public void onAccountLoading() { EventBus.EVENT_BUS.fireEvent(new AccountLoadingEvent(this, getAccounts())); } - - public Config getRawConfig() { - return ConfigHolder.CONFIG.clone(); - } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java index 9b9ab8c45..c8e9ddf34 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java @@ -30,6 +30,8 @@ import java.util.List; import java.util.Optional; import java.util.stream.Collectors; +import static org.jackhuang.hmcl.setting.ConfigHolder.CONFIG; + /** * * @author huangyuhui @@ -517,10 +519,10 @@ public final class VersionSetting { .setFullscreen(isFullscreen()) .setServerIp(getServerIp()) .setWrapper(getWrapper()) - .setProxyHost(Settings.INSTANCE.getProxyHost()) - .setProxyPort(Settings.INSTANCE.getProxyPort()) - .setProxyUser(Settings.INSTANCE.getProxyUser()) - .setProxyPass(Settings.INSTANCE.getProxyPass()) + .setProxyHost(CONFIG.getProxyHost()) + .setProxyPort(CONFIG.getProxyPort()) + .setProxyUser(CONFIG.getProxyUser()) + .setProxyPass(CONFIG.getProxyPass()) .setPrecalledCommand(getPreLaunchCommand()) .setNoGeneratedJVMArgs(isNoJVMArgs()) .create(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AddAccountPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AddAccountPane.java index 65f83b772..f10c269fb 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AddAccountPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AddAccountPane.java @@ -41,7 +41,6 @@ import org.jackhuang.hmcl.auth.yggdrasil.RemoteAuthenticationException; import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount; import org.jackhuang.hmcl.game.AccountHelper; import org.jackhuang.hmcl.setting.Accounts; -import org.jackhuang.hmcl.setting.ConfigHolder; import org.jackhuang.hmcl.setting.Settings; import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Task; @@ -52,6 +51,7 @@ import org.jackhuang.hmcl.ui.construct.SpinnerPane; import org.jackhuang.hmcl.ui.construct.Validator; import org.jackhuang.hmcl.util.Constants; import org.jackhuang.hmcl.util.Logging; +import static org.jackhuang.hmcl.setting.ConfigHolder.CONFIG; import static org.jackhuang.hmcl.ui.FXUtils.jfxListCellFactory; import static org.jackhuang.hmcl.ui.FXUtils.onInvalidating; import static org.jackhuang.hmcl.ui.FXUtils.stringConverter; @@ -81,7 +81,7 @@ public class AddAccountPane extends StackPane { cboServers.setCellFactory(jfxListCellFactory(server -> new TwoLineListItem(server.getName(), server.getUrl()))); cboServers.setConverter(stringConverter(AuthlibInjectorServer::getName)); - Bindings.bindContent(cboServers.getItems(), ConfigHolder.CONFIG.authlibInjectorServers); + Bindings.bindContent(cboServers.getItems(), CONFIG.getAuthlibInjectorServers()); cboServers.getItems().addListener(onInvalidating(this::selectDefaultServer)); selectDefaultServer(); @@ -151,7 +151,7 @@ public class AddAccountPane extends StackPane { lblCreationWarning.setText(""); setDisable(true); - Task.ofResult("create_account", () -> factory.create(new Selector(), username, password, addtionalData, Settings.INSTANCE.getProxy())) + Task.ofResult("create_account", () -> factory.create(new Selector(), username, password, addtionalData)) .finalized(Schedulers.javafx(), variables -> { Settings.INSTANCE.addAccount(variables.get("create_account")); acceptPane.hideSpinner(); @@ -211,7 +211,7 @@ public class AddAccountPane extends StackPane { for (GameProfile profile : names) { Image image; try { - image = AccountHelper.getSkinImmediately(yggdrasilAccount, profile, 4, Settings.INSTANCE.getProxy()); + image = AccountHelper.getSkinImmediately(yggdrasilAccount, profile, 4); } catch (Exception e) { Logging.LOG.log(Level.WARNING, "Failed to get skin for " + profile.getName(), e); image = null; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AddAuthlibInjectorServerPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AddAuthlibInjectorServerPane.java index 66d4a4fa9..2fbf48b94 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AddAuthlibInjectorServerPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AddAuthlibInjectorServerPane.java @@ -22,7 +22,6 @@ import static org.jackhuang.hmcl.util.i18n.I18n.i18n; import java.io.IOException; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer; -import org.jackhuang.hmcl.setting.ConfigHolder; import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.animation.ContainerAnimations; @@ -40,6 +39,8 @@ import javafx.fxml.FXML; import javafx.scene.control.Label; import javafx.scene.layout.StackPane; +import static org.jackhuang.hmcl.setting.ConfigHolder.CONFIG; + public class AddAuthlibInjectorServerPane extends StackPane { @FXML private StackPane addServerContainer; @@ -132,8 +133,8 @@ public class AddAuthlibInjectorServerPane extends StackPane { @FXML private void onAddFinish() { - if (!ConfigHolder.CONFIG.authlibInjectorServers.contains(serverBeingAdded)) { - ConfigHolder.CONFIG.authlibInjectorServers.add(serverBeingAdded); + if (!CONFIG.getAuthlibInjectorServers().contains(serverBeingAdded)) { + CONFIG.getAuthlibInjectorServers().add(serverBeingAdded); } fireEvent(new DialogCloseEvent()); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AuthlibInjectorServersPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AuthlibInjectorServersPage.java index e2fae365a..3cdc611bb 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AuthlibInjectorServersPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AuthlibInjectorServersPage.java @@ -22,7 +22,6 @@ import static org.jackhuang.hmcl.ui.FXUtils.loadFXML; import static org.jackhuang.hmcl.ui.FXUtils.smoothScrolling; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; -import org.jackhuang.hmcl.setting.ConfigHolder; import org.jackhuang.hmcl.ui.wizard.DecoratorPage; import javafx.beans.InvalidationListener; @@ -34,6 +33,8 @@ import javafx.scene.control.ScrollPane; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; +import static org.jackhuang.hmcl.setting.ConfigHolder.CONFIG; + public class AuthlibInjectorServersPage extends StackPane implements DecoratorPage { private final StringProperty title = new SimpleStringProperty(this, "title", i18n("account.injector.manage.title")); @@ -48,15 +49,15 @@ public class AuthlibInjectorServersPage extends StackPane implements DecoratorPa smoothScrolling(scrollPane); serversListener = observable -> updateServersList(); - ConfigHolder.CONFIG.authlibInjectorServers.addListener(new WeakInvalidationListener(serversListener)); + CONFIG.getAuthlibInjectorServers().addListener(new WeakInvalidationListener(serversListener)); updateServersList(); } private void updateServersList() { listPane.getChildren().setAll( - ConfigHolder.CONFIG.authlibInjectorServers.stream() + CONFIG.getAuthlibInjectorServers().stream() .map(server -> new AuthlibInjectorServerItem(server, - item -> ConfigHolder.CONFIG.authlibInjectorServers.remove(item.getServer()))) + item -> CONFIG.getAuthlibInjectorServers().remove(item.getServer()))) .collect(toList())); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java index 41695e1cb..91bb9ae33 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java @@ -76,6 +76,8 @@ import java.util.Queue; import java.util.Random; import java.util.concurrent.ConcurrentLinkedQueue; +import static org.jackhuang.hmcl.setting.ConfigHolder.CONFIG; + public final class Decorator extends StackPane implements TaskExecutorDialogWizardDisplayer { private static final SVGGlyph minus = Lang.apply(new SVGGlyph(0, "MINUS", "M804.571 420.571v109.714q0 22.857-16 38.857t-38.857 16h-694.857q-22.857 0-38.857-16t-16-38.857v-109.714q0-22.857 16-38.857t38.857-16h694.857q22.857 0 38.857 16t16 38.857z", Color.WHITE), glyph -> { glyph.setSize(12, 2); glyph.setTranslateY(4); }); @@ -219,10 +221,10 @@ public final class Decorator extends StackPane implements TaskExecutorDialogWiza try { Image background; - if (Settings.INSTANCE.getBackgroundImageType() == EnumBackgroundImage.DEFAULT) + if (CONFIG.getBackgroundImageType() == EnumBackgroundImage.DEFAULT) background = searchBackgroundImage(new Image("/assets/img/background.jpg"), ""); else - background = searchBackgroundImage(new Image("/assets/img/background.jpg"), Settings.INSTANCE.getBackgroundImage()); + background = searchBackgroundImage(new Image("/assets/img/background.jpg"), CONFIG.getBackgroundImage()); drawerWrapper.setBackground(new Background(new BackgroundImage(background, BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT, BackgroundPosition.DEFAULT, new BackgroundSize(800, 480, false, false, true, true)))); } catch (IllegalArgumentException ignore) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsPage.java index a691adc87..25a4aa39e 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsPage.java @@ -20,7 +20,8 @@ package org.jackhuang.hmcl.ui; import com.jfoenix.controls.*; import com.jfoenix.effects.JFXDepthManager; import javafx.application.Platform; -import javafx.beans.binding.Bindings; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.collections.FXCollections; @@ -28,7 +29,6 @@ import javafx.collections.ObservableList; import javafx.fxml.FXML; import javafx.scene.control.Label; import javafx.scene.control.ScrollPane; -import javafx.scene.control.Toggle; import javafx.scene.control.ToggleGroup; import javafx.scene.layout.GridPane; import javafx.scene.layout.Pane; @@ -45,12 +45,13 @@ import org.jackhuang.hmcl.ui.wizard.DecoratorPage; import org.jackhuang.hmcl.util.Lang; import org.jackhuang.hmcl.util.i18n.Locales; +import static org.jackhuang.hmcl.setting.ConfigHolder.CONFIG; +import static org.jackhuang.hmcl.ui.FXUtils.onInvalidating; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; import java.net.Proxy; -import java.util.Arrays; import java.util.Collections; -import java.util.stream.Collectors; +import java.util.Objects; public final class SettingsPage extends StackPane implements DecoratorPage { private final StringProperty title = new SimpleStringProperty(this, "title", i18n("settings.launcher")); @@ -88,9 +89,7 @@ public final class SettingsPage extends StackPane implements DecoratorPage { @FXML private StackPane themeColorPickerContainer; @FXML - private JFXRadioButton chkNoProxy; - @FXML - private JFXRadioButton chkManualProxy; + private JFXCheckBox chkEnableProxy; @FXML private JFXRadioButton chkProxyHttp; @FXML @@ -107,18 +106,6 @@ public final class SettingsPage extends StackPane implements DecoratorPage { FXUtils.smoothScrolling(scroll); - txtProxyHost.setText(Settings.INSTANCE.getProxyHost()); - txtProxyHost.textProperty().addListener((a, b, newValue) -> Settings.INSTANCE.setProxyHost(newValue)); - - txtProxyPort.setText(Settings.INSTANCE.getProxyPort()); - txtProxyPort.textProperty().addListener((a, b, newValue) -> Settings.INSTANCE.setProxyPort(newValue)); - - txtProxyUsername.setText(Settings.INSTANCE.getProxyUser()); - txtProxyUsername.textProperty().addListener((a, b, newValue) -> Settings.INSTANCE.setProxyUser(newValue)); - - txtProxyPassword.setText(Settings.INSTANCE.getProxyPass()); - txtProxyPassword.textProperty().addListener((a, b, newValue) -> Settings.INSTANCE.setProxyPass(newValue)); - cboDownloadSource.getSelectionModel().select(DownloadProviders.DOWNLOAD_PROVIDERS.indexOf(Settings.INSTANCE.getDownloadProvider())); cboDownloadSource.getSelectionModel().selectedIndexProperty().addListener((a, b, newValue) -> Settings.INSTANCE.setDownloadProvider(DownloadProviders.getDownloadProvider(newValue.intValue()))); @@ -149,37 +136,50 @@ public final class SettingsPage extends StackPane implements DecoratorPage { cboLanguage.getSelectionModel().select(Locales.LOCALES.indexOf(Settings.INSTANCE.getLocale())); cboLanguage.getSelectionModel().selectedIndexProperty().addListener((a, b, newValue) -> Settings.INSTANCE.setLocale(Locales.getLocale(newValue.intValue()))); + // ==== Proxy ==== + txtProxyHost.textProperty().bindBidirectional(CONFIG.proxyHostProperty()); + txtProxyPort.textProperty().bindBidirectional(CONFIG.proxyPortProperty()); + txtProxyUsername.textProperty().bindBidirectional(CONFIG.proxyUserProperty()); + txtProxyPassword.textProperty().bindBidirectional(CONFIG.proxyPassProperty()); + + proxyPane.disableProperty().bind(chkEnableProxy.selectedProperty().not()); + authPane.disableProperty().bind(chkProxyAuthentication.selectedProperty().not()); + + chkEnableProxy.selectedProperty().bindBidirectional(CONFIG.hasProxyProperty()); + chkProxyAuthentication.selectedProperty().bindBidirectional(CONFIG.hasProxyAuthProperty()); + + ObjectProperty selectedProxyType = new SimpleObjectProperty(Proxy.Type.HTTP) { + { + invalidated(); + } + + @Override + protected void invalidated() { + Proxy.Type type = Objects.requireNonNull(get()); + if (type == Proxy.Type.DIRECT) { + set(Proxy.Type.HTTP); // HTTP by default + } else { + chkProxyHttp.setSelected(type == Proxy.Type.HTTP); + chkProxySocks.setSelected(type == Proxy.Type.SOCKS); + } + } + }; + selectedProxyType.bindBidirectional(CONFIG.proxyTypeProperty()); ToggleGroup proxyConfigurationGroup = new ToggleGroup(); chkProxyHttp.setUserData(Proxy.Type.HTTP); chkProxyHttp.setToggleGroup(proxyConfigurationGroup); chkProxySocks.setUserData(Proxy.Type.SOCKS); chkProxySocks.setToggleGroup(proxyConfigurationGroup); + proxyConfigurationGroup.getToggles().forEach( + toggle -> toggle.selectedProperty().addListener((observable, oldValue, newValue) -> { + if (newValue) { + selectedProxyType.set((Proxy.Type) toggle.getUserData()); + } + })); + // ==== - for (Toggle toggle : proxyConfigurationGroup.getToggles()) - if (toggle.getUserData() == Settings.INSTANCE.getProxyType()) - toggle.setSelected(true); - - ToggleGroup hasProxyGroup = new ToggleGroup(); - chkNoProxy.setToggleGroup(hasProxyGroup); - chkManualProxy.setToggleGroup(hasProxyGroup); - if (!Settings.INSTANCE.hasProxy()) - chkNoProxy.setSelected(true); - else - chkManualProxy.setSelected(true); - proxyPane.disableProperty().bind(chkNoProxy.selectedProperty()); - - hasProxyGroup.selectedToggleProperty().addListener((a, b, newValue) -> - Settings.INSTANCE.setHasProxy(newValue != chkNoProxy)); - - proxyConfigurationGroup.selectedToggleProperty().addListener((a, b, newValue) -> - Settings.INSTANCE.setProxyType((Proxy.Type) newValue.getUserData())); - - chkProxyAuthentication.setSelected(Settings.INSTANCE.hasProxyAuth()); - chkProxyAuthentication.selectedProperty().addListener((a, b, newValue) -> Settings.INSTANCE.setHasProxyAuth(newValue)); - authPane.disableProperty().bind(chkProxyAuthentication.selectedProperty().not()); - - fileCommonLocation.pathProperty().bindBidirectional(Settings.INSTANCE.commonPathProperty()); + fileCommonLocation.pathProperty().bindBidirectional(CONFIG.commonDirectoryProperty()); FXUtils.installTooltip(btnUpdate, i18n("update.tooltip")); checkUpdate(); @@ -189,17 +189,17 @@ public final class SettingsPage extends StackPane implements DecoratorPage { backgroundItem.createChildren(i18n("launcher.background.default"), EnumBackgroundImage.DEFAULT) )); - FXUtils.bindString(backgroundItem.getTxtCustom(), Settings.INSTANCE.backgroundImageProperty()); + FXUtils.bindString(backgroundItem.getTxtCustom(), CONFIG.backgroundImageProperty()); backgroundItem.setCustomUserData(EnumBackgroundImage.CUSTOM); - backgroundItem.getGroup().getToggles().stream().filter(it -> it.getUserData() == Settings.INSTANCE.getBackgroundImageType()).findFirst().ifPresent(it -> it.setSelected(true)); + backgroundItem.getGroup().getToggles().stream().filter(it -> it.getUserData() == CONFIG.getBackgroundImageType()).findFirst().ifPresent(it -> it.setSelected(true)); - Settings.INSTANCE.backgroundImageProperty().setChangedListener(it -> initBackgroundItemSubtitle()); - Settings.INSTANCE.backgroundImageTypeProperty().setChangedListener(it -> initBackgroundItemSubtitle()); + CONFIG.backgroundImageProperty().addListener(onInvalidating(this::initBackgroundItemSubtitle)); + CONFIG.backgroundImageTypeProperty().addListener(onInvalidating(this::initBackgroundItemSubtitle)); initBackgroundItemSubtitle(); backgroundItem.setToggleSelectedListener(newValue -> - Settings.INSTANCE.setBackgroundImageType((EnumBackgroundImage) newValue.getUserData())); + CONFIG.setBackgroundImageType((EnumBackgroundImage) newValue.getUserData())); // theme JFXColorPicker picker = new JFXColorPicker(Color.web(Settings.INSTANCE.getTheme().getColor()), null); @@ -216,12 +216,12 @@ public final class SettingsPage extends StackPane implements DecoratorPage { } private void initBackgroundItemSubtitle() { - switch (Settings.INSTANCE.getBackgroundImageType()) { + switch (CONFIG.getBackgroundImageType()) { case DEFAULT: backgroundItem.setSubtitle(i18n("launcher.background.default")); break; case CUSTOM: - backgroundItem.setSubtitle(Settings.INSTANCE.getBackgroundImage()); + backgroundItem.setSubtitle(CONFIG.getBackgroundImage()); break; } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ExportWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ExportWizardProvider.java index 9e8730110..65520fb8b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ExportWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ExportWizardProvider.java @@ -25,7 +25,6 @@ import org.jackhuang.hmcl.mod.Modpack; import org.jackhuang.hmcl.setting.Config; import org.jackhuang.hmcl.setting.ConfigHolder; import org.jackhuang.hmcl.setting.Profile; -import org.jackhuang.hmcl.setting.Settings; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.wizard.WizardController; import org.jackhuang.hmcl.ui.wizard.WizardProvider; @@ -81,18 +80,18 @@ public final class ExportWizardProvider implements WizardProvider { boolean flag = true; try (ZipEngine zip = new ZipEngine(modpackFile)) { - Config config = Settings.INSTANCE.getRawConfig(); + Config config = ConfigHolder.CONFIG.clone(); - config.hasProxy.set(false); - config.selectedProfile.set(""); - config.commonDirectory.set(null); - config.fontFamily.set("Consolas"); - config.fontSize.set(12); - config.localization.set(null); - config.accounts.clear(); - config.selectedAccount.set(""); - config.logLines.set(100); - config.configurations.clear(); + config.setHasProxy(false); + config.setSelectedProfile(""); + config.setCommonDirectory(null); + config.setFontFamily("Consolas"); + config.setFontSize(12); + config.setLocalization(null); + config.getAccounts().clear(); + config.setSelectedAccount(""); + config.setLogLines(100); + config.getConfigurations().clear(); zip.putTextFile(config.toJson(), ConfigHolder.CONFIG_FILENAME); zip.putFile(tempModpack, "modpack.zip"); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java index 1cd70a89b..bfd7af422 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java @@ -185,7 +185,7 @@ public class AppDataUpgrader extends IUpgrader { @Override public Collection getDependents() { - return Collections.singleton(new FileDownloadTask(downloadLink, tempFile, Proxy.NO_PROXY, new IntegrityCheck("SHA-1", hash))); + return Collections.singleton(new FileDownloadTask(downloadLink, tempFile, new IntegrityCheck("SHA-1", hash))); } @Override @@ -235,7 +235,7 @@ public class AppDataUpgrader extends IUpgrader { @Override public Collection getDependents() { - return Collections.singleton(new FileDownloadTask(downloadLink, tempFile, Proxy.NO_PROXY, new IntegrityCheck("SHA-1", hash))); + return Collections.singleton(new FileDownloadTask(downloadLink, tempFile, new IntegrityCheck("SHA-1", hash))); } @Override diff --git a/HMCL/src/main/resources/assets/fxml/setting.fxml b/HMCL/src/main/resources/assets/fxml/setting.fxml index 2fd147469..8b069368f 100644 --- a/HMCL/src/main/resources/assets/fxml/setting.fxml +++ b/HMCL/src/main/resources/assets/fxml/setting.fxml @@ -55,8 +55,7 @@ - - + diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 5ed764590..ca86a7bfd 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -288,8 +288,7 @@ settings.launcher.language=Language settings.launcher.log_font=Log Font settings.launcher.proxy=Proxy settings.launcher.proxy.authentication=Proxy Authentication -settings.launcher.proxy.no_proxy=No proxy -settings.launcher.proxy.has_proxy=Proxy configuration +settings.launcher.proxy.enable=Enable Proxy settings.launcher.proxy.host=Host settings.launcher.proxy.http=HTTP settings.launcher.proxy.password=Password diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 2d480d78f..706a9c5aa 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -287,9 +287,8 @@ settings.launcher.download_source=下載源 settings.launcher.language=語言 settings.launcher.log_font=日誌字體 settings.launcher.proxy=代理 -settings.launcher.proxy.authentication=代理賬戶 -settings.launcher.proxy.no_proxy=直連 -settings.launcher.proxy.has_proxy=啓用驗證 +settings.launcher.proxy.authentication=身份驗證 +settings.launcher.proxy.enable=启用代理 settings.launcher.proxy.host=主機 settings.launcher.proxy.http=HTTP settings.launcher.proxy.password=密碼 diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties index fe5751a81..f183968d6 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -287,9 +287,8 @@ settings.launcher.download_source=下载源 settings.launcher.language=语言 settings.launcher.log_font=日志字体 settings.launcher.proxy=代理 -settings.launcher.proxy.authentication=代理账户 -settings.launcher.proxy.no_proxy=直连 -settings.launcher.proxy.has_proxy=启用验证 +settings.launcher.proxy.authentication=身份验证 +settings.launcher.proxy.enable=启用代理 settings.launcher.proxy.host=主机 settings.launcher.proxy.http=HTTP settings.launcher.proxy.password=密码 diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/Account.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/Account.java index 8eaf538cd..585f45e80 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/Account.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/Account.java @@ -17,8 +17,13 @@ */ package org.jackhuang.hmcl.auth; +import org.jackhuang.hmcl.util.ObservableHelper; import org.jackhuang.hmcl.util.ToStringBuilder; +import javafx.application.Platform; +import javafx.beans.InvalidationListener; +import javafx.beans.Observable; + import java.util.Map; import java.util.Optional; import java.util.UUID; @@ -27,7 +32,7 @@ import java.util.UUID; * * @author huangyuhui */ -public abstract class Account { +public abstract class Account implements Observable { /** * @return the name of the account who owns the character @@ -66,6 +71,26 @@ public abstract class Account { public abstract void clearCache(); + private ObservableHelper helper = new ObservableHelper(this); + + @Override + public void addListener(InvalidationListener listener) { + helper.addListener(listener); + } + + @Override + public void removeListener(InvalidationListener listener) { + helper.removeListener(listener); + } + + /** + * Called when the account has changed. + * This method can be called from any thread. + */ + protected void invalidate() { + Platform.runLater(helper::invalidate); + } + @Override public String toString() { return new ToStringBuilder(this) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/AccountBuilder.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/AccountBuilder.java index c9dbf3450..2e2ecfd93 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/AccountBuilder.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/AccountBuilder.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.auth; -import java.net.Proxy; import java.util.Objects; public final class AccountBuilder { @@ -25,7 +24,6 @@ public final class AccountBuilder { private String username; private String password = null; private Object additionalData = null; - private Proxy proxy = Proxy.NO_PROXY; public AccountBuilder() { } @@ -50,12 +48,7 @@ public final class AccountBuilder { return this; } - public AccountBuilder setProxy(Proxy proxy) { - this.proxy = Objects.requireNonNull(proxy); - return this; - } - public T create(AccountFactory factory) throws AuthenticationException { - return factory.create(selector, Objects.requireNonNull(username), password, additionalData, proxy); + return factory.create(selector, Objects.requireNonNull(username), password, additionalData); } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/AccountFactory.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/AccountFactory.java index 62f5fab78..65c4c0f27 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/AccountFactory.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/AccountFactory.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.auth; -import java.net.Proxy; import java.util.Map; /** @@ -26,7 +25,7 @@ import java.util.Map; */ public abstract class AccountFactory { - public abstract T create(CharacterSelector selector, String username, String password, Object additionalData, Proxy proxy) throws AuthenticationException; + public abstract T create(CharacterSelector selector, String username, String password, Object additionalData) throws AuthenticationException; - public abstract T fromStorage(Map storage, Proxy proxy); + public abstract T fromStorage(Map storage); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorAccountFactory.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorAccountFactory.java index 94b7587c0..d664d861b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorAccountFactory.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorAccountFactory.java @@ -25,7 +25,6 @@ import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilSession; import org.jackhuang.hmcl.util.ExceptionalSupplier; import java.io.IOException; -import java.net.Proxy; import java.util.Map; import java.util.Objects; import java.util.function.Function; @@ -45,24 +44,22 @@ public class AuthlibInjectorAccountFactory extends AccountFactory storage, Proxy proxy) { + public AuthlibInjectorAccount fromStorage(Map storage) { Objects.requireNonNull(storage); - Objects.requireNonNull(proxy); YggdrasilSession session = YggdrasilSession.fromStorage(storage); @@ -73,7 +70,7 @@ public class AuthlibInjectorAccountFactory extends AccountFactory new IntegrityCheck("SHA-256", checksum)) .orElse(null)) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/offline/OfflineAccountFactory.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/offline/OfflineAccountFactory.java index a1ac4f56b..0556916fd 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/offline/OfflineAccountFactory.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/offline/OfflineAccountFactory.java @@ -21,7 +21,6 @@ import org.jackhuang.hmcl.auth.AccountFactory; import org.jackhuang.hmcl.auth.CharacterSelector; import org.jackhuang.hmcl.util.UUIDTypeAdapter; -import java.net.Proxy; import java.util.Map; import java.util.UUID; @@ -39,12 +38,12 @@ public class OfflineAccountFactory extends AccountFactory { } @Override - public OfflineAccount create(CharacterSelector selector, String username, String password, Object additionalData, Proxy proxy) { + public OfflineAccount create(CharacterSelector selector, String username, String password, Object additionalData) { return new OfflineAccount(username, getUUIDFromUserName(username)); } @Override - public OfflineAccount fromStorage(Map storage, Proxy proxy) { + public OfflineAccount fromStorage(Map storage) { String username = tryCast(storage.get("username"), String.class) .orElseThrow(() -> new IllegalStateException("Offline account configuration malformed.")); UUID uuid = tryCast(storage.get("uuid"), String.class) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccount.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccount.java index 112bdfc3c..4d47c1f8f 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccount.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccount.java @@ -114,6 +114,7 @@ public class YggdrasilAccount extends Account { } this.characterUUID = this.session.getSelectedProfile().getId(); + invalidate(); } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccountFactory.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccountFactory.java index 3fb044793..77c557670 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccountFactory.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilAccountFactory.java @@ -22,7 +22,6 @@ import org.jackhuang.hmcl.auth.AuthenticationException; import org.jackhuang.hmcl.auth.CharacterSelector; import org.jackhuang.hmcl.util.UUIDTypeAdapter; -import java.net.Proxy; import java.util.Map; import java.util.Objects; import java.util.UUID; @@ -42,28 +41,26 @@ public class YggdrasilAccountFactory extends AccountFactory { } @Override - public YggdrasilAccount create(CharacterSelector selector, String username, String password, Object additionalData, Proxy proxy) throws AuthenticationException { + public YggdrasilAccount create(CharacterSelector selector, String username, String password, Object additionalData) throws AuthenticationException { Objects.requireNonNull(selector); Objects.requireNonNull(username); Objects.requireNonNull(password); - Objects.requireNonNull(proxy); - YggdrasilAccount account = new YggdrasilAccount(new YggdrasilService(provider, proxy), username, null, null); + YggdrasilAccount account = new YggdrasilAccount(new YggdrasilService(provider), username, null, null); account.logInWithPassword(password, selector); return account; } @Override - public YggdrasilAccount fromStorage(Map storage, Proxy proxy) { + public YggdrasilAccount fromStorage(Map storage) { Objects.requireNonNull(storage); - Objects.requireNonNull(proxy); YggdrasilSession session = YggdrasilSession.fromStorage(storage); String username = tryCast(storage.get("username"), String.class) .orElseThrow(() -> new IllegalArgumentException("storage does not have username")); - return new YggdrasilAccount(new YggdrasilService(provider, proxy), username, session.getSelectedProfile().getId(), session); + return new YggdrasilAccount(new YggdrasilService(provider), username, session.getSelectedProfile().getId(), session); } public static String randomToken() { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilService.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilService.java index 1f1c8cacd..a56483e46 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilService.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/yggdrasil/YggdrasilService.java @@ -9,7 +9,6 @@ import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.UUIDTypeAdapter; import java.io.IOException; -import java.net.Proxy; import java.net.URL; import java.util.*; @@ -21,15 +20,9 @@ import static org.jackhuang.hmcl.util.Pair.pair; public class YggdrasilService { private final YggdrasilProvider provider; - private final Proxy proxy; public YggdrasilService(YggdrasilProvider provider) { - this(provider, Proxy.NO_PROXY); - } - - public YggdrasilService(YggdrasilProvider provider, Proxy proxy) { this.provider = provider; - this.proxy = proxy; } public YggdrasilSession authenticate(String username, String password, String clientToken) throws AuthenticationException { @@ -155,7 +148,7 @@ public class YggdrasilService { private String request(URL url, Object payload) throws AuthenticationException { try { if (payload == null) - return NetworkUtils.doGet(url, proxy); + return NetworkUtils.doGet(url); else return NetworkUtils.doPost(url, payload instanceof String ? (String) payload : GSON.toJson(payload), "application/json"); } catch (IOException e) { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java index f86b080e1..b1297fecc 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java @@ -29,8 +29,6 @@ import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.task.ParallelTask; import org.jackhuang.hmcl.task.Task; -import java.net.Proxy; - /** * Note: This class has no state. * @@ -40,16 +38,10 @@ public class DefaultDependencyManager extends AbstractDependencyManager { private final DefaultGameRepository repository; private final DownloadProvider downloadProvider; - private final Proxy proxy; public DefaultDependencyManager(DefaultGameRepository repository, DownloadProvider downloadProvider) { - this(repository, downloadProvider, Proxy.NO_PROXY); - } - - public DefaultDependencyManager(DefaultGameRepository repository, DownloadProvider downloadProvider, Proxy proxy) { this.repository = repository; this.downloadProvider = downloadProvider; - this.proxy = proxy; } @Override @@ -62,11 +54,6 @@ public class DefaultDependencyManager extends AbstractDependencyManager { return downloadProvider; } - @Override - public Proxy getProxy() { - return proxy; - } - @Override public GameBuilder gameBuilder() { return new DefaultGameBuilder(this); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DependencyManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DependencyManager.java index 830b90314..c3b00047b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DependencyManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DependencyManager.java @@ -21,8 +21,6 @@ import org.jackhuang.hmcl.game.GameRepository; import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.task.Task; -import java.net.Proxy; - /** * Do everything that will connect to Internet. * Downloading Minecraft files. @@ -36,11 +34,6 @@ public interface DependencyManager { */ GameRepository getGameRepository(); - /** - * The proxy that all network operations should go through. - */ - Proxy getProxy(); - /** * Check if the game is complete. * Check libraries, assets, logging files and so on. diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetDownloadTask.java index 8f95de725..d60ecc76a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetDownloadTask.java @@ -53,7 +53,7 @@ public final class GameAssetDownloadTask extends Task { /** * Constructor. * - * @param dependencyManager the dependency manager that can provides proxy settings and {@link org.jackhuang.hmcl.game.GameRepository} + * @param dependencyManager the dependency manager that can provides {@link org.jackhuang.hmcl.game.GameRepository} * @param version the resolved version */ public GameAssetDownloadTask(AbstractDependencyManager dependencyManager, Version version) { @@ -107,7 +107,7 @@ public final class GameAssetDownloadTask extends Task { flag = !file.exists(); } if (flag) { - FileDownloadTask task = new FileDownloadTask(NetworkUtils.toURL(url), file, dependencyManager.getProxy(), new IntegrityCheck("SHA-1", assetObject.getHash())); + FileDownloadTask task = new FileDownloadTask(NetworkUtils.toURL(url), file, new IntegrityCheck("SHA-1", assetObject.getHash())); task.setName(assetObject.getHash()); dependencies.add(task); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetIndexDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetIndexDownloadTask.java index 9e1878024..0e05560f9 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetIndexDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetIndexDownloadTask.java @@ -44,7 +44,7 @@ public final class GameAssetIndexDownloadTask extends Task { /** * Constructor. * - * @param dependencyManager the dependency manager that can provides proxy settings and {@link org.jackhuang.hmcl.game.GameRepository} + * @param dependencyManager the dependency manager that can provides {@link org.jackhuang.hmcl.game.GameRepository} * @param version the resolved version */ public GameAssetIndexDownloadTask(AbstractDependencyManager dependencyManager, Version version) { @@ -67,7 +67,7 @@ public final class GameAssetIndexDownloadTask extends Task { File assetIndexFile = dependencyManager.getGameRepository().getIndexFile(version.getId(), assetIndexInfo.getId()); dependencies.add(new FileDownloadTask( NetworkUtils.toURL(dependencyManager.getDownloadProvider().injectURL(assetIndexInfo.getUrl())), - assetIndexFile, dependencyManager.getProxy() + assetIndexFile )); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetRefreshTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetRefreshTask.java index a7b34f51c..9b825a1d3 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetRefreshTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetRefreshTask.java @@ -51,7 +51,7 @@ public final class GameAssetRefreshTask extends TaskResultresolved version */ public GameAssetRefreshTask(AbstractDependencyManager dependencyManager, Version version) { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameDownloadTask.java index 9400f771f..7db56833c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameDownloadTask.java @@ -56,7 +56,6 @@ public final class GameDownloadTask extends Task { dependencies.add(new FileDownloadTask( NetworkUtils.toURL(dependencyManager.getDownloadProvider().injectURL(version.getDownloadInfo().getUrl())), jar, - dependencyManager.getProxy(), new IntegrityCheck("SHA-1", version.getDownloadInfo().getSha1()) )); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameLibrariesTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameLibrariesTask.java index 46baf515c..b667a8e73 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameLibrariesTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameLibrariesTask.java @@ -41,7 +41,7 @@ public final class GameLibrariesTask extends Task { /** * Constructor. * - * @param dependencyManager the dependency manager that can provides proxy settings and {@link org.jackhuang.hmcl.game.GameRepository} + * @param dependencyManager the dependency manager that can provides {@link org.jackhuang.hmcl.game.GameRepository} * @param version the resolved version */ public GameLibrariesTask(AbstractDependencyManager dependencyManager, Version version) { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameLoggingDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameLoggingDownloadTask.java index 981de53f0..895191020 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameLoggingDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameLoggingDownloadTask.java @@ -44,7 +44,7 @@ public final class GameLoggingDownloadTask extends Task { /** * Constructor. * - * @param dependencyManager the dependency manager that can provides proxy settings and {@link org.jackhuang.hmcl.game.GameRepository} + * @param dependencyManager the dependency manager that can provides {@link org.jackhuang.hmcl.game.GameRepository} * @param version the resolved version */ public GameLoggingDownloadTask(DependencyManager dependencyManager, Version version) { @@ -66,7 +66,7 @@ public final class GameLoggingDownloadTask extends Task { LoggingInfo logging = version.getLogging().get(DownloadType.CLIENT); File file = dependencyManager.getGameRepository().getLoggingObject(version.getId(), version.getAssetIndex().getId(), logging); if (!file.exists()) - dependencies.add(new FileDownloadTask(NetworkUtils.toURL(logging.getFile().getUrl()), file, dependencyManager.getProxy())); + dependencies.add(new FileDownloadTask(NetworkUtils.toURL(logging.getFile().getUrl()), file)); } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/LibraryDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/LibraryDownloadTask.java index e979f008f..67de5b5bf 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/LibraryDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/LibraryDownloadTask.java @@ -43,13 +43,13 @@ public final class LibraryDownloadTask extends Task { xzFile = new File(file.getAbsoluteFile().getParentFile(), file.getName() + ".pack.xz"); xzTask = new FileDownloadTask(NetworkUtils.toURL(url + ".pack.xz"), - xzFile, dependencyManager.getProxy(), null, 1); + xzFile, null, 1); xzTask.setSignificance(TaskSignificance.MINOR); setSignificance(TaskSignificance.MODERATE); task = new FileDownloadTask(NetworkUtils.toURL(url), - file, dependencyManager.getProxy(), + file, library.getDownload().getSha1() != null ? new IntegrityCheck("SHA-1", library.getDownload().getSha1()) : null); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonDownloadTask.java index ff660ba7d..061c393ca 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonDownloadTask.java @@ -24,7 +24,6 @@ import org.jackhuang.hmcl.task.GetTask; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.NetworkUtils; -import java.net.Proxy; import java.util.Collection; import java.util.LinkedList; import java.util.List; @@ -66,7 +65,7 @@ public final class VersionJsonDownloadTask extends Task { RemoteVersion remoteVersion = gameVersionList.getVersions(gameVersion).stream().findFirst() .orElseThrow(() -> new IllegalStateException("Cannot find specific version " + gameVersion + " in remote repository")); String jsonURL = dependencyManager.getDownloadProvider().injectURL(remoteVersion.getUrl()); - dependencies.add(new GetTask(NetworkUtils.toURL(jsonURL), Proxy.NO_PROXY, ID)); + dependencies.add(new GetTask(NetworkUtils.toURL(jsonURL), ID)); } public static final String ID = "raw_version_json"; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/CurseCompletionTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/CurseCompletionTask.java index da7f1b355..b915d83bd 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/CurseCompletionTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/CurseCompletionTask.java @@ -109,7 +109,7 @@ public final class CurseCompletionTask extends Task { updateProgress(finished.incrementAndGet(), manifest.getFiles().size()); if (StringUtils.isBlank(file.getFileName())) { try { - return file.withFileName(NetworkUtils.detectFileName(file.getUrl(), dependencyManager.getProxy())); + return file.withFileName(NetworkUtils.detectFileName(file.getUrl())); } catch (IOException ioe) { Logging.LOG.log(Level.WARNING, "Unable to fetch the file name of URL: " + file.getUrl(), ioe); flag.set(false); @@ -125,7 +125,7 @@ public final class CurseCompletionTask extends Task { if (StringUtils.isNotBlank(file.getFileName())) { File dest = new File(run, "mods/" + file.getFileName()); if (!dest.exists()) - dependencies.add(new FileDownloadTask(file.getUrl(), dest, dependencyManager.getProxy())); + dependencies.add(new FileDownloadTask(file.getUrl(), dest)); } // Let this task fail if the curse manifest has not been completed. diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java index 37f6aefc7..c3a5afe91 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java @@ -31,7 +31,6 @@ import java.io.InputStream; import java.io.RandomAccessFile; import java.math.BigInteger; import java.net.HttpURLConnection; -import java.net.Proxy; import java.net.URL; import java.security.MessageDigest; import java.util.logging.Level; @@ -79,7 +78,6 @@ public class FileDownloadTask extends Task { private final File file; private final IntegrityCheck integrityCheck; private final int retry; - private final Proxy proxy; private final EventManager> onFailed = new EventManager<>(); private RandomAccessFile rFile; private InputStream stream; @@ -89,26 +87,16 @@ public class FileDownloadTask extends Task { * @param file the location that download to. */ public FileDownloadTask(URL url, File file) { - this(url, file, Proxy.NO_PROXY); + this(url, file, null); } /** * @param url the URL of remote file. * @param file the location that download to. - * @param proxy the proxy. - */ - public FileDownloadTask(URL url, File file, Proxy proxy) { - this(url, file, proxy, null); - } - - /** - * @param url the URL of remote file. - * @param file the location that download to. - * @param proxy the proxy. * @param integrityCheck the integrity check to perform, null if no integrity check is to be performed */ - public FileDownloadTask(URL url, File file, Proxy proxy, IntegrityCheck integrityCheck) { - this(url, file, proxy, integrityCheck, 5); + public FileDownloadTask(URL url, File file, IntegrityCheck integrityCheck) { + this(url, file, integrityCheck, 5); } /** @@ -116,14 +104,12 @@ public class FileDownloadTask extends Task { * @param file the location that download to. * @param integrityCheck the integrity check to perform, null if no integrity check is to be performed * @param retry the times for retrying if downloading fails. - * @param proxy the proxy. */ - public FileDownloadTask(URL url, File file, Proxy proxy, IntegrityCheck integrityCheck, int retry) { + public FileDownloadTask(URL url, File file, IntegrityCheck integrityCheck, int retry) { this.url = url; this.file = file; this.integrityCheck = integrityCheck; this.retry = retry; - this.proxy = proxy; setName(file.getName()); } @@ -174,7 +160,7 @@ public class FileDownloadTask extends Task { try { updateProgress(0); - HttpURLConnection con = NetworkUtils.createConnection(url, proxy); + HttpURLConnection con = NetworkUtils.createConnection(url); con.connect(); if (con.getResponseCode() / 100 != 2) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.java index 4e8ff1b70..c74b2fbf7 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.java @@ -25,7 +25,6 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; -import java.net.Proxy; import java.net.URL; import java.nio.charset.Charset; import java.util.logging.Level; @@ -41,30 +40,24 @@ public final class GetTask extends TaskResult { private final URL url; private final Charset charset; private final int retry; - private final Proxy proxy; private final String id; public GetTask(URL url) { - this(url, Proxy.NO_PROXY); + this(url, ID); } - public GetTask(URL url, Proxy proxy) { - this(url, proxy, ID); + public GetTask(URL url, String id) { + this(url, id, UTF_8); } - public GetTask(URL url, Proxy proxy, String id) { - this(url, proxy, id, UTF_8); + public GetTask(URL url, String id, Charset charset) { + this(url, id, charset, 5); } - public GetTask(URL url, Proxy proxy, String id, Charset charset) { - this(url, proxy, id, charset, 5); - } - - public GetTask(URL url, Proxy proxy, String id, Charset charset, int retry) { + public GetTask(URL url, String id, Charset charset, int retry) { this.url = url; this.charset = charset; this.retry = retry; - this.proxy = proxy; this.id = id; setName(url.toString()); @@ -88,7 +81,7 @@ public final class GetTask extends TaskResult { Logging.LOG.log(Level.WARNING, "Failed to download, repeat times: " + time); try { updateProgress(0); - HttpURLConnection conn = NetworkUtils.createConnection(url, proxy); + HttpURLConnection conn = NetworkUtils.createConnection(url); InputStream input = conn.getInputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buf = new byte[IOUtils.DEFAULT_BUFFER_SIZE]; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/EnumOrdinalDeserializer.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/EnumOrdinalDeserializer.java new file mode 100644 index 000000000..e1c3cc95b --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/EnumOrdinalDeserializer.java @@ -0,0 +1,63 @@ +/* + * Hello Minecraft! Launcher. + * Copyright (C) 2018 huangyuhui + * + * 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 java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.annotations.SerializedName; + +/** + * A deserializer that supports deserializing strings and **numbers** into enums. + * + * @author yushijinhun + */ +public class EnumOrdinalDeserializer> implements JsonDeserializer { + + private Map mapping = new HashMap<>(); + + public EnumOrdinalDeserializer(Class enumClass) { + for (T constant : enumClass.getEnumConstants()) { + mapping.put(String.valueOf(constant.ordinal()), constant); + String name = constant.name(); + try { + SerializedName annotation = enumClass.getField(name).getAnnotation(SerializedName.class); + if (annotation != null) { + name = annotation.value(); + for (String alternate : annotation.alternate()) { + mapping.put(alternate, constant); + } + } + } catch (NoSuchFieldException e) { + throw new AssertionError(e); + } + mapping.put(name, constant); + } + } + + @Override + public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + return mapping.get(json.getAsString()); + } + +} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/NetworkUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/NetworkUtils.java index 8323e2586..91fecb24f 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/NetworkUtils.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/NetworkUtils.java @@ -48,8 +48,8 @@ public final class NetworkUtils { NetworkUtils.userAgentSupplier = Objects.requireNonNull(userAgentSupplier); } - public static HttpURLConnection createConnection(URL url, Proxy proxy) throws IOException { - HttpURLConnection connection = (HttpURLConnection) url.openConnection(proxy); + public static HttpURLConnection createConnection(URL url) throws IOException { + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setDoInput(true); connection.setUseCaches(false); connection.setConnectTimeout(15000); @@ -59,11 +59,7 @@ public final class NetworkUtils { } public static String doGet(URL url) throws IOException { - return IOUtils.readFullyAsString(createConnection(url, Proxy.NO_PROXY).getInputStream()); - } - - public static String doGet(URL url, Proxy proxy) throws IOException { - return IOUtils.readFullyAsString(createConnection(url, proxy).getInputStream()); + return IOUtils.readFullyAsString(createConnection(url).getInputStream()); } public static String doPost(URL u, Map params) throws IOException { @@ -80,14 +76,10 @@ public final class NetworkUtils { return doPost(u, post, "application/x-www-form-urlencoded"); } - public static String doPost(URL u, String post, String contentType) throws IOException { - return doPost(u, post, contentType, Proxy.NO_PROXY); - } - - public static String doPost(URL url, String post, String contentType, Proxy proxy) throws IOException { + public static String doPost(URL url, String post, String contentType) throws IOException { byte[] bytes = post.getBytes(UTF_8); - HttpURLConnection con = createConnection(url, proxy); + HttpURLConnection con = createConnection(url); con.setRequestMethod("POST"); con.setDoOutput(true); con.setRequestProperty("Content-Type", contentType + "; charset=utf-8"); @@ -120,11 +112,7 @@ public final class NetworkUtils { } public static String detectFileName(URL url) throws IOException { - return detectFileName(url, Proxy.NO_PROXY); - } - - public static String detectFileName(URL url, Proxy proxy) throws IOException { - HttpURLConnection conn = createConnection(url, proxy); + HttpURLConnection conn = createConnection(url); conn.connect(); if (conn.getResponseCode() / 100 != 2) throw new IOException("Response code " + conn.getResponseCode()); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ObservableHelper.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ObservableHelper.java new file mode 100644 index 000000000..ba5a9a882 --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ObservableHelper.java @@ -0,0 +1,69 @@ +/* + * Hello Minecraft! Launcher. + * Copyright (C) 2018 huangyuhui + * + * 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 java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +import javafx.beans.InvalidationListener; +import javafx.beans.Observable; + +/** + * Helper class for implementing {@link Observable}. + * + * @author yushijinhun + */ +public class ObservableHelper implements Observable, InvalidationListener { + + private List listeners = new CopyOnWriteArrayList<>(); + private Observable source; + + public ObservableHelper(Observable source) { + this.source = source; + } + + /** + * This method can be called from any thread. + */ + @Override + public void addListener(InvalidationListener listener) { + listeners.add(listener); + } + + /** + * This method can be called from any thread. + */ + @Override + public void removeListener(InvalidationListener listener) { + listeners.remove(listener); + } + + public void invalidate() { + listeners.forEach(it -> it.invalidated(source)); + } + + @Override + public void invalidated(Observable observable) { + this.invalidate(); + } + + public void receiveUpdatesFrom(Observable observable) { + observable.removeListener(this); // remove the previously added listener(if any) + observable.addListener(this); + } +}