fix liteloader & add controller

This commit is contained in:
Tungstend 2023-01-13 20:23:57 +08:00
parent 25b640609e
commit ba77213394
16 changed files with 385 additions and 52 deletions

View File

@ -0,0 +1,7 @@
{
"name": "Default",
"version": "1.0.0",
"author": "Tungsten",
"description": "Default controller of Fold Craft Launcher.",
"controllerVersion": 0
}

View File

@ -64,12 +64,6 @@ public final class Config implements Cloneable, Observable {
@SerializedName("commonpath") @SerializedName("commonpath")
private StringProperty commonDirectory = new SimpleStringProperty(FCLPath.SHARED_COMMON_DIR); 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") @SerializedName("autoDownloadThreads")
private BooleanProperty autoDownloadThreads = new SimpleBooleanProperty(false); private BooleanProperty autoDownloadThreads = new SimpleBooleanProperty(false);
@ -166,30 +160,6 @@ public final class Config implements Cloneable, Observable {
return commonDirectory; 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() { public boolean getAutoDownloadThreads() {
return autoDownloadThreads.get(); return autoDownloadThreads.get();
} }

View File

@ -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<Controller>, JsonDeserializer<Controller> {
@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);
}
}
}

View File

@ -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<Controller> controllers = observableArrayList(controller -> new Observable[] { controller });
private static final ReadOnlyListWrapper<Controller> 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<Controller> getControllersFromDisk() {
ArrayList<Controller> list = new ArrayList<>();
List<File> 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<Controller> getControllers() {
return controllers;
}
public static ReadOnlyListProperty<Controller> controllersProperty() {
return controllersWrapper.getReadOnlyProperty();
}
}

View File

@ -28,6 +28,7 @@ public final class Settings {
DownloadProviders.init(); DownloadProviders.init();
Accounts.init(); Accounts.init();
Profiles.init(); Profiles.init();
Controllers.init();
AuthlibInjectorServers.init(); AuthlibInjectorServers.init();
CacheRepository.setInstance(FCLCacheRepository.REPOSITORY); CacheRepository.setInstance(FCLCacheRepository.REPOSITORY);

View File

@ -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) { public void addPropertyChangedListener(InvalidationListener listener) {
usesGlobalProperty.addListener(listener); usesGlobalProperty.addListener(listener);
javaProperty.addListener(listener); javaProperty.addListener(listener);

View File

@ -1,12 +1,24 @@
package com.tungsten.fcl.ui.controller; package com.tungsten.fcl.ui.controller;
import android.content.Context; 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.fclcore.task.Task;
import com.tungsten.fcllibrary.component.ui.FCLCommonUI; import com.tungsten.fcllibrary.component.ui.FCLCommonUI;
import com.tungsten.fcllibrary.component.view.FCLLinearLayout;
import com.tungsten.fcllibrary.component.view.FCLUILayout; 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) { public ControllerUI(Context context, FCLUILayout parent, int id) {
super(context, parent, id); super(context, parent, id);
@ -21,4 +33,9 @@ public class ControllerUI extends FCLCommonUI {
public Task<?> refresh(Object... param) { public Task<?> refresh(Object... param) {
return null; return null;
} }
@Override
public void onClick(View view) {
}
} }

View File

@ -273,6 +273,7 @@ public class VersionSettingPage extends FCLCommonPage implements ManageUI.Versio
} }
VersionSetting versionSetting = profile.getVersionSetting(versionId); VersionSetting versionSetting = profile.getVersionSetting(versionId);
versionSetting.checkController();
modpack.set(versionId != null && profile.getRepository().isModpack(versionId)); modpack.set(versionId != null && profile.getRepository().isModpack(versionId));
usedMemory.set(MemoryUtils.getUsedDeviceMemory(getContext())); usedMemory.set(MemoryUtils.getUsedDeviceMemory(getContext()));

View File

