From ba77213394f8f6fd3fa31e1b5e3a367dd48c7fd4 Mon Sep 17 00:00:00 2001 From: Tungstend Date: Fri, 13 Jan 2023 20:23:57 +0800 Subject: [PATCH] fix liteloader & add controller --- .../lwjgl2/{Lwjgl2.jar => lwjgl.jar} | Bin .../main/assets/app_runtime/lwjgl2/version | 2 +- .../lwjgl3/{Lwjgl3.jar => lwjgl.jar} | Bin .../main/assets/app_runtime/lwjgl3/version | 2 +- FCL/src/main/assets/controllers/Default.json | 7 + .../java/com/tungsten/fcl/setting/Config.java | 30 --- .../com/tungsten/fcl/setting/Controller.java | 218 ++++++++++++++++++ .../com/tungsten/fcl/setting/Controllers.java | 113 +++++++++ .../com/tungsten/fcl/setting/Settings.java | 1 + .../tungsten/fcl/setting/VersionSetting.java | 11 + .../fcl/ui/controller/ControllerUI.java | 19 +- .../fcl/ui/manage/VersionSettingPage.java | 1 + FCL/src/main/res/layout/ui_controller.xml | 12 +- .../tungsten/fclcore/game/GameRepository.java | 16 +- .../com/tungsten/fclcore/util/LibFilter.java | 2 +- .../java/com/tungsten/fclauncher/FCLPath.java | 3 + 16 files changed, 385 insertions(+), 52 deletions(-) rename FCL/src/main/assets/app_runtime/lwjgl2/{Lwjgl2.jar => lwjgl.jar} (100%) rename FCL/src/main/assets/app_runtime/lwjgl3/{Lwjgl3.jar => lwjgl.jar} (100%) create mode 100644 FCL/src/main/assets/controllers/Default.json create mode 100644 FCL/src/main/java/com/tungsten/fcl/setting/Controller.java create mode 100644 FCL/src/main/java/com/tungsten/fcl/setting/Controllers.java diff --git a/FCL/src/main/assets/app_runtime/lwjgl2/Lwjgl2.jar b/FCL/src/main/assets/app_runtime/lwjgl2/lwjgl.jar similarity index 100% rename from FCL/src/main/assets/app_runtime/lwjgl2/Lwjgl2.jar rename to FCL/src/main/assets/app_runtime/lwjgl2/lwjgl.jar diff --git a/FCL/src/main/assets/app_runtime/lwjgl2/version b/FCL/src/main/assets/app_runtime/lwjgl2/version index d8263ee9..e440e5c8 100644 --- a/FCL/src/main/assets/app_runtime/lwjgl2/version +++ b/FCL/src/main/assets/app_runtime/lwjgl2/version @@ -1 +1 @@ -2 \ No newline at end of file +3 \ No newline at end of file diff --git a/FCL/src/main/assets/app_runtime/lwjgl3/Lwjgl3.jar b/FCL/src/main/assets/app_runtime/lwjgl3/lwjgl.jar similarity index 100% rename from FCL/src/main/assets/app_runtime/lwjgl3/Lwjgl3.jar rename to FCL/src/main/assets/app_runtime/lwjgl3/lwjgl.jar diff --git a/FCL/src/main/assets/app_runtime/lwjgl3/version b/FCL/src/main/assets/app_runtime/lwjgl3/version index e440e5c8..bf0d87ab 100644 --- a/FCL/src/main/assets/app_runtime/lwjgl3/version +++ b/FCL/src/main/assets/app_runtime/lwjgl3/version @@ -1 +1 @@ -3 \ No newline at end of file +4 \ No newline at end of file diff --git a/FCL/src/main/assets/controllers/Default.json b/FCL/src/main/assets/controllers/Default.json new file mode 100644 index 00000000..a48f0073 --- /dev/null +++ b/FCL/src/main/assets/controllers/Default.json @@ -0,0 +1,7 @@ +{ + "name": "Default", + "version": "1.0.0", + "author": "Tungsten", + "description": "Default controller of Fold Craft Launcher.", + "controllerVersion": 0 +} \ No newline at end of file diff --git a/FCL/src/main/java/com/tungsten/fcl/setting/Config.java b/FCL/src/main/java/com/tungsten/fcl/setting/Config.java index 84140a2e..64b52dba 100644 --- a/FCL/src/main/java/com/tungsten/fcl/setting/Config.java +++ b/FCL/src/main/java/com/tungsten/fcl/setting/Config.java @@ -64,12 +64,6 @@ public final class Config implements Cloneable, Observable { @SerializedName("commonpath") private StringProperty commonDirectory = new SimpleStringProperty(FCLPath.SHARED_COMMON_DIR); - @SerializedName("width") - private DoubleProperty width = new SimpleDoubleProperty(); - - @SerializedName("height") - private DoubleProperty height = new SimpleDoubleProperty(); - @SerializedName("autoDownloadThreads") private BooleanProperty autoDownloadThreads = new SimpleBooleanProperty(false); @@ -166,30 +160,6 @@ public final class Config implements Cloneable, Observable { return commonDirectory; } - public double getWidth() { - return width.get(); - } - - public DoubleProperty widthProperty() { - return width; - } - - public void setWidth(double width) { - this.width.set(width); - } - - public double getHeight() { - return height.get(); - } - - public DoubleProperty heightProperty() { - return height; - } - - public void setHeight(double height) { - this.height.set(height); - } - public boolean getAutoDownloadThreads() { return autoDownloadThreads.get(); } diff --git a/FCL/src/main/java/com/tungsten/fcl/setting/Controller.java b/FCL/src/main/java/com/tungsten/fcl/setting/Controller.java new file mode 100644 index 00000000..3bb6c330 --- /dev/null +++ b/FCL/src/main/java/com/tungsten/fcl/setting/Controller.java @@ -0,0 +1,218 @@ +package com.tungsten.fcl.setting; + +import static com.tungsten.fcl.util.FXUtils.onInvalidating; + +import androidx.annotation.NonNull; + +import com.google.gson.GsonBuilder; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import com.google.gson.annotations.JsonAdapter; +import com.tungsten.fcl.util.Constants; +import com.tungsten.fclauncher.FCLPath; +import com.tungsten.fclcore.fakefx.beans.InvalidationListener; +import com.tungsten.fclcore.fakefx.beans.Observable; +import com.tungsten.fclcore.fakefx.beans.property.IntegerProperty; +import com.tungsten.fclcore.fakefx.beans.property.ReadOnlyIntegerProperty; +import com.tungsten.fclcore.fakefx.beans.property.SimpleIntegerProperty; +import com.tungsten.fclcore.fakefx.beans.property.SimpleStringProperty; +import com.tungsten.fclcore.fakefx.beans.property.StringProperty; +import com.tungsten.fclcore.util.ToStringBuilder; +import com.tungsten.fclcore.util.fakefx.ObservableHelper; +import com.tungsten.fclcore.util.gson.fakefx.factories.JavaFxPropertyTypeAdapterFactory; +import com.tungsten.fclcore.util.io.FileUtils; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.Optional; + +@JsonAdapter(Controller.Serializer.class) +public class Controller implements Observable { + + private final SimpleStringProperty name; + + public StringProperty nameProperty() { + return name; + } + + public String getName() { + return name.get(); + } + + public void setName(String name) { + this.name.set(name); + } + + private final SimpleStringProperty version; + + public StringProperty versionProperty() { + return version; + } + + public String getVersion() { + return version.get(); + } + + public void setVersion(String version) { + this.version.set(version); + } + + private final SimpleStringProperty author; + + public StringProperty authorProperty() { + return author; + } + + public String getAuthor() { + return author.get(); + } + + public void setAuthor(String author) { + this.author.set(author); + } + + private final SimpleStringProperty description; + + public StringProperty descriptionProperty() { + return description; + } + + public String getDescription() { + return description.get(); + } + + public void setDescription(String description) { + this.description.set(description); + } + + private final IntegerProperty controllerVersion = new SimpleIntegerProperty(this, "controllerVersion"); + + public ReadOnlyIntegerProperty controllerVersionProperty() { + return controllerVersion; + } + + public int getControllerVersion() { + return controllerVersion.get(); + } + + public Controller(String name) { + this(name, "1.0.0"); + } + + public Controller(String name, String version) { + this(name, version, ""); + } + + public Controller(String name, String version, String author) { + this(name, version, author, ""); + } + + public Controller(String name, String version, String author, String description) { + this(name, version, author, description, Constants.CONTROLLER_VERSION); + } + + public Controller(String name, String version, String author, String description, int controllerVersion) { + this.name = new SimpleStringProperty(this, "name", name); + this.version = new SimpleStringProperty(this, "version", version); + this.author = new SimpleStringProperty(this, "author", author); + this.description = new SimpleStringProperty(this, "description", description); + + this.controllerVersion.set(controllerVersion); + + addPropertyChangedListener(onInvalidating(this::invalidate)); + } + + @NonNull + @Override + public String toString() { + return new ToStringBuilder(this) + .append("name", getName()) + .append("version", getVersion()) + .append("author", getAuthor()) + .append("description", getDescription()) + .append("controllerVersion", getControllerVersion()) + .toString(); + } + + private void addPropertyChangedListener(InvalidationListener listener) { + name.addListener(listener); + version.addListener(listener); + author.addListener(listener); + description.addListener(listener); + controllerVersion.addListener(listener); + } + + private ObservableHelper observableHelper = new ObservableHelper(this); + + @Override + public void addListener(InvalidationListener listener) { + observableHelper.addListener(listener); + } + + @Override + public void removeListener(InvalidationListener listener) { + observableHelper.removeListener(listener); + } + + private void invalidate() { + observableHelper.invalidate(); + } + + // function + + public String getFileName() { + return getName() + ".json"; + } + + public void saveToDisk() throws IOException { + String str = new GsonBuilder() + .registerTypeAdapterFactory(new JavaFxPropertyTypeAdapterFactory(true, true)) + .setPrettyPrinting() + .create().toJson(this); + FileUtils.writeText(new File(FCLPath.CONTROLLER_DIR, getFileName()), str); + } + + public void rename(String newName) throws IOException { + FileUtils.copyFile(new File(FCLPath.CONTROLLER_DIR, getFileName()), new File(FCLPath.CONTROLLER_DIR, newName + ".json")); + new File(FCLPath.CONTROLLER_DIR, getFileName()).delete(); + setName(newName); + } + + public static final class Serializer implements JsonSerializer, JsonDeserializer { + @Override + public JsonElement serialize(Controller src, Type typeOfSrc, JsonSerializationContext context) { + if (src == null) + return JsonNull.INSTANCE; + + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("name", src.getName()); + jsonObject.addProperty("version", src.getVersion()); + jsonObject.addProperty("author", src.getAuthor()); + jsonObject.addProperty("description", src.getDescription()); + jsonObject.addProperty("controllerVersion", src.getControllerVersion()); + + return jsonObject; + } + + @Override + public Controller deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + if (json == JsonNull.INSTANCE || !(json instanceof JsonObject)) return null; + JsonObject obj = (JsonObject) json; + String name = Optional.ofNullable(obj.get("name")).map(JsonElement::getAsString).orElse("Error"); + String version = Optional.ofNullable(obj.get("version")).map(JsonElement::getAsString).orElse("1.0.0"); + String author = Optional.ofNullable(obj.get("author")).map(JsonElement::getAsString).orElse(""); + String description = Optional.ofNullable(obj.get("description")).map(JsonElement::getAsString).orElse(""); + int controllerVersion = Optional.ofNullable(obj.get("controllerVersion")).map(JsonElement::getAsInt).orElse(Constants.CONTROLLER_VERSION); + + return new Controller(name, version, author, description, controllerVersion); + } + + } +} diff --git a/FCL/src/main/java/com/tungsten/fcl/setting/Controllers.java b/FCL/src/main/java/com/tungsten/fcl/setting/Controllers.java new file mode 100644 index 00000000..e0dd252c --- /dev/null +++ b/FCL/src/main/java/com/tungsten/fcl/setting/Controllers.java @@ -0,0 +1,113 @@ +package com.tungsten.fcl.setting; + +import static com.tungsten.fcl.util.FXUtils.onInvalidating; +import static com.tungsten.fclcore.fakefx.collections.FXCollections.observableArrayList; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.tungsten.fclauncher.FCLPath; +import com.tungsten.fclcore.fakefx.beans.Observable; +import com.tungsten.fclcore.fakefx.beans.property.ReadOnlyListProperty; +import com.tungsten.fclcore.fakefx.beans.property.ReadOnlyListWrapper; +import com.tungsten.fclcore.fakefx.collections.ObservableList; +import com.tungsten.fclcore.util.Logging; +import com.tungsten.fclcore.util.gson.fakefx.factories.JavaFxPropertyTypeAdapterFactory; +import com.tungsten.fclcore.util.io.FileUtils; +import com.tungsten.fclcore.util.io.IOUtils; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; + +public class Controllers { + + private Controllers() { + } + + private static final ObservableList controllers = observableArrayList(controller -> new Observable[] { controller }); + private static final ReadOnlyListWrapper controllersWrapper = new ReadOnlyListWrapper<>(controllers); + + public static void checkControllers() { + if (controllers.isEmpty()) { + try { + String str = IOUtils.readFullyAsString(Controllers.class.getResourceAsStream("/assets/controllers/Default.json"), StandardCharsets.UTF_8); + Controller controller = new GsonBuilder() + .registerTypeAdapterFactory(new JavaFxPropertyTypeAdapterFactory(true, true)) + .setPrettyPrinting() + .create().fromJson(str, Controller.class); + controller.saveToDisk(); + } catch (IOException e) { + Logging.LOG.log(Level.SEVERE, "Failed to generate default controller!", e.getMessage()); + } + controllers.addAll(getControllersFromDisk()); + } + } + + /** + * True if {@link #init()} hasn't been called. + */ + private static boolean initialized = false; + + private static void updateControllerStorages() { + // don't update the underlying storage before data loading is completed + // otherwise it might cause data loss + if (!initialized) + return; + // update storage + for (Controller controller : controllers) { + try { + controller.saveToDisk(); + } catch (IOException e) { + Logging.LOG.log(Level.SEVERE, "Failed to save controller!"); + } + } + } + + static { + controllers.addListener(onInvalidating(Controllers::updateControllerStorages)); + controllers.addListener(onInvalidating(Controllers::checkControllers)); + } + + static void init() { + if (initialized) + throw new IllegalStateException("Already initialized"); + + getControllersFromDisk(); + controllers.addAll(getControllersFromDisk()); + checkControllers(); + + initialized = true; + } + + private static ArrayList getControllersFromDisk() { + ArrayList list = new ArrayList<>(); + List jsons = FileUtils.listFilesByExtension(new File(FCLPath.CONTROLLER_DIR), "json"); + for (File json : jsons) { + if (json.isFile()) { + try { + String str = FileUtils.readText(json); + Controller controller = new GsonBuilder() + .registerTypeAdapterFactory(new JavaFxPropertyTypeAdapterFactory(true, true)) + .setPrettyPrinting() + .create().fromJson(str, Controller.class); + list.add(controller); + } catch (IOException e) { + Logging.LOG.log(Level.WARNING, "Can't read file: " + json.getAbsolutePath(), e.getMessage()); + } + } + } + return list; + } + + public static ObservableList getControllers() { + return controllers; + } + + public static ReadOnlyListProperty controllersProperty() { + return controllersWrapper.getReadOnlyProperty(); + } + +} diff --git a/FCL/src/main/java/com/tungsten/fcl/setting/Settings.java b/FCL/src/main/java/com/tungsten/fcl/setting/Settings.java index dfddb6ff..9172e981 100644 --- a/FCL/src/main/java/com/tungsten/fcl/setting/Settings.java +++ b/FCL/src/main/java/com/tungsten/fcl/setting/Settings.java @@ -28,6 +28,7 @@ public final class Settings { DownloadProviders.init(); Accounts.init(); Profiles.init(); + Controllers.init(); AuthlibInjectorServers.init(); CacheRepository.setInstance(FCLCacheRepository.REPOSITORY); diff --git a/FCL/src/main/java/com/tungsten/fcl/setting/VersionSetting.java b/FCL/src/main/java/com/tungsten/fcl/setting/VersionSetting.java index ba97122b..e9865d42 100644 --- a/FCL/src/main/java/com/tungsten/fcl/setting/VersionSetting.java +++ b/FCL/src/main/java/com/tungsten/fcl/setting/VersionSetting.java @@ -341,6 +341,17 @@ public final class VersionSetting implements Cloneable { }); } + public void checkController() { + Controllers.checkControllers(); + + Controller controller = Controllers.getControllers().stream() + .filter(it -> it.getName().equals(getController())) + .findFirst() + .orElse(Controllers.getControllers().get(0)); + + setController(controller.getName()); + } + public void addPropertyChangedListener(InvalidationListener listener) { usesGlobalProperty.addListener(listener); javaProperty.addListener(listener); diff --git a/FCL/src/main/java/com/tungsten/fcl/ui/controller/ControllerUI.java b/FCL/src/main/java/com/tungsten/fcl/ui/controller/ControllerUI.java index 5a43c00d..24705080 100644 --- a/FCL/src/main/java/com/tungsten/fcl/ui/controller/ControllerUI.java +++ b/FCL/src/main/java/com/tungsten/fcl/ui/controller/ControllerUI.java @@ -1,12 +1,24 @@ package com.tungsten.fcl.ui.controller; import android.content.Context; +import android.view.View; +import android.widget.ListView; + +import androidx.appcompat.widget.LinearLayoutCompat; import com.tungsten.fclcore.task.Task; import com.tungsten.fcllibrary.component.ui.FCLCommonUI; +import com.tungsten.fcllibrary.component.view.FCLLinearLayout; import com.tungsten.fcllibrary.component.view.FCLUILayout; -public class ControllerUI extends FCLCommonUI { +public class ControllerUI extends FCLCommonUI implements View.OnClickListener { + + private ListView listView; + + private LinearLayoutCompat importController; + private LinearLayoutCompat createController; + + private FCLLinearLayout infoLayout; public ControllerUI(Context context, FCLUILayout parent, int id) { super(context, parent, id); @@ -21,4 +33,9 @@ public class ControllerUI extends FCLCommonUI { public Task refresh(Object... param) { return null; } + + @Override + public void onClick(View view) { + + } } diff --git a/FCL/src/main/java/com/tungsten/fcl/ui/manage/VersionSettingPage.java b/FCL/src/main/java/com/tungsten/fcl/ui/manage/VersionSettingPage.java index 1f7afdb6..2ffa7cb4 100644 --- a/FCL/src/main/java/com/tungsten/fcl/ui/manage/VersionSettingPage.java +++ b/FCL/src/main/java/com/tungsten/fcl/ui/manage/VersionSettingPage.java @@ -273,6 +273,7 @@ public class VersionSettingPage extends FCLCommonPage implements ManageUI.Versio } VersionSetting versionSetting = profile.getVersionSetting(versionId); + versionSetting.checkController(); modpack.set(versionId != null && profile.getRepository().isModpack(versionId)); usedMemory.set(MemoryUtils.getUsedDeviceMemory(getContext())); diff --git a/FCL/src/main/res/layout/ui_controller.xml b/FCL/src/main/res/layout/ui_controller.xml index dec75159..e331345a 100644 --- a/FCL/src/main/res/layout/ui_controller.xml +++ b/FCL/src/main/res/layout/ui_controller.xml @@ -95,15 +95,17 @@ - + app:layout_constraintEnd_toEndOf="parent"> + + + + \ No newline at end of file diff --git a/FCLCore/src/main/java/com/tungsten/fclcore/game/GameRepository.java b/FCLCore/src/main/java/com/tungsten/fclcore/game/GameRepository.java index 057cdddf..b0076ea6 100644 --- a/FCLCore/src/main/java/com/tungsten/fclcore/game/GameRepository.java +++ b/FCLCore/src/main/java/com/tungsten/fclcore/game/GameRepository.java @@ -220,19 +220,9 @@ public interface GameRepository extends VersionProvider { default List getClasspath(Version version) { List classpath = new ArrayList<>(); if (version.getMinimumLauncherVersion() >= 21) { -// classpath.add(FCLPath.LWJGL3_DIR + "/lwjgl.jar"); -// classpath.add(FCLPath.LWJGL3_DIR + "/lwjgl-glfw.jar"); -// classpath.add(FCLPath.LWJGL3_DIR + "/lwjgl-jemalloc.jar"); -// classpath.add(FCLPath.LWJGL3_DIR + "/lwjgl-openal.jar"); -// classpath.add(FCLPath.LWJGL3_DIR + "/lwjgl-opengl.jar"); -// classpath.add(FCLPath.LWJGL3_DIR + "/lwjgl-stb.jar"); -// classpath.add(FCLPath.LWJGL3_DIR + "/lwjgl-tinyfd.jar"); - classpath.add(FCLPath.LWJGL3_DIR + "/Lwjgl3.jar"); - } - else { - classpath.add(FCLPath.LWJGL2_DIR + "/Lwjgl2.jar"); -// classpath.add(FCLPath.LWJGL2_DIR + "/lwjgl.jar"); -// classpath.add(FCLPath.LWJGL2_DIR + "/lwjgl_util.jar"); + classpath.add(FCLPath.LWJGL3_DIR + "/lwjgl.jar"); + } else { + classpath.add(FCLPath.LWJGL2_DIR + "/lwjgl.jar"); } for (Library library : version.getLibraries()) if (library.appliesToCurrentEnvironment() && !library.isNative()) { diff --git a/FCLCore/src/main/java/com/tungsten/fclcore/util/LibFilter.java b/FCLCore/src/main/java/com/tungsten/fclcore/util/LibFilter.java index eefde7ab..9ee07c8d 100644 --- a/FCLCore/src/main/java/com/tungsten/fclcore/util/LibFilter.java +++ b/FCLCore/src/main/java/com/tungsten/fclcore/util/LibFilter.java @@ -15,7 +15,7 @@ public class LibFilter { public static List filterLibs(List libraries) { ArrayList newLibraries = new ArrayList<>(); for (Library library : libraries) { - if (!library.isNative() && !library.getName().contains("net.java.jinput") && !library.getName().contains("org.lwjgl") && !library.getName().contains("platform")) { + if (!library.isNative() && !library.getName().contains("org.lwjgl") && !library.getName().contains("platform")) { newLibraries.add(library); } } diff --git a/FCLauncher/src/main/java/com/tungsten/fclauncher/FCLPath.java b/FCLauncher/src/main/java/com/tungsten/fclauncher/FCLPath.java index bbebf060..a5154998 100644 --- a/FCLauncher/src/main/java/com/tungsten/fclauncher/FCLPath.java +++ b/FCLauncher/src/main/java/com/tungsten/fclauncher/FCLPath.java @@ -25,6 +25,7 @@ public class FCLPath { public static String FILES_DIR; public static String PLUGIN_DIR; public static String BACKGROUND_DIR; + public static String CONTROLLER_DIR; public static String PRIVATE_COMMON_DIR; public static String SHARED_COMMON_DIR = Environment.getExternalStorageDirectory().getAbsolutePath() + "/FCL/.minecraft"; @@ -52,6 +53,7 @@ public class FCLPath { FILES_DIR = context.getFilesDir().getAbsolutePath(); PLUGIN_DIR = FILES_DIR + "/plugins"; BACKGROUND_DIR = FILES_DIR + "/background"; + CONTROLLER_DIR = FILES_DIR + "/control"; PRIVATE_COMMON_DIR = context.getExternalFilesDir(".minecraft").getAbsolutePath(); @@ -71,6 +73,7 @@ public class FCLPath { init(FILES_DIR); init(PLUGIN_DIR); init(BACKGROUND_DIR); + init(CONTROLLER_DIR); init(PRIVATE_COMMON_DIR); init(SHARED_COMMON_DIR); }