feat: port to commons 1.7
ci/woodpecker/push/docs Pipeline was successful Details
ci/woodpecker/push/jfmod Pipeline was successful Details

This commit is contained in:
Johannes Frohnmeyer 2024-04-18 23:09:35 +02:00
parent 38ea9f1f44
commit cb1821853b
Signed by: Johannes
GPG Key ID: E76429612C2929F4
23 changed files with 171 additions and 152 deletions

View File

@ -4,9 +4,8 @@ minecraft = "1.20.4"
yarn = "build.3" yarn = "build.3"
fabric-loader = "0.15.7" fabric-loader = "0.15.7"
fabric-api = "0.96.4+1.20.4" fabric-api = "0.96.4+1.20.4"
jf-commons = "1.6-SNAPSHOT" jf-commons = "1.7-SNAPSHOT"
modmenu = "9.0.0" modmenu = "9.0.0"
gson-compile = "1.4-SNAPSHOT"
annotations = "24.1.0" annotations = "24.1.0"
javapoet = "1.13.0" javapoet = "1.13.0"
@ -16,12 +15,13 @@ commons-http-client = { module = "io.gitlab.jfronny:commons-http-client", versio
commons-io = { module = "io.gitlab.jfronny:commons-io", version.ref="jf-commons" } commons-io = { module = "io.gitlab.jfronny:commons-io", version.ref="jf-commons" }
commons-logger = { module = "io.gitlab.jfronny:commons-logger", version.ref="jf-commons" } commons-logger = { module = "io.gitlab.jfronny:commons-logger", version.ref="jf-commons" }
commons-serialize = { module = "io.gitlab.jfronny:commons-serialize", version.ref="jf-commons" } commons-serialize = { module = "io.gitlab.jfronny:commons-serialize", version.ref="jf-commons" }
commons-serialize-gson = { module = "io.gitlab.jfronny:commons-serialize-gson", version.ref="jf-commons" } commons-serialize-databind = { module = "io.gitlab.jfronny:commons-serialize-databind", version.ref="jf-commons" }
commons-serialize-json = { module = "io.gitlab.jfronny:commons-serialize-json", version.ref="jf-commons" }
commons-serialize-generator-core = { module = "io.gitlab.jfronny:commons-serialize-generator-core", version.ref="jf-commons" }
commons-unsafe = { module = "io.gitlab.jfronny:commons-unsafe", version.ref="jf-commons" } commons-unsafe = { module = "io.gitlab.jfronny:commons-unsafe", version.ref="jf-commons" }
modmenu = { module = "com.terraformersmc:modmenu", version.ref="modmenu" } modmenu = { module = "com.terraformersmc:modmenu", version.ref="modmenu" }
gson-compile-processor-core = { module = "io.gitlab.jfronny.gson:gson-compile-processor-core", version.ref="gson-compile" }
annotations = { module = "org.jetbrains:annotations", version.ref="annotations" } annotations = { module = "org.jetbrains:annotations", version.ref="annotations" }
javapoet = { module = "com.squareup:javapoet", version.ref="javapoet" } javapoet = { module = "com.squareup:javapoet", version.ref="javapoet" }
[bundles] [bundles]
commons = ["commons", "commons-http-client", "commons-logger", "commons-io", "commons-serialize", "commons-serialize-gson"] commons = ["commons", "commons-http-client", "commons-logger", "commons-io", "commons-serialize", "commons-serialize-databind", "commons-serialize-json"]

View File

@ -1,10 +1,12 @@
package io.gitlab.jfronny.libjf; package io.gitlab.jfronny.libjf;
import io.gitlab.jfronny.commons.Serializer;
import io.gitlab.jfronny.commons.logger.DelegateLogger; import io.gitlab.jfronny.commons.logger.DelegateLogger;
import io.gitlab.jfronny.commons.logger.HotswapLoggerFinder; import io.gitlab.jfronny.commons.logger.HotswapLoggerFinder;
import io.gitlab.jfronny.commons.logger.SystemLoggerPlus; import io.gitlab.jfronny.commons.logger.SystemLoggerPlus;
import io.gitlab.jfronny.commons.serialize.gson.api.v2.GsonHolders; import io.gitlab.jfronny.commons.serialize.databind.DatabindSerializer;
import io.gitlab.jfronny.libjf.gson.HiddenAnnotationExclusionStrategy; import io.gitlab.jfronny.commons.serialize.databind.ObjectMapper;
import io.gitlab.jfronny.commons.serialize.json.JsonTransport;
import io.gitlab.jfronny.libjf.log.JULBridge; import io.gitlab.jfronny.libjf.log.JULBridge;
import io.gitlab.jfronny.libjf.log.SLF4JPlatformLogger; import io.gitlab.jfronny.libjf.log.SLF4JPlatformLogger;
import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint; import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint;
@ -13,10 +15,11 @@ import org.slf4j.LoggerFactory;
public class LibJf implements PreLaunchEntrypoint { public class LibJf implements PreLaunchEntrypoint {
public static final String MOD_ID = "libjf"; public static final String MOD_ID = "libjf";
public static final SystemLoggerPlus LOGGER = SystemLoggerPlus.forName(MOD_ID); public static final SystemLoggerPlus LOGGER = SystemLoggerPlus.forName(MOD_ID);
public static final ObjectMapper MAPPER = new ObjectMapper();
public static final JsonTransport JSON_TRANSPORT = new JsonTransport();
static { static {
HiddenAnnotationExclusionStrategy.register(); Serializer.setInstance(new DatabindSerializer<>(JSON_TRANSPORT, MAPPER));
GsonHolders.registerSerializer();
} }
@Override @Override

View File

@ -1,8 +0,0 @@
package io.gitlab.jfronny.libjf.gson;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ClientOnly {
}

View File

@ -1,30 +0,0 @@
package io.gitlab.jfronny.libjf.gson;
import io.gitlab.jfronny.gson.*;
import net.fabricmc.loader.api.metadata.CustomValue;
import java.util.Map;
public class FabricLoaderGsonGenerator {
public static JsonElement toGson(CustomValue customValue) {
if (customValue == null) return null;
return switch (customValue.getType()) {
case OBJECT -> {
JsonObject jo = new JsonObject();
for (Map.Entry<String, CustomValue> value : customValue.getAsObject())
jo.add(value.getKey(), toGson(value.getValue()));
yield jo;
}
case ARRAY -> {
JsonArray jo = new JsonArray();
for (CustomValue value : customValue.getAsArray())
jo.add(toGson(value));
yield jo;
}
case STRING -> new JsonPrimitive(customValue.getAsString());
case NUMBER -> new JsonPrimitive(customValue.getAsNumber());
case BOOLEAN -> new JsonPrimitive(customValue.getAsBoolean());
case NULL -> JsonNull.INSTANCE;
};
}
}

View File

@ -1,7 +0,0 @@
package io.gitlab.jfronny.libjf.gson;
import io.gitlab.jfronny.gson.GsonBuilder;
public interface GsonAdapter {
void apply(GsonBuilder builder);
}

View File

@ -1,22 +0,0 @@
package io.gitlab.jfronny.libjf.gson;
import io.gitlab.jfronny.commons.serialize.gson.api.v2.GsonHolders;
import io.gitlab.jfronny.gson.ExclusionStrategy;
import io.gitlab.jfronny.gson.FieldAttributes;
import net.fabricmc.api.EnvType;
import net.fabricmc.loader.api.FabricLoader;
public class HiddenAnnotationExclusionStrategy implements ExclusionStrategy {
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
public boolean shouldSkipField(FieldAttributes fieldAttributes) {
return FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT
? fieldAttributes.getAnnotation(ServerOnly.class) != null
: fieldAttributes.getAnnotation(ClientOnly.class) != null;
}
public static void register() {
GsonHolders.applyTransform(builder -> builder.setExclusionStrategies(new HiddenAnnotationExclusionStrategy()));
}
}

View File

@ -1,8 +0,0 @@
package io.gitlab.jfronny.libjf.gson;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ServerOnly {
}

View File

@ -0,0 +1,30 @@
package io.gitlab.jfronny.libjf.serialize;
import io.gitlab.jfronny.commons.serialize.emulated.DataElement;
import net.fabricmc.loader.api.metadata.CustomValue;
import java.util.Map;
public class FabricLoaderDataMapper {
public static DataElement toGson(CustomValue customValue) {
if (customValue == null) return null;
return switch (customValue.getType()) {
case OBJECT -> {
DataElement.Object jo = new DataElement.Object();
for (Map.Entry<String, CustomValue> value : customValue.getAsObject())
jo.members().put(value.getKey(), toGson(value.getValue()));
yield jo;
}
case ARRAY -> {
DataElement.Array jo = new DataElement.Array();
for (CustomValue value : customValue.getAsArray())
jo.elements().add(toGson(value));
yield jo;
}
case STRING -> new DataElement.Primitive.String(customValue.getAsString());
case NUMBER -> new DataElement.Primitive.Number(customValue.getAsNumber());
case BOOLEAN -> new DataElement.Primitive.Boolean(customValue.getAsBoolean());
case NULL -> new DataElement.Null();
};
}
}

View File

@ -0,0 +1,24 @@
package io.gitlab.jfronny.libjf.serialize;
import io.gitlab.jfronny.commons.serialize.SerializeReader;
import io.gitlab.jfronny.commons.serialize.SerializeWriter;
import io.gitlab.jfronny.commons.serialize.json.JsonWriter;
public class SerializationMode {
public static <TEx extends Exception, Reader extends SerializeReader<TEx, Reader>> void asConfig(Reader reader) {
reader.setLenient(true)
.setSerializeSpecialFloatingPointValues(true);
}
public static <TEx extends Exception, Writer extends SerializeWriter<TEx, Writer>> void asConfig(Writer writer) {
writer.setLenient(true)
.setSerializeSpecialFloatingPointValues(true)
.setSerializeNulls(true);
if (writer instanceof JsonWriter jw) {
jw.setIndent(" ")
.setNewline("\n")
.setOmitQuotes(true)
.setCommentUnexpectedNames(true);
}
}
}

View File

@ -14,11 +14,12 @@ repositories {
} }
dependencies { dependencies {
implementation(libs.gson.compile.processor.core) implementation(libs.commons.serialize.generator.core)
implementation(devProject(":libjf-config-core-v2")) implementation(devProject(":libjf-config-core-v2"))
implementation(libs.annotations) implementation(libs.annotations)
implementation(libs.commons) implementation(libs.commons)
implementation(libs.commons.serialize.gson) implementation(libs.commons.serialize.databind)
implementation(libs.commons.serialize.json)
implementation(libs.javapoet) implementation(libs.javapoet)
testAnnotationProcessor(sourceSets.main.get().output) testAnnotationProcessor(sourceSets.main.get().output)
configurations.testAnnotationProcessor.get().extendsFrom(configurations.implementation.get()) configurations.testAnnotationProcessor.get().extendsFrom(configurations.implementation.get())

View File

@ -2,8 +2,8 @@ package io.gitlab.jfronny.libjf.config.plugin;
import com.squareup.javapoet.*; import com.squareup.javapoet.*;
import io.gitlab.jfronny.commons.StringFormatter; import io.gitlab.jfronny.commons.StringFormatter;
import io.gitlab.jfronny.gson.compile.processor.core.*; import io.gitlab.jfronny.commons.serialize.databind.api.TypeToken;
import io.gitlab.jfronny.gson.reflect.TypeToken; import io.gitlab.jfronny.commons.serialize.generator.core.*;
import io.gitlab.jfronny.libjf.config.api.v2.*; import io.gitlab.jfronny.libjf.config.api.v2.*;
import io.gitlab.jfronny.libjf.config.api.v2.dsl.DSL; import io.gitlab.jfronny.libjf.config.api.v2.dsl.DSL;
import io.gitlab.jfronny.libjf.config.api.v2.type.Type; import io.gitlab.jfronny.libjf.config.api.v2.type.Type;

View File

@ -1,6 +1,7 @@
package io.gitlab.jfronny.libjf.config.api.v2; package io.gitlab.jfronny.libjf.config.api.v2;
import io.gitlab.jfronny.gson.stream.*; import io.gitlab.jfronny.commons.serialize.SerializeReader;
import io.gitlab.jfronny.commons.serialize.SerializeWriter;
import io.gitlab.jfronny.libjf.config.api.v2.type.Type; import io.gitlab.jfronny.libjf.config.api.v2.type.Type;
import io.gitlab.jfronny.libjf.config.impl.dsl.DslEntryInfo; import io.gitlab.jfronny.libjf.config.impl.dsl.DslEntryInfo;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
@ -68,13 +69,13 @@ public interface EntryInfo<T> {
* Set this entry's value to that of the element * Set this entry's value to that of the element
* @param reader The reader to read from * @param reader The reader to read from
*/ */
void loadFromJson(JsonReader reader) throws IOException, IllegalAccessException; <TEx extends Exception, Reader extends SerializeReader<TEx, Reader>> void loadFromJson(Reader reader) throws TEx, IllegalAccessException;
/** /**
* Write the currently cached value to the writer * Write the currently cached value to the writer
* @param writer The writer to write to * @param writer The writer to write to
*/ */
void writeTo(JsonWriter writer, String translationPrefix) throws IOException, IllegalAccessException; <TEx extends Exception, Writer extends SerializeWriter<TEx, Writer>> void writeTo(Writer writer, String translationPrefix) throws TEx, IllegalAccessException;
/** /**
* @return Get the width for this entry * @return Get the width for this entry

View File

@ -1,10 +1,10 @@
package io.gitlab.jfronny.libjf.config.api.v2.dsl; package io.gitlab.jfronny.libjf.config.api.v2.dsl;
import io.gitlab.jfronny.gson.stream.JsonReader; import io.gitlab.jfronny.commons.serialize.SerializeReader;
import java.io.IOException; import java.io.IOException;
@FunctionalInterface @FunctionalInterface
public interface Migration { public interface Migration {
void apply(JsonReader reader) throws IOException; <TEx extends Exception, Reader extends SerializeReader<TEx, Reader>> void apply(Reader reader) throws IOException;
} }

View File

@ -1,16 +1,17 @@
package io.gitlab.jfronny.libjf.config.impl; package io.gitlab.jfronny.libjf.config.impl;
import io.gitlab.jfronny.commons.serialize.gson.api.v2.GsonHolders; import io.gitlab.jfronny.commons.serialize.emulated.DataElement;
import io.gitlab.jfronny.libjf.config.api.v2.Category; import io.gitlab.jfronny.libjf.config.api.v2.Category;
import io.gitlab.jfronny.libjf.config.api.v2.JfConfig; import io.gitlab.jfronny.libjf.config.api.v2.JfConfig;
import io.gitlab.jfronny.libjf.config.api.v2.dsl.CategoryBuilder; import io.gitlab.jfronny.libjf.config.api.v2.dsl.CategoryBuilder;
import io.gitlab.jfronny.libjf.gson.FabricLoaderGsonGenerator; import io.gitlab.jfronny.libjf.serialize.FabricLoaderDataMapper;
import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.metadata.CustomValue; import net.fabricmc.loader.api.metadata.CustomValue;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map;
import static io.gitlab.jfronny.libjf.config.impl.ConfigCore.MODULE_ID; import static io.gitlab.jfronny.libjf.config.impl.ConfigCore.MODULE_ID;
@ -43,11 +44,30 @@ public class AuxiliaryMetadata {
cv = cv.getAsObject().get("config"); cv = cv.getAsObject().get("config");
} }
} }
if (cv != null) metaRef.meta = GsonHolders.API.getGson().fromJson(FabricLoaderGsonGenerator.toGson(cv), AuxiliaryMetadata.class); if (cv != null) metaRef.meta = read(FabricLoaderDataMapper.toGson(cv));
}); });
return metaRef.meta; return metaRef.meta;
} }
public static AuxiliaryMetadata read(DataElement data) {
if (!(data instanceof DataElement.Object obj)) throw new IllegalArgumentException("AuxiliaryMetadata must be an object");
AuxiliaryMetadata meta = new AuxiliaryMetadata();
for (Map.Entry<String, DataElement> entry : obj.members().entrySet()) {
switch (entry.getKey()) {
case "referencedConfigs" -> {
if (!(entry.getValue() instanceof DataElement.Array arr)) throw new IllegalArgumentException("referencedConfigs must be an array");
meta.referencedConfigs = new LinkedList<>();
arr.elements().forEach(element -> {
if (!(element instanceof DataElement.Primitive.String str)) throw new IllegalArgumentException("referencedConfigs must be an array of strings");
meta.referencedConfigs.add(str.value());
});
}
default -> throw new IllegalArgumentException("Unknown key in AuxiliaryMetadata: " + entry.getKey());
}
}
return meta;
}
public List<String> referencedConfigs; public List<String> referencedConfigs;
public void applyTo(CategoryBuilder<?> builder) { public void applyTo(CategoryBuilder<?> builder) {

View File

@ -1,7 +1,7 @@
package io.gitlab.jfronny.libjf.config.impl.dsl; package io.gitlab.jfronny.libjf.config.impl.dsl;
import io.gitlab.jfronny.commons.serialize.SerializeReader;
import io.gitlab.jfronny.commons.throwable.Coerce; import io.gitlab.jfronny.commons.throwable.Coerce;
import io.gitlab.jfronny.gson.stream.JsonReader;
import io.gitlab.jfronny.libjf.LibJf; import io.gitlab.jfronny.libjf.LibJf;
import io.gitlab.jfronny.libjf.config.api.v2.*; import io.gitlab.jfronny.libjf.config.api.v2.*;
import io.gitlab.jfronny.libjf.config.api.v2.dsl.CategoryBuilder; import io.gitlab.jfronny.libjf.config.api.v2.dsl.CategoryBuilder;
@ -21,7 +21,8 @@ public class CategoryBuilderImpl<Builder extends CategoryBuilderImpl<Builder>> i
public final Map<String, Consumer<ConfigCategory>> presets = new LinkedHashMap<>(); public final Map<String, Consumer<ConfigCategory>> presets = new LinkedHashMap<>();
public final List<Supplier<List<ConfigInstance>>> referencedConfigs = new LinkedList<>(); public final List<Supplier<List<ConfigInstance>>> referencedConfigs = new LinkedList<>();
public final List<Consumer<ConfigCategory>> verifiers = new LinkedList<>(); public final List<Consumer<ConfigCategory>> verifiers = new LinkedList<>();
public final Map<String, Consumer<JsonReader>> migrations = new LinkedHashMap<>(); @SuppressWarnings("rawtypes") // recursive types aren't really needed here
public final Map<String, Consumer<SerializeReader>> migrations = new LinkedHashMap<>();
private boolean built = false; private boolean built = false;
public CategoryBuilderImpl(String id, String categoryPath) { public CategoryBuilderImpl(String id, String categoryPath) {
@ -174,7 +175,7 @@ public class CategoryBuilderImpl<Builder extends CategoryBuilderImpl<Builder>> i
public Builder addMigration(String element, Migration migration) { public Builder addMigration(String element, Migration migration) {
checkBuilt(); checkBuilt();
if (migrations.containsKey(element)) LibJf.LOGGER.warn("Duplicate migration registered for " + categoryPath + id + ": " + element + ", overriding"); if (migrations.containsKey(element)) LibJf.LOGGER.warn("Duplicate migration registered for " + categoryPath + id + ": " + element + ", overriding");
migrations.put(element, Coerce.consumer(migration::apply).addHandler(e -> LibJf.LOGGER.error("Could not apply migration for " + element, e))); migrations.put(element, Coerce.<SerializeReader, Exception>consumer(migration::apply).addHandler(e -> LibJf.LOGGER.error("Could not apply migration for " + element, e)));
return asBuilder(); return asBuilder();
} }

View File

@ -1,12 +1,14 @@
package io.gitlab.jfronny.libjf.config.impl.dsl; package io.gitlab.jfronny.libjf.config.impl.dsl;
import io.gitlab.jfronny.commons.serialize.gson.api.v2.GsonHolders; import io.gitlab.jfronny.commons.serialize.SerializeReader;
import io.gitlab.jfronny.gson.*; import io.gitlab.jfronny.commons.serialize.Token;
import io.gitlab.jfronny.gson.stream.*; import io.gitlab.jfronny.commons.serialize.json.JsonReader;
import io.gitlab.jfronny.commons.serialize.json.JsonWriter;
import io.gitlab.jfronny.libjf.LibJf; import io.gitlab.jfronny.libjf.LibJf;
import io.gitlab.jfronny.libjf.config.api.v2.*; import io.gitlab.jfronny.libjf.config.api.v2.*;
import io.gitlab.jfronny.libjf.config.impl.entrypoint.JfConfigSafe; import io.gitlab.jfronny.libjf.config.impl.entrypoint.JfConfigSafe;
import io.gitlab.jfronny.libjf.config.impl.watch.JfConfigWatchService; import io.gitlab.jfronny.libjf.config.impl.watch.JfConfigWatchService;
import io.gitlab.jfronny.libjf.serialize.SerializationMode;
import java.io.*; import java.io.*;
import java.nio.file.Files; import java.nio.file.Files;
@ -19,7 +21,8 @@ public class DefaultConfigIO {
// Actions cannot be cached since entries can change // Actions cannot be cached since entries can change
if (Files.exists(path)) { if (Files.exists(path)) {
try (BufferedReader br = Files.newBufferedReader(path); try (BufferedReader br = Files.newBufferedReader(path);
JsonReader jr = GsonHolders.CONFIG.getGson().newJsonReader(br)) { JsonReader jr = new JsonReader(br)) {
SerializationMode.asConfig(jr);
runActions(id, createActions(c), jr); runActions(id, createActions(c), jr);
} catch (Exception e) { } catch (Exception e) {
LibJf.LOGGER.error("Could not read config for " + id, e); LibJf.LOGGER.error("Could not read config for " + id, e);
@ -29,21 +32,21 @@ public class DefaultConfigIO {
}); });
} }
record Action(Consumer<JsonReader> task, boolean required) { record Action(Consumer<SerializeReader> task, boolean required) {
public Action(Consumer<JsonReader> task) { public Action(Consumer<SerializeReader> task) {
this(task, true); this(task, true);
} }
} }
private static void runActions(String id, Map<String, Action> actions, JsonReader reader) { private static <TEx extends Exception, Reader extends SerializeReader<TEx, Reader>> void runActions(String id, Map<String, Action> actions, Reader reader) {
try { try {
if (reader.peek() != JsonToken.BEGIN_OBJECT) { if (reader.peek() != Token.BEGIN_OBJECT) {
LibJf.LOGGER.error("Invalid config: Not a JSON object for " + id); LibJf.LOGGER.error("Invalid config: Not a JSON object for " + id);
return; return;
} }
Set<String> appeared = new HashSet<>(); Set<String> appeared = new HashSet<>();
reader.beginObject(); reader.beginObject();
while (reader.peek() != JsonToken.END_OBJECT) { while (reader.peek() != Token.END_OBJECT) {
String name = reader.nextName(); String name = reader.nextName();
if (!actions.containsKey(name)) { if (!actions.containsKey(name)) {
LibJf.LOGGER.warn("Unrecognized key in config for " + id + ": " + name); LibJf.LOGGER.warn("Unrecognized key in config for " + id + ": " + name);
@ -61,8 +64,8 @@ public class DefaultConfigIO {
LibJf.LOGGER.error("Missing entry in config for " + id + ": " + name); LibJf.LOGGER.error("Missing entry in config for " + id + ": " + name);
} }
}); });
} catch (IOException e) { } catch (Exception e) {
throw new JsonParseException("Could not read config", e); throw new IllegalStateException("Could not read config", e);
} }
} }
@ -71,7 +74,7 @@ public class DefaultConfigIO {
category.getEntries().forEach(entry -> actions.putIfAbsent(entry.getName(), new Action(reader -> { category.getEntries().forEach(entry -> actions.putIfAbsent(entry.getName(), new Action(reader -> {
try { try {
entry.loadFromJson(reader); entry.loadFromJson(reader);
} catch (IllegalAccessException | IOException e) { } catch (Exception e) {
LibJf.LOGGER.error("Could not set config entry value of " + entry.getName(), e); LibJf.LOGGER.error("Could not set config entry value of " + entry.getName(), e);
} }
}))); })));
@ -91,7 +94,8 @@ public class DefaultConfigIO {
public static Consumer<ConfigInstance> writer(String id) { public static Consumer<ConfigInstance> writer(String id) {
return c -> c.getFilePath().ifPresent(path -> JfConfigWatchService.lock(path, () -> { return c -> c.getFilePath().ifPresent(path -> JfConfigWatchService.lock(path, () -> {
try (BufferedWriter bw = Files.newBufferedWriter(path); try (BufferedWriter bw = Files.newBufferedWriter(path);
JsonWriter jw = GsonHolders.CONFIG.getGson().newJsonWriter(bw)) { JsonWriter jw = new JsonWriter(bw)) {
SerializationMode.asConfig(jw);
writeTo(jw, c); writeTo(jw, c);
} catch (Exception e) { } catch (Exception e) {
LibJf.LOGGER.error("Could not write config for " + id, e); LibJf.LOGGER.error("Could not write config for " + id, e);

View File

@ -1,6 +1,6 @@
package io.gitlab.jfronny.libjf.config.impl.dsl; package io.gitlab.jfronny.libjf.config.impl.dsl;
import io.gitlab.jfronny.gson.stream.JsonReader; import io.gitlab.jfronny.commons.serialize.SerializeReader;
import io.gitlab.jfronny.libjf.config.api.v2.*; import io.gitlab.jfronny.libjf.config.api.v2.*;
import io.gitlab.jfronny.libjf.config.api.v2.dsl.CategoryBuilder; import io.gitlab.jfronny.libjf.config.api.v2.dsl.CategoryBuilder;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
@ -17,7 +17,7 @@ public class DslConfigCategory implements ConfigCategory {
private final List<EntryInfo<?>> entries; private final List<EntryInfo<?>> entries;
private final Map<String, Runnable> presets; private final Map<String, Runnable> presets;
private final List<Supplier<List<ConfigInstance>>> referencedConfigs; private final List<Supplier<List<ConfigInstance>>> referencedConfigs;
@ApiStatus.Internal public final Map<String, Consumer<JsonReader>> migrations; @ApiStatus.Internal public final Map<String, Consumer<SerializeReader>> migrations;
private final Map<String, ConfigCategory> categories; private final Map<String, ConfigCategory> categories;
private final Supplier<ConfigInstance> root; private final Supplier<ConfigInstance> root;
private final List<Consumer<ConfigCategory>> verifiers; private final List<Consumer<ConfigCategory>> verifiers;
@ -31,7 +31,7 @@ public class DslConfigCategory implements ConfigCategory {
List<CategoryBuilder<?>> categories, List<CategoryBuilder<?>> categories,
Supplier<ConfigInstance> root, Supplier<ConfigInstance> root,
List<Consumer<ConfigCategory>> verifiers, List<Consumer<ConfigCategory>> verifiers,
Map<String, Consumer<JsonReader>> migrations) { Map<String, Consumer<SerializeReader>> migrations) {
this.id = id; this.id = id;
this.categoryPath = categoryPath; this.categoryPath = categoryPath;
this.translationPrefix = translationPrefix; this.translationPrefix = translationPrefix;

View File

@ -1,6 +1,6 @@
package io.gitlab.jfronny.libjf.config.impl.dsl; package io.gitlab.jfronny.libjf.config.impl.dsl;
import io.gitlab.jfronny.gson.stream.JsonReader; import io.gitlab.jfronny.commons.serialize.SerializeReader;
import io.gitlab.jfronny.libjf.config.api.v2.*; import io.gitlab.jfronny.libjf.config.api.v2.*;
import io.gitlab.jfronny.libjf.config.api.v2.dsl.CategoryBuilder; import io.gitlab.jfronny.libjf.config.api.v2.dsl.CategoryBuilder;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -23,7 +23,7 @@ public class DslConfigInstance extends DslConfigCategory implements ConfigInstan
List<CategoryBuilder<?>> categories, List<CategoryBuilder<?>> categories,
Supplier<ConfigInstance> root, Supplier<ConfigInstance> root,
List<Consumer<ConfigCategory>> verifiers, List<Consumer<ConfigCategory>> verifiers,
Map<String, Consumer<JsonReader>> migrations, Map<String, Consumer<SerializeReader>> migrations,
Consumer<ConfigInstance> load, Consumer<ConfigInstance> load,
Consumer<ConfigInstance> write, Consumer<ConfigInstance> write,
@Nullable Path path) { @Nullable Path path) {

View File

@ -1,16 +1,19 @@
package io.gitlab.jfronny.libjf.config.impl.dsl; package io.gitlab.jfronny.libjf.config.impl.dsl;
import io.gitlab.jfronny.commons.serialize.gson.api.v2.GsonHolders; import io.gitlab.jfronny.commons.Serializer;
import io.gitlab.jfronny.commons.serialize.MalformedDataException;
import io.gitlab.jfronny.commons.serialize.SerializeReader;
import io.gitlab.jfronny.commons.serialize.SerializeWriter;
import io.gitlab.jfronny.commons.serialize.Token;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeToken;
import io.gitlab.jfronny.commons.throwable.ThrowingConsumer; import io.gitlab.jfronny.commons.throwable.ThrowingConsumer;
import io.gitlab.jfronny.commons.throwable.ThrowingSupplier; import io.gitlab.jfronny.commons.throwable.ThrowingSupplier;
import io.gitlab.jfronny.gson.stream.*;
import io.gitlab.jfronny.libjf.LibJf; import io.gitlab.jfronny.libjf.LibJf;
import io.gitlab.jfronny.libjf.config.api.v2.Entry; import io.gitlab.jfronny.libjf.config.api.v2.Entry;
import io.gitlab.jfronny.libjf.config.api.v2.EntryInfo; import io.gitlab.jfronny.libjf.config.api.v2.EntryInfo;
import io.gitlab.jfronny.libjf.config.api.v2.type.Type; import io.gitlab.jfronny.libjf.config.api.v2.type.Type;
import io.gitlab.jfronny.libjf.config.impl.entrypoint.JfConfigSafe; import io.gitlab.jfronny.libjf.config.impl.entrypoint.JfConfigSafe;
import java.io.IOException;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.Arrays; import java.util.Arrays;
import java.util.Objects; import java.util.Objects;
@ -127,38 +130,42 @@ public class DslEntryInfo<T> implements EntryInfo<T> {
} }
@Override @Override
public void loadFromJson(JsonReader reader) throws IOException, IllegalAccessException { public <TEx extends Exception, Reader extends SerializeReader<TEx, Reader>> void loadFromJson(Reader reader) throws TEx, IllegalAccessException {
var next = reader.peek(); var next = reader.peek();
if (type.isBool()) { if (type.isBool()) {
if (next == JsonToken.BOOLEAN) setUnchecked(reader.nextBoolean()); if (next == Token.BOOLEAN) setUnchecked(reader.nextBoolean());
else LibJf.LOGGER.error("Unexpected value for " + name + ": expected boolean but got " + next); else LibJf.LOGGER.error("Unexpected value for " + name + ": expected boolean but got " + next);
} else if (type.isString()) { } else if (type.isString()) {
if (next == JsonToken.STRING || next == JsonToken.NUMBER) setUnchecked(reader.nextString()); if (next == Token.STRING || next == Token.NUMBER) setUnchecked(reader.nextString());
else if (next == JsonToken.BOOLEAN) setUnchecked(Boolean.toString(reader.nextBoolean())); else if (next == Token.BOOLEAN) setUnchecked(Boolean.toString(reader.nextBoolean()));
else if (next == JsonToken.NULL) { else if (next == Token.NULL) {
reader.nextNull(); reader.nextNull();
setUnchecked(null); setUnchecked(null);
} else LibJf.LOGGER.error("Unexpected value for " + name + ": expected string but got " + next); } else LibJf.LOGGER.error("Unexpected value for " + name + ": expected string but got " + next);
} else if (type.isInt()) { } else if (type.isInt()) {
if (next == JsonToken.NUMBER) setUnchecked(reader.nextInt()); if (next == Token.NUMBER) setUnchecked(reader.nextInt());
else LibJf.LOGGER.error("Unexpected value for " + name + ": expected number but got " + next); else LibJf.LOGGER.error("Unexpected value for " + name + ": expected number but got " + next);
} else if (type.isLong()) { } else if (type.isLong()) {
if (next == JsonToken.NUMBER) setUnchecked(reader.nextLong()); if (next == Token.NUMBER) setUnchecked(reader.nextLong());
else LibJf.LOGGER.error("Unexpected value for " + name + ": expected number but got " + next); else LibJf.LOGGER.error("Unexpected value for " + name + ": expected number but got " + next);
} else if (type.isDouble()) { } else if (type.isDouble()) {
if (next == JsonToken.NUMBER) { if (next == Token.NUMBER) {
setUnchecked(reader.nextDouble()); setUnchecked(reader.nextDouble());
} }
else LibJf.LOGGER.error("Unexpected value for " + name + ": expected number but got " + next); else LibJf.LOGGER.error("Unexpected value for " + name + ": expected number but got " + next);
} else if (type.isFloat()) { } else if (type.isFloat()) {
if (next == JsonToken.NUMBER) setUnchecked((float) reader.nextDouble()); if (next == Token.NUMBER) setUnchecked((float) reader.nextDouble());
else LibJf.LOGGER.error("Unexpected value for " + name + ": expected number but got " + next); else LibJf.LOGGER.error("Unexpected value for " + name + ": expected number but got " + next);
} else if (type.isEnum()) { } else if (type.isEnum()) {
Type.TEnum<T> e = (Type.TEnum<T>) type; Type.TEnum<T> e = (Type.TEnum<T>) type;
if (next == JsonToken.STRING) setUnchecked(e.optionForString(reader.nextString())); if (next == Token.STRING) setUnchecked(e.optionForString(reader.nextString()));
else LibJf.LOGGER.error("Unexpected value for " + name + ": expected string but got " + next); else LibJf.LOGGER.error("Unexpected value for " + name + ": expected string but got " + next);
} else { } else {
setValue(GsonHolders.CONFIG.getGson().fromJson(reader, type.asClass())); try {
setValue((T) LibJf.MAPPER.getAdapter(TypeToken.get(type.asClass())).deserialize(reader));
} catch (MalformedDataException e) {
LibJf.LOGGER.error("Could not read " + name, e);
}
} }
} }
@ -169,7 +176,7 @@ public class DslEntryInfo<T> implements EntryInfo<T> {
} }
@Override @Override
public void writeTo(JsonWriter writer, String translationPrefix) throws IOException, IllegalAccessException { public <TEx extends Exception, Writer extends SerializeWriter<TEx, Writer>> void writeTo(Writer writer, String translationPrefix) throws TEx, IllegalAccessException {
T value = getValue(); T value = getValue();
String commentText; String commentText;
if ((commentText = JfConfigSafe.TRANSLATION_SUPPLIER.apply(translationPrefix + getName() + ".tooltip")) != null) { if ((commentText = JfConfigSafe.TRANSLATION_SUPPLIER.apply(translationPrefix + getName() + ".tooltip")) != null) {
@ -179,7 +186,11 @@ public class DslEntryInfo<T> implements EntryInfo<T> {
writer.comment("Valid: [" + Arrays.stream(((Type.TEnum<T>)type).options()).map(Objects::toString).collect(Collectors.joining(", ")) + "]"); writer.comment("Valid: [" + Arrays.stream(((Type.TEnum<T>)type).options()).map(Objects::toString).collect(Collectors.joining(", ")) + "]");
} }
writer.name(name); writer.name(name);
GsonHolders.CONFIG.getGson().toJson(value, Objects.requireNonNullElse(type.asClass(), String.class), writer); try {
LibJf.MAPPER.getAdapter((TypeToken<T>) TypeToken.get(Objects.requireNonNullElse(type.asClass(), String.class))).serialize(value, writer);
} catch (MalformedDataException e) {
LibJf.LOGGER.error("Could not write " + name, e);
}
} }
@Override @Override

View File

@ -1,18 +1,14 @@
package io.gitlab.jfronny.libjf.config.impl.network.rci.entry; package io.gitlab.jfronny.libjf.config.impl.network.rci.entry;
import io.gitlab.jfronny.gson.stream.JsonReader; import io.gitlab.jfronny.commons.serialize.SerializeReader;
import io.gitlab.jfronny.gson.stream.JsonWriter; import io.gitlab.jfronny.commons.serialize.SerializeWriter;
import io.gitlab.jfronny.libjf.config.api.v2.EntryInfo; import io.gitlab.jfronny.libjf.config.api.v2.EntryInfo;
import io.gitlab.jfronny.libjf.config.api.v2.type.Type;
import io.gitlab.jfronny.libjf.config.impl.network.rci.MirrorConfigCategory; import io.gitlab.jfronny.libjf.config.impl.network.rci.MirrorConfigCategory;
import io.gitlab.jfronny.libjf.config.impl.network.rci.MirrorObject; import io.gitlab.jfronny.libjf.config.impl.network.rci.MirrorObject;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.fabricmc.fabric.api.networking.v1.PacketSender; import net.fabricmc.fabric.api.networking.v1.PacketSender;
import net.minecraft.network.PacketByteBuf; import net.minecraft.network.PacketByteBuf;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
public abstract class MirrorEntryInfoBase<T> extends MirrorObject implements EntryInfo<T> { public abstract class MirrorEntryInfoBase<T> extends MirrorObject implements EntryInfo<T> {
protected final MirrorConfigCategory category; protected final MirrorConfigCategory category;
protected final String entryName; protected final String entryName;
@ -34,13 +30,13 @@ public abstract class MirrorEntryInfoBase<T> extends MirrorObject implements Ent
} }
@Override @Override
public void loadFromJson(JsonReader reader) throws IOException, IllegalAccessException { public <TEx extends Exception, Reader extends SerializeReader<TEx, Reader>> void loadFromJson(Reader reader) {
throw new UnsupportedEncodingException(); throw new UnsupportedOperationException();
} }
@Override @Override
public void writeTo(JsonWriter writer, String translationPrefix) throws IOException, IllegalAccessException { public <TEx extends Exception, Writer extends SerializeWriter<TEx, Writer>> void writeTo(Writer writer, String translationPrefix) {
throw new UnsupportedEncodingException(); throw new UnsupportedOperationException();
} }
@Override @Override
@ -51,7 +47,7 @@ public abstract class MirrorEntryInfoBase<T> extends MirrorObject implements Ent
} }
@Override @Override
public void reset() throws IllegalAccessException { public void reset() {
PacketByteBuf buf = PacketByteBufs.create(); PacketByteBuf buf = PacketByteBufs.create();
writePath(buf); writePath(buf);
sendRequest("resetEntry", buf); sendRequest("resetEntry", buf);

View File

@ -1,6 +1,6 @@
package io.gitlab.jfronny.libjf.config.impl.ui.tiny; package io.gitlab.jfronny.libjf.config.impl.ui.tiny;
import io.gitlab.jfronny.commons.serialize.gson.api.v2.GsonHolders; import io.gitlab.jfronny.commons.Serializer;
import io.gitlab.jfronny.libjf.LibJf; import io.gitlab.jfronny.libjf.LibJf;
import io.gitlab.jfronny.libjf.config.api.v2.ConfigInstance; import io.gitlab.jfronny.libjf.config.api.v2.ConfigInstance;
import io.gitlab.jfronny.libjf.config.api.v2.EntryInfo; import io.gitlab.jfronny.libjf.config.api.v2.EntryInfo;
@ -13,6 +13,8 @@ import net.minecraft.client.resource.language.I18n;
import net.minecraft.client.toast.SystemToast; import net.minecraft.client.toast.SystemToast;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import java.io.IOException;
// IDEA doesn't like this, but it does work in practice // IDEA doesn't like this, but it does work in practice
public class TinyConfigScreenFactory implements ConfigScreenFactory<Screen, TinyConfigScreenFactory.Built> { public class TinyConfigScreenFactory implements ConfigScreenFactory<Screen, TinyConfigScreenFactory.Built> {
@Override @Override
@ -26,8 +28,9 @@ public class TinyConfigScreenFactory implements ConfigScreenFactory<Screen, Tiny
if (type != null && !type.isInt() && !type.isLong() && !type.isFloat() && !type.isDouble() && !type.isString() && !type.isBool() && !type.isEnum()) { if (type != null && !type.isInt() && !type.isLong() && !type.isFloat() && !type.isDouble() && !type.isString() && !type.isBool() && !type.isEnum()) {
final String jsonified; final String jsonified;
try { try {
jsonified = GsonHolders.CONFIG.getGson().toJson(entry.getValue()); var value = entry.getValue();
} catch (IllegalAccessException e) { jsonified = LibJf.JSON_TRANSPORT.write(writer -> LibJf.MAPPER.serialize(value, writer));
} catch (IllegalAccessException | IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
String key = config.getTranslationPrefix() + entry.getName(); String key = config.getTranslationPrefix() + entry.getName();
@ -38,7 +41,7 @@ public class TinyConfigScreenFactory implements ConfigScreenFactory<Screen, Tiny
jsonified, jsonified,
json -> { json -> {
try { try {
entry.setValue(GsonHolders.CONFIG.getGson().fromJson(json, type.asClass())); entry.setValue(Serializer.getInstance().deserialize(json, type.asClass()));
config.write(); config.write();
} catch (Throwable e) { } catch (Throwable e) {
LibJf.LOGGER.error("Could not write element", e); LibJf.LOGGER.error("Could not write element", e);

View File

@ -1,7 +1,7 @@
package io.gitlab.jfronny.libjf.config.impl.ui.tiny.entry; package io.gitlab.jfronny.libjf.config.impl.ui.tiny.entry;
import io.gitlab.jfronny.commons.Serializer;
import io.gitlab.jfronny.commons.ref.R; import io.gitlab.jfronny.commons.ref.R;
import io.gitlab.jfronny.commons.serialize.gson.api.v2.GsonHolders;
import io.gitlab.jfronny.commons.throwable.Try; import io.gitlab.jfronny.commons.throwable.Try;
import io.gitlab.jfronny.libjf.LibJf; import io.gitlab.jfronny.libjf.LibJf;
import io.gitlab.jfronny.libjf.config.api.v2.ConfigCategory; import io.gitlab.jfronny.libjf.config.api.v2.ConfigCategory;
@ -171,7 +171,7 @@ public class EntryInfoWidgetBuilder {
final String jsonified; final String jsonified;
if (state.tempValue == null) { if (state.tempValue == null) {
try { try {
jsonified = GsonHolders.CONFIG.getGson().toJson(state.cachedValue); jsonified = Serializer.getInstance().serialize(state.cachedValue);
} catch (Throwable e) { } catch (Throwable e) {
LibJf.LOGGER.error("Could not stringify element", e); LibJf.LOGGER.error("Could not stringify element", e);
SystemToast.add( SystemToast.add(
@ -193,7 +193,7 @@ public class EntryInfoWidgetBuilder {
jsonified, jsonified,
json -> { json -> {
try { try {
state.updateCache(GsonHolders.CONFIG.getGson().fromJson(json, info.getValueType().asClass())); state.updateCache(Serializer.getInstance().deserialize(json, info.getValueType().asClass()));
state.tempValue = null; state.tempValue = null;
} catch (Throwable e) { } catch (Throwable e) {
LibJf.LOGGER.error("Could not write element", e); LibJf.LOGGER.error("Could not write element", e);

View File

@ -1,7 +1,7 @@
package io.gitlab.jfronny.libjf.translate.impl.libretranslate; package io.gitlab.jfronny.libjf.translate.impl.libretranslate;
import io.gitlab.jfronny.commons.http.client.HttpClient; import io.gitlab.jfronny.commons.http.client.HttpClient;
import io.gitlab.jfronny.gson.reflect.TypeToken; import io.gitlab.jfronny.commons.serialize.databind.api.TypeToken;
import io.gitlab.jfronny.libjf.translate.api.TranslateException; import io.gitlab.jfronny.libjf.translate.api.TranslateException;
import io.gitlab.jfronny.libjf.translate.impl.AbstractTranslateService; import io.gitlab.jfronny.libjf.translate.impl.AbstractTranslateService;
import io.gitlab.jfronny.libjf.translate.impl.libretranslate.model.*; import io.gitlab.jfronny.libjf.translate.impl.libretranslate.model.*;