@ -95,15 +95,17 @@
</androidx.appcompat.widget.LinearLayoutCompat> </androidx.appcompat.widget.LinearLayoutCompat>
<ListView <com.tungsten.fcllibrary.component.view.FCLLinearLayout
android:id="@+id/list" android:id="@+id/info_layout"
android:divider="@android:color/transparent"
android:dividerHeight="0dp"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
app:layout_constraintHorizontal_bias="1" app:layout_constraintHorizontal_bias="1"
app:layout_constraintWidth_percent="0.7" app:layout_constraintWidth_percent="0.7"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/> app:layout_constraintEnd_toEndOf="parent">
</com.tungsten.fcllibrary.component.view.FCLLinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -220,19 +220,9 @@ public interface GameRepository extends VersionProvider {
default List<String> getClasspath(Version version) { default List<String> getClasspath(Version version) {
List<String> classpath = new ArrayList<>(); List<String> classpath = new ArrayList<>();
if (version.getMinimumLauncherVersion() >= 21) { if (version.getMinimumLauncherVersion() >= 21) {
// classpath.add(FCLPath.LWJGL3_DIR + "/lwjgl.jar"); classpath.add(FCLPath.LWJGL3_DIR + "/lwjgl.jar");
// classpath.add(FCLPath.LWJGL3_DIR + "/lwjgl-glfw.jar"); } else {
// classpath.add(FCLPath.LWJGL3_DIR + "/lwjgl-jemalloc.jar"); classpath.add(FCLPath.LWJGL2_DIR + "/lwjgl.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");
} }
for (Library library : version.getLibraries()) for (Library library : version.getLibraries())
if (library.appliesToCurrentEnvironment() && !library.isNative()) { if (library.appliesToCurrentEnvironment() && !library.isNative()) {

View File

@ -15,7 +15,7 @@ public class LibFilter {
public static List<Library> filterLibs(List<Library> libraries) { public static List<Library> filterLibs(List<Library> libraries) {
ArrayList<Library> newLibraries = new ArrayList<>(); ArrayList<Library> newLibraries = new ArrayList<>();
for (Library library : libraries) { 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); newLibraries.add(library);
} }
} }

View File

@ -25,6 +25,7 @@ public class FCLPath {
public static String FILES_DIR; public static String FILES_DIR;
public static String PLUGIN_DIR; public static String PLUGIN_DIR;
public static String BACKGROUND_DIR; public static String BACKGROUND_DIR;
public static String CONTROLLER_DIR;
public static String PRIVATE_COMMON_DIR; public static String PRIVATE_COMMON_DIR;
public static String SHARED_COMMON_DIR = Environment.getExternalStorageDirectory().getAbsolutePath() + "/FCL/.minecraft"; public static String SHARED_COMMON_DIR = Environment.getExternalStorageDirectory().getAbsolutePath() + "/FCL/.minecraft";
@ -52,6 +53,7 @@ public class FCLPath {
FILES_DIR = context.getFilesDir().getAbsolutePath(); FILES_DIR = context.getFilesDir().getAbsolutePath();
PLUGIN_DIR = FILES_DIR + "/plugins"; PLUGIN_DIR = FILES_DIR + "/plugins";
BACKGROUND_DIR = FILES_DIR + "/background"; BACKGROUND_DIR = FILES_DIR + "/background";
CONTROLLER_DIR = FILES_DIR + "/control";
PRIVATE_COMMON_DIR = context.getExternalFilesDir(".minecraft").getAbsolutePath(); PRIVATE_COMMON_DIR = context.getExternalFilesDir(".minecraft").getAbsolutePath();
@ -71,6 +73,7 @@ public class FCLPath {
init(FILES_DIR); init(FILES_DIR);
init(PLUGIN_DIR); init(PLUGIN_DIR);
init(BACKGROUND_DIR); init(BACKGROUND_DIR);
init(CONTROLLER_DIR);
init(PRIVATE_COMMON_DIR); init(PRIVATE_COMMON_DIR);
init(SHARED_COMMON_DIR); init(SHARED_COMMON_DIR);
} }