forked from Clones/Controlify
227 lines
8.0 KiB
Java
227 lines
8.0 KiB
Java
package dev.isxander.controlify.config;
|
|
|
|
import com.google.gson.*;
|
|
import dev.isxander.controlify.Controlify;
|
|
import dev.isxander.controlify.ControllerManager;
|
|
import dev.isxander.controlify.controller.Controller;
|
|
import dev.isxander.controlify.controller.joystick.CompoundJoystickInfo;
|
|
import dev.isxander.controlify.utils.DebugLog;
|
|
import dev.isxander.controlify.utils.Log;
|
|
import net.fabricmc.loader.api.FabricLoader;
|
|
import net.fabricmc.loader.api.Version;
|
|
import net.fabricmc.loader.api.VersionParsingException;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
import java.io.IOException;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.nio.file.StandardOpenOption;
|
|
import java.util.Map;
|
|
import java.util.function.Function;
|
|
import java.util.stream.Collectors;
|
|
|
|
public class ControlifyConfig {
|
|
public static final Path CONFIG_PATH = FabricLoader.getInstance().getConfigDir().resolve("controlify.json");
|
|
|
|
private static final Gson GSON = new GsonBuilder()
|
|
.serializeNulls()
|
|
.setPrettyPrinting()
|
|
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
|
|
.registerTypeHierarchyAdapter(Class.class, new TypeAdapters.ClassTypeAdapter())
|
|
.registerTypeHierarchyAdapter(Version.class, new TypeAdapters.VersionTypeAdapter())
|
|
.create();
|
|
|
|
private final Controlify controlify;
|
|
|
|
private String currentControllerUid;
|
|
private JsonObject controllerData = new JsonObject();
|
|
private Map<String, CompoundJoystickInfo> compoundJoysticks = Map.of();
|
|
private GlobalSettings globalSettings = new GlobalSettings();
|
|
private boolean firstLaunch;
|
|
private Version lastSeenVersion = null;
|
|
|
|
private boolean dirty;
|
|
|
|
public ControlifyConfig(Controlify controlify) {
|
|
this.controlify = controlify;
|
|
}
|
|
|
|
public void save() {
|
|
Log.LOGGER.info("Saving Controlify config...");
|
|
|
|
try {
|
|
Files.deleteIfExists(CONFIG_PATH);
|
|
Files.writeString(CONFIG_PATH, GSON.toJson(generateConfig()), StandardOpenOption.CREATE_NEW, StandardOpenOption.TRUNCATE_EXISTING);
|
|
dirty = false;
|
|
} catch (IOException e) {
|
|
throw new IllegalStateException("Failed to save config!", e);
|
|
}
|
|
}
|
|
|
|
public void load() {
|
|
Log.LOGGER.info("Loading Controlify config...");
|
|
|
|
if (!Files.exists(CONFIG_PATH)) {
|
|
firstLaunch = true;
|
|
if (lastSeenVersion == null) {
|
|
try {
|
|
lastSeenVersion = Version.parse("0.0.0");
|
|
} catch (VersionParsingException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
setDirty();
|
|
}
|
|
save();
|
|
return;
|
|
}
|
|
|
|
try {
|
|
applyConfig(GSON.fromJson(Files.readString(CONFIG_PATH), JsonObject.class));
|
|
} catch (Exception e) {
|
|
Log.LOGGER.error("Failed to load Controlify config!", e);
|
|
}
|
|
|
|
if (dirty) {
|
|
DebugLog.log("Config was dirty after load, saving...");
|
|
save();
|
|
}
|
|
}
|
|
|
|
private JsonObject generateConfig() {
|
|
JsonObject config = new JsonObject();
|
|
|
|
config.addProperty("last_seen_version", Log.VERSION.getFriendlyString());
|
|
|
|
JsonObject newControllerData = controllerData.deepCopy(); // we use the old config, so we don't lose disconnected controller data
|
|
|
|
for (var controller : ControllerManager.getConnectedControllers()) {
|
|
// `add` replaces if already existing
|
|
newControllerData.add(controller.uid(), generateControllerConfig(controller));
|
|
}
|
|
|
|
controllerData = newControllerData;
|
|
config.addProperty("current_controller", currentControllerUid = controlify.getCurrentController().map(Controller::uid).orElse(null));
|
|
config.add("controllers", controllerData);
|
|
config.add("compound_joysticks", GSON.toJsonTree(compoundJoysticks.values().toArray(new CompoundJoystickInfo[0])));
|
|
config.add("global", GSON.toJsonTree(globalSettings));
|
|
|
|
return config;
|
|
}
|
|
|
|
private JsonObject generateControllerConfig(Controller<?, ?> controller) {
|
|
JsonObject object = new JsonObject();
|
|
|
|
object.add("config", GSON.toJsonTree(controller.config()));
|
|
object.add("bindings", controller.bindings().toJson());
|
|
|
|
return object;
|
|
}
|
|
|
|
private void applyConfig(JsonObject object) throws VersionParsingException {
|
|
if (lastSeenVersion == null) {
|
|
boolean hasLastSeenVersion = object.has("last_seen_version");
|
|
lastSeenVersion = hasLastSeenVersion ? Version.parse(object.get("last_seen_version").getAsString()) : Version.parse("0.0.0");
|
|
if (!hasLastSeenVersion || lastSeenVersion.compareTo(Log.VERSION) < 0) {
|
|
setDirty();
|
|
}
|
|
}
|
|
|
|
globalSettings = GSON.fromJson(object.getAsJsonObject("global"), GlobalSettings.class);
|
|
if (globalSettings == null) {
|
|
globalSettings = new GlobalSettings();
|
|
setDirty();
|
|
}
|
|
|
|
JsonObject controllers = object.getAsJsonObject("controllers");
|
|
if (controllers != null) {
|
|
this.controllerData = controllers;
|
|
for (var controller : ControllerManager.getConnectedControllers()) {
|
|
loadOrCreateControllerData(controller);
|
|
}
|
|
} else {
|
|
setDirty();
|
|
}
|
|
|
|
if (object.has("compound_joysticks")) {
|
|
this.compoundJoysticks = object
|
|
.getAsJsonArray("compound_joysticks")
|
|
.asList()
|
|
.stream()
|
|
.map(element -> GSON.fromJson(element, CompoundJoystickInfo.class))
|
|
.collect(Collectors.toMap(info -> info.type().mappingId(), Function.identity()));
|
|
} else {
|
|
this.compoundJoysticks = Map.of();
|
|
}
|
|
|
|
if (object.has("current_controller")) {
|
|
JsonElement element = object.get("current_controller");
|
|
currentControllerUid = element.isJsonNull() ? null : element.getAsString();
|
|
} else {
|
|
currentControllerUid = controlify.getCurrentController().map(Controller::uid).orElse(null);
|
|
setDirty();
|
|
}
|
|
}
|
|
|
|
public void loadOrCreateControllerData(Controller<?, ?> controller) {
|
|
var uid = controller.uid();
|
|
if (controllerData.has(uid)) {
|
|
DebugLog.log("Loading controller data for " + uid);
|
|
applyControllerConfig(controller, controllerData.getAsJsonObject(uid));
|
|
} else {
|
|
DebugLog.log("New controller found, setting config dirty ({})", uid);
|
|
setDirty();
|
|
}
|
|
}
|
|
|
|
private void applyControllerConfig(Controller<?, ?> controller, JsonObject object) {
|
|
try {
|
|
controller.setConfig(GSON, object.getAsJsonObject("config"));
|
|
dirty |= !controller.bindings().fromJson(object.getAsJsonObject("bindings"));
|
|
} catch (Exception e) {
|
|
Log.LOGGER.error("Failed to load controller data for " + controller.uid() + ". Resetting to default!", e);
|
|
controller.resetConfig();
|
|
save();
|
|
}
|
|
}
|
|
|
|
public void setDirty() {
|
|
dirty = true;
|
|
}
|
|
|
|
public void saveIfDirty() {
|
|
if (dirty) {
|
|
DebugLog.log("Config is dirty. Saving...");
|
|
save();
|
|
}
|
|
}
|
|
|
|
public Map<String, CompoundJoystickInfo> getCompoundJoysticks() {
|
|
return compoundJoysticks;
|
|
}
|
|
|
|
public GlobalSettings globalSettings() {
|
|
return globalSettings;
|
|
}
|
|
|
|
public boolean isFirstLaunch() {
|
|
return firstLaunch;
|
|
}
|
|
|
|
public boolean isLastSeenVersionLessThan(Version version) {
|
|
return lastSeenVersion.compareTo(version) < 0;
|
|
}
|
|
|
|
public boolean isLastSeenVersionLessThan(String version) {
|
|
try {
|
|
return isLastSeenVersionLessThan(Version.parse(version));
|
|
} catch (VersionParsingException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
|
|
@Nullable
|
|
public String currentControllerUid() {
|
|
return currentControllerUid;
|
|
}
|
|
}
|