Merge pull request #351 from yushijinhun/refactor-yggdrasil
authlib-injector 部分重构
This commit is contained in:
@@ -23,6 +23,7 @@ import org.jackhuang.hmcl.auth.AccountFactory;
|
|||||||
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount;
|
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount;
|
||||||
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccountFactory;
|
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccountFactory;
|
||||||
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorBuildInfo;
|
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorBuildInfo;
|
||||||
|
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer;
|
||||||
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServerResponse;
|
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServerResponse;
|
||||||
import org.jackhuang.hmcl.auth.offline.OfflineAccount;
|
import org.jackhuang.hmcl.auth.offline.OfflineAccount;
|
||||||
import org.jackhuang.hmcl.auth.offline.OfflineAccountFactory;
|
import org.jackhuang.hmcl.auth.offline.OfflineAccountFactory;
|
||||||
@@ -30,8 +31,6 @@ import org.jackhuang.hmcl.auth.yggdrasil.MojangYggdrasilProvider;
|
|||||||
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount;
|
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount;
|
||||||
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccountFactory;
|
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccountFactory;
|
||||||
import org.jackhuang.hmcl.task.FileDownloadTask;
|
import org.jackhuang.hmcl.task.FileDownloadTask;
|
||||||
import org.jackhuang.hmcl.task.Task;
|
|
||||||
import org.jackhuang.hmcl.task.TaskResult;
|
|
||||||
import org.jackhuang.hmcl.util.Constants;
|
import org.jackhuang.hmcl.util.Constants;
|
||||||
import org.jackhuang.hmcl.util.FileUtils;
|
import org.jackhuang.hmcl.util.FileUtils;
|
||||||
import org.jackhuang.hmcl.util.NetworkUtils;
|
import org.jackhuang.hmcl.util.NetworkUtils;
|
||||||
@@ -41,8 +40,10 @@ import java.io.IOException;
|
|||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import static org.jackhuang.hmcl.util.Lang.mapOf;
|
import static org.jackhuang.hmcl.util.Lang.mapOf;
|
||||||
|
import static org.jackhuang.hmcl.util.Logging.LOG;
|
||||||
import static org.jackhuang.hmcl.util.Pair.pair;
|
import static org.jackhuang.hmcl.util.Pair.pair;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -58,7 +59,7 @@ public final class Accounts {
|
|||||||
public static final Map<String, AccountFactory<?>> ACCOUNT_FACTORY = mapOf(
|
public static final Map<String, AccountFactory<?>> ACCOUNT_FACTORY = mapOf(
|
||||||
pair(OFFLINE_ACCOUNT_KEY, OfflineAccountFactory.INSTANCE),
|
pair(OFFLINE_ACCOUNT_KEY, OfflineAccountFactory.INSTANCE),
|
||||||
pair(YGGDRASIL_ACCOUNT_KEY, new YggdrasilAccountFactory(MojangYggdrasilProvider.INSTANCE)),
|
pair(YGGDRASIL_ACCOUNT_KEY, new YggdrasilAccountFactory(MojangYggdrasilProvider.INSTANCE)),
|
||||||
pair(AUTHLIB_INJECTOR_ACCOUNT_KEY, new AuthlibInjectorAccountFactory(Accounts::downloadAuthlibInjector))
|
pair(AUTHLIB_INJECTOR_ACCOUNT_KEY, new AuthlibInjectorAccountFactory(Accounts::downloadAuthlibInjector, Accounts::getOrCreateAuthlibInjectorServer))
|
||||||
);
|
);
|
||||||
|
|
||||||
private static final Map<String, String> AUTHLIB_INJECTOR_SERVER_NAMES = new HashMap<>();
|
private static final Map<String, String> AUTHLIB_INJECTOR_SERVER_NAMES = new HashMap<>();
|
||||||
@@ -104,7 +105,23 @@ public final class Accounts {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TaskResult<String> getAuthlibInjectorServerNameAsync(AuthlibInjectorAccount account) {
|
private static AuthlibInjectorServer getOrCreateAuthlibInjectorServer(String url) {
|
||||||
return Task.ofResult("serverName", () -> Accounts.getAuthlibInjectorServerName(account.getServerBaseURL()));
|
return Settings.SETTINGS.authlibInjectorServers.stream()
|
||||||
|
.filter(server -> url.equals(server.getUrl()))
|
||||||
|
.findFirst()
|
||||||
|
.orElseGet(() -> {
|
||||||
|
// this usually happens when migrating data from an older version
|
||||||
|
String name;
|
||||||
|
try {
|
||||||
|
name = Accounts.getAuthlibInjectorServerName(url);
|
||||||
|
LOG.info("Migrated authlib injector server [" + url + "], name=[" + name + "]");
|
||||||
|
} catch (Exception e) {
|
||||||
|
name = url;
|
||||||
|
LOG.log(Level.WARNING, "Failed to migrate authlib injector server [" + url + "]", e);
|
||||||
|
}
|
||||||
|
AuthlibInjectorServer server = new AuthlibInjectorServer(url, name);
|
||||||
|
Settings.SETTINGS.authlibInjectorServers.add(server);
|
||||||
|
return server;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,11 +17,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.setting;
|
package org.jackhuang.hmcl.setting;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import org.jackhuang.hmcl.Launcher;
|
import org.jackhuang.hmcl.Launcher;
|
||||||
|
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer;
|
||||||
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
import javafx.beans.property.BooleanProperty;
|
import javafx.beans.property.BooleanProperty;
|
||||||
@@ -35,7 +36,6 @@ import javafx.beans.property.StringProperty;
|
|||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.collections.ObservableMap;
|
import javafx.collections.ObservableMap;
|
||||||
import javafx.collections.ObservableSet;
|
|
||||||
|
|
||||||
public final class Config implements Cloneable {
|
public final class Config implements Cloneable {
|
||||||
|
|
||||||
@@ -99,8 +99,7 @@ public final class Config implements Cloneable {
|
|||||||
@SerializedName("logLines")
|
@SerializedName("logLines")
|
||||||
public final IntegerProperty logLines = new SimpleIntegerProperty(100);
|
public final IntegerProperty logLines = new SimpleIntegerProperty(100);
|
||||||
|
|
||||||
@SerializedName("authlibInjectorServerURLs")
|
public final ObservableList<AuthlibInjectorServer> authlibInjectorServers = FXCollections.observableArrayList();
|
||||||
public final ObservableSet<String> authlibInjectorServerURLs = FXCollections.observableSet(new HashSet<>());
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Config clone() {
|
public Config clone() {
|
||||||
|
|||||||
@@ -20,14 +20,18 @@ package org.jackhuang.hmcl.setting;
|
|||||||
import org.jackhuang.hmcl.Launcher;
|
import org.jackhuang.hmcl.Launcher;
|
||||||
|
|
||||||
public final class Profiles {
|
public final class Profiles {
|
||||||
|
|
||||||
|
public static final String DEFAULT_PROFILE = "Default";
|
||||||
|
public static final String HOME_PROFILE = "Home";
|
||||||
|
|
||||||
private Profiles() {
|
private Profiles() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getProfileDisplayName(Profile profile) {
|
public static String getProfileDisplayName(Profile profile) {
|
||||||
switch (profile.getName()) {
|
switch (profile.getName()) {
|
||||||
case Settings.DEFAULT_PROFILE:
|
case Profiles.DEFAULT_PROFILE:
|
||||||
return Launcher.i18n("profile.default");
|
return Launcher.i18n("profile.default");
|
||||||
case Settings.HOME_PROFILE:
|
case Profiles.HOME_PROFILE:
|
||||||
return Launcher.i18n("profile.home");
|
return Launcher.i18n("profile.home");
|
||||||
default:
|
default:
|
||||||
return profile.getName();
|
return profile.getName();
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package org.jackhuang.hmcl.setting;
|
|||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
|
|
||||||
import javafx.beans.property.ObjectProperty;
|
import javafx.beans.property.ObjectProperty;
|
||||||
import javafx.beans.property.StringProperty;
|
import javafx.beans.property.StringProperty;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
@@ -35,6 +36,7 @@ import org.jackhuang.hmcl.Launcher;
|
|||||||
import org.jackhuang.hmcl.auth.Account;
|
import org.jackhuang.hmcl.auth.Account;
|
||||||
import org.jackhuang.hmcl.auth.AccountFactory;
|
import org.jackhuang.hmcl.auth.AccountFactory;
|
||||||
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount;
|
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount;
|
||||||
|
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer;
|
||||||
import org.jackhuang.hmcl.download.DownloadProvider;
|
import org.jackhuang.hmcl.download.DownloadProvider;
|
||||||
import org.jackhuang.hmcl.event.*;
|
import org.jackhuang.hmcl.event.*;
|
||||||
import org.jackhuang.hmcl.task.Schedulers;
|
import org.jackhuang.hmcl.task.Schedulers;
|
||||||
@@ -51,7 +53,10 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static java.util.stream.Collectors.toList;
|
||||||
|
import static org.jackhuang.hmcl.ui.FXUtils.onInvalidating;
|
||||||
import static org.jackhuang.hmcl.util.Lang.tryCast;
|
import static org.jackhuang.hmcl.util.Lang.tryCast;
|
||||||
|
import static org.jackhuang.hmcl.util.Logging.LOG;
|
||||||
|
|
||||||
public class Settings {
|
public class Settings {
|
||||||
public static final Gson GSON = new GsonBuilder()
|
public static final Gson GSON = new GsonBuilder()
|
||||||
@@ -65,15 +70,12 @@ public class Settings {
|
|||||||
.setPrettyPrinting()
|
.setPrettyPrinting()
|
||||||
.create();
|
.create();
|
||||||
|
|
||||||
public static final String DEFAULT_PROFILE = "Default";
|
|
||||||
public static final String HOME_PROFILE = "Home";
|
|
||||||
|
|
||||||
public static final String SETTINGS_FILE_NAME = "hmcl.json";
|
public static final String SETTINGS_FILE_NAME = "hmcl.json";
|
||||||
public static final File SETTINGS_FILE = new File(SETTINGS_FILE_NAME).getAbsoluteFile();
|
public static final File SETTINGS_FILE = new File(SETTINGS_FILE_NAME).getAbsoluteFile();
|
||||||
|
|
||||||
public static final Settings INSTANCE = new Settings();
|
public static final Config SETTINGS = initSettings();
|
||||||
|
|
||||||
private final Config SETTINGS = initSettings();
|
public static final Settings INSTANCE = new Settings();
|
||||||
|
|
||||||
private final Map<String, Account> accounts = new ConcurrentHashMap<>();
|
private final Map<String, Account> accounts = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@@ -84,7 +86,7 @@ public class Settings {
|
|||||||
Map<Object, Object> settings = iterator.next();
|
Map<Object, Object> settings = iterator.next();
|
||||||
AccountFactory<?> factory = Accounts.ACCOUNT_FACTORY.get(tryCast(settings.get("type"), String.class).orElse(""));
|
AccountFactory<?> factory = Accounts.ACCOUNT_FACTORY.get(tryCast(settings.get("type"), String.class).orElse(""));
|
||||||
if (factory == null) {
|
if (factory == null) {
|
||||||
// unrecognized account type, so remove it.
|
LOG.warning("Unrecognized account type, removing: " + settings);
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -93,7 +95,7 @@ public class Settings {
|
|||||||
try {
|
try {
|
||||||
account = factory.fromStorage(settings, getProxy());
|
account = factory.fromStorage(settings, getProxy());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// storage is malformed, delete.
|
LOG.log(Level.WARNING, "Malformed account storage, removing: " + settings, e);
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -101,7 +103,8 @@ public class Settings {
|
|||||||
accounts.put(Accounts.getAccountId(account), account);
|
accounts.put(Accounts.getAccountId(account), account);
|
||||||
}
|
}
|
||||||
|
|
||||||
checkAuthlibInjectorAccounts();
|
SETTINGS.authlibInjectorServers.addListener(onInvalidating(this::removeDanglingAuthlibInjectorAccounts));
|
||||||
|
|
||||||
checkProfileMap();
|
checkProfileMap();
|
||||||
|
|
||||||
save();
|
save();
|
||||||
@@ -115,7 +118,7 @@ public class Settings {
|
|||||||
Lang.ignoringException(() -> Runtime.getRuntime().addShutdownHook(new Thread(this::save)));
|
Lang.ignoringException(() -> Runtime.getRuntime().addShutdownHook(new Thread(this::save)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Config initSettings() {
|
private static Config initSettings() {
|
||||||
Config c = new Config();
|
Config c = new Config();
|
||||||
if (SETTINGS_FILE.exists())
|
if (SETTINGS_FILE.exists())
|
||||||
try {
|
try {
|
||||||
@@ -305,30 +308,17 @@ public class Settings {
|
|||||||
* AUTHLIB INJECTORS *
|
* AUTHLIB INJECTORS *
|
||||||
****************************************/
|
****************************************/
|
||||||
|
|
||||||
public Set<String> getAuthlibInjectorServerURLs() {
|
/**
|
||||||
return SETTINGS.authlibInjectorServerURLs;
|
* After an {@link AuthlibInjectorServer} is removed, the associated accounts should also be removed.
|
||||||
}
|
* This method performs a check and removes the dangling accounts.
|
||||||
|
* Don't call this before {@link #migrateAuthlibInjectorServers()} is called, otherwise old data would be lost.
|
||||||
public void removeAuthlibInjectorServerURL(String serverURL) {
|
*/
|
||||||
SETTINGS.authlibInjectorServerURLs.remove(serverURL);
|
private void removeDanglingAuthlibInjectorAccounts() {
|
||||||
|
accounts.values().stream()
|
||||||
checkAuthlibInjectorAccounts();
|
.filter(AuthlibInjectorAccount.class::isInstance)
|
||||||
save();
|
.filter(it -> !SETTINGS.authlibInjectorServers.contains(((AuthlibInjectorAccount) it).getServer()))
|
||||||
}
|
.collect(toList())
|
||||||
|
.forEach(this::deleteAccount);
|
||||||
public void addAuthlibInjectorServerURL(String serverURL) {
|
|
||||||
SETTINGS.authlibInjectorServerURLs.add(serverURL);
|
|
||||||
save();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkAuthlibInjectorAccounts() {
|
|
||||||
for (Account account : getAccounts()) {
|
|
||||||
if (account instanceof AuthlibInjectorAccount) {
|
|
||||||
AuthlibInjectorAccount injectorAccount = (AuthlibInjectorAccount) account;
|
|
||||||
if (!SETTINGS.authlibInjectorServerURLs.contains(injectorAccount.getServerBaseURL()))
|
|
||||||
deleteAccount(account);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************
|
/****************************************
|
||||||
@@ -561,8 +551,8 @@ public class Settings {
|
|||||||
|
|
||||||
private void checkProfileMap() {
|
private void checkProfileMap() {
|
||||||
if (getProfileMap().isEmpty()) {
|
if (getProfileMap().isEmpty()) {
|
||||||
getProfileMap().put(DEFAULT_PROFILE, new Profile(DEFAULT_PROFILE));
|
getProfileMap().put(Profiles.DEFAULT_PROFILE, new Profile(Profiles.DEFAULT_PROFILE));
|
||||||
getProfileMap().put(HOME_PROFILE, new Profile(HOME_PROFILE, Launcher.MINECRAFT_DIRECTORY));
|
getProfileMap().put(Profiles.HOME_PROFILE, new Profile(Profiles.HOME_PROFILE, Launcher.MINECRAFT_DIRECTORY));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount;
|
|||||||
import org.jackhuang.hmcl.auth.offline.OfflineAccount;
|
import org.jackhuang.hmcl.auth.offline.OfflineAccount;
|
||||||
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount;
|
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount;
|
||||||
import org.jackhuang.hmcl.game.AccountHelper;
|
import org.jackhuang.hmcl.game.AccountHelper;
|
||||||
import org.jackhuang.hmcl.setting.Accounts;
|
|
||||||
import org.jackhuang.hmcl.setting.Settings;
|
import org.jackhuang.hmcl.setting.Settings;
|
||||||
import org.jackhuang.hmcl.setting.Theme;
|
import org.jackhuang.hmcl.setting.Theme;
|
||||||
import org.jackhuang.hmcl.task.Schedulers;
|
import org.jackhuang.hmcl.task.Schedulers;
|
||||||
@@ -80,8 +79,7 @@ public class AccountPage extends StackPane implements DecoratorPage {
|
|||||||
|
|
||||||
FXUtils.setLimitWidth(this, 300);
|
FXUtils.setLimitWidth(this, 300);
|
||||||
if (account instanceof AuthlibInjectorAccount) {
|
if (account instanceof AuthlibInjectorAccount) {
|
||||||
Accounts.getAuthlibInjectorServerNameAsync((AuthlibInjectorAccount) account)
|
lblServer.setText(((AuthlibInjectorAccount) account).getServer().getName());
|
||||||
.subscribe(Schedulers.javafx(), variables -> lblServer.setText(variables.get("serverName")));
|
|
||||||
FXUtils.setLimitHeight(this, 182);
|
FXUtils.setLimitHeight(this, 182);
|
||||||
} else {
|
} else {
|
||||||
componentList.removeChildren(paneServer);
|
componentList.removeChildren(paneServer);
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import javafx.scene.layout.StackPane;
|
|||||||
import org.jackhuang.hmcl.Launcher;
|
import org.jackhuang.hmcl.Launcher;
|
||||||
import org.jackhuang.hmcl.auth.*;
|
import org.jackhuang.hmcl.auth.*;
|
||||||
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount;
|
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount;
|
||||||
|
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer;
|
||||||
import org.jackhuang.hmcl.auth.offline.OfflineAccount;
|
import org.jackhuang.hmcl.auth.offline.OfflineAccount;
|
||||||
import org.jackhuang.hmcl.auth.yggdrasil.GameProfile;
|
import org.jackhuang.hmcl.auth.yggdrasil.GameProfile;
|
||||||
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount;
|
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount;
|
||||||
@@ -46,16 +47,17 @@ import org.jackhuang.hmcl.ui.animation.TransitionHandler;
|
|||||||
import org.jackhuang.hmcl.ui.construct.AdvancedListBox;
|
import org.jackhuang.hmcl.ui.construct.AdvancedListBox;
|
||||||
import org.jackhuang.hmcl.ui.construct.IconedItem;
|
import org.jackhuang.hmcl.ui.construct.IconedItem;
|
||||||
import org.jackhuang.hmcl.ui.construct.Validator;
|
import org.jackhuang.hmcl.ui.construct.Validator;
|
||||||
|
import org.jackhuang.hmcl.util.Constants;
|
||||||
import org.jackhuang.hmcl.util.Logging;
|
import org.jackhuang.hmcl.util.Logging;
|
||||||
|
|
||||||
import java.util.Collection;
|
import static org.jackhuang.hmcl.ui.FXUtils.jfxListCellFactory;
|
||||||
|
import static org.jackhuang.hmcl.ui.FXUtils.stringConverter;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
public class AddAccountPane extends StackPane {
|
public class AddAccountPane extends StackPane {
|
||||||
|
|
||||||
@@ -64,7 +66,7 @@ public class AddAccountPane extends StackPane {
|
|||||||
@FXML private Label lblCreationWarning;
|
@FXML private Label lblCreationWarning;
|
||||||
@FXML private Label lblPassword;
|
@FXML private Label lblPassword;
|
||||||
@FXML private JFXComboBox<String> cboType;
|
@FXML private JFXComboBox<String> cboType;
|
||||||
@FXML private JFXComboBox<TwoLineListItem> cboServers;
|
@FXML private JFXComboBox<AuthlibInjectorServer> cboServers;
|
||||||
@FXML private Label lblInjectorServer;
|
@FXML private Label lblInjectorServer;
|
||||||
@FXML private Hyperlink linkManageInjectorServers;
|
@FXML private Hyperlink linkManageInjectorServers;
|
||||||
@FXML private JFXDialogLayout layout;
|
@FXML private JFXDialogLayout layout;
|
||||||
@@ -82,7 +84,13 @@ public class AddAccountPane extends StackPane {
|
|||||||
transitionHandler = new TransitionHandler(acceptPane);
|
transitionHandler = new TransitionHandler(acceptPane);
|
||||||
acceptPane.getChildren().setAll(btnAccept);
|
acceptPane.getChildren().setAll(btnAccept);
|
||||||
|
|
||||||
loadServers();
|
cboServers.setCellFactory(jfxListCellFactory(server -> new TwoLineListItem(server.getName(), server.getUrl())));
|
||||||
|
cboServers.setConverter(stringConverter(AuthlibInjectorServer::getName));
|
||||||
|
cboServers.setItems(Settings.INSTANCE.SETTINGS.authlibInjectorServers);
|
||||||
|
|
||||||
|
// workaround: otherwise the combox will be black
|
||||||
|
if (!cboServers.getItems().isEmpty())
|
||||||
|
cboServers.getSelectionModel().select(0);
|
||||||
|
|
||||||
cboType.getItems().setAll(Launcher.i18n("account.methods.offline"), Launcher.i18n("account.methods.yggdrasil"), Launcher.i18n("account.methods.authlib_injector"));
|
cboType.getItems().setAll(Launcher.i18n("account.methods.offline"), Launcher.i18n("account.methods.yggdrasil"), Launcher.i18n("account.methods.authlib_injector"));
|
||||||
cboType.getSelectionModel().selectedIndexProperty().addListener((a, b, newValue) -> {
|
cboType.getSelectionModel().selectedIndexProperty().addListener((a, b, newValue) -> {
|
||||||
@@ -95,10 +103,6 @@ public class AddAccountPane extends StackPane {
|
|||||||
});
|
});
|
||||||
cboType.getSelectionModel().select(0);
|
cboType.getSelectionModel().select(0);
|
||||||
|
|
||||||
// These two lines can eliminate black, don't know why.
|
|
||||||
cboServers.getItems().setAll(new TwoLineListItem("", ""));
|
|
||||||
cboServers.getSelectionModel().select(0);
|
|
||||||
|
|
||||||
txtPassword.setOnAction(e -> onCreationAccept());
|
txtPassword.setOnAction(e -> onCreationAccept());
|
||||||
txtUsername.setOnAction(e -> onCreationAccept());
|
txtUsername.setOnAction(e -> onCreationAccept());
|
||||||
txtUsername.getValidators().add(new Validator(Launcher.i18n("input.email"), str -> !txtPassword.isVisible() || str.contains("@")));
|
txtUsername.getValidators().add(new Validator(Launcher.i18n("input.email"), str -> !txtPassword.isVisible() || str.contains("@")));
|
||||||
@@ -111,24 +115,6 @@ public class AddAccountPane extends StackPane {
|
|||||||
btnAccept.setDisable(!txtUsername.validate() || (cboType.getSelectionModel().getSelectedIndex() != 0 && !txtPassword.validate()));
|
btnAccept.setDisable(!txtUsername.validate() || (cboType.getSelectionModel().getSelectedIndex() != 0 && !txtPassword.validate()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadServers() {
|
|
||||||
Task.ofResult("list", () -> Settings.INSTANCE.getAuthlibInjectorServerURLs().parallelStream()
|
|
||||||
.flatMap(serverURL -> {
|
|
||||||
try {
|
|
||||||
return Stream.of(new TwoLineListItem(Accounts.getAuthlibInjectorServerName(serverURL), serverURL));
|
|
||||||
} catch (Exception e) {
|
|
||||||
Logging.LOG.log(Level.WARNING, "Authlib-injector server root " + serverURL + " cannot be recognized.", e);
|
|
||||||
return Stream.empty();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect(Collectors.toList()))
|
|
||||||
.subscribe(Task.of(Schedulers.javafx(), variables -> {
|
|
||||||
cboServers.getItems().setAll(variables.<Collection<TwoLineListItem>>get("list"));
|
|
||||||
if (!cboServers.getItems().isEmpty())
|
|
||||||
cboServers.getSelectionModel().select(0);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showSpinner() {
|
private void showSpinner() {
|
||||||
transitionHandler.setContent(spinnerAccept, ContainerAnimations.FADE.getAnimationProducer());
|
transitionHandler.setContent(spinnerAccept, ContainerAnimations.FADE.getAnimationProducer());
|
||||||
}
|
}
|
||||||
@@ -139,34 +125,51 @@ public class AddAccountPane extends StackPane {
|
|||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private void onCreationAccept() {
|
private void onCreationAccept() {
|
||||||
int type = cboType.getSelectionModel().getSelectedIndex();
|
|
||||||
String username = txtUsername.getText();
|
String username = txtUsername.getText();
|
||||||
String password = txtPassword.getText();
|
String password = txtPassword.getText();
|
||||||
String apiRoot = Optional.ofNullable(cboServers.getSelectionModel().getSelectedItem()).map(TwoLineListItem::getSubtitle).orElse(null);
|
Object addtionalData;
|
||||||
|
|
||||||
|
int type = cboType.getSelectionModel().getSelectedIndex();
|
||||||
|
AccountFactory<?> factory;
|
||||||
|
switch (type) {
|
||||||
|
case 0:
|
||||||
|
factory = Accounts.ACCOUNT_FACTORY.get(Accounts.OFFLINE_ACCOUNT_KEY);
|
||||||
|
addtionalData = null;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
factory = Accounts.ACCOUNT_FACTORY.get(Accounts.YGGDRASIL_ACCOUNT_KEY);
|
||||||
|
addtionalData = null;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
factory = Accounts.ACCOUNT_FACTORY.get(Accounts.AUTHLIB_INJECTOR_ACCOUNT_KEY);
|
||||||
|
Optional<AuthlibInjectorServer> server = Optional.ofNullable(cboServers.getSelectionModel().getSelectedItem());
|
||||||
|
if (server.isPresent()) {
|
||||||
|
addtionalData = server.get();
|
||||||
|
} else {
|
||||||
|
lblCreationWarning.setText(Launcher.i18n("account.failed.no_selected_server"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
|
|
||||||
showSpinner();
|
showSpinner();
|
||||||
lblCreationWarning.setText("");
|
lblCreationWarning.setText("");
|
||||||
Task.ofResult("create_account", () -> {
|
|
||||||
AccountFactory<?> factory;
|
|
||||||
switch (type) {
|
|
||||||
case 0: factory = Accounts.ACCOUNT_FACTORY.get(Accounts.OFFLINE_ACCOUNT_KEY); break;
|
|
||||||
case 1: factory = Accounts.ACCOUNT_FACTORY.get(Accounts.YGGDRASIL_ACCOUNT_KEY); break;
|
|
||||||
case 2: factory = Accounts.ACCOUNT_FACTORY.get(Accounts.AUTHLIB_INJECTOR_ACCOUNT_KEY); break;
|
|
||||||
default: throw new Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
return factory.create(new Selector(), username, password, apiRoot, Settings.INSTANCE.getProxy());
|
Task.ofResult("create_account", () -> factory.create(new Selector(), username, password, addtionalData, Settings.INSTANCE.getProxy()))
|
||||||
}).finalized(Schedulers.javafx(), variables -> {
|
.finalized(Schedulers.javafx(), variables -> {
|
||||||
Settings.INSTANCE.addAccount(variables.get("create_account"));
|
Settings.INSTANCE.addAccount(variables.get("create_account"));
|
||||||
hideSpinner();
|
hideSpinner();
|
||||||
finalization.accept(this);
|
finalization.accept(this);
|
||||||
}, exception -> {
|
}, exception -> {
|
||||||
if (exception instanceof NoSelectedCharacterException) {
|
if (exception instanceof NoSelectedCharacterException) {
|
||||||
finalization.accept(this);
|
finalization.accept(this);
|
||||||
} else {
|
} else {
|
||||||
lblCreationWarning.setText(accountException(exception));
|
lblCreationWarning.setText(accountException(exception));
|
||||||
}
|
}
|
||||||
hideSpinner();
|
hideSpinner();
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
@@ -224,13 +227,13 @@ public class AddAccountPane extends StackPane {
|
|||||||
image = AccountHelper.getSkinImmediately(yggdrasilAccount, profile, 4, Settings.INSTANCE.getProxy());
|
image = AccountHelper.getSkinImmediately(yggdrasilAccount, profile, 4, Settings.INSTANCE.getProxy());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Logging.LOG.log(Level.WARNING, "Failed to get skin for " + profile.getName(), e);
|
Logging.LOG.log(Level.WARNING, "Failed to get skin for " + profile.getName(), e);
|
||||||
image = FXUtils.DEFAULT_ICON;
|
image = null;
|
||||||
}
|
}
|
||||||
ImageView portraitView = new ImageView();
|
ImageView portraitView = new ImageView();
|
||||||
portraitView.setSmooth(false);
|
portraitView.setSmooth(false);
|
||||||
if (image == FXUtils.DEFAULT_ICON)
|
if (image == null) {
|
||||||
portraitView.setImage(FXUtils.DEFAULT_ICON);
|
portraitView.setImage(Constants.DEFAULT_ICON.get());
|
||||||
else {
|
} else {
|
||||||
portraitView.setImage(image);
|
portraitView.setImage(image);
|
||||||
portraitView.setViewport(AccountHelper.getViewport(4));
|
portraitView.setViewport(AccountHelper.getViewport(4));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,19 +23,19 @@ import javafx.geometry.Pos;
|
|||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.layout.BorderPane;
|
import javafx.scene.layout.BorderPane;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServerInfo;
|
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer;
|
||||||
import org.jackhuang.hmcl.setting.Theme;
|
import org.jackhuang.hmcl.setting.Theme;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public final class AuthlibInjectorServerItem extends BorderPane {
|
public final class AuthlibInjectorServerItem extends BorderPane {
|
||||||
private final AuthlibInjectorServerInfo info;
|
private final AuthlibInjectorServer server;
|
||||||
|
|
||||||
private final Label lblServerName = new Label();
|
private final Label lblServerName = new Label();
|
||||||
private final Label lblServerIp = new Label();
|
private final Label lblServerIp = new Label();
|
||||||
|
|
||||||
public AuthlibInjectorServerItem(AuthlibInjectorServerInfo info, Consumer<AuthlibInjectorServerItem> deleteCallback) {
|
public AuthlibInjectorServerItem(AuthlibInjectorServer server, Consumer<AuthlibInjectorServerItem> deleteCallback) {
|
||||||
this.info = info;
|
this.server = server;
|
||||||
|
|
||||||
lblServerName.setStyle("-fx-font-size: 15;");
|
lblServerName.setStyle("-fx-font-size: 15;");
|
||||||
lblServerIp.setStyle("-fx-font-size: 10;");
|
lblServerIp.setStyle("-fx-font-size: 10;");
|
||||||
@@ -54,11 +54,11 @@ public final class AuthlibInjectorServerItem extends BorderPane {
|
|||||||
|
|
||||||
setStyle("-fx-background-radius: 2; -fx-background-color: white; -fx-padding: 8;");
|
setStyle("-fx-background-radius: 2; -fx-background-color: white; -fx-padding: 8;");
|
||||||
JFXDepthManager.setDepth(this, 1);
|
JFXDepthManager.setDepth(this, 1);
|
||||||
lblServerName.setText(info.getServerName());
|
lblServerName.setText(server.getName());
|
||||||
lblServerIp.setText(info.getServerIp());
|
lblServerIp.setText(server.getUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
public AuthlibInjectorServerInfo getInfo() {
|
public AuthlibInjectorServer getServer() {
|
||||||
return info;
|
return server;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,12 @@ import com.jfoenix.controls.*;
|
|||||||
import javafx.beans.property.SimpleStringProperty;
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
import javafx.beans.property.StringProperty;
|
import javafx.beans.property.StringProperty;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.scene.Node;
|
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.ScrollPane;
|
import javafx.scene.control.ScrollPane;
|
||||||
import javafx.scene.layout.StackPane;
|
import javafx.scene.layout.StackPane;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import org.jackhuang.hmcl.Launcher;
|
import org.jackhuang.hmcl.Launcher;
|
||||||
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServerInfo;
|
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer;
|
||||||
import org.jackhuang.hmcl.setting.Accounts;
|
import org.jackhuang.hmcl.setting.Accounts;
|
||||||
import org.jackhuang.hmcl.setting.Settings;
|
import org.jackhuang.hmcl.setting.Settings;
|
||||||
import org.jackhuang.hmcl.task.Schedulers;
|
import org.jackhuang.hmcl.task.Schedulers;
|
||||||
@@ -18,35 +17,32 @@ import org.jackhuang.hmcl.task.Task;
|
|||||||
import org.jackhuang.hmcl.ui.animation.ContainerAnimations;
|
import org.jackhuang.hmcl.ui.animation.ContainerAnimations;
|
||||||
import org.jackhuang.hmcl.ui.animation.TransitionHandler;
|
import org.jackhuang.hmcl.ui.animation.TransitionHandler;
|
||||||
import org.jackhuang.hmcl.ui.wizard.DecoratorPage;
|
import org.jackhuang.hmcl.ui.wizard.DecoratorPage;
|
||||||
import org.jackhuang.hmcl.util.Logging;
|
|
||||||
import org.jackhuang.hmcl.util.NetworkUtils;
|
import org.jackhuang.hmcl.util.NetworkUtils;
|
||||||
|
|
||||||
import java.util.Collection;
|
import static java.util.stream.Collectors.toList;
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
public class AuthlibInjectorServersPage extends StackPane implements DecoratorPage {
|
public class AuthlibInjectorServersPage extends StackPane implements DecoratorPage {
|
||||||
private final StringProperty title = new SimpleStringProperty(this, "title", Launcher.i18n("account.injector.server"));
|
private final StringProperty title = new SimpleStringProperty(this, "title", Launcher.i18n("account.injector.server"));
|
||||||
|
|
||||||
@FXML private ScrollPane scrollPane;
|
@FXML private ScrollPane scrollPane;
|
||||||
@FXML private StackPane addServerContainer;
|
@FXML private StackPane addServerContainer;
|
||||||
@FXML private Label lblServerIp;
|
@FXML private Label lblServerUrl;
|
||||||
@FXML private Label lblServerName;
|
@FXML private Label lblServerName;
|
||||||
@FXML private Label lblCreationWarning;
|
@FXML private Label lblCreationWarning;
|
||||||
@FXML private Label lblServerWarning;
|
@FXML private Label lblServerWarning;
|
||||||
@FXML private VBox listPane;
|
@FXML private VBox listPane;
|
||||||
@FXML private JFXTextField txtServerIp;
|
@FXML private JFXTextField txtServerUrl;
|
||||||
@FXML private JFXDialogLayout addServerPane;
|
@FXML private JFXDialogLayout addServerPane;
|
||||||
@FXML private JFXDialogLayout confirmServerPane;
|
@FXML private JFXDialogLayout confirmServerPane;
|
||||||
@FXML private JFXDialog dialog;
|
@FXML private JFXDialog dialog;
|
||||||
@FXML private StackPane contentPane;
|
@FXML private StackPane contentPane;
|
||||||
@FXML private JFXSpinner spinner;
|
|
||||||
@FXML private JFXProgressBar progressBar;
|
@FXML private JFXProgressBar progressBar;
|
||||||
@FXML private JFXButton btnAddNext;
|
@FXML private JFXButton btnAddNext;
|
||||||
|
|
||||||
private final TransitionHandler transitionHandler;
|
private final TransitionHandler transitionHandler;
|
||||||
|
|
||||||
|
private AuthlibInjectorServer serverBeingAdded;
|
||||||
|
|
||||||
{
|
{
|
||||||
FXUtils.loadFXML(this, "/assets/fxml/authlib-injector-servers.fxml");
|
FXUtils.loadFXML(this, "/assets/fxml/authlib-injector-servers.fxml");
|
||||||
FXUtils.smoothScrolling(scrollPane);
|
FXUtils.smoothScrolling(scrollPane);
|
||||||
@@ -55,49 +51,33 @@ public class AuthlibInjectorServersPage extends StackPane implements DecoratorPa
|
|||||||
getChildren().remove(dialog);
|
getChildren().remove(dialog);
|
||||||
dialog.setDialogContainer(this);
|
dialog.setDialogContainer(this);
|
||||||
|
|
||||||
txtServerIp.textProperty().addListener((a, b, newValue) ->
|
txtServerUrl.textProperty().addListener((a, b, newValue) ->
|
||||||
btnAddNext.setDisable(!txtServerIp.validate()));
|
btnAddNext.setDisable(!txtServerUrl.validate()));
|
||||||
|
|
||||||
loading();
|
reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeServer(AuthlibInjectorServerItem item) {
|
private void removeServer(AuthlibInjectorServerItem item) {
|
||||||
Settings.INSTANCE.removeAuthlibInjectorServerURL(item.getInfo().getServerIp());
|
Settings.INSTANCE.SETTINGS.authlibInjectorServers.remove(item.getServer());
|
||||||
loading();
|
reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loading() {
|
private void reload() {
|
||||||
getChildren().remove(contentPane);
|
listPane.getChildren().setAll(
|
||||||
spinner.setVisible(true);
|
Settings.INSTANCE.SETTINGS.authlibInjectorServers.stream()
|
||||||
|
.map(server -> new AuthlibInjectorServerItem(server, this::removeServer))
|
||||||
Task.ofResult("list", () -> Settings.INSTANCE.getAuthlibInjectorServerURLs().parallelStream()
|
.collect(toList()));
|
||||||
.flatMap(serverURL -> {
|
if (Settings.INSTANCE.SETTINGS.authlibInjectorServers.isEmpty()) {
|
||||||
try {
|
|
||||||
return Stream.of(new AuthlibInjectorServerItem(new AuthlibInjectorServerInfo(serverURL, Accounts.getAuthlibInjectorServerName(serverURL)), this::removeServer));
|
|
||||||
} catch (Exception e) {
|
|
||||||
Logging.LOG.log(Level.WARNING, "Authlib-injector server root " + serverURL + " cannot be recognized.", e);
|
|
||||||
return Stream.empty();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect(Collectors.toList()))
|
|
||||||
.subscribe(Task.of(Schedulers.javafx(), variables -> {
|
|
||||||
listPane.getChildren().setAll(variables.<Collection<? extends Node>>get("list"));
|
|
||||||
loadingCompleted();
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadingCompleted() {
|
|
||||||
getChildren().add(contentPane);
|
|
||||||
spinner.setVisible(false);
|
|
||||||
|
|
||||||
if (Settings.INSTANCE.getAuthlibInjectorServerURLs().isEmpty())
|
|
||||||
onAdd();
|
onAdd();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private void onAdd() {
|
private void onAdd() {
|
||||||
transitionHandler.setContent(addServerPane, ContainerAnimations.NONE.getAnimationProducer());
|
transitionHandler.setContent(addServerPane, ContainerAnimations.NONE.getAnimationProducer());
|
||||||
txtServerIp.setText("");
|
txtServerUrl.setText("");
|
||||||
|
txtServerUrl.resetValidation();
|
||||||
|
lblCreationWarning.setText("");
|
||||||
addServerPane.setDisable(false);
|
addServerPane.setDisable(false);
|
||||||
progressBar.setVisible(false);
|
progressBar.setVisible(false);
|
||||||
dialog.show();
|
dialog.show();
|
||||||
@@ -110,26 +90,28 @@ public class AuthlibInjectorServersPage extends StackPane implements DecoratorPa
|
|||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private void onAddNext() {
|
private void onAddNext() {
|
||||||
String serverIp = txtServerIp.getText();
|
String url = fixInputUrl(txtServerUrl.getText());
|
||||||
|
|
||||||
progressBar.setVisible(true);
|
progressBar.setVisible(true);
|
||||||
addServerPane.setDisable(true);
|
addServerPane.setDisable(true);
|
||||||
|
|
||||||
Task.ofResult("serverName", () -> Accounts.getAuthlibInjectorServerName(serverIp))
|
Task.of(() -> {
|
||||||
.finalized(Schedulers.javafx(), (variables, isDependentsSucceeded) -> {
|
serverBeingAdded = new AuthlibInjectorServer(url, Accounts.getAuthlibInjectorServerName(url));
|
||||||
progressBar.setVisible(false);
|
}).finalized(Schedulers.javafx(), (variables, isDependentsSucceeded) -> {
|
||||||
addServerPane.setDisable(false);
|
progressBar.setVisible(false);
|
||||||
|
addServerPane.setDisable(false);
|
||||||
|
|
||||||
if (isDependentsSucceeded) {
|
if (isDependentsSucceeded) {
|
||||||
lblServerName.setText(variables.get("serverName"));
|
lblServerName.setText(serverBeingAdded.getName());
|
||||||
lblServerIp.setText(txtServerIp.getText());
|
lblServerUrl.setText(serverBeingAdded.getUrl());
|
||||||
|
|
||||||
lblServerWarning.setVisible("http".equals(NetworkUtils.toURL(serverIp).getProtocol()));
|
lblServerWarning.setVisible("http".equals(NetworkUtils.toURL(serverBeingAdded.getUrl()).getProtocol()));
|
||||||
|
|
||||||
transitionHandler.setContent(confirmServerPane, ContainerAnimations.SWIPE_LEFT.getAnimationProducer());
|
|
||||||
} else
|
|
||||||
lblCreationWarning.setText(variables.<Exception>get("lastException").getLocalizedMessage());
|
|
||||||
}).start();
|
|
||||||
|
|
||||||
|
transitionHandler.setContent(confirmServerPane, ContainerAnimations.SWIPE_LEFT.getAnimationProducer());
|
||||||
|
} else {
|
||||||
|
lblCreationWarning.setText(variables.<Exception>get("lastException").getLocalizedMessage());
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,11 +122,10 @@ public class AuthlibInjectorServersPage extends StackPane implements DecoratorPa
|
|||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private void onAddFinish() {
|
private void onAddFinish() {
|
||||||
String ip = txtServerIp.getText();
|
if (!Settings.INSTANCE.SETTINGS.authlibInjectorServers.contains(serverBeingAdded)) {
|
||||||
if (!ip.endsWith("/"))
|
Settings.INSTANCE.SETTINGS.authlibInjectorServers.add(serverBeingAdded);
|
||||||
ip += "/";
|
}
|
||||||
Settings.INSTANCE.addAuthlibInjectorServerURL(ip);
|
reload();
|
||||||
loading();
|
|
||||||
dialog.close();
|
dialog.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,4 +141,11 @@ public class AuthlibInjectorServersPage extends StackPane implements DecoratorPa
|
|||||||
public void setTitle(String title) {
|
public void setTitle(String title) {
|
||||||
this.title.set(title);
|
this.title.set(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String fixInputUrl(String url) {
|
||||||
|
if (!url.endsWith("/")) {
|
||||||
|
url += "/";
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import javafx.animation.Interpolator;
|
|||||||
import javafx.animation.KeyFrame;
|
import javafx.animation.KeyFrame;
|
||||||
import javafx.animation.Timeline;
|
import javafx.animation.Timeline;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
|
import javafx.beans.InvalidationListener;
|
||||||
import javafx.beans.property.Property;
|
import javafx.beans.property.Property;
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.beans.value.ChangeListener;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
@@ -30,18 +31,22 @@ import javafx.beans.value.WeakChangeListener;
|
|||||||
import javafx.event.EventHandler;
|
import javafx.event.EventHandler;
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.control.ListCell;
|
||||||
import javafx.scene.control.ListView;
|
import javafx.scene.control.ListView;
|
||||||
import javafx.scene.control.ScrollBar;
|
import javafx.scene.control.ScrollBar;
|
||||||
import javafx.scene.control.ScrollPane;
|
import javafx.scene.control.ScrollPane;
|
||||||
import javafx.scene.control.Tooltip;
|
import javafx.scene.control.Tooltip;
|
||||||
import javafx.scene.image.Image;
|
|
||||||
import javafx.scene.image.ImageView;
|
import javafx.scene.image.ImageView;
|
||||||
import javafx.scene.input.MouseEvent;
|
import javafx.scene.input.MouseEvent;
|
||||||
import javafx.scene.input.ScrollEvent;
|
import javafx.scene.input.ScrollEvent;
|
||||||
import javafx.scene.layout.Region;
|
import javafx.scene.layout.Region;
|
||||||
import javafx.scene.shape.Rectangle;
|
import javafx.scene.shape.Rectangle;
|
||||||
|
import javafx.util.Callback;
|
||||||
import javafx.util.Duration;
|
import javafx.util.Duration;
|
||||||
|
import javafx.util.StringConverter;
|
||||||
|
|
||||||
import org.jackhuang.hmcl.Launcher;
|
import org.jackhuang.hmcl.Launcher;
|
||||||
|
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer;
|
||||||
import org.jackhuang.hmcl.util.*;
|
import org.jackhuang.hmcl.util.*;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -52,6 +57,7 @@ import java.net.URI;
|
|||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
@@ -68,6 +74,10 @@ public final class FXUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static InvalidationListener onInvalidating(Runnable action) {
|
||||||
|
return arg -> action.run();
|
||||||
|
}
|
||||||
|
|
||||||
public static <T> void onChange(ObservableValue<T> value, Consumer<T> consumer) {
|
public static <T> void onChange(ObservableValue<T> value, Consumer<T> consumer) {
|
||||||
value.addListener((a, b, c) -> consumer.accept(c));
|
value.addListener((a, b, c) -> consumer.accept(c));
|
||||||
}
|
}
|
||||||
@@ -402,7 +412,32 @@ public final class FXUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final Image DEFAULT_ICON = new Image("/assets/img/icon.png");
|
public static <T> StringConverter<T> stringConverter(Function<T, String> func) {
|
||||||
|
return new StringConverter<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(T object) {
|
||||||
|
return object == null ? "" : func.apply(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T fromString(String string) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Callback<ListView<T>, ListCell<T>> jfxListCellFactory(Function<T, Node> graphicBuilder) {
|
||||||
|
return view -> new JFXListCell<T>() {
|
||||||
|
@Override
|
||||||
|
public void updateItem(T item, boolean empty) {
|
||||||
|
super.updateItem(item, empty);
|
||||||
|
if (!empty) {
|
||||||
|
setGraphic(graphicBuilder.apply(item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public static final Interpolator SINE = new Interpolator() {
|
public static final Interpolator SINE = new Interpolator() {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -186,9 +186,9 @@ public final class LeftPaneController {
|
|||||||
} else
|
} else
|
||||||
item.setImage(AccountHelper.getDefaultSkin(account.getUUID(), 4), AccountHelper.getViewport(4));
|
item.setImage(AccountHelper.getDefaultSkin(account.getUUID(), 4), AccountHelper.getViewport(4));
|
||||||
|
|
||||||
if (account instanceof AuthlibInjectorAccount)
|
if (account instanceof AuthlibInjectorAccount) {
|
||||||
Accounts.getAuthlibInjectorServerNameAsync((AuthlibInjectorAccount) account)
|
FXUtils.installTooltip(ripplerContainer, 500, 5000, 0, new Tooltip(((AuthlibInjectorAccount) account).getServer().getName()));
|
||||||
.subscribe(Schedulers.javafx(), variables -> FXUtils.installTooltip(ripplerContainer, 500, 5000, 0, new Tooltip(variables.get("serverName"))));
|
}
|
||||||
|
|
||||||
if (selectedAccount == account)
|
if (selectedAccount == account)
|
||||||
ripplerContainer.setSelected(true);
|
ripplerContainer.setSelected(true);
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ public final class VersionSettingsController {
|
|||||||
if (iconFile.exists())
|
if (iconFile.exists())
|
||||||
iconPickerItem.setImage(new Image("file:" + iconFile.getAbsolutePath()));
|
iconPickerItem.setImage(new Image("file:" + iconFile.getAbsolutePath()));
|
||||||
else
|
else
|
||||||
iconPickerItem.setImage(FXUtils.DEFAULT_ICON);
|
iconPickerItem.setImage(Constants.DEFAULT_ICON.get());
|
||||||
FXUtils.limitSize(iconPickerItem.getImageView(), 32, 32);
|
FXUtils.limitSize(iconPickerItem.getImageView(), 32, 32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
<fx:root xmlns="http://javafx.com/javafx"
|
<fx:root xmlns="http://javafx.com/javafx"
|
||||||
xmlns:fx="http://javafx.com/fxml"
|
xmlns:fx="http://javafx.com/fxml"
|
||||||
type="StackPane">
|
type="StackPane">
|
||||||
<JFXSpinner fx:id="spinner" style="-fx-radius:16" styleClass="materialDesign-purple, first-spinner" />
|
|
||||||
<StackPane fx:id="contentPane">
|
<StackPane fx:id="contentPane">
|
||||||
<ScrollPane fx:id="scrollPane" fitToWidth="true" fitToHeight="true">
|
<ScrollPane fx:id="scrollPane" fitToWidth="true" fitToHeight="true">
|
||||||
<VBox fx:id="listPane" spacing="10" style="-fx-padding: 20 20 70 20;">
|
<VBox fx:id="listPane" spacing="10" style="-fx-padding: 20 20 70 20;">
|
||||||
@@ -32,7 +31,7 @@
|
|||||||
<Label text="%account.injector.add" />
|
<Label text="%account.injector.add" />
|
||||||
</heading>
|
</heading>
|
||||||
<body>
|
<body>
|
||||||
<JFXTextField fx:id="txtServerIp" promptText="%account.injector.server_ip">
|
<JFXTextField fx:id="txtServerUrl" promptText="%account.injector.server_url">
|
||||||
<validators>
|
<validators>
|
||||||
<URLValidator message="%input.url">
|
<URLValidator message="%input.url">
|
||||||
</URLValidator>
|
</URLValidator>
|
||||||
@@ -62,10 +61,10 @@
|
|||||||
<ColumnConstraints maxWidth="100" />
|
<ColumnConstraints maxWidth="100" />
|
||||||
<ColumnConstraints />
|
<ColumnConstraints />
|
||||||
</columnConstraints>
|
</columnConstraints>
|
||||||
<Label text="%account.injector.server_ip" GridPane.columnIndex="0" GridPane.rowIndex="0" />
|
<Label text="%account.injector.server_url" GridPane.columnIndex="0" GridPane.rowIndex="0" />
|
||||||
<Label text="%account.injector.server_name" GridPane.columnIndex="0" GridPane.rowIndex="1" />
|
<Label text="%account.injector.server_name" GridPane.columnIndex="0" GridPane.rowIndex="1" />
|
||||||
|
|
||||||
<Label fx:id="lblServerIp" GridPane.columnIndex="1" GridPane.rowIndex="0" />
|
<Label fx:id="lblServerUrl" GridPane.columnIndex="1" GridPane.rowIndex="0" />
|
||||||
<Label fx:id="lblServerName" GridPane.columnIndex="1" GridPane.rowIndex="1" />
|
<Label fx:id="lblServerName" GridPane.columnIndex="1" GridPane.rowIndex="1" />
|
||||||
|
|
||||||
<Label fx:id="lblServerWarning" text="%account.injector.http" style="-fx-text-fill: red;" GridPane.rowIndex="2" GridPane.columnSpan="2" GridPane.columnIndex="0" />
|
<Label fx:id="lblServerWarning" text="%account.injector.http" style="-fx-text-fill: red;" GridPane.rowIndex="2" GridPane.columnSpan="2" GridPane.columnIndex="0" />
|
||||||
|
|||||||
@@ -39,11 +39,12 @@ account.failed.invalid_credentials=Incorrect password. Or forbidden to log in te
|
|||||||
account.failed.invalid_password=Invalid password
|
account.failed.invalid_password=Invalid password
|
||||||
account.failed.invalid_token=Please log out and re-input your password to log in.
|
account.failed.invalid_token=Please log out and re-input your password to log in.
|
||||||
account.failed.no_charactor=No character in this account.
|
account.failed.no_charactor=No character in this account.
|
||||||
|
account.failed.no_selected_server=No authentication server is selected.
|
||||||
account.injector.add=Add authentication server
|
account.injector.add=Add authentication server
|
||||||
account.injector.manage=Manage authentication servers
|
account.injector.manage=Manage authentication servers
|
||||||
account.injector.http=Warning: This server is using HTTP, which will cause your password be transmitted in clear text.
|
account.injector.http=Warning: This server is using HTTP, which will cause your password be transmitted in clear text.
|
||||||
account.injector.server=Auth Server
|
account.injector.server=Auth Server
|
||||||
account.injector.server_ip=Server URL
|
account.injector.server_url=Server URL
|
||||||
account.injector.server_name=Server Name
|
account.injector.server_name=Server Name
|
||||||
account.methods=Login Type
|
account.methods=Login Type
|
||||||
account.methods.authlib_injector=authlib-injector
|
account.methods.authlib_injector=authlib-injector
|
||||||
|
|||||||
@@ -39,11 +39,12 @@ account.failed.invalid_credentials=您的用户名或密码错误,或者登录
|
|||||||
account.failed.invalid_password=无效的密码
|
account.failed.invalid_password=无效的密码
|
||||||
account.failed.invalid_token=请尝试登出并重新输入密码登录
|
account.failed.invalid_token=请尝试登出并重新输入密码登录
|
||||||
account.failed.no_charactor=该帐号没有角色
|
account.failed.no_charactor=该帐号没有角色
|
||||||
|
account.failed.no_selected_server=未选择认证服务器
|
||||||
account.injector.add=添加认证服务器
|
account.injector.add=添加认证服务器
|
||||||
account.injector.manage=管理认证服务器
|
account.injector.manage=管理认证服务器
|
||||||
account.injector.http=警告:此服务器使用不安全的http协议,您的密码在登录时会被明文传输。
|
account.injector.http=警告:此服务器使用不安全的http协议,您的密码在登录时会被明文传输。
|
||||||
account.injector.server=认证服务器
|
account.injector.server=认证服务器
|
||||||
account.injector.server_ip=服务器地址
|
account.injector.server_url=服务器地址
|
||||||
account.injector.server_name=服务器名称
|
account.injector.server_name=服务器名称
|
||||||
account.methods=登录方式
|
account.methods=登录方式
|
||||||
account.methods.authlib_injector=authlib-injector 登录
|
account.methods.authlib_injector=authlib-injector 登录
|
||||||
|
|||||||
@@ -37,14 +37,14 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
public class AuthlibInjectorAccount extends YggdrasilAccount {
|
public class AuthlibInjectorAccount extends YggdrasilAccount {
|
||||||
private final String serverBaseURL;
|
private final AuthlibInjectorServer server;
|
||||||
private final ExceptionalSupplier<String, ?> injectorJarPath;
|
private final ExceptionalSupplier<String, ?> injectorJarPath;
|
||||||
|
|
||||||
protected AuthlibInjectorAccount(YggdrasilService service, String serverBaseURL, ExceptionalSupplier<String, ?> injectorJarPath, String username, UUID characterUUID, YggdrasilSession session) {
|
protected AuthlibInjectorAccount(YggdrasilService service, AuthlibInjectorServer server, ExceptionalSupplier<String, ?> injectorJarPath, String username, UUID characterUUID, YggdrasilSession session) {
|
||||||
super(service, username, characterUUID, session);
|
super(service, username, characterUUID, session);
|
||||||
|
|
||||||
this.injectorJarPath = injectorJarPath;
|
this.injectorJarPath = injectorJarPath;
|
||||||
this.serverBaseURL = serverBaseURL;
|
this.server = server;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -59,7 +59,7 @@ public class AuthlibInjectorAccount extends YggdrasilAccount {
|
|||||||
|
|
||||||
private AuthInfo inject(ExceptionalSupplier<AuthInfo, AuthenticationException> supplier) throws AuthenticationException {
|
private AuthInfo inject(ExceptionalSupplier<AuthInfo, AuthenticationException> supplier) throws AuthenticationException {
|
||||||
// Authlib Injector recommends launchers to pre-fetch the server basic information before launched the game to save time.
|
// Authlib Injector recommends launchers to pre-fetch the server basic information before launched the game to save time.
|
||||||
GetTask getTask = new GetTask(NetworkUtils.toURL(serverBaseURL));
|
GetTask getTask = new GetTask(NetworkUtils.toURL(server.getUrl()));
|
||||||
AtomicBoolean flag = new AtomicBoolean(true);
|
AtomicBoolean flag = new AtomicBoolean(true);
|
||||||
Thread thread = Lang.thread(() -> flag.set(getTask.test()));
|
Thread thread = Lang.thread(() -> flag.set(getTask.test()));
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ public class AuthlibInjectorAccount extends YggdrasilAccount {
|
|||||||
try {
|
try {
|
||||||
thread.join();
|
thread.join();
|
||||||
|
|
||||||
Arguments arguments = new Arguments().addJVMArguments("-javaagent:" + injectorJarPath.get() + "=" + serverBaseURL);
|
Arguments arguments = new Arguments().addJVMArguments("-javaagent:" + injectorJarPath.get() + "=" + server.getUrl());
|
||||||
|
|
||||||
if (flag.get())
|
if (flag.get())
|
||||||
arguments = arguments.addJVMArguments("-Dorg.to2mbn.authlibinjector.config.prefetched=" + new String(Base64.getEncoder().encode(getTask.getResult().getBytes()), UTF_8));
|
arguments = arguments.addJVMArguments("-Dorg.to2mbn.authlibinjector.config.prefetched=" + new String(Base64.getEncoder().encode(getTask.getResult().getBytes()), UTF_8));
|
||||||
@@ -81,12 +81,12 @@ public class AuthlibInjectorAccount extends YggdrasilAccount {
|
|||||||
@Override
|
@Override
|
||||||
public Map<Object, Object> toStorage() {
|
public Map<Object, Object> toStorage() {
|
||||||
Map<Object, Object> map = super.toStorage();
|
Map<Object, Object> map = super.toStorage();
|
||||||
map.put("serverBaseURL", serverBaseURL);
|
map.put("serverBaseURL", server.getUrl());
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getServerBaseURL() {
|
public AuthlibInjectorServer getServer() {
|
||||||
return serverBaseURL;
|
return server;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,33 +6,37 @@ import org.jackhuang.hmcl.auth.CharacterSelector;
|
|||||||
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilService;
|
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilService;
|
||||||
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilSession;
|
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilSession;
|
||||||
import org.jackhuang.hmcl.util.ExceptionalSupplier;
|
import org.jackhuang.hmcl.util.ExceptionalSupplier;
|
||||||
import org.jackhuang.hmcl.util.NetworkUtils;
|
|
||||||
|
|
||||||
import java.net.Proxy;
|
import java.net.Proxy;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
import static org.jackhuang.hmcl.util.Lang.tryCast;
|
import static org.jackhuang.hmcl.util.Lang.tryCast;
|
||||||
|
|
||||||
public class AuthlibInjectorAccountFactory extends AccountFactory<AuthlibInjectorAccount> {
|
public class AuthlibInjectorAccountFactory extends AccountFactory<AuthlibInjectorAccount> {
|
||||||
private final ExceptionalSupplier<String, ?> injectorJarPathSupplier;
|
private final ExceptionalSupplier<String, ?> injectorJarPathSupplier;
|
||||||
|
private Function<String, AuthlibInjectorServer> serverLookup;
|
||||||
|
|
||||||
public AuthlibInjectorAccountFactory(ExceptionalSupplier<String, ?> injectorJarPathSupplier) {
|
/**
|
||||||
|
* @param serverLookup a function that looks up {@link AuthlibInjectorServer} by url
|
||||||
|
*/
|
||||||
|
public AuthlibInjectorAccountFactory(ExceptionalSupplier<String, ?> injectorJarPathSupplier, Function<String, AuthlibInjectorServer> serverLookup) {
|
||||||
this.injectorJarPathSupplier = injectorJarPathSupplier;
|
this.injectorJarPathSupplier = injectorJarPathSupplier;
|
||||||
|
this.serverLookup = serverLookup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AuthlibInjectorAccount create(CharacterSelector selector, String username, String password, Object serverBaseURL, Proxy proxy) throws AuthenticationException {
|
public AuthlibInjectorAccount create(CharacterSelector selector, String username, String password, Object additionalData, Proxy proxy) throws AuthenticationException {
|
||||||
Objects.requireNonNull(selector);
|
Objects.requireNonNull(selector);
|
||||||
Objects.requireNonNull(username);
|
Objects.requireNonNull(username);
|
||||||
Objects.requireNonNull(password);
|
Objects.requireNonNull(password);
|
||||||
Objects.requireNonNull(proxy);
|
Objects.requireNonNull(proxy);
|
||||||
|
|
||||||
if (!(serverBaseURL instanceof String) || !NetworkUtils.isURL((String) serverBaseURL))
|
AuthlibInjectorServer server = (AuthlibInjectorServer) additionalData;
|
||||||
throw new IllegalArgumentException("Additional data should be server base url string for authlib injector accounts.");
|
|
||||||
|
|
||||||
AuthlibInjectorAccount account = new AuthlibInjectorAccount(new YggdrasilService(new AuthlibInjectorProvider((String) serverBaseURL), proxy),
|
AuthlibInjectorAccount account = new AuthlibInjectorAccount(new YggdrasilService(new AuthlibInjectorProvider(server.getUrl()), proxy),
|
||||||
(String) serverBaseURL, injectorJarPathSupplier, username, null, null);
|
server, injectorJarPathSupplier, username, null, null);
|
||||||
account.logInWithPassword(password, selector);
|
account.logInWithPassword(password, selector);
|
||||||
return account;
|
return account;
|
||||||
}
|
}
|
||||||
@@ -49,7 +53,9 @@ public class AuthlibInjectorAccountFactory extends AccountFactory<AuthlibInjecto
|
|||||||
String apiRoot = tryCast(storage.get("serverBaseURL"), String.class)
|
String apiRoot = tryCast(storage.get("serverBaseURL"), String.class)
|
||||||
.orElseThrow(() -> new IllegalArgumentException("storage does not have API root."));
|
.orElseThrow(() -> new IllegalArgumentException("storage does not have API root."));
|
||||||
|
|
||||||
return new AuthlibInjectorAccount(new YggdrasilService(new AuthlibInjectorProvider(apiRoot), proxy),
|
AuthlibInjectorServer server = serverLookup.apply(apiRoot);
|
||||||
apiRoot, injectorJarPathSupplier, username, session.getSelectedProfile().getId(), session);
|
|
||||||
|
return new AuthlibInjectorAccount(new YggdrasilService(new AuthlibInjectorProvider(server.getUrl()), proxy),
|
||||||
|
server, injectorJarPathSupplier, username, session.getSelectedProfile().getId(), session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,20 +17,35 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.auth.authlibinjector;
|
package org.jackhuang.hmcl.auth.authlibinjector;
|
||||||
|
|
||||||
public class AuthlibInjectorServerInfo {
|
public class AuthlibInjectorServer {
|
||||||
private final String serverIp;
|
private String url;
|
||||||
private final String serverName;
|
private String name;
|
||||||
|
|
||||||
public AuthlibInjectorServerInfo(String serverIp, String serverName) {
|
public AuthlibInjectorServer(String url, String name) {
|
||||||
this.serverIp = serverIp;
|
this.url = url;
|
||||||
this.serverName = serverName;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getServerIp() {
|
public String getUrl() {
|
||||||
return serverIp;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getServerName() {
|
public String getName() {
|
||||||
return serverName;
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return url.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj == this)
|
||||||
|
return true;
|
||||||
|
if (!(obj instanceof AuthlibInjectorServer))
|
||||||
|
return false;
|
||||||
|
AuthlibInjectorServer another = (AuthlibInjectorServer) obj;
|
||||||
|
return this.url.equals(another.url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,6 +19,11 @@ package org.jackhuang.hmcl.util;
|
|||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
|
|
||||||
|
import javafx.beans.binding.Bindings;
|
||||||
|
import javafx.beans.binding.ObjectBinding;
|
||||||
|
import javafx.scene.image.Image;
|
||||||
|
|
||||||
import org.jackhuang.hmcl.game.Argument;
|
import org.jackhuang.hmcl.game.Argument;
|
||||||
import org.jackhuang.hmcl.game.Library;
|
import org.jackhuang.hmcl.game.Library;
|
||||||
import org.jackhuang.hmcl.game.RuledArgument;
|
import org.jackhuang.hmcl.game.RuledArgument;
|
||||||
@@ -65,6 +70,9 @@ public final class Constants {
|
|||||||
javafx.application.Platform.runLater(s);
|
javafx.application.Platform.runLater(s);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// lazy loading
|
||||||
|
public static final ObjectBinding<Image> DEFAULT_ICON = Bindings.createObjectBinding(() -> new Image("/assets/img/icon.png"));
|
||||||
|
|
||||||
public static final Gson GSON = new GsonBuilder()
|
public static final Gson GSON = new GsonBuilder()
|
||||||
.enableComplexMapKeySerialization()
|
.enableComplexMapKeySerialization()
|
||||||
.setPrettyPrinting()
|
.setPrettyPrinting()
|
||||||
|
|||||||
Reference in New Issue
Block a user