@@ -20,8 +20,7 @@ package org.jackhuang.hmcl.game;
|
|||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import org.jackhuang.hmcl.mod.Modpack;
|
import org.jackhuang.hmcl.mod.Modpack;
|
||||||
import org.jackhuang.hmcl.util.CompressingUtils;
|
import org.jackhuang.hmcl.util.CompressingUtils;
|
||||||
import org.jackhuang.hmcl.util.Constants;
|
import org.jackhuang.hmcl.util.JsonUtils;
|
||||||
import org.jackhuang.hmcl.util.Lang;
|
|
||||||
import org.jackhuang.hmcl.util.StringUtils;
|
import org.jackhuang.hmcl.util.StringUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -82,9 +81,9 @@ public final class HMCLModpackManager {
|
|||||||
*/
|
*/
|
||||||
public static Modpack readHMCLModpackManifest(File file) throws IOException, JsonParseException {
|
public static Modpack readHMCLModpackManifest(File file) throws IOException, JsonParseException {
|
||||||
String manifestJson = CompressingUtils.readTextZipEntry(file, "modpack.json");
|
String manifestJson = CompressingUtils.readTextZipEntry(file, "modpack.json");
|
||||||
Modpack manifest = Lang.requireJsonNonNull(Constants.GSON.fromJson(manifestJson, Modpack.class));
|
Modpack manifest = JsonUtils.fromNonNullJson(manifestJson, Modpack.class);
|
||||||
String gameJson = CompressingUtils.readTextZipEntry(file, "minecraft/pack.json");
|
String gameJson = CompressingUtils.readTextZipEntry(file, "minecraft/pack.json");
|
||||||
Version game = Lang.requireJsonNonNull(Constants.GSON.fromJson(gameJson, Version.class));
|
Version game = JsonUtils.fromNonNullJson(gameJson, Version.class);
|
||||||
if (game.getJar() == null)
|
if (game.getJar() == null)
|
||||||
if (StringUtils.isBlank(manifest.getVersion()))
|
if (StringUtils.isBlank(manifest.getVersion()))
|
||||||
throw new JsonParseException("Cannot recognize the game version of modpack " + file + ".");
|
throw new JsonParseException("Cannot recognize the game version of modpack " + file + ".");
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ public final class ModpackHelper {
|
|||||||
else throw new IllegalStateException("Unrecognized modpack: " + modpack);
|
else throw new IllegalStateException("Unrecognized modpack: " + modpack);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task getUpdateTask(Profile profile, File zipFile, String name, ModpackConfiguration configuration) throws UnsupportedModpackException, MismatchedModpackTypeException, IOException {
|
public static Task getUpdateTask(Profile profile, File zipFile, String name, ModpackConfiguration<?> configuration) throws UnsupportedModpackException, MismatchedModpackTypeException, IOException {
|
||||||
Modpack modpack = ModpackHelper.readModpackManifest(zipFile);
|
Modpack modpack = ModpackHelper.readModpackManifest(zipFile);
|
||||||
|
|
||||||
switch (configuration.getType()) {
|
switch (configuration.getType()) {
|
||||||
|
|||||||
@@ -73,9 +73,8 @@ public final class Accounts {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Optional<String> getCurrentCharacter(Map<Object, Object> storage) {
|
public static Optional<String> getCurrentCharacter(Map<Object, Object> storage) {
|
||||||
Optional<Map> properties = Lang.get(storage, "properties", Map.class);
|
return Lang.get(storage, "properties", Map.class)
|
||||||
if (!properties.isPresent()) return Optional.empty();
|
.flatMap(properties -> Lang.get(properties, "character", String.class));
|
||||||
return Lang.get(properties.get(), "character", String.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static String getAccountId(Account account) {
|
static String getAccountId(Account account) {
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ public class Settings {
|
|||||||
{
|
{
|
||||||
for (Map<Object, Object> settings : SETTINGS.getAccounts()) {
|
for (Map<Object, Object> settings : SETTINGS.getAccounts()) {
|
||||||
Optional<String> characterName = Accounts.getCurrentCharacter(settings);
|
Optional<String> characterName = Accounts.getCurrentCharacter(settings);
|
||||||
AccountFactory factory = Accounts.ACCOUNT_FACTORY.get(Lang.get(settings, "type", String.class, ""));
|
AccountFactory<?> factory = Accounts.ACCOUNT_FACTORY.get(Lang.get(settings, "type", String.class, ""));
|
||||||
if (factory == null || !characterName.isPresent()) {
|
if (factory == null || !characterName.isPresent()) {
|
||||||
// unrecognized account type, so remove it.
|
// unrecognized account type, so remove it.
|
||||||
SETTINGS.getAccounts().remove(settings);
|
SETTINGS.getAccounts().remove(settings);
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ public final class VersionSetting {
|
|||||||
permSizeProperty.set(permSize);
|
permSizeProperty.set(permSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final ImmediateIntegerProperty maxMemoryProperty = new ImmediateIntegerProperty(this, "maxMemory", (int) OperatingSystem.SUGGESTED_MEMORY);
|
private final ImmediateIntegerProperty maxMemoryProperty = new ImmediateIntegerProperty(this, "maxMemory", OperatingSystem.SUGGESTED_MEMORY);
|
||||||
|
|
||||||
public ImmediateIntegerProperty maxMemoryProperty() {
|
public ImmediateIntegerProperty maxMemoryProperty() {
|
||||||
return maxMemoryProperty;
|
return maxMemoryProperty;
|
||||||
|
|||||||
@@ -214,19 +214,19 @@ public final class AccountsPage extends StackPane implements DecoratorPage {
|
|||||||
this.title.set(title);
|
this.title.set(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String accountException(Exception account) {
|
public static String accountException(Exception exception) {
|
||||||
if (account instanceof InvalidCredentialsException) {
|
if (exception instanceof InvalidCredentialsException) {
|
||||||
return Main.i18n("account.failed.invalid_credentials");
|
return Main.i18n("account.failed.invalid_credentials");
|
||||||
} else if (account instanceof NoCharacterException) {
|
} else if (exception instanceof NoCharacterException) {
|
||||||
return Main.i18n("account.failed.no_charactor");
|
return Main.i18n("account.failed.no_charactor");
|
||||||
} else if (account instanceof ServerDisconnectException) {
|
} else if (exception instanceof ServerDisconnectException) {
|
||||||
return Main.i18n("account.failed.connect_authentication_server");
|
return Main.i18n("account.failed.connect_authentication_server");
|
||||||
} else if (account instanceof InvalidTokenException) {
|
} else if (exception instanceof InvalidTokenException) {
|
||||||
return Main.i18n("account.failed.invalid_token");
|
return Main.i18n("account.failed.invalid_token");
|
||||||
} else if (account instanceof InvalidPasswordException) {
|
} else if (exception instanceof InvalidPasswordException) {
|
||||||
return Main.i18n("account.failed.invalid_password");
|
return Main.i18n("account.failed.invalid_password");
|
||||||
} else {
|
} else {
|
||||||
return account.getClass() + ": " + ((Exception) account).getLocalizedMessage();
|
return exception.getClass() + ": " + exception.getLocalizedMessage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -94,19 +94,36 @@ public final class FXUtils {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> void addListener(Node node, String key, ObservableValue<T> value, Consumer<T> callback) {
|
private static class ListenerPair<T> {
|
||||||
ChangeListener<T> listener = (a, b, newValue) -> callback.accept(newValue);
|
ObservableValue<T> value;
|
||||||
node.getProperties().put(key, new Pair<>(callback, listener));
|
ChangeListener<? super T> listener;
|
||||||
value.addListener(listener);
|
|
||||||
|
ListenerPair(ObservableValue<T> value, ChangeListener<? super T> listener) {
|
||||||
|
this.value = value;
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind() {
|
||||||
|
value.addListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
void unbind() {
|
||||||
|
value.removeListener(listener);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> void removeListener(Node node, String key) {
|
public static <T> void addListener(Node node, String key, ObservableValue<T> value, Consumer<? super T> callback) {
|
||||||
if (node.getProperties().get(key) instanceof Pair) {
|
ListenerPair<T> pair = new ListenerPair<>(value, (a, b, newValue) -> callback.accept(newValue));
|
||||||
Pair pair = (Pair) node.getProperties().get(key);
|
node.getProperties().put(key, pair);
|
||||||
if (pair.getValue() instanceof ObservableValue && pair.getKey() instanceof ChangeListener) {
|
pair.bind();
|
||||||
((ObservableValue) pair.getValue()).removeListener((ChangeListener) pair.getKey());
|
}
|
||||||
}
|
|
||||||
}
|
public static void removeListener(Node node, String key) {
|
||||||
|
Lang.convert(node.getProperties().get(key), ListenerPair.class)
|
||||||
|
.ifPresent(info -> {
|
||||||
|
info.unbind();
|
||||||
|
node.getProperties().remove(key);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setValidateWhileTextChanged(Node field, boolean validate) {
|
public static void setValidateWhileTextChanged(Node field, boolean validate) {
|
||||||
|
|||||||
@@ -21,13 +21,9 @@ import javafx.collections.FXCollections;
|
|||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.scene.control.MultipleSelectionModel;
|
import javafx.scene.control.MultipleSelectionModel;
|
||||||
|
|
||||||
public final class NoneMultipleSelectionModel<T> extends MultipleSelectionModel<T> {
|
public class NoneMultipleSelectionModel<T> extends MultipleSelectionModel<T> {
|
||||||
private static final NoneMultipleSelectionModel INSTANCE = new NoneMultipleSelectionModel();
|
|
||||||
private NoneMultipleSelectionModel() {}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
public NoneMultipleSelectionModel() {
|
||||||
public static <T> NoneMultipleSelectionModel<T> getInstance() {
|
|
||||||
return (NoneMultipleSelectionModel<T>) INSTANCE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -217,10 +217,12 @@ public class RipplerContainer extends StackPane {
|
|||||||
private static class StyleableProperties {
|
private static class StyleableProperties {
|
||||||
|
|
||||||
private static final CssMetaData<RipplerContainer, Paint> RIPPLER_FILL = new CssMetaData<RipplerContainer, Paint>("-jfx-rippler-fill", StyleConverter.getPaintConverter(), Color.rgb(0, 200, 255)) {
|
private static final CssMetaData<RipplerContainer, Paint> RIPPLER_FILL = new CssMetaData<RipplerContainer, Paint>("-jfx-rippler-fill", StyleConverter.getPaintConverter(), Color.rgb(0, 200, 255)) {
|
||||||
|
@Override
|
||||||
public boolean isSettable(RipplerContainer control) {
|
public boolean isSettable(RipplerContainer control) {
|
||||||
return control.ripplerFill == null || !control.ripplerFill.isBound();
|
return control.ripplerFill == null || !control.ripplerFill.isBound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public StyleableProperty<Paint> getStyleableProperty(RipplerContainer control) {
|
public StyleableProperty<Paint> getStyleableProperty(RipplerContainer control) {
|
||||||
return control.ripplerFillProperty();
|
return control.ripplerFillProperty();
|
||||||
}
|
}
|
||||||
@@ -232,7 +234,7 @@ public class RipplerContainer extends StackPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
List<CssMetaData<? extends Styleable, ?>> styleables = new ArrayList<>(Parent.getClassCssMetaData());
|
List<CssMetaData<? extends Styleable, ?>> styleables = new ArrayList<>(Node.getClassCssMetaData());
|
||||||
Collections.addAll(styleables, RIPPLER_FILL);
|
Collections.addAll(styleables, RIPPLER_FILL);
|
||||||
STYLEABLES = Collections.unmodifiableList(styleables);
|
STYLEABLES = Collections.unmodifiableList(styleables);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,10 @@ public final class ExportWizardProvider implements WizardProvider {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object finish(Map<String, Object> settings) {
|
public Object finish(Map<String, Object> settings) {
|
||||||
return new HMCLModpackExportTask(profile.getRepository(), version, (List<String>) settings.get(ModpackFileSelectionPage.MODPACK_FILE_SELECTION),
|
@SuppressWarnings("unchecked")
|
||||||
|
List<String> whitelist = (List<String>) settings.get(ModpackFileSelectionPage.MODPACK_FILE_SELECTION);
|
||||||
|
|
||||||
|
return new HMCLModpackExportTask(profile.getRepository(), version, whitelist,
|
||||||
new Modpack(
|
new Modpack(
|
||||||
(String) settings.get(ModpackInfoPage.MODPACK_NAME),
|
(String) settings.get(ModpackInfoPage.MODPACK_NAME),
|
||||||
(String) settings.get(ModpackInfoPage.MODPACK_AUTHOR),
|
(String) settings.get(ModpackInfoPage.MODPACK_AUTHOR),
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ public final class ModpackFileSelectionPage extends StackPane implements WizardP
|
|||||||
FXUtils.loadFXML(this, "/assets/fxml/modpack/selection.fxml");
|
FXUtils.loadFXML(this, "/assets/fxml/modpack/selection.fxml");
|
||||||
rootNode = getTreeItem(profile.getRepository().getRunDirectory(version), "minecraft");
|
rootNode = getTreeItem(profile.getRepository().getRunDirectory(version), "minecraft");
|
||||||
treeView.setRoot(rootNode);
|
treeView.setRoot(rootNode);
|
||||||
treeView.setSelectionModel(NoneMultipleSelectionModel.getInstance());
|
treeView.setSelectionModel(new NoneMultipleSelectionModel<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
private CheckBoxTreeItem<String> getTreeItem(File file, String basePath) {
|
private CheckBoxTreeItem<String> getTreeItem(File file, String basePath) {
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ public class AppDataUpgrader extends IUpgrader {
|
|||||||
al.add("--noupdate");
|
al.add("--noupdate");
|
||||||
AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> {
|
AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> {
|
||||||
new URLClassLoader(new URL[]{jar.toURI().toURL()},
|
new URLClassLoader(new URL[]{jar.toURI().toURL()},
|
||||||
URLClassLoader.getSystemClassLoader().getParent()).loadClass(mainClass)
|
ClassLoader.getSystemClassLoader().getParent()).loadClass(mainClass)
|
||||||
.getMethod("main", String[].class).invoke(null, new Object[]{al.toArray(new String[0])});
|
.getMethod("main", String[].class).invoke(null, new Object[]{al.toArray(new String[0])});
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ public class OfflineAccount extends Account {
|
|||||||
throw new IllegalArgumentException("Username cannot be blank");
|
throw new IllegalArgumentException("Username cannot be blank");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public UUID getUUID() {
|
public UUID getUUID() {
|
||||||
return UUIDTypeAdapter.fromString(uuid);
|
return UUIDTypeAdapter.fromString(uuid);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
package org.jackhuang.hmcl.auth.yggdrasil;
|
package org.jackhuang.hmcl.auth.yggdrasil;
|
||||||
|
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import org.jackhuang.hmcl.util.Constants;
|
|
||||||
import org.jackhuang.hmcl.util.Immutable;
|
import org.jackhuang.hmcl.util.Immutable;
|
||||||
import org.jackhuang.hmcl.util.Lang;
|
import org.jackhuang.hmcl.util.JsonUtils;
|
||||||
import org.jackhuang.hmcl.util.NetworkUtils;
|
import org.jackhuang.hmcl.util.NetworkUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -36,7 +35,7 @@ public final class AuthlibInjectorBuildInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static AuthlibInjectorBuildInfo requestBuildInfo(String updateUrl) throws IOException, JsonParseException {
|
public static AuthlibInjectorBuildInfo requestBuildInfo(String updateUrl) throws IOException, JsonParseException {
|
||||||
return Lang.requireJsonNonNull(Constants.GSON.fromJson(NetworkUtils.doGet(NetworkUtils.toURL(updateUrl)), AuthlibInjectorBuildInfo.class));
|
return JsonUtils.fromNonNullJson(NetworkUtils.doGet(NetworkUtils.toURL(updateUrl)), AuthlibInjectorBuildInfo.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String UPDATE_URL = "https://authlib-injector.to2mbn.org/api/buildInfo";
|
public static final String UPDATE_URL = "https://authlib-injector.to2mbn.org/api/buildInfo";
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ public class DefaultLauncher extends Launcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final Map<String, Supplier<Boolean>> forbiddens = Lang.mapOf(
|
private final Map<String, Supplier<Boolean>> forbiddens = Lang.mapOf(
|
||||||
new Pair<>("-Xincgc", () -> options.getJava().getParsedVersion() >= JavaVersion.JAVA_9)
|
new Pair<String, Supplier<Boolean>>("-Xincgc", () -> options.getJava().getParsedVersion() >= JavaVersion.JAVA_9)
|
||||||
);
|
);
|
||||||
|
|
||||||
protected Map<String, Supplier<Boolean>> getForbiddens() {
|
protected Map<String, Supplier<Boolean>> getForbiddens() {
|
||||||
|
|||||||
@@ -20,15 +20,13 @@ package org.jackhuang.hmcl.mod;
|
|||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
import org.jackhuang.hmcl.util.CompressingUtils;
|
import org.jackhuang.hmcl.util.CompressingUtils;
|
||||||
import org.jackhuang.hmcl.util.Constants;
|
|
||||||
import org.jackhuang.hmcl.util.Immutable;
|
import org.jackhuang.hmcl.util.Immutable;
|
||||||
import org.jackhuang.hmcl.util.Lang;
|
import org.jackhuang.hmcl.util.JsonUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -120,7 +118,7 @@ public final class CurseManifest {
|
|||||||
*/
|
*/
|
||||||
public static Modpack readCurseForgeModpackManifest(File f) throws IOException, JsonParseException {
|
public static Modpack readCurseForgeModpackManifest(File f) throws IOException, JsonParseException {
|
||||||
String json = CompressingUtils.readTextZipEntry(f, "manifest.json");
|
String json = CompressingUtils.readTextZipEntry(f, "manifest.json");
|
||||||
CurseManifest manifest = Lang.requireJsonNonNull(Constants.GSON.fromJson(json, CurseManifest.class));
|
CurseManifest manifest = JsonUtils.fromNonNullJson(json, CurseManifest.class);
|
||||||
return new Modpack(manifest.getName(), manifest.getAuthor(), manifest.getVersion(), manifest.getMinecraft().getGameVersion(),
|
return new Modpack(manifest.getName(), manifest.getAuthor(), manifest.getVersion(), manifest.getMinecraft().getGameVersion(),
|
||||||
CompressingUtils.readTextZipEntryQuietly(f, "modlist.html").orElse( "No description"), manifest);
|
CompressingUtils.readTextZipEntryQuietly(f, "modlist.html").orElse( "No description"), manifest);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,4 +94,8 @@ public final class Constants {
|
|||||||
public static <T> Predicate<T> falsePredicate() {
|
public static <T> Predicate<T> falsePredicate() {
|
||||||
return s -> false;
|
return s -> false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <T> Consumer<T> emptyConsumer() {
|
||||||
|
return x -> {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ public class ImmediateBooleanProperty extends SimpleBooleanProperty {
|
|||||||
super.unbind();
|
super.unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Consumer<Boolean> listener = Lang.EMPTY_CONSUMER;
|
private Consumer<Boolean> listener = Constants.emptyConsumer();
|
||||||
private final ChangeListener<Boolean> changeListener = (a, b, newValue) -> listener.accept(newValue);
|
private final ChangeListener<Boolean> changeListener = (a, b, newValue) -> listener.accept(newValue);
|
||||||
|
|
||||||
public void setChangedListener(Consumer<Boolean> listener) {
|
public void setChangedListener(Consumer<Boolean> listener) {
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ public class ImmediateDoubleProperty extends SimpleDoubleProperty {
|
|||||||
super.unbind();
|
super.unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Consumer<Double> listener = Lang.EMPTY_CONSUMER;
|
private Consumer<Double> listener = Constants.emptyConsumer();
|
||||||
private final ChangeListener<Number> changeListener = (a, b, newValue) -> listener.accept(newValue.doubleValue());
|
private final ChangeListener<Number> changeListener = (a, b, newValue) -> listener.accept(newValue.doubleValue());
|
||||||
|
|
||||||
public void setChangedListener(Consumer<Double> listener) {
|
public void setChangedListener(Consumer<Double> listener) {
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ public class ImmediateIntegerProperty extends SimpleIntegerProperty {
|
|||||||
super.unbind();
|
super.unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Consumer<Integer> listener = Lang.EMPTY_CONSUMER;
|
private Consumer<Integer> listener = Constants.emptyConsumer();
|
||||||
private final ChangeListener<Number> changeListener = (a, b, newValue) -> listener.accept(newValue.intValue());
|
private final ChangeListener<Number> changeListener = (a, b, newValue) -> listener.accept(newValue.intValue());
|
||||||
|
|
||||||
public void setChangedListener(Consumer<Integer> listener) {
|
public void setChangedListener(Consumer<Integer> listener) {
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ public class ImmediateObjectProperty<T> extends SimpleObjectProperty<T> {
|
|||||||
super.unbind();
|
super.unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Consumer<T> listener = Lang.EMPTY_CONSUMER;
|
private Consumer<T> listener = Constants.emptyConsumer();
|
||||||
private final ChangeListener<T> changeListener = (a, b, newValue) -> listener.accept(newValue);
|
private final ChangeListener<T> changeListener = (a, b, newValue) -> listener.accept(newValue);
|
||||||
|
|
||||||
public void setChangedListener(Consumer<T> listener) {
|
public void setChangedListener(Consumer<T> listener) {
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package org.jackhuang.hmcl.util;
|
||||||
|
|
||||||
|
import com.google.gson.JsonParseException;
|
||||||
|
|
||||||
|
public final class JsonUtils {
|
||||||
|
|
||||||
|
private JsonUtils() {}
|
||||||
|
|
||||||
|
public static <T> T fromNonNullJson(String json, Class<T> classOfT) throws JsonParseException {
|
||||||
|
T parsed = Constants.GSON.fromJson(json, classOfT);
|
||||||
|
if (parsed == null)
|
||||||
|
throw new JsonParseException("Json object cannot be null.");
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,8 +5,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.util;
|
package org.jackhuang.hmcl.util;
|
||||||
|
|
||||||
import com.google.gson.JsonParseException;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
@@ -22,19 +20,7 @@ public final class Lang {
|
|||||||
private Lang() {
|
private Lang() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final Consumer EMPTY_CONSUMER = a -> {
|
@SafeVarargs
|
||||||
};
|
|
||||||
|
|
||||||
public static <T> T requireJsonNonNull(T obj) throws JsonParseException {
|
|
||||||
return requireJsonNonNull(obj, "Json object cannot be null.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T requireJsonNonNull(T obj, String message) throws JsonParseException {
|
|
||||||
if (obj == null)
|
|
||||||
throw new JsonParseException(message);
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <K, V> Map<K, V> mapOf(Pair<K, V>... pairs) {
|
public static <K, V> Map<K, V> mapOf(Pair<K, V>... pairs) {
|
||||||
HashMap<K, V> map = new HashMap<>();
|
HashMap<K, V> map = new HashMap<>();
|
||||||
for (Pair<K, V> pair : pairs)
|
for (Pair<K, V> pair : pairs)
|
||||||
@@ -42,14 +28,14 @@ public final class Lang {
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <K, V> V getOrPut(Map<K, V> map, K key, Supplier<V> defaultValue) {
|
public static <K, V> V computeIfAbsent(Map<K, V> map, K key, Supplier<V> computingFunction) {
|
||||||
V value = map.get(key);
|
V value = map.get(key);
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
V answer = defaultValue.get();
|
V newValue = computingFunction.get();
|
||||||
map.put(key, answer);
|
map.put(key, newValue);
|
||||||
return answer;
|
return newValue;
|
||||||
} else
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <E extends Throwable> void throwable(Throwable exception) throws E {
|
public static <E extends Throwable> void throwable(Throwable exception) throws E {
|
||||||
@@ -230,8 +216,8 @@ public final class Lang {
|
|||||||
return convert(map.get(key), clazz, defaultValue);
|
return convert(map.get(key), clazz, defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> List<T> merge(Collection<T> a, Collection<T> b) {
|
public static <T> List<T> merge(Collection<? extends T> a, Collection<? extends T> b) {
|
||||||
LinkedList<T> result = new LinkedList<>();
|
List<T> result = new ArrayList<>();
|
||||||
if (a != null)
|
if (a != null)
|
||||||
result.addAll(a);
|
result.addAll(a);
|
||||||
if (b != null)
|
if (b != null)
|
||||||
@@ -239,17 +225,6 @@ public final class Lang {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> List<T> merge(Collection<T> a, Collection<T> b, Collection<T> c) {
|
|
||||||
LinkedList<T> result = new LinkedList<>();
|
|
||||||
if (a != null)
|
|
||||||
result.addAll(a);
|
|
||||||
if (b != null)
|
|
||||||
result.addAll(b);
|
|
||||||
if (c != null)
|
|
||||||
result.addAll(c);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void executeDelayed(Runnable runnable, TimeUnit timeUnit, long timeout, boolean isDaemon) {
|
public static void executeDelayed(Runnable runnable, TimeUnit timeUnit, long timeout, boolean isDaemon) {
|
||||||
thread(() -> {
|
thread(() -> {
|
||||||
try {
|
try {
|
||||||
@@ -322,6 +297,7 @@ public final class Lang {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SafeVarargs
|
||||||
public static <T> T nonNull(T... t) {
|
public static <T> T nonNull(T... t) {
|
||||||
for (T a : t) if (a != null) return a;
|
for (T a : t) if (a != null) return a;
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -17,10 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.util;
|
package org.jackhuang.hmcl.util;
|
||||||
|
|
||||||
import javax.net.ssl.HostnameVerifier;
|
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
|
||||||
import javax.net.ssl.SSLContext;
|
|
||||||
import javax.net.ssl.X509TrustManager;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
@@ -28,9 +24,6 @@ import java.net.HttpURLConnection;
|
|||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.Proxy;
|
import java.net.Proxy;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.security.GeneralSecurityException;
|
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.security.cert.X509Certificate;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
@@ -46,41 +39,6 @@ public final class NetworkUtils {
|
|||||||
private NetworkUtils() {
|
private NetworkUtils() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final X509TrustManager XTM = new X509TrustManager() {
|
|
||||||
@Override
|
|
||||||
public void checkClientTrusted(X509Certificate[] xcs, String string) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void checkServerTrusted(X509Certificate[] xcs, String string) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public X509Certificate[] getAcceptedIssuers() {
|
|
||||||
return new X509Certificate[0];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private static final HostnameVerifier HNV = (a, b) -> true;
|
|
||||||
|
|
||||||
private static volatile boolean initHttps = false;
|
|
||||||
|
|
||||||
private static synchronized void initHttps() {
|
|
||||||
if (initHttps)
|
|
||||||
return;
|
|
||||||
|
|
||||||
initHttps = true;
|
|
||||||
|
|
||||||
System.setProperty("https.protocols", "SSLv3,TLSv1");
|
|
||||||
try {
|
|
||||||
SSLContext c = SSLContext.getInstance("SSL");
|
|
||||||
c.init(null, new X509TrustManager[] { XTM }, new SecureRandom());
|
|
||||||
HttpsURLConnection.setDefaultSSLSocketFactory(c.getSocketFactory());
|
|
||||||
} catch (GeneralSecurityException ignore) {
|
|
||||||
}
|
|
||||||
HttpsURLConnection.setDefaultHostnameVerifier(HNV);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Supplier<String> userAgentSupplier = RandomUserAgent::randomUserAgent;
|
private static Supplier<String> userAgentSupplier = RandomUserAgent::randomUserAgent;
|
||||||
|
|
||||||
public static String getUserAgent() {
|
public static String getUserAgent() {
|
||||||
@@ -92,7 +50,6 @@ public final class NetworkUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static HttpURLConnection createConnection(URL url, Proxy proxy) throws IOException {
|
public static HttpURLConnection createConnection(URL url, Proxy proxy) throws IOException {
|
||||||
initHttps();
|
|
||||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection(proxy);
|
HttpURLConnection connection = (HttpURLConnection) url.openConnection(proxy);
|
||||||
connection.setDoInput(true);
|
connection.setDoInput(true);
|
||||||
connection.setUseCaches(false);
|
connection.setUseCaches(false);
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ package org.jackhuang.hmcl.util;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optifine has blocked Java's useragent, so we have to make up one.
|
||||||
|
*/
|
||||||
public class RandomUserAgent {
|
public class RandomUserAgent {
|
||||||
|
|
||||||
private static final HashMap<String, String[]> uaMap = new HashMap<>();
|
private static final HashMap<String, String[]> uaMap = new HashMap<>();
|
||||||
|
|||||||
@@ -52,14 +52,14 @@ public final class ReflectionHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PRIMITIVES = Lang.mapOf(
|
PRIMITIVES = Lang.mapOf(
|
||||||
new Pair("byte", Byte.class),
|
new Pair<>("byte", Byte.class),
|
||||||
new Pair("short", Short.class),
|
new Pair<>("short", Short.class),
|
||||||
new Pair("int", Integer.class),
|
new Pair<>("int", Integer.class),
|
||||||
new Pair("long", Long.class),
|
new Pair<>("long", Long.class),
|
||||||
new Pair("char", Character.class),
|
new Pair<>("char", Character.class),
|
||||||
new Pair("float", Float.class),
|
new Pair<>("float", Float.class),
|
||||||
new Pair("double", Double.class),
|
new Pair<>("double", Double.class),
|
||||||
new Pair("boolean", Boolean.class)
|
new Pair<>("boolean", Boolean.class)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ public final class SimpleMultimap<K, V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Collection<V> get(K key) {
|
public Collection<V> get(K key) {
|
||||||
return Lang.getOrPut(map, key, valuer);
|
return Lang.computeIfAbsent(map, key, valuer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void put(K key, V value) {
|
public void put(K key, V value) {
|
||||||
|
|||||||
Reference in New Issue
Block a user