feat: check style & format

This commit is contained in:
huanghongxun
2021-05-30 03:34:44 +08:00
parent 6d75c4d34f
commit fc017515c5
68 changed files with 347 additions and 185 deletions

View File

@@ -163,7 +163,7 @@ public final class Launcher extends Application {
File jarFile = new File(Launcher.class.getProtectionDomain().getCodeSource().getLocation().getPath()); File jarFile = new File(Launcher.class.getProtectionDomain().getCodeSource().getLocation().getPath());
String ext = FileUtils.getExtension(jarFile); String ext = FileUtils.getExtension(jarFile);
if ("jar".equals(ext) || "exe".equals(ext)) if ("jar".equals(ext) || "exe".equals(ext))
result.add(jarFile); result.add(jarFile);
} }
if (result.isEmpty()) if (result.isEmpty())
return null; return null;

View File

@@ -43,6 +43,9 @@ import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
public final class Main { public final class Main {
private Main() {
}
public static void main(String[] args) { public static void main(String[] args) {
System.setProperty("java.net.useSystemProxies", "true"); System.setProperty("java.net.useSystemProxies", "true");
System.setProperty("http.agent", "HMCL/" + Metadata.VERSION); System.setProperty("http.agent", "HMCL/" + Metadata.VERSION);

View File

@@ -31,15 +31,17 @@ import java.nio.file.Path;
* @author huangyuhui * @author huangyuhui
*/ */
public final class HMCLModpackManager { public final class HMCLModpackManager {
private HMCLModpackManager() {
}
/** /**
* Read the manifest in a HMCL modpack. * Read the manifest in a HMCL modpack.
* *
* @param file a HMCL modpack file. * @param file a HMCL modpack file.
* @param encoding encoding of modpack zip file. * @param encoding encoding of modpack zip file.
* @throws IOException if the file is not a valid zip file.
* @throws JsonParseException if the manifest.json is missing or malformed.
* @return the manifest of HMCL modpack. * @return the manifest of HMCL modpack.
* @throws IOException if the file is not a valid zip file.
* @throws JsonParseException if the manifest.json is missing or malformed.
*/ */
public static Modpack readHMCLModpackManifest(Path file, Charset encoding) throws IOException, JsonParseException { public static Modpack readHMCLModpackManifest(Path file, Charset encoding) throws IOException, JsonParseException {
String manifestJson = CompressingUtils.readTextZipEntry(file, "modpack.json", encoding); String manifestJson = CompressingUtils.readTextZipEntry(file, "modpack.json", encoding);

View File

@@ -26,11 +26,7 @@ import org.jackhuang.hmcl.Metadata;
import org.jackhuang.hmcl.auth.Account; import org.jackhuang.hmcl.auth.Account;
import org.jackhuang.hmcl.auth.ServerResponseMalformedException; import org.jackhuang.hmcl.auth.ServerResponseMalformedException;
import org.jackhuang.hmcl.auth.microsoft.MicrosoftAccount; import org.jackhuang.hmcl.auth.microsoft.MicrosoftAccount;
import org.jackhuang.hmcl.auth.yggdrasil.Texture; import org.jackhuang.hmcl.auth.yggdrasil.*;
import org.jackhuang.hmcl.auth.yggdrasil.TextureModel;
import org.jackhuang.hmcl.auth.yggdrasil.TextureType;
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount;
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilService;
import org.jackhuang.hmcl.task.FileDownloadTask; import org.jackhuang.hmcl.task.FileDownloadTask;
import org.jackhuang.hmcl.util.ResourceNotFoundError; import org.jackhuang.hmcl.util.ResourceNotFoundError;
import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.StringUtils;
@@ -39,13 +35,15 @@ import org.jackhuang.hmcl.util.javafx.BindingMapping;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import java.awt.*; import java.awt.*;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.*; import java.util.EnumMap;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;

View File

@@ -23,11 +23,11 @@ import org.jackhuang.hmcl.game.HMCLCacheRepository;
import org.jackhuang.hmcl.util.CacheRepository; import org.jackhuang.hmcl.util.CacheRepository;
import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.io.FileUtils;
import static org.jackhuang.hmcl.setting.ConfigHolder.config;
import java.util.Locale; import java.util.Locale;
public class Settings { import static org.jackhuang.hmcl.setting.ConfigHolder.config;
public final class Settings {
private static Settings instance; private static Settings instance;

View File

@@ -44,8 +44,6 @@ import java.util.stream.Collectors;
@JsonAdapter(VersionSetting.Serializer.class) @JsonAdapter(VersionSetting.Serializer.class)
public final class VersionSetting implements Cloneable { public final class VersionSetting implements Cloneable {
public transient String id;
private boolean global = false; private boolean global = false;
public boolean isGlobal() { public boolean isGlobal() {

View File

@@ -3,7 +3,10 @@ package org.jackhuang.hmcl.ui;
import java.awt.*; import java.awt.*;
import java.lang.reflect.Method; import java.lang.reflect.Method;
public class AwtUtils { public final class AwtUtils {
private AwtUtils() {
}
public static void setAppleIcon(Image image) { public static void setAppleIcon(Image image) {
try { try {
Class<?> taskbarClass = Class.forName("java.awt.TaskBar"); Class<?> taskbarClass = Class.forName("java.awt.TaskBar");

View File

@@ -66,6 +66,9 @@ public final class Controllers {
private static RootPage rootPage; private static RootPage rootPage;
private static DecoratorController decorator; private static DecoratorController decorator;
private Controllers() {
}
public static Scene getScene() { public static Scene getScene() {
return scene; return scene;
} }

View File

@@ -31,6 +31,8 @@ import java.util.concurrent.atomic.AtomicReference;
import static org.jackhuang.hmcl.ui.FXUtils.runInFX; import static org.jackhuang.hmcl.ui.FXUtils.runInFX;
public final class DialogController { public final class DialogController {
private DialogController() {
}
public static AuthInfo logIn(Account account) throws CancellationException, AuthenticationException, InterruptedException { public static AuthInfo logIn(Account account) throws CancellationException, AuthenticationException, InterruptedException {
if (account instanceof YggdrasilAccount) { if (account instanceof YggdrasilAccount) {
@@ -38,8 +40,8 @@ public final class DialogController {
AtomicReference<AuthInfo> res = new AtomicReference<>(null); AtomicReference<AuthInfo> res = new AtomicReference<>(null);
runInFX(() -> { runInFX(() -> {
AccountLoginPane pane = new AccountLoginPane(account, it -> { AccountLoginPane pane = new AccountLoginPane(account, it -> {
res.set(it); res.set(it);
latch.countDown(); latch.countDown();
}, latch::countDown); }, latch::countDown);
Controllers.dialog(pane); Controllers.dialog(pane);
}); });

View File

@@ -430,6 +430,7 @@ public final class FXUtils {
* You should <b>only and always</b> use {@code bindEnum} as well as {@code unbindEnum} at the same time. * You should <b>only and always</b> use {@code bindEnum} as well as {@code unbindEnum} at the same time.
* @param comboBox the combo box being bound with the property which can be inferred by {@code bindEnum}. * @param comboBox the combo box being bound with the property which can be inferred by {@code bindEnum}.
* @see #bindEnum(JFXComboBox, Property) * @see #bindEnum(JFXComboBox, Property)
* @deprecated Use {@link ExtendedProperties#selectedItemPropertyFor(ComboBox)}
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Deprecated @Deprecated

View File

@@ -102,11 +102,11 @@ public class InstallerItem extends Control {
} }
public static class InstallerItemGroup { public static class InstallerItemGroup {
public InstallerItem game = new InstallerItem(MINECRAFT); public final InstallerItem game = new InstallerItem(MINECRAFT);
public InstallerItem fabric = new InstallerItem(FABRIC); public final InstallerItem fabric = new InstallerItem(FABRIC);
public InstallerItem forge = new InstallerItem(FORGE); public final InstallerItem forge = new InstallerItem(FORGE);
public InstallerItem liteLoader = new InstallerItem(LITELOADER); public final InstallerItem liteLoader = new InstallerItem(LITELOADER);
public InstallerItem optiFine = new InstallerItem(OPTIFINE); public final InstallerItem optiFine = new InstallerItem(OPTIFINE);
public InstallerItemGroup() { public InstallerItemGroup() {
forge.incompatibleLibraryName.bind(Bindings.createStringBinding(() -> { forge.incompatibleLibraryName.bind(Bindings.createStringBinding(() -> {
@@ -133,7 +133,7 @@ public class InstallerItem extends Control {
} }
public InstallerItem[] getLibraries() { public InstallerItem[] getLibraries() {
return new InstallerItem[]{game, fabric, forge, liteLoader, optiFine}; return new InstallerItem[]{game, fabric, forge, liteLoader, optiFine};
} }
} }

View File

@@ -23,7 +23,10 @@ import javafx.util.Duration;
public interface AnimationHandler { public interface AnimationHandler {
Duration getDuration(); Duration getDuration();
Pane getCurrentRoot(); Pane getCurrentRoot();
Node getPreviousNode(); Node getPreviousNode();
Node getCurrentNode(); Node getCurrentNode();
} }

View File

@@ -99,9 +99,10 @@ public class FloatScrollBarSkin implements Skin<ScrollBar> {
// we're getting dragged without getting a mouse press // we're getting dragged without getting a mouse press
dragStart = thumb.localToParent(me.getX(), me.getY()); dragStart = thumb.localToParent(me.getX(), me.getY());
} }
double dragPos = getSkinnable().getOrientation() == Orientation.VERTICAL ? cur.getY() - dragStart.getY(): cur.getX() - dragStart.getX(); double dragPos = getSkinnable().getOrientation() == Orientation.VERTICAL ? cur.getY() - dragStart.getY() : cur.getX() - dragStart.getX();
double position = preDragThumbPos + dragPos / (trackLength() - thumbLength()); double position = preDragThumbPos + dragPos / (trackLength() - thumbLength());
if (!getSkinnable().isFocused() && getSkinnable().isFocusTraversable()) getSkinnable().requestFocus(); if (!getSkinnable().isFocused() && getSkinnable().isFocusTraversable())
getSkinnable().requestFocus();
double newValue = (position * (getSkinnable().getMax() - getSkinnable().getMin())) + getSkinnable().getMin(); double newValue = (position * (getSkinnable().getMax() - getSkinnable().getMin())) + getSkinnable().getMin();
if (!Double.isNaN(newValue)) { if (!Double.isNaN(newValue)) {
getSkinnable().setValue(Lang.clamp(getSkinnable().getMin(), newValue, getSkinnable().getMax())); getSkinnable().setValue(Lang.clamp(getSkinnable().getMin(), newValue, getSkinnable().getMax()));

View File

@@ -42,11 +42,11 @@ public class SpinnerPane extends Control {
private final BooleanProperty loading = new SimpleBooleanProperty(this, "loading"); private final BooleanProperty loading = new SimpleBooleanProperty(this, "loading");
public void showSpinner() { public void showSpinner() {
setLoading(true); setLoading(true);
} }
public void hideSpinner() { public void hideSpinner() {
setLoading(false); setLoading(false);
} }
public Node getContent() { public Node getContent() {
@@ -62,15 +62,15 @@ public class SpinnerPane extends Control {
} }
public boolean isLoading() { public boolean isLoading() {
return loading.get(); return loading.get();
} }
public BooleanProperty loadingProperty() { public BooleanProperty loadingProperty() {
return loading; return loading;
} }
public void setLoading(boolean loading) { public void setLoading(boolean loading) {
this.loading.set(loading); this.loading.set(loading);
} }
@Override @Override

View File

@@ -174,7 +174,7 @@ public interface TabControl {
} }
} }
public static class Tab { class Tab {
private final StringProperty id = new SimpleStringProperty(this, "id"); private final StringProperty id = new SimpleStringProperty(this, "id");
private final StringProperty text = new SimpleStringProperty(this, "text"); private final StringProperty text = new SimpleStringProperty(this, "text");
private final ReadOnlyBooleanWrapper selected = new ReadOnlyBooleanWrapper(this, "selected"); private final ReadOnlyBooleanWrapper selected = new ReadOnlyBooleanWrapper(this, "selected");

View File

@@ -25,7 +25,6 @@ import org.jackhuang.hmcl.ui.construct.PageCloseEvent;
import org.jackhuang.hmcl.ui.wizard.*; import org.jackhuang.hmcl.ui.wizard.*;
import java.util.Map; import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
public class DecoratorWizardDisplayer extends DecoratorTransitionPage implements WizardDisplayer { public class DecoratorWizardDisplayer extends DecoratorTransitionPage implements WizardDisplayer {

View File

@@ -87,21 +87,24 @@ public final class ModpackFileSelectionPage extends StackPane implements WizardP
if (file.isDirectory()) { if (file.isDirectory()) {
File[] files = file.listFiles(); File[] files = file.listFiles();
if (files != null) if (files != null) {
for (File it : files) { for (File it : files) {
CheckBoxTreeItem<String> subNode = getTreeItem(it, basePath + "/" + it.getName()); CheckBoxTreeItem<String> subNode = getTreeItem(it, basePath + "/" + it.getName());
if (subNode != null) { if (subNode != null) {
node.setSelected(subNode.isSelected() || node.isSelected()); node.setSelected(subNode.isSelected() || node.isSelected());
if (!subNode.isSelected()) if (!subNode.isSelected()) {
node.setIndeterminate(true); node.setIndeterminate(true);
node.getChildren().add(subNode); }
node.getChildren().add(subNode);
}
} }
} }
if (!node.isSelected()) node.setIndeterminate(false); if (!node.isSelected()) node.setIndeterminate(false);
// Empty folder need not to be displayed. // Empty folder need not to be displayed.
if (node.getChildren().isEmpty()) if (node.getChildren().isEmpty()) {
return null; return null;
}
} }
HBox graphic = new HBox(); HBox graphic = new HBox();
@@ -130,8 +133,9 @@ public final class ModpackFileSelectionPage extends StackPane implements WizardP
if (basePath.length() > "minecraft/".length()) if (basePath.length() > "minecraft/".length())
list.add(StringUtils.substringAfter(basePath, "minecraft/")); list.add(StringUtils.substringAfter(basePath, "minecraft/"));
for (TreeItem<String> child : node.getChildren()) { for (TreeItem<String> child : node.getChildren()) {
if (child instanceof CheckBoxTreeItem) if (child instanceof CheckBoxTreeItem) {
getFilesNeeded(((CheckBoxTreeItem<String>) child), basePath + "/" + child.getValue(), list); getFilesNeeded(((CheckBoxTreeItem<String>) child), basePath + "/" + child.getValue(), list);
}
} }
} }
} }

View File

@@ -535,8 +535,12 @@ public abstract class SettingsView extends StackPane {
} }
protected abstract void onUpdate(); protected abstract void onUpdate();
protected abstract void onHelp(); protected abstract void onHelp();
protected abstract void onExportLogs(); protected abstract void onExportLogs();
protected abstract void onSponsor(); protected abstract void onSponsor();
protected abstract void clearCacheDirectory(); protected abstract void clearCacheDirectory();
} }

View File

@@ -68,6 +68,7 @@ public final class ProfilePage extends StackPane implements DecoratorPage {
{ {
setMessage(i18n("profile.already_exists")); setMessage(i18n("profile.already_exists"));
} }
@Override @Override
protected void eval() { protected void eval() {
JFXTextField control = (JFXTextField) this.getSrcControl(); JFXTextField control = (JFXTextField) this.getSrcControl();

View File

@@ -36,7 +36,10 @@ import javafx.scene.layout.VBox;
import javafx.stage.FileChooser; import javafx.stage.FileChooser;
import org.jackhuang.hmcl.game.GameDirectoryType; import org.jackhuang.hmcl.game.GameDirectoryType;
import org.jackhuang.hmcl.game.NativesDirectoryType; import org.jackhuang.hmcl.game.NativesDirectoryType;
import org.jackhuang.hmcl.setting.*; import org.jackhuang.hmcl.setting.LauncherVisibility;
import org.jackhuang.hmcl.setting.Profile;
import org.jackhuang.hmcl.setting.Profiles;
import org.jackhuang.hmcl.setting.VersionSetting;
import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Schedulers;
import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.Controllers;

View File

@@ -46,7 +46,9 @@ import java.util.logging.Level;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n; import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
public class Versions { public final class Versions {
private Versions() {
}
public static void deleteVersion(Profile profile, String version) { public static void deleteVersion(Profile profile, String version) {
boolean isIndependent = profile.getVersionSetting(version).getGameDirType() == GameDirectoryType.VERSION_FOLDER; boolean isIndependent = profile.getVersionSetting(version).getGameDirType() == GameDirectoryType.VERSION_FOLDER;
@@ -156,7 +158,7 @@ public class Versions {
Controllers.getRootPage().checkAccount(); Controllers.getRootPage().checkAccount();
else if (id == null || !profile.getRepository().isLoaded() || !profile.getRepository().hasVersion(id)) else if (id == null || !profile.getRepository().isLoaded() || !profile.getRepository().hasVersion(id))
Controllers.dialog(i18n("version.empty.launch"), i18n("launch.failed"), MessageDialogPane.MessageType.ERROR, () -> { Controllers.dialog(i18n("version.empty.launch"), i18n("launch.failed"), MessageDialogPane.MessageType.ERROR, () -> {
Controllers.getRootPage().getSelectionModel().select(Controllers.getRootPage().getGameTab()); Controllers.getRootPage().getSelectionModel().select(Controllers.getRootPage().getGameTab());
}); });
else else
return true; return true;

View File

@@ -50,7 +50,6 @@ public class WorldExportPage extends WizardSinglePage {
return new WorldExportPageSkin(this); return new WorldExportPageSkin(this);
} }
public StringProperty pathProperty() { public StringProperty pathProperty() {
return path; return path;
} }

View File

@@ -94,5 +94,4 @@ public class WorldExportPageSkin extends SkinBase<WorldExportPage> {
getChildren().setAll(container); getChildren().setAll(container);
} }
} }

View File

@@ -22,11 +22,17 @@ import org.jackhuang.hmcl.ui.animation.ContainerAnimations;
public interface Navigation { public interface Navigation {
void onStart(); void onStart();
void onNext(); void onNext();
void onPrev(boolean cleanUp); void onPrev(boolean cleanUp);
boolean canPrev(); boolean canPrev();
void onFinish(); void onFinish();
void onEnd(); void onEnd();
void onCancel(); void onCancel();
enum NavigationDirection { enum NavigationDirection {

View File

@@ -23,9 +23,13 @@ import java.util.Map;
public interface WizardProvider { public interface WizardProvider {
void start(Map<String, Object> settings); void start(Map<String, Object> settings);
Object finish(Map<String, Object> settings); Object finish(Map<String, Object> settings);
Node createPage(WizardController controller, int step, Map<String, Object> settings); Node createPage(WizardController controller, int step, Map<String, Object> settings);
boolean cancel(); boolean cancel();
default boolean cancelIfCannotGoBack() { default boolean cancelIfCannotGoBack() {
return false; return false;
} }

View File

@@ -8,7 +8,10 @@ import java.util.Set;
* *
* @author ZekerZhayard * @author ZekerZhayard
*/ */
public class JavaFXPatcher { public final class JavaFXPatcher {
private JavaFXPatcher() {
}
public static void patch(Set<String> modules, Path... jarPaths) { public static void patch(Set<String> modules, Path... jarPaths) {
// Nothing to do with Java 8 // Nothing to do with Java 8
} }

View File

@@ -30,7 +30,10 @@ import static org.jackhuang.hmcl.util.platform.JavaVersion.CURRENT_JAVA;
* *
* @author Matt * @author Matt
*/ */
public class SelfDependencyPatcher { public final class SelfDependencyPatcher {
private SelfDependencyPatcher() {
}
private static final Path DEPENDENCIES_DIR_PATH = HMCL_DIRECTORY.resolve("dependencies"); private static final Path DEPENDENCIES_DIR_PATH = HMCL_DIRECTORY.resolve("dependencies");
private static final String DEFAULT_JFX_VERSION = "16"; private static final String DEFAULT_JFX_VERSION = "16";
private static final Map<String, String> JFX_DEPENDENCIES = new HashMap<>(); private static final Map<String, String> JFX_DEPENDENCIES = new HashMap<>();
@@ -106,10 +109,8 @@ public class SelfDependencyPatcher {
/** /**
* Inject them into the current classpath. * Inject them into the current classpath.
* *
* @throws IOException * @throws IOException When the locally cached dependency urls cannot be resolved.
* When the locally cached dependency urls cannot be resolved. * @throws ReflectiveOperationException When the call to add these urls to the system classpath failed.
* @throws ReflectiveOperationException
* When the call to add these urls to the system classpath failed.
*/ */
private static void loadFromCache() throws IOException, ReflectiveOperationException { private static void loadFromCache() throws IOException, ReflectiveOperationException {
LOG.info(" - Loading dependencies..."); LOG.info(" - Loading dependencies...");

View File

@@ -28,6 +28,8 @@ import java.util.Locale;
import java.util.ResourceBundle; import java.util.ResourceBundle;
public final class Locales { public final class Locales {
private Locales() {
}
public static final SupportedLocale DEFAULT = new SupportedLocale(Locale.getDefault(), "lang.default"); public static final SupportedLocale DEFAULT = new SupportedLocale(Locale.getDefault(), "lang.default");
@@ -61,12 +63,18 @@ public final class Locales {
public static SupportedLocale getLocaleByName(String name) { public static SupportedLocale getLocaleByName(String name) {
if (name == null) return DEFAULT; if (name == null) return DEFAULT;
switch (name.toLowerCase()) { switch (name.toLowerCase()) {
case "en": return EN; case "en":
case "zh": return ZH; return EN;
case "zh_cn": return ZH_CN; case "zh":
case "es": return ES; return ZH;
case "ru": return RU; case "zh_cn":
default: return DEFAULT; return ZH_CN;
case "es":
return ES;
case "ru":
return RU;
default:
return DEFAULT;
} }
} }

View File

@@ -17,7 +17,10 @@ import jdk.internal.loader.BuiltinClassLoader;
* *
* @author ZekerZhayard * @author ZekerZhayard
*/ */
public class JavaFXPatcher { public final class JavaFXPatcher {
private JavaFXPatcher() {
}
private static final String[] addOpens = { private static final String[] addOpens = {
"javafx.base/com.sun.javafx.runtime", "javafx.base/com.sun.javafx.runtime",
"javafx.base/com.sun.javafx.binding", "javafx.base/com.sun.javafx.binding",

View File

@@ -17,19 +17,19 @@
*/ */
package org.jackhuang.hmcl.auth.authlibinjector; package org.jackhuang.hmcl.auth.authlibinjector;
import static org.jackhuang.hmcl.util.io.NetworkUtils.decodeURL;
import java.util.Optional;
import java.util.function.Consumer;
import javafx.event.EventHandler; import javafx.event.EventHandler;
import javafx.scene.input.DragEvent; import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard; import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode; import javafx.scene.input.TransferMode;
import java.util.Optional;
import java.util.function.Consumer;
import static org.jackhuang.hmcl.util.io.NetworkUtils.decodeURL;
/** /**
* @author yushijinhun * @author yushijinhun
* @see https://github.com/yushijinhun/authlib-injector/wiki/%E5%90%AF%E5%8A%A8%E5%99%A8%E6%8A%80%E6%9C%AF%E8%A7%84%E8%8C%83#dnd-%E6%96%B9%E5%BC%8F%E6%B7%BB%E5%8A%A0-yggdrasil-%E6%9C%8D%E5%8A%A1%E7%AB%AF * @see <a href="https://github.com/yushijinhun/authlib-injector/wiki/%E5%90%AF%E5%8A%A8%E5%99%A8%E6%8A%80%E6%9C%AF%E8%A7%84%E8%8C%83#dnd-%E6%96%B9%E5%BC%8F%E6%B7%BB%E5%8A%A0-yggdrasil-%E6%9C%8D%E5%8A%A1%E7%AB%AF">Launcher Technical Specification for Authlib-Injector</a>
*/ */
public final class AuthlibInjectorDnD { public final class AuthlibInjectorDnD {

View File

@@ -31,7 +31,7 @@ import static org.jackhuang.hmcl.util.Lang.tryCast;
* *
* @author huangyuhui * @author huangyuhui
*/ */
public class OfflineAccountFactory extends AccountFactory<OfflineAccount> { public final class OfflineAccountFactory extends AccountFactory<OfflineAccount> {
public static final OfflineAccountFactory INSTANCE = new OfflineAccountFactory(); public static final OfflineAccountFactory INSTANCE = new OfflineAccountFactory();
private OfflineAccountFactory() { private OfflineAccountFactory() {

View File

@@ -17,20 +17,13 @@
*/ */
package org.jackhuang.hmcl.auth.yggdrasil; package org.jackhuang.hmcl.auth.yggdrasil;
import static java.util.Collections.unmodifiableMap; import com.google.gson.*;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import com.google.gson.JsonArray; import static java.util.Collections.unmodifiableMap;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
public class PropertyMapSerializer implements JsonSerializer<Map<String, String>>, JsonDeserializer<Map<String, String>> { public class PropertyMapSerializer implements JsonSerializer<Map<String, String>>, JsonDeserializer<Map<String, String>> {

View File

@@ -17,8 +17,6 @@
*/ */
package org.jackhuang.hmcl.download; package org.jackhuang.hmcl.download;
import org.jackhuang.hmcl.util.io.NetworkUtils;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;

View File

@@ -38,7 +38,7 @@ public abstract class GameBuilder {
} }
/** /**
* The new game version name, for .minecraft/<version name>. * The new game version name, for .minecraft/&lt;version name&gt;.
* *
* @param name the name of new game version. * @param name the name of new game version.
*/ */

View File

@@ -130,7 +130,7 @@ public class ForgeNewInstallTask extends Task<Version> {
@Override @Override
public void execute() throws Exception { public void execute() throws Exception {
Path temp = Files.createTempDirectory("forge_installer"); Path temp = Files.createTempDirectory("forge_installer");
int finished = 0; int finished = 0;
try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(installer)) { try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(installer)) {
List<ForgeNewInstallProfile.Processor> processors = profile.getProcessors(); List<ForgeNewInstallProfile.Processor> processors = profile.getProcessors();

View File

@@ -105,7 +105,6 @@ public final class GameAssetIndexDownloadTask extends Task<Void> {
dependencies.add(task); dependencies.add(task);
} }
public static class GameAssetIndexMalformedException extends IOException { public static class GameAssetIndexMalformedException extends IOException {
} }
} }

View File

@@ -19,12 +19,8 @@ package org.jackhuang.hmcl.download.game;
import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.DefaultDependencyManager;
import org.jackhuang.hmcl.download.LibraryAnalyzer; import org.jackhuang.hmcl.download.LibraryAnalyzer;
import org.jackhuang.hmcl.game.GameVersion;
import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.game.Version;
import org.jackhuang.hmcl.task.FileDownloadTask;
import org.jackhuang.hmcl.task.FileDownloadTask.IntegrityCheck;
import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.CacheRepository;
import org.jackhuang.hmcl.util.io.CompressingUtils; import org.jackhuang.hmcl.util.io.CompressingUtils;
import org.jackhuang.hmcl.util.versioning.VersionNumber; import org.jackhuang.hmcl.util.versioning.VersionNumber;
@@ -33,11 +29,9 @@ import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem; import java.nio.file.FileSystem;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Optional;
/** /**
* Remove class digital verification file in game jar * Remove class digital verification file in game jar

View File

@@ -17,6 +17,8 @@ import java.util.logging.Level;
import static org.jackhuang.hmcl.util.Logging.LOG; import static org.jackhuang.hmcl.util.Logging.LOG;
public final class JavaRepository { public final class JavaRepository {
private JavaRepository() {
}
public static Task<?> downloadJava(GameJavaVersion javaVersion, DownloadProvider downloadProvider) { public static Task<?> downloadJava(GameJavaVersion javaVersion, DownloadProvider downloadProvider) {
return new JavaDownloadTask(javaVersion, getJavaStoragePath(), downloadProvider) return new JavaDownloadTask(javaVersion, getJavaStoragePath(), downloadProvider)

View File

@@ -199,10 +199,10 @@ public final class OptiFineInstallTask extends Task<Version> {
* Install OptiFine library from existing local file. * Install OptiFine library from existing local file.
* *
* @param dependencyManager game repository * @param dependencyManager game repository
* @param version version.json * @param version version.json
* @param installer the OptiFine installer * @param installer the OptiFine installer
* @return the task to install library * @return the task to install library
* @throws IOException if unable to read compressed content of installer file, or installer file is corrupted, or the installer is not the one we want. * @throws IOException if unable to read compressed content of installer file, or installer file is corrupted, or the installer is not the one we want.
* @throws VersionMismatchException if required game version of installer does not match the actual one. * @throws VersionMismatchException if required game version of installer does not match the actual one.
*/ */
public static Task<Version> install(DefaultDependencyManager dependencyManager, Version version, Path installer) throws IOException, VersionMismatchException { public static Task<Version> install(DefaultDependencyManager dependencyManager, Version version, Path installer) throws IOException, VersionMismatchException {
@@ -227,7 +227,7 @@ public final class OptiFineInstallTask extends Task<Version> {
throw new VersionMismatchException(mcVersion, gameVersion.get()); throw new VersionMismatchException(mcVersion, gameVersion.get());
return new OptiFineInstallTask(dependencyManager, version, return new OptiFineInstallTask(dependencyManager, version,
new OptiFineRemoteVersion(mcVersion, ofEdition + "_" + ofRelease, Collections.singletonList(""), false), installer); new OptiFineRemoteVersion(mcVersion, ofEdition + "_" + ofRelease, Collections.singletonList(""), false), installer);
} }
} }
} }

View File

@@ -22,7 +22,7 @@ import org.jackhuang.hmcl.util.platform.ManagedProcess;
/** /**
* This event gets fired when a JavaProcess exited abnormally and the exit code is not zero. * This event gets fired when a JavaProcess exited abnormally and the exit code is not zero.
* <br></br> *
* This event is fired on the {@link org.jackhuang.hmcl.event.EventBus#EVENT_BUS} * This event is fired on the {@link org.jackhuang.hmcl.event.EventBus#EVENT_BUS}
* *
* @author huangyuhui * @author huangyuhui
@@ -34,7 +34,7 @@ public final class ProcessExitedAbnormallyEvent extends Event {
/** /**
* Constructor. * Constructor.
* *
* @param source {@link org.jackhuang.hmcl.launch.ExitWaiter} * @param source {@link org.jackhuang.hmcl.launch.ExitWaiter}
* @param process The process that exited abnormally. * @param process The process that exited abnormally.
*/ */
public ProcessExitedAbnormallyEvent(Object source, ManagedProcess process) { public ProcessExitedAbnormallyEvent(Object source, ManagedProcess process) {

View File

@@ -29,7 +29,7 @@ public final class RefreshedVersionsEvent extends Event {
/** /**
* Constructor. * Constructor.
* *
* @param source {@link org.jackhuang.hmcl.game.GameRepository] * @param source {@link org.jackhuang.hmcl.game.GameRepository}
*/ */
public RefreshedVersionsEvent(Object source) { public RefreshedVersionsEvent(Object source) {
super(source); super(source);

View File

@@ -88,7 +88,7 @@ public interface GameRepository extends VersionProvider {
/** /**
* Gets the root folder of specific version. * Gets the root folder of specific version.
* The root folders the versions must be unique. * The root folders the versions must be unique.
* For example, .minecraft/versions/<version name>/. * For example, .minecraft/versions/&lt;version name&gt;/.
*/ */
File getVersionRoot(String id); File getVersionRoot(String id);

View File

@@ -45,6 +45,9 @@ import static org.jackhuang.hmcl.util.Logging.LOG;
* @author huangyuhui * @author huangyuhui
*/ */
public final class GameVersion { public final class GameVersion {
private GameVersion() {
}
private static Optional<String> getVersionFromJson(Path versionJson) { private static Optional<String> getVersionFromJson(Path versionJson) {
try { try {
Map<?, ?> version = JsonUtils.fromNonNullJson(FileUtils.readText(versionJson), Map.class); Map<?, ?> version = JsonUtils.fromNonNullJson(FileUtils.readText(versionJson), Map.class);

View File

@@ -68,7 +68,7 @@ public final class FabricModMetadata {
FabricModMetadata metadata = JsonUtils.fromNonNullJson(FileUtils.readText(mcmod), FabricModMetadata.class); FabricModMetadata metadata = JsonUtils.fromNonNullJson(FileUtils.readText(mcmod), FabricModMetadata.class);
String authors = metadata.authors == null ? "" : metadata.authors.stream().map(author -> author.name).collect(Collectors.joining(", ")); String authors = metadata.authors == null ? "" : metadata.authors.stream().map(author -> author.name).collect(Collectors.joining(", "));
return new ModInfo(modManager, modFile, metadata.name, new ModInfo.Description(metadata.description), return new ModInfo(modManager, modFile, metadata.name, new ModInfo.Description(metadata.description),
authors, metadata.version, "", metadata.contact != null ? metadata.contact.getOrDefault("homepage", "") : ""); authors, metadata.version, "", metadata.contact != null ? metadata.contact.getOrDefault("homepage", "") : "");
} }
} }

View File

@@ -67,9 +67,9 @@ public final class ModInfo implements Comparable<ModInfo> {
try { try {
if (get()) if (get())
ModInfo.this.file = modManager.enableMod(path); ModInfo.this.file = modManager.enableMod(path);
else else
ModInfo.this.file = modManager.disableMod(path); ModInfo.this.file = modManager.disableMod(path);
} catch (IOException e) { } catch (IOException e) {
Logging.LOG.log(Level.SEVERE, "Unable to invert state of mod file " + path, e); Logging.LOG.log(Level.SEVERE, "Unable to invert state of mod file " + path, e);
} }

View File

@@ -36,7 +36,7 @@ public final class ModpackConfiguration<T> implements Validation {
private final List<FileInformation> overrides; private final List<FileInformation> overrides;
public ModpackConfiguration() { public ModpackConfiguration() {
this(null, null, "", null, Collections.emptyList()); this(null, null, "", null, Collections.emptyList());
} }
public ModpackConfiguration(T manifest, String type, String name, String version, List<FileInformation> overrides) { public ModpackConfiguration(T manifest, String type, String name, String version, List<FileInformation> overrides) {
@@ -110,6 +110,7 @@ public final class ModpackConfiguration<T> implements Validation {
/** /**
* The relative path to Minecraft run directory * The relative path to Minecraft run directory
*
* @return the relative path to Minecraft run directory. * @return the relative path to Minecraft run directory.
*/ */
public String getPath() { public String getPath() {

View File

@@ -23,7 +23,7 @@ import org.jackhuang.hmcl.util.Immutable;
/** /**
* CurseMetaMod is JSON structure for * CurseMetaMod is JSON structure for
* https://cursemeta.dries007.net/&lt;projectID&gt;/&lt;fileID&gt;.json * https://cursemeta.dries007.net/&lt;projectID&gt;/&lt;fileID&gt;.json
* https://addons-ecs.forgesvc.net/api/v2/addon/&lt;projectID&gt;/file/<fileID&gt; * https://addons-ecs.forgesvc.net/api/v2/addon/&lt;projectID&gt;/file/&lt;fileID&gt;
*/ */
@Immutable @Immutable
public final class CurseMetaMod { public final class CurseMetaMod {

View File

@@ -79,8 +79,6 @@ public final class MultiMCManifest {
@SerializedName("suggests") @SerializedName("suggests")
private final String suggests; private final String suggests;
public MultiMCManifestCachedRequires(String equalsVersion, String uid, String suggests) { public MultiMCManifestCachedRequires(String equalsVersion, String uid, String suggests) {
this.equalsVersion = equalsVersion; this.equalsVersion = equalsVersion;
this.uid = uid; this.uid = uid;

View File

@@ -169,11 +169,11 @@ public final class MultiMCModpackInstallTask extends Task<Void> {
Path libraries = root.resolve("libraries"); Path libraries = root.resolve("libraries");
if (Files.exists(libraries)) if (Files.exists(libraries))
FileUtils.copyDirectory(libraries, repository.getVersionRoot(name).toPath().resolve("libraries")); FileUtils.copyDirectory(libraries, repository.getVersionRoot(name).toPath().resolve("libraries"));
Path jarmods = root.resolve("jarmods"); Path jarmods = root.resolve("jarmods");
if (Files.exists(jarmods)) if (Files.exists(jarmods))
FileUtils.copyDirectory(jarmods, repository.getVersionRoot(name).toPath().resolve("jarmods")); FileUtils.copyDirectory(jarmods, repository.getVersionRoot(name).toPath().resolve("jarmods"));
} }
dependencies.add(repository.saveAsync(version)); dependencies.add(repository.saveAsync(version));

View File

@@ -280,7 +280,6 @@ public abstract class Task<T> {
*/ */
public void postExecute() throws Exception {} public void postExecute() throws Exception {}
/** /**
* The collection of sub-tasks that should execute **before** this task running. * The collection of sub-tasks that should execute **before** this task running.
*/ */

View File

@@ -54,6 +54,7 @@ public enum Log4jLevel {
public boolean lessOrEqual(Log4jLevel level) { public boolean lessOrEqual(Log4jLevel level) {
return this.level <= level.level; return this.level <= level.level;
} }
public static final Pattern MINECRAFT_LOGGER = Pattern.compile("\\[(?<timestamp>[0-9:]+)] \\[[^/]+/(?<level>[^]]+)]"); public static final Pattern MINECRAFT_LOGGER = Pattern.compile("\\[(?<timestamp>[0-9:]+)] \\[[^/]+/(?<level>[^]]+)]");
public static final Pattern MINECRAFT_LOGGER_CATEGORY = Pattern.compile("\\[(?<timestamp>[0-9:]+)] \\[[^/]+/(?<level>[^]]+)] \\[(?<category>[^]]+)]"); public static final Pattern MINECRAFT_LOGGER_CATEGORY = Pattern.compile("\\[(?<timestamp>[0-9:]+)] \\[[^/]+/(?<level>[^]]+)] \\[(?<category>[^]]+)]");
public static final String JAVA_SYMBOL = "([a-zA-Z_$][a-zA-Z\\d_$]*\\.)+[a-zA-Z_$][a-zA-Z\\d_$]*"; public static final String JAVA_SYMBOL = "([a-zA-Z_$][a-zA-Z\\d_$]*\\.)+[a-zA-Z_$][a-zA-Z\\d_$]*";

View File

@@ -31,6 +31,8 @@ import java.util.logging.*;
* @author huangyuhui * @author huangyuhui
*/ */
public final class Logging { public final class Logging {
private Logging() {
}
public static final Logger LOG = Logger.getLogger("HMCL"); public static final Logger LOG = Logger.getLogger("HMCL");
private static ByteArrayOutputStream storedLogs = new ByteArrayOutputStream(); private static ByteArrayOutputStream storedLogs = new ByteArrayOutputStream();

View File

@@ -24,7 +24,7 @@ import java.util.Objects;
* *
* @author huangyuhui * @author huangyuhui
*/ */
public class Pair<K, V> implements Map.Entry<K, V> { public final class Pair<K, V> implements Map.Entry<K, V> {
public static <K, V> Pair<K, V> pair(K key, V value) { public static <K, V> Pair<K, V> pair(K key, V value) {
return new Pair<>(key, value); return new Pair<>(key, value);

View File

@@ -27,13 +27,16 @@ import java.util.function.Predicate;
* @author huangyuhui * @author huangyuhui
*/ */
public final class ReflectionHelper { public final class ReflectionHelper {
private ReflectionHelper() {
}
private static Method accessible0; private static Method accessible0;
static { static {
try { try {
accessible0 = AccessibleObject.class.getDeclaredMethod("setAccessible0", boolean.class); accessible0 = AccessibleObject.class.getDeclaredMethod("setAccessible0", boolean.class);
accessible0.setAccessible(true); accessible0.setAccessible(true);
} catch (Throwable ex) { } catch (Throwable ignored) {
} }
} }
@@ -43,6 +46,7 @@ public final class ReflectionHelper {
/** /**
* Get caller, this method is caller sensitive. * Get caller, this method is caller sensitive.
*
* @param packageFilter returns false if we consider the given package is internal calls, not the caller * @param packageFilter returns false if we consider the given package is internal calls, not the caller
* @return the caller, method name, source file, line number * @return the caller, method name, source file, line number
*/ */

View File

@@ -67,7 +67,6 @@ public class JsonTypeAdapterFactory implements TypeAdapterFactory {
}; };
} }
private <T> TypeAdapter<T> createForJsonSubtype(Gson gson, TypeToken<T> type) { private <T> TypeAdapter<T> createForJsonSubtype(Gson gson, TypeToken<T> type) {
Class<? super T> rawType = type.getRawType(); Class<? super T> rawType = type.getRawType();
if (rawType.getSuperclass() == null) return null; if (rawType.getSuperclass() == null) return null;

View File

@@ -29,7 +29,7 @@ public interface Validation {
/** /**
* 1. Check some non-null fields and; * 1. Check some non-null fields and;
* 2. Check strings and; * 2. Check strings and;
* 3. Check generic type of lists <T> and maps <K, V> are correct. * 3. Check generic type of lists &lt;T&gt; and maps &lt;K, V&gt; are correct.
* *
* Will be called immediately after initialization. * Will be called immediately after initialization.
* Throw an exception when values are malformed. * Throw an exception when values are malformed.

View File

@@ -21,9 +21,9 @@ import java.io.IOException;
public class ChecksumMismatchException extends IOException { public class ChecksumMismatchException extends IOException {
private String algorithm; private final String algorithm;
private String expectedChecksum; private final String expectedChecksum;
private String actualChecksum; private final String actualChecksum;
public ChecksumMismatchException(String algorithm, String expectedChecksum, String actualChecksum) { public ChecksumMismatchException(String algorithm, String expectedChecksum, String actualChecksum) {
super("Incorrect checksum (" + algorithm + "), expected: " + expectedChecksum + ", actual: " + actualChecksum); super("Incorrect checksum (" + algorithm + "), expected: " + expectedChecksum + ", actual: " + actualChecksum);

View File

@@ -124,10 +124,11 @@ public final class FileUtils {
/** /**
* Write plain text to file. Characters are encoded into bytes using UTF-8. * Write plain text to file. Characters are encoded into bytes using UTF-8.
* * <p>
* We don't care about platform difference of line separator. Because readText accept all possibilities of line separator. * We don't care about platform difference of line separator. Because readText accept all possibilities of line separator.
* It will create the file if it does not exist, or truncate the existing file to empty for rewriting. * It will create the file if it does not exist, or truncate the existing file to empty for rewriting.
* All characters in text will be written into the file in binary format. Existing data will be erased. * All characters in text will be written into the file in binary format. Existing data will be erased.
*
* @param file the path to the file * @param file the path to the file
* @param text the text being written to file * @param text the text being written to file
* @throws IOException if an I/O error occurs * @throws IOException if an I/O error occurs
@@ -138,12 +139,13 @@ public final class FileUtils {
/** /**
* Write plain text to file. * Write plain text to file.
* * <p>
* We don't care about platform difference of line separator. Because readText accept all possibilities of line separator. * We don't care about platform difference of line separator. Because readText accept all possibilities of line separator.
* It will create the file if it does not exist, or truncate the existing file to empty for rewriting. * It will create the file if it does not exist, or truncate the existing file to empty for rewriting.
* All characters in text will be written into the file in binary format. Existing data will be erased. * All characters in text will be written into the file in binary format. Existing data will be erased.
* @param file the path to the file *
* @param text the text being written to file * @param file the path to the file
* @param text the text being written to file
* @param charset the charset to use for encoding * @param charset the charset to use for encoding
* @throws IOException if an I/O error occurs * @throws IOException if an I/O error occurs
*/ */
@@ -155,7 +157,8 @@ public final class FileUtils {
* Write byte array to file. * Write byte array to file.
* It will create the file if it does not exist, or truncate the existing file to empty for rewriting. * It will create the file if it does not exist, or truncate the existing file to empty for rewriting.
* All bytes in byte array will be written into the file in binary format. Existing data will be erased. * All bytes in byte array will be written into the file in binary format. Existing data will be erased.
* @param file the path to the file *
* @param file the path to the file
* @param array the data being written to file * @param array the data being written to file
* @throws IOException if an I/O error occurs * @throws IOException if an I/O error occurs
*/ */
@@ -192,7 +195,7 @@ public final class FileUtils {
* Copy directory. * Copy directory.
* Paths of all files relative to source directory will be the same as the ones relative to destination directory. * Paths of all files relative to source directory will be the same as the ones relative to destination directory.
* *
* @param src the source directory. * @param src the source directory.
* @param dest the destination directory, which will be created if not existing. * @param dest the destination directory, which will be created if not existing.
* @throws IOException if an I/O error occurs. * @throws IOException if an I/O error occurs.
*/ */
@@ -201,7 +204,7 @@ public final class FileUtils {
} }
public static void copyDirectory(Path src, Path dest, Predicate<String> filePredicate) throws IOException { public static void copyDirectory(Path src, Path dest, Predicate<String> filePredicate) throws IOException {
Files.walkFileTree(src, new SimpleFileVisitor<Path>(){ Files.walkFileTree(src, new SimpleFileVisitor<Path>() {
@Override @Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
if (!filePredicate.test(src.relativize(file).toString())) { if (!filePredicate.test(src.relativize(file).toString())) {
@@ -228,7 +231,7 @@ public final class FileUtils {
/** /**
* Move file to trash. * Move file to trash.
* * <p>
* This method is only implemented in Java 9. Please check we are using Java 9 by invoking isMovingToTrashSupported. * This method is only implemented in Java 9. Please check we are using Java 9 by invoking isMovingToTrashSupported.
* Example: * Example:
* <pre>{@code * <pre>{@code
@@ -236,9 +239,10 @@ public final class FileUtils {
* FileUtils.moveToTrash(file); * FileUtils.moveToTrash(file);
* } * }
* }</pre> * }</pre>
*
* @param file the file being moved to trash. * @param file the file being moved to trash.
* @see FileUtils#isMovingToTrashSupported()
* @return false if moveToTrash does not exist, or platform does not support Desktop.Action.MOVE_TO_TRASH * @return false if moveToTrash does not exist, or platform does not support Desktop.Action.MOVE_TO_TRASH
* @see FileUtils#isMovingToTrashSupported()
*/ */
public static boolean moveToTrash(File file) { public static boolean moveToTrash(File file) {
try { try {
@@ -253,6 +257,7 @@ public final class FileUtils {
/** /**
* Check if {@code java.awt.Desktop.moveToTrash} exists. * Check if {@code java.awt.Desktop.moveToTrash} exists.
*
* @return true if the method exists. * @return true if the method exists.
*/ */
public static boolean isMovingToTrashSupported() { public static boolean isMovingToTrashSupported() {

View File

@@ -31,6 +31,8 @@ import java.util.jar.JarFile;
import java.util.jar.Manifest; import java.util.jar.Manifest;
public final class JarUtils { public final class JarUtils {
private JarUtils() {
}
public static Optional<Path> thisJar() { public static Optional<Path> thisJar() {
CodeSource codeSource = JarUtils.class.getProtectionDomain().getCodeSource(); CodeSource codeSource = JarUtils.class.getProtectionDomain().getCodeSource();

View File

@@ -86,6 +86,7 @@ public final class NetworkUtils {
break; break;
case '?': case '?':
left = false; left = false;
// fallthrough
default: default:
if (ch >= 0x80) if (ch >= 0x80)
sb.append(encodeURL(Character.toString(ch))); sb.append(encodeURL(Character.toString(ch)));

View File

@@ -17,7 +17,6 @@
*/ */
package org.jackhuang.hmcl.util.io; package org.jackhuang.hmcl.util.io;
import org.jackhuang.hmcl.util.function.ExceptionalPredicate; import org.jackhuang.hmcl.util.function.ExceptionalPredicate;
import java.io.Closeable; import java.io.Closeable;

View File

@@ -17,20 +17,19 @@
*/ */
package org.jackhuang.hmcl.util.javafx; package org.jackhuang.hmcl.util.javafx;
import static java.util.Objects.requireNonNull; import javafx.application.Platform;
import static org.jackhuang.hmcl.util.Lang.handleUncaughtException; import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.ObjectBinding;
import javafx.beans.value.ObservableValue;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier; import java.util.function.Supplier;
import static java.util.Objects.requireNonNull;
import javafx.application.Platform; import static org.jackhuang.hmcl.util.Lang.handleUncaughtException;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.ObjectBinding;
import javafx.beans.value.ObservableValue;
/** /**
* @author yushijinhun * @author yushijinhun

View File

@@ -17,72 +17,72 @@
*/ */
package org.jackhuang.hmcl.util.javafx; package org.jackhuang.hmcl.util.javafx;
import java.util.function.Function;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.beans.binding.ObjectBinding; import javafx.beans.binding.ObjectBinding;
import javafx.beans.property.Property; import javafx.beans.property.Property;
import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import java.util.function.Function;
/** /**
* @author yushijinhun * @author yushijinhun
*/ */
public class MappedProperty<T, U> extends SimpleObjectProperty<U> { public class MappedProperty<T, U> extends SimpleObjectProperty<U> {
private final Property<T> predecessor; private final Property<T> predecessor;
private final Function<U, T> reservedMapper; private final Function<U, T> reservedMapper;
private final ObjectBinding<U> binding; private final ObjectBinding<U> binding;
public MappedProperty(Property<T> predecessor, Function<T, U> mapper, Function<U, T> reservedMapper) { public MappedProperty(Property<T> predecessor, Function<T, U> mapper, Function<U, T> reservedMapper) {
this(null, "", predecessor, mapper, reservedMapper); this(null, "", predecessor, mapper, reservedMapper);
} }
public MappedProperty(Object bean, String name, Property<T> predecessor, Function<T, U> mapper, Function<U, T> reservedMapper) { public MappedProperty(Object bean, String name, Property<T> predecessor, Function<T, U> mapper, Function<U, T> reservedMapper) {
super(bean, name); super(bean, name);
this.predecessor = predecessor; this.predecessor = predecessor;
this.reservedMapper = reservedMapper; this.reservedMapper = reservedMapper;
binding = new ObjectBinding<U>() { binding = new ObjectBinding<U>() {
{ {
bind(predecessor); bind(predecessor);
} }
@Override @Override
protected U computeValue() { protected U computeValue() {
return mapper.apply(predecessor.getValue()); return mapper.apply(predecessor.getValue());
} }
@Override @Override
protected void onInvalidating() { protected void onInvalidating() {
MappedProperty.this.fireValueChangedEvent(); MappedProperty.this.fireValueChangedEvent();
} }
}; };
} }
@Override @Override
public U get() { public U get() {
return binding.get(); return binding.get();
} }
@Override @Override
public void set(U value) { public void set(U value) {
predecessor.setValue(reservedMapper.apply(value)); predecessor.setValue(reservedMapper.apply(value));
} }
@Override @Override
public void bind(ObservableValue<? extends U> observable) { public void bind(ObservableValue<? extends U> observable) {
predecessor.bind(Bindings.createObjectBinding(() -> reservedMapper.apply(observable.getValue()), observable)); predecessor.bind(Bindings.createObjectBinding(() -> reservedMapper.apply(observable.getValue()), observable));
} }
@Override @Override
public void unbind() { public void unbind() {
predecessor.unbind(); predecessor.unbind();
} }
@Override @Override
public boolean isBound() { public boolean isBound() {
return predecessor.isBound(); return predecessor.isBound();
} }
} }

View File

@@ -351,5 +351,5 @@ public class VersionNumber implements Comparable<VersionNumber> {
return canonical.hashCode(); return canonical.hashCode();
} }
public static Comparator<String> VERSION_COMPARATOR = Comparator.comparing(VersionNumber::asVersion); public static final Comparator<String> VERSION_COMPARATOR = Comparator.comparing(VersionNumber::asVersion);
} }

View File

@@ -5,6 +5,10 @@ buildscript {
} }
} }
plugins {
id 'checkstyle'
}
group 'org.jackhuang' group 'org.jackhuang'
version '3.0' version '3.0'
@@ -12,6 +16,7 @@ subprojects {
apply plugin: 'java' apply plugin: 'java'
apply plugin: 'idea' apply plugin: 'idea'
apply plugin: 'maven-publish' apply plugin: 'maven-publish'
apply plugin: 'checkstyle'
repositories { repositories {
mavenCentral() mavenCentral()

View File

@@ -0,0 +1,108 @@
<?xml version="1.0" ?><!DOCTYPE module PUBLIC
"-//Puppy Crawl//DTD Check Configuration 1.2//EN"
"http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
<module name="Checker">
<module name="NewlineAtEndOfFile"/> <!-- force newline, important for git merge and POSIX compatibility: http://checkstyle.sourceforge.net/config_misc.html#NewlineAtEndOfFile -->
<module name="FileTabCharacter"/> <!-- e.g. disallow tab character outside of strings -->
<module name="UniqueProperties"><!-- must not have duplicate properties in .properties files: http://checkstyle.sourceforge.net/config_misc.html#UniqueProperties -->
<property name="fileExtensions" value="properties"/>
</module>
<module name="FileLength"><!-- max line length for single file: http://checkstyle.sourceforge.net/config_sizes.html#FileLength -->
<property name="max" value="1500"/>
</module>
<module name="TreeWalker">
<module name="SuppressionCommentFilter"/> <!-- use //CHECKSTYLE:OFF (...) //CHECKSTYLE:ON to disable checkstyle: http://checkstyle.sourceforge.net/config_filters.html#SuppressionCommentFilter -->
<!-- Annotations -->
<module name="MissingDeprecated"> <!-- if @deprecated and javadoc is there, must be explained in javadoc: http://checkstyle.sourceforge.net/config_annotation.html#MissingDeprecated -->
</module>
<module name="MissingOverride"/> <!-- if has @inheritDoc in javadoc must have @Override http://checkstyle.sourceforge.net/config_annotation.html#MissingOverride -->
<module name="PackageAnnotation"/> <!-- must only be in package-info: http://checkstyle.sourceforge.net/config_annotation.html#PackageAnnotation -->
<!-- Blocks -->
<module name="EmptyCatchBlock"> <!-- empty catch blocks exception var name must be 'ignored' or must not be empty: http://checkstyle.sourceforge.net/config_blocks.html#EmptyCatchBlock -->
<property name="exceptionVariableName" value="expected|ignore"/>
</module>
<!-- Misc -->
<module name="ArrayTypeStyle"/> <!-- e.g. int[] array is ok int array[] not: http://checkstyle.sourceforge.net/config_misc.html#ArrayTypeStyle -->
<module name="MutableException"/> <!-- exception classes must be immutable: http://checkstyle.sourceforge.net/config_design.html#MutableException -->
<module name="UpperEll"/> <!-- long values must be postfixed with 'L' not 'l': http://checkstyle.sourceforge.net/config_misc.html#UpperEll -->
<module name="Indentation"> <!-- Checks correct indentation of Java code: http://checkstyle.sourceforge.net/config_misc.html#Indentation -->
<property name="basicOffset" value="4"/>
<property name="arrayInitIndent" value="8"/>
<property name="braceAdjustment" value="0"/>
<property name="caseIndent" value="4"/>
<property name="throwsIndent" value="4"/>
<property name="lineWrappingIndentation" value="4"/>
<property name="forceStrictCondition" value="false"/>
</module>
<!-- Modifier -->
<module name="RedundantModifier"> <!-- Checks for redundant modifiers: http://checkstyle.sourceforge.net/config_modifier.html#RedundantModifier -->
<property name="tokens" value="METHOD_DEF, VARIABLE_DEF, INTERFACE_DEF, ANNOTATION_FIELD_DEF, ENUM_DEF, CLASS_DEF"/>
</module>
<!-- Classes -->
<module name="FinalClass"/> <!-- class with only private constructor must be final: http://checkstyle.sourceforge.net/config_design.html#FinalClass -->
<module name="SimplifyBooleanReturn"/> <!-- directly return boolean does not check and return http://checkstyle.sourceforge.net/config_design.html#SimplifyBooleanReturn -->
<module name="StringLiteralEquality"/> <!-- you can't write myString == "this" http://checkstyle.sourceforge.net/config_design.html#StringLiteralEquality -->
<module name="OneTopLevelClass"/> <!-- only one root class per file http://checkstyle.sourceforge.net/config_design.html#OneTopLevelClass -->
<module name="ThrowsCount"> <!-- max 5 throws definitions per method: http://checkstyle.sourceforge.net/config_design.html#ThrowsCount -->
<property name="max" value="5"/>
</module>
<module name="InterfaceIsType"/> <!-- interface must contain methods, should not be used for const only: http://checkstyle.sourceforge.net/config_design.html#InterfaceIsType -->
<module name="OuterTypeFilename"/> <!-- class Foo must be in Foo.java: http://checkstyle.sourceforge.net/config_misc.html#OuterTypeFilename -->
<module name="HideUtilityClassConstructor"/> <!-- utility class constructor must be private: http://checkstyle.sourceforge.net/config_design.html#HideUtilityClassConstructor -->
<!-- <module name="VisibilityModifier"> &lt;!&ndash; most members must be private http://checkstyle.sourceforge.net/config_design.html#VisibilityModifier &ndash;&gt;-->
<!-- <property name="protectedAllowed" value="true"/>-->
<!-- <property name="packageAllowed" value="true"/>-->
<!-- <property name="allowPublicImmutableFields" value="true"/>-->
<!-- <property name="allowPublicFinalFields" value="true"/>-->
<!-- <property name="publicMemberPattern" value="^TAG$|^CREATOR$"/>-->
<!-- </module>-->
<!-- Coding -->
<module name="CovariantEquals"/> <!-- if you override equals with different type you must provide equals with same type: http://checkstyle.sourceforge.net/config_coding.html#CovariantEquals -->
<module name="DefaultComesLast"/> <!-- in switch case default must be the last elem: http://checkstyle.sourceforge.net/config_coding.html#DefaultComesLast -->
<module name="EmptyStatement"/> <!-- basically an empty semicolon: http://checkstyle.sourceforge.net/config_coding.html#EmptyStatement -->
<module name="EqualsHashCode"/> <!-- if you implement equals, you must implement hashcode and vice versa: http://checkstyle.sourceforge.net/config_coding.html#EqualsHashCode -->
<module name="NoFinalizer"/> <!-- Verifies there are no finalize() methods defined in a class: http://checkstyle.sourceforge.net/config_coding.html#NoFinalizer -->
<module name="FallThrough"/> <!-- switch fallthrough with statement not allowed http://checkstyle.sourceforge.net/config_coding.html#FallThrough -->
<module name="IllegalInstantiation"/> <!-- Must not use const of certain types (Activity, Fragment): http://checkstyle.sourceforge.net/config_coding.html#IllegalInstantiation -->
<!-- Size Limitiations -->
<module name="ParameterNumber"><!-- max params for method http://checkstyle.sourceforge.net/config_sizes.html#ParameterNumber -->
<property name="max" value="10"/>
<property name="ignoreOverriddenMethods" value="true"/>
<property name="tokens" value="METHOD_DEF"/>
</module>
<!-- Naming Conventions -->
<!--<module name="ConstantName" /> for possible futer use-->
<!-- Whitespaces -->
<module name="EmptyLineSeparator"> <!-- Checks for correct empty line placements, omit VAR token: http://checkstyle.sourceforge.net/config_whitespace.html#EmptyLineSeparator -->
<property name="allowMultipleEmptyLines" value="false"/>
<property name="tokens" value="IMPORT, CLASS_DEF, INTERFACE_DEF, ENUM_DEF, STATIC_INIT, INSTANCE_INIT, METHOD_DEF, CTOR_DEF"/>
</module>
<module name="SingleSpaceSeparator"/> <!-- Checks if a token is surrounded by whitespace: http://checkstyle.sourceforge.net/config_whitespace.html#SingleSpaceSeparator -->
<module name="GenericWhitespace"/> <!-- Checks whitespaces with Java Generics <>: http://checkstyle.sourceforge.net/config_whitespace.html#GenericWhitespace -->
<module name="WhitespaceAround"> <!-- Checks if a token is surrounded by whitespace: http://checkstyle.sourceforge.net/config_whitespace.html#WhitespaceAround -->
<property name="allowEmptyConstructors" value="true"/>
<property name="allowEmptyMethods" value="true"/>
<property name="allowEmptyTypes" value="true"/>
<property name="allowEmptyLambdas" value="true"/>
<property name="allowEmptyCatches" value="true"/>
</module>
<!-- Imports -->
<module name="RedundantImport"/> <!-- e.g. double import statements: http://checkstyle.sourceforge.net/config_imports.html#RedundantImport -->
<module name="UnusedImports"/> <!-- http://checkstyle.sourceforge.net/config_imports.html#UnusedImports -->
<module name="IllegalImport"/> <!-- checks if import sun.* is used http://checkstyle.sourceforge.net/config_imports.html#IllegalImport -->
</module>
</module>