feat: initial work on 1.20.5 and commons 1.7 port

This commit is contained in:
Johannes Frohnmeyer 2024-04-24 19:33:50 +02:00
parent cba440978b
commit 8dba128843
Signed by: Johannes
GPG Key ID: E76429612C2929F4
39 changed files with 561 additions and 363 deletions

View File

@ -1,5 +1,5 @@
plugins {
id("jfmod") version "1.5-SNAPSHOT"
id("jfmod") version "1.6-SNAPSHOT"
}
allprojects { group = "io.gitlab.jfronny" }
@ -25,14 +25,14 @@ repositories {
}
}
val fabricVersion = "0.91.1+1.20.4"
val muscriptVersion = "1.5-SNAPSHOT"
val modmenuVersion = "9.0.0-pre.1"
val muscriptVersion = "1.7-SNAPSHOT"
val modmenuVersion = "10.0.0-beta.1"
jfMod {
minecraftVersion = "1.20.4"
minecraftVersion = "1.20.5"
yarn("build.1")
loaderVersion = "0.15.0"
libJfVersion = "3.14.1"
loaderVersion = "0.15.10"
libJfVersion = "3.15.1"
fabricApiVersion = "0.97.5+1.20.5"
modrinth {
projectId = "respackopts"
@ -47,17 +47,20 @@ jfMod {
}
dependencies {
modImplementation("net.fabricmc.fabric-api:fabric-api:$fabricVersion")
include(modImplementation("io.gitlab.jfronny:muscript:$muscriptVersion")!!)
include(modImplementation("io.gitlab.jfronny:muscript-gson:$muscriptVersion")!!)
modImplementation("io.gitlab.jfronny.libjf:libjf-data-manipulation-v0:${jfMod.libJfVersion.get()}")
modImplementation("io.gitlab.jfronny.libjf:libjf-config-core-v2:${jfMod.libJfVersion.get()}")
modImplementation("io.gitlab.jfronny.libjf:libjf-config-ui-tiny:${jfMod.libJfVersion.get()}")
modImplementation("net.fabricmc.fabric-api:fabric-api")
include(modImplementation("io.gitlab.jfronny:muscript-all:$muscriptVersion")!!)
modImplementation("io.gitlab.jfronny:muscript-json:$muscriptVersion") {
isTransitive = false
}
include("io.gitlab.jfronny:muscript-json:$muscriptVersion")
modImplementation("io.gitlab.jfronny.libjf:libjf-data-manipulation-v0")
modImplementation("io.gitlab.jfronny.libjf:libjf-config-core-v2")
modImplementation("io.gitlab.jfronny.libjf:libjf-config-ui-tiny")
val nofabric: Action<ExternalModuleDependency> = Action {
exclude("net.fabricmc") // required to work around duplicate fabric loaders
}
modLocalRuntime("io.gitlab.jfronny.libjf:libjf-devutil:${jfMod.libJfVersion.get()}", nofabric)
modLocalRuntime("io.gitlab.jfronny.libjf:libjf-devutil", nofabric)
modLocalRuntime("com.terraformersmc:modmenu:$modmenuVersion", nofabric) // Temporarily disabled since modmenu doesn't support snapshots
modClientCompileOnly("com.terraformersmc:modmenu:$modmenuVersion", nofabric)
@ -66,6 +69,9 @@ dependencies {
testImplementation("org.junit.jupiter:junit-jupiter:5.9.3")
compileOnly("io.gitlab.jfronny:commons-serialize-generator-annotations:$muscriptVersion")
annotationProcessor("io.gitlab.jfronny:commons-serialize-generator:$muscriptVersion")
// Canvas for FREX testing
// modClientRuntimeOnly("io.vram:canvas-fabric:20.0.+")

View File

@ -2,6 +2,8 @@ pluginManagement {
repositories {
maven("https://maven.fabricmc.net/") // FabricMC
maven("https://maven.frohnmeyer-wds.de/artifacts") // scripts
maven("https://maven.architectury.dev/") // Architectury
maven("https://files.minecraftforge.net/maven/") // Forge
gradlePluginPortal()
}
}

View File

@ -75,7 +75,7 @@ public class RespackoptsClient implements ClientModInitializer, SaveHook {
IntegratedServer is = MinecraftClient.getInstance().getServer();
if (is != null) {
is.getDataPackManager().scanPacks();
return is.reloadResources(is.getDataPackManager().getEnabledNames());
return is.reloadResources(is.getDataPackManager().getEnabledIds());
}
return CompletableFuture.completedFuture(null);
}

View File

@ -5,8 +5,14 @@ import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.arguments.StringArgumentType;
import io.gitlab.jfronny.commons.throwable.ThrowingConsumer;
import io.gitlab.jfronny.commons.throwable.ThrowingSupplier;
import io.gitlab.jfronny.muscript.compiler.Parser;
import io.gitlab.jfronny.muscript.error.LocationalException;
import io.gitlab.jfronny.muscript.ast.Expr;
import io.gitlab.jfronny.muscript.ast.context.ExprUtils;
import io.gitlab.jfronny.muscript.core.LocationalException;
import io.gitlab.jfronny.muscript.data.additional.DataExprMapper;
import io.gitlab.jfronny.muscript.data.dynamic.Dynamic;
import io.gitlab.jfronny.muscript.parser.Parser;
import io.gitlab.jfronny.muscript.runtime.Runtime;
import io.gitlab.jfronny.muscript.serialize.Decompiler;
import io.gitlab.jfronny.respackopts.muscript.ScopeVersion;
import io.gitlab.jfronny.respackopts.util.MetaCache;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
@ -23,6 +29,8 @@ import java.io.*;
import java.nio.file.*;
import java.util.concurrent.CompletableFuture;
import static io.gitlab.jfronny.muscript.ast.context.ExprUtils.asString;
import static io.gitlab.jfronny.muscript.serialize.Decompiler.decompile;
import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.*;
public class RpoClientCommand {
@ -42,13 +50,13 @@ public class RpoClientCommand {
return 1;
};
Command<FabricClientCommandSource> dumpScope = ctx -> {
ctx.getSource().sendFeedback(dump(MetaCache.getScope(Respackopts.META_VERSION).toExpr().toString(), "_root.mu"));
MetaCache.forEach((id, branch) -> ctx.getSource().sendFeedback(dump(branch.executionScope().getOverrides().toExpr().toString(), branch.packId() + ".mu")));
ctx.getSource().sendFeedback(dump(MetaCache.getScope(Respackopts.META_VERSION), "_root.mu"));
MetaCache.forEach((id, branch) -> ctx.getSource().sendFeedback(dump(branch.executionScope().getOverrides(), branch.packId() + ".mu")));
return 1;
};
Command<FabricClientCommandSource> dumpScopeVersioned = ctx -> {
ctx.getSource().sendFeedback(dump(MetaCache.getScope(IntegerArgumentType.getInteger(ctx, "version")).toExpr().toString(), "_root.mu"));
MetaCache.forEach((id, branch) -> ctx.getSource().sendFeedback(dump(branch.executionScope().getOverrides().toExpr().toString(), branch.packId() + ".mu")));
ctx.getSource().sendFeedback(dump(MetaCache.getScope(IntegerArgumentType.getInteger(ctx, "version")), "_root.mu"));
MetaCache.forEach((id, branch) -> ctx.getSource().sendFeedback(dump(branch.executionScope().getOverrides(), branch.packId() + ".mu")));
return 1;
};
Command<FabricClientCommandSource> dumpAsset = ctx -> {
@ -60,7 +68,7 @@ public class RpoClientCommand {
String snippet = StringArgumentType.getString(ctx, "snippet");
try {
int ver = IntegerArgumentType.getInteger(ctx, "version");
String result = Parser.parse(ScopeVersion.by(ver).muScriptVersion, snippet, "snippet").asStringExpr().get(MetaCache.getScope(ver));
String result = Runtime.evaluate(asString(Parser.parse(ScopeVersion.by(ver).muScriptVersion, snippet, "snippet")), MetaCache.getScope(ver));
ctx.getSource().sendFeedback(Text.translatable("respackopts.snippet.success", result));
} catch (LocationalException | Parser.ParseException e) {
Respackopts.LOGGER.error("Could not execute snippet", e);
@ -92,6 +100,13 @@ public class RpoClientCommand {
});
}
private static Text dump(Dynamic dynamic, String fileName) {
return dump(DataExprMapper.map(dynamic), fileName);
}
private static Text dump(Expr expr, String fileName) {
return dump(decompile(expr), fileName);
}
private static final Path dumpPath = FabricLoader.getInstance().getGameDir().resolve("respackopts").toAbsolutePath();
private static Text dump(String text, String fileName) {
return dump(path -> Files.writeString(path, text, StandardOpenOption.CREATE), fileName);

View File

@ -20,11 +20,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(PackListWidget.ResourcePackEntry.class)
public abstract class ResourcePackEntryMixin {
@Final @Shadow private PackListWidget widget;
@Shadow protected abstract boolean isSelectable();
@Shadow @Final private ResourcePackOrganizer.Pack pack;
boolean rpo$selected;
@Unique boolean rpo$selected;
@Inject(at = @At("TAIL"), method = "render(Lnet/minecraft/client/gui/DrawContext;IIIIIIIZF)V")
private void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta, CallbackInfo info) {
@ -37,23 +35,23 @@ public abstract class ResourcePackEntryMixin {
}
}
@Inject(at = @At("RETURN"), method = "mouseClicked(DDI)Z", cancellable = true)
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/widget/AlwaysSelectedEntryListWidget$Entry;mouseClicked(DDI)Z"), method = "mouseClicked(DDI)Z", cancellable = true)
public void mouseClicked(double mouseX, double mouseY, int button, CallbackInfoReturnable<Boolean> info) {
if (!info.getReturnValue()) {
if (this.isSelectable()) {
CacheKey dataLocation = MetaCache.getKeyByDisplayName(pack.getDisplayName().getString());
if (dataLocation != null && rpo$selected) {
info.setReturnValue(true);
MinecraftClient c = MinecraftClient.getInstance();
String id = MetaCache.getId(dataLocation);
ConfigInstance ci = DSL.create(id).config(builder -> MetaCache.getBranch(dataLocation).buildConfig(builder, id, dataLocation.dataLocation()));
ConfigScreenFactory.Built<?> screen = ConfigScreenFactory.getInstance().create(ci, c.currentScreen);
c.setScreen(screen.get());
}
// Inject before super call
if (this.isSelectable()) {
CacheKey dataLocation = MetaCache.getKeyByDisplayName(pack.getDisplayName().getString());
if (dataLocation != null && rpo$selected) {
info.setReturnValue(true);
MinecraftClient c = MinecraftClient.getInstance();
String id = MetaCache.getId(dataLocation);
ConfigInstance ci = DSL.create(id).config(builder -> MetaCache.getBranch(dataLocation).buildConfig(builder, id, dataLocation.dataLocation()));
ConfigScreenFactory.Built<?> screen = ConfigScreenFactory.getInstance().create(ci, c.currentScreen);
c.setScreen(screen.get());
}
}
}
@Unique
private void rpo$renderButton(DrawContext context, boolean hovered, Identifier texture, int x, int y) {
RenderSystem.setShaderColor(1, 1, 1, 1f);
RenderSystem.disableDepthTest();

View File

@ -1,14 +1,8 @@
package io.gitlab.jfronny.respackopts;
import io.gitlab.jfronny.commons.logging.Logger;
import io.gitlab.jfronny.gson.*;
import io.gitlab.jfronny.muscript.ast.*;
import io.gitlab.jfronny.commons.logger.SystemLoggerPlus;
import io.gitlab.jfronny.respackopts.filters.*;
import io.gitlab.jfronny.respackopts.gson.*;
import io.gitlab.jfronny.respackopts.gson.entry.*;
import io.gitlab.jfronny.respackopts.integration.SaveHook;
import io.gitlab.jfronny.respackopts.model.Condition;
import io.gitlab.jfronny.respackopts.model.tree.*;
import io.gitlab.jfronny.respackopts.server.ServerInstanceHolder;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.ModInitializer;
@ -23,21 +17,9 @@ import java.util.regex.Pattern;
public class Respackopts implements ModInitializer, SaveHook {
public static final Integer META_VERSION = 12;
public static final String FILE_EXTENSION = ".rpo";
public static final Gson GSON = new GsonBuilder()
.registerTypeAdapter(ConfigEnumEntry.class, new EnumEntrySerializer())
.registerTypeAdapter(ConfigNumericEntry.class, new NumericEntrySerializer())
.registerTypeAdapter(ConfigBooleanEntry.class, new BooleanEntrySerializer())
.registerTypeAdapter(ConfigBranch.class, new ConfigBranchSerializer())
.registerTypeAdapter(Expr.class, new ExprDeserializer())
.registerTypeAdapter(StringExpr.class, new StringExprDeserializer())
.registerTypeAdapter(BoolExpr.class, new BoolExprDeserializer())
.registerTypeAdapter(Condition.class, new ConditionDeserializer())
.setStrictness(Strictness.LENIENT)
.setPrettyPrinting()
.create();
public static final String ID = "respackopts";
public static final Logger LOGGER = Logger.forName(ID);
public static final SystemLoggerPlus LOGGER = SystemLoggerPlus.forName(ID);
public static final Path FALLBACK_CONF_DIR = FabricLoader.getInstance().getConfigDir().resolve(ID);

View File

@ -23,7 +23,7 @@ public enum DebugEvents implements UserResourceEvents.FindResource, UserResource
@Override
public ResourcePack.ResultConsumer findResources(ResourceType type, String namespace, String prefix, ResourcePack.ResultConsumer previous, ResourcePack pack) {
Respackopts.LOGGER.info("FIND_RESOURCE " + type + " in " + namespace + " " + prefix + " of " + pack.getName());
Respackopts.LOGGER.info("FIND_RESOURCE " + type + " in " + namespace + " " + prefix + " of " + pack.getId());
Set<Identifier> results = new HashSet<>();
return (identifier, inputStreamInputSupplier) -> {
if (!results.add(identifier)) {
@ -35,19 +35,19 @@ public enum DebugEvents implements UserResourceEvents.FindResource, UserResource
@Override
public InputSupplier<InputStream> open(ResourceType type, Identifier id, InputSupplier<InputStream> previous, ResourcePack pack) {
Respackopts.LOGGER.info("OPEN " + type + " at " + id + " of " + pack.getName());
Respackopts.LOGGER.info("OPEN " + type + " at " + id + " of " + pack.getId());
return previous;
}
@Override
public InputSupplier<InputStream> openRoot(String[] fileName, InputSupplier<InputStream> previous, ResourcePack pack) {
Respackopts.LOGGER.info("OPEN_ROOT " + String.join("/", fileName) + " of " + pack.getName());
Respackopts.LOGGER.info("OPEN_ROOT " + String.join("/", fileName) + " of " + pack.getId());
return previous;
}
@Override
public <T> T parseMetadata(ResourceMetadataReader<T> reader, Supplier<T> previous, ResourcePack pack) {
Respackopts.LOGGER.info("PARSE_METADATA " + reader.getKey() + " of " + pack.getName());
Respackopts.LOGGER.info("PARSE_METADATA " + reader.getKey() + " of " + pack.getId());
return previous.get();
}
}

View File

@ -1,11 +1,13 @@
package io.gitlab.jfronny.respackopts.filters;
import io.gitlab.jfronny.libjf.LibJf;
import io.gitlab.jfronny.libjf.ResourcePath;
import io.gitlab.jfronny.libjf.data.manipulation.api.UserResourceEvents;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.filters.util.DirRpoResult;
import io.gitlab.jfronny.respackopts.gson.AttachmentHolder;
import io.gitlab.jfronny.respackopts.model.DirRpo;
import io.gitlab.jfronny.respackopts.model.GC_DirRpo;
import io.gitlab.jfronny.respackopts.model.cache.CacheKey;
import io.gitlab.jfronny.respackopts.model.cache.CachedPackState;
import io.gitlab.jfronny.respackopts.model.enums.PackCapability;
@ -139,7 +141,7 @@ public enum DirFilterEvents implements UserResourceEvents.Open, UserResourceEven
if (state.tracker() != null) state.tracker().addDependency(path, rp);
try (Reader w = new InputStreamReader(is.get())) {
List<DirRpo> currentRPOs = new LinkedList<>(parentRPOs);
DirRpo newRPO = AttachmentHolder.deserialize(state.metadata().version, w, DirRpo.class);
DirRpo newRPO = AttachmentHolder.attach(state.metadata().version, () -> GC_DirRpo.deserialize(w, LibJf.LENIENT_TRANSPORT));
newRPO.hydrate(path);
if (newRPO.fallback != null && !newRPO.fallback.endsWith("/"))
newRPO.fallback += "/";

View File

@ -1,8 +1,8 @@
package io.gitlab.jfronny.respackopts.filters.util;
import io.gitlab.jfronny.commons.LazySupplier;
import io.gitlab.jfronny.muscript.data.Scope;
import io.gitlab.jfronny.muscript.debug.ObjectGraphPrinter;
import io.gitlab.jfronny.muscript.data.additional.context.Scope;
import io.gitlab.jfronny.muscript.data.additional.impl.ObjectGraphPrinter;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.model.Condition;
import io.gitlab.jfronny.respackopts.model.DirRpo;

View File

@ -1,12 +1,10 @@
package io.gitlab.jfronny.respackopts.filters.util;
import io.gitlab.jfronny.muscript.debug.ObjectGraphPrinter;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.model.Condition;
import io.gitlab.jfronny.respackopts.model.cache.CacheKey;
import io.gitlab.jfronny.respackopts.muscript.RespackoptsFS;
import io.gitlab.jfronny.respackopts.util.MetaCache;
import net.minecraft.resource.ResourcePack;
public class FileExclusionProvider {
public static boolean fileHidden(CacheKey key, RespackoptsFS fs, String file) {
@ -18,7 +16,7 @@ public class FileExclusionProvider {
} catch (Condition.ConditionException e) {
String res = "Could not evaluate condition for " + file + " (pack: " + key.packName() + ")";
try {
Respackopts.LOGGER.error(res + " with condition:\n" + ObjectGraphPrinter.printGraph(rpo.condition) + ")", e);
Respackopts.LOGGER.error(res + " with condition:\n" + rpo.condition + ")", e);
} catch (Throwable ex) {
Respackopts.LOGGER.error(res, e);
}

View File

@ -1,8 +1,10 @@
package io.gitlab.jfronny.respackopts.filters.util;
import io.gitlab.jfronny.muscript.ast.StringExpr;
import io.gitlab.jfronny.muscript.data.additional.context.Scope;
import io.gitlab.jfronny.muscript.data.dynamic.DObject;
import io.gitlab.jfronny.muscript.data.dynamic.Dynamic;
import io.gitlab.jfronny.muscript.runtime.Runtime;
import io.gitlab.jfronny.respackopts.model.cache.CacheKey;
import io.gitlab.jfronny.respackopts.muscript.RespackoptsFS;
import io.gitlab.jfronny.respackopts.util.MetaCache;
@ -15,7 +17,7 @@ public class FileExpansionProvider {
public static synchronized InputStream replace(DObject parameter, InputStream is, Map<String, StringExpr> expansions) throws IOException {
String s = new String(is.readAllBytes());
for (Map.Entry<String, StringExpr> entry : expansions.entrySet()) {
s = s.replace("${" + entry.getKey() + "}", entry.getValue().get(parameter));
s = s.replace("${" + entry.getKey() + "}", Runtime.evaluate(entry.getValue(), Scope.of(parameter)));
}
return new ByteArrayInputStream(s.getBytes());
}

View File

@ -1,8 +1,10 @@
package io.gitlab.jfronny.respackopts.filters.util;
import io.gitlab.jfronny.libjf.LibJf;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.gson.AttachmentHolder;
import io.gitlab.jfronny.respackopts.model.FileRpo;
import io.gitlab.jfronny.respackopts.model.GC_FileRpo;
import io.gitlab.jfronny.respackopts.model.cache.CacheKey;
import io.gitlab.jfronny.respackopts.model.cache.CachedPackState;
import io.gitlab.jfronny.respackopts.muscript.RespackoptsFS;
@ -27,7 +29,7 @@ public class FileRpoSearchProvider {
if (is == null) return defaultValue;
if (state.tracker() != null) state.tracker().addDependency(fileName, rpoPathS);
try (Reader w = new InputStreamReader(is.get())) {
FileRpo frp = AttachmentHolder.deserialize(state.metadata().version, w, FileRpo.class);
FileRpo frp = AttachmentHolder.attach(state.metadata().version, () -> GC_FileRpo.deserialize(w, LibJf.LENIENT_TRANSPORT));
frp.hydrate(rpoPathS);
rpoCache.put(rpoPathS, frp);
return action.run(frp);

View File

@ -1,36 +1,29 @@
package io.gitlab.jfronny.respackopts.gson;
import io.gitlab.jfronny.commons.concurrent.ScopedValue;
import io.gitlab.jfronny.commons.throwable.ExceptionWrapper;
import io.gitlab.jfronny.commons.throwable.ThrowingRunnable;
import io.gitlab.jfronny.commons.throwable.ThrowingSupplier;
import io.gitlab.jfronny.respackopts.Respackopts;
import java.io.Reader;
public class AttachmentHolder {
private static final ThreadLocal<Attachment> attachments = new ThreadLocal<>();
private static final ScopedValue<Attachment> attachments = new ScopedValue<>();
public static <TEx extends Throwable> void attach(int version, ThrowingRunnable<TEx> runnable) throws TEx {
try {
attachments.set(new Attachment(version));
runnable.run();
} finally {
attachments.remove();
ScopedValue.runWhere(attachments, new Attachment(version), runnable.orThrow());
} catch (ExceptionWrapper e) {
throw (TEx) ExceptionWrapper.unwrap(e);
}
}
public static <TOut, TEx extends Throwable> TOut attach(int version, ThrowingSupplier<TOut, TEx> runnable) throws TEx {
try {
attachments.set(new Attachment(version));
return runnable.get();
} finally {
attachments.remove();
return ScopedValue.getWhere(attachments, new Attachment(version), runnable.orThrow());
} catch (ExceptionWrapper e) {
throw (TEx) ExceptionWrapper.unwrap(e);
}
}
public static <T> T deserialize(int version, Reader r, Class<T> klazz) {
return attach(version, () -> Respackopts.GSON.fromJson(r, klazz));
}
public static int getAttachedVersion() {
return attachments.get().version;
}

View File

@ -1,68 +1,81 @@
package io.gitlab.jfronny.respackopts.gson;
import io.gitlab.jfronny.gson.*;
import io.gitlab.jfronny.gson.reflect.TypeToken;
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.databind.api.SerializerFor;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeAdapter;
import io.gitlab.jfronny.muscript.ast.context.ExprUtils;
import io.gitlab.jfronny.muscript.parser.lexer.Token;
import io.gitlab.jfronny.muscript.ast.*;
import io.gitlab.jfronny.muscript.ast.bool.*;
import io.gitlab.jfronny.muscript.ast.compare.Equal;
import io.gitlab.jfronny.muscript.ast.dynamic.*;
import io.gitlab.jfronny.muscript.compiler.CodeLocation;
import io.gitlab.jfronny.muscript.compiler.Token;
import io.gitlab.jfronny.muscript.core.CodeLocation;
import java.lang.reflect.Type;
import java.util.*;
public class BoolExprDeserializer implements JsonDeserializer<BoolExpr> {
private static final Type conditionListType = new TypeToken<List<BoolExpr>>(){}.getType();
@SerializerFor(targets = BoolExpr.class)
public class BoolExprDeserializer extends TypeAdapter<BoolExpr> {
public static final BoolExprDeserializer INSTANCE = new BoolExprDeserializer();
@Override
public BoolExpr deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
public <TEx extends Exception, Reader extends SerializeReader<TEx, Reader>> BoolExpr deserialize(Reader reader) throws TEx, MalformedDataException {
if (AttachmentHolder.getAttachedVersion() > 7) {
return context.<Expr<?>>deserialize(json, Expr.class).asBoolExpr();
return ExprUtils.asBool(ExprDeserializer.INSTANCE.deserialize(reader));
}
// Legacy JSON syntax
if (json.isJsonObject()) {
JsonObject jo = json.getAsJsonObject();
if (jo.size() != 1)
throw new JsonParseException("More than one key in a condition object");
Map.Entry<String, JsonElement> entry = jo.entrySet().stream().findFirst().orElseThrow();
return switch (entry.getKey().toLowerCase(Locale.ROOT)) {
case "and", "add", "&" -> merge(context.deserialize(entry.getValue(), conditionListType), Token.And);
case "==", "=", "equal", "eq" -> merge(context.deserialize(entry.getValue(), conditionListType), Token.EqualEqual);
case "not", "nor", "!" -> new Not(CodeLocation.NONE, merge(context.deserialize(entry.getValue(), conditionListType), Token.Or));
case "or", "|" -> merge(context.deserialize(entry.getValue(), conditionListType), Token.Or);
case "^", "xor" -> merge(context.deserialize(entry.getValue(), conditionListType), Token.BangEqual);
default -> throw new JsonParseException("Unknown condition type: " + entry.getKey());
};
}
else if (json.isJsonArray()) {
return merge(context.deserialize(json, conditionListType), Token.And);
}
else if (json.isJsonPrimitive()) {
JsonPrimitive pr = json.getAsJsonPrimitive();
if (pr.isString()) {
String name = pr.getAsString();
if (name.toLowerCase(Locale.ROOT).equals("true"))
return Expr.literal(CodeLocation.NONE, true);
if (name.toLowerCase(Locale.ROOT).equals("false"))
return Expr.literal(CodeLocation.NONE, false);
return rpoBooleanCondition(name);
}
else if (pr.isBoolean()) {
return Expr.literal(CodeLocation.NONE, pr.getAsBoolean());
if (reader.peek() == io.gitlab.jfronny.commons.serialize.Token.BEGIN_OBJECT) {
reader.beginObject();
if (reader.hasNext()) {
String key = reader.nextName();
BoolExpr expr = switch (key.toLowerCase(Locale.ROOT)) {
case "and", "add", "&" -> merge(reader, Token.And);
case "==", "=", "equal", "eq" -> merge(reader, Token.EqualEqual);
case "not", "nor", "!" -> new Not(CodeLocation.NONE, merge(reader, Token.Or));
case "or", "|" -> merge(reader, Token.Or);
case "^", "xor" -> merge(reader, Token.BangEqual);
default -> throw new MalformedDataException("Unknown condition type: " + key);
};
reader.endObject();
return expr;
} else {
reader.endObject();
throw new MalformedDataException("Empty condition object");
}
} else if (reader.peek() == io.gitlab.jfronny.commons.serialize.Token.BEGIN_ARRAY) {
return merge(reader, Token.And);
} else if (reader.peek() == io.gitlab.jfronny.commons.serialize.Token.STRING) {
String name = reader.nextString();
if (name.toLowerCase(Locale.ROOT).equals("true"))
return Expr.literal(CodeLocation.NONE, true);
if (name.toLowerCase(Locale.ROOT).equals("false"))
return Expr.literal(CodeLocation.NONE, false);
return rpoBooleanCondition(name);
} else if (reader.peek() == io.gitlab.jfronny.commons.serialize.Token.BOOLEAN) {
return Expr.literal(CodeLocation.NONE, reader.nextBoolean());
} else {
throw new MalformedDataException("Invalid data type for condition");
}
throw new JsonParseException("Invalid data type for condition");
}
private BoolExpr merge(List<BoolExpr> expressions, Token token) {
private <TEx extends Exception, Reader extends SerializeReader<TEx, Reader>> BoolExpr merge(Reader source, Token token) throws TEx, MalformedDataException {
if (token == Token.BangEqual)
return new Not(CodeLocation.NONE, merge(expressions, Token.EqualEqual));
BoolExpr current = expressions.get(0);
return new Not(CodeLocation.NONE, merge(source, Token.EqualEqual));
List<BoolExpr> expressions = new ArrayList<>();
if (source.peek() == io.gitlab.jfronny.commons.serialize.Token.BEGIN_ARRAY) {
source.beginArray();
while (source.hasNext()) {
expressions.add(deserialize(source));
}
source.endArray();
} else {
expressions.add(deserialize(source));
}
BoolExpr current = expressions.getFirst();
for (BoolExpr expr : expressions.subList(1, expressions.size())) {
current = switch (token) {
case EqualEqual -> new Equal(CodeLocation.NONE, current, expr);
case EqualEqual -> new Equals(CodeLocation.NONE, current, expr);
case And -> new And(CodeLocation.NONE, current, expr);
case Or -> new Or(CodeLocation.NONE, current, expr);
default -> throw new IllegalArgumentException();
@ -71,15 +84,15 @@ public class BoolExprDeserializer implements JsonDeserializer<BoolExpr> {
return current;
}
private BoolExpr rpoBooleanCondition(String name) {
private BoolExpr rpoBooleanCondition(String name) throws MalformedDataException {
if (name.startsWith("modversion:")) {
String code = name.substring("modversion:".length());
String mod = code.substring(0, code.indexOf(':'));
String predicate = code.substring(code.indexOf(':') + 1);
return new Call(CodeLocation.NONE, new Variable(CodeLocation.NONE, "version"), List.of(
new Call.Arg(Expr.literal(mod).asDynamicExpr(), false),
new Call.Arg(Expr.literal(predicate).asDynamicExpr(), false)
)).asBoolExpr();
return ExprUtils.asBool(new Call(CodeLocation.NONE, new Variable(CodeLocation.NONE, "version"), List.of(
new Call.Argument(ExprUtils.asDynamic(Expr.literal(mod)), false),
new Call.Argument(ExprUtils.asDynamic(Expr.literal(predicate)), false)
)));
}
DynamicExpr e = null;
String[] arr = name.split("[:.]");
@ -87,7 +100,12 @@ public class BoolExprDeserializer implements JsonDeserializer<BoolExpr> {
if (i == 0) e = new Variable(CodeLocation.NONE, arr[i]);
else e = new Get(CodeLocation.NONE, e, Expr.literal(arr[i]));
}
if (e == null) throw new JsonParseException("Invalid RPO condition: \"" + name + "\"");
return e.asBoolExpr();
if (e == null) throw new MalformedDataException("Invalid RPO condition: \"" + name + "\"");
return ExprUtils.asBool(e);
}
@Override
public <TEx extends Exception, Writer extends SerializeWriter<TEx, Writer>> void serialize(BoolExpr boolExpr, Writer writer) throws TEx, MalformedDataException {
ExprDeserializer.INSTANCE.serialize(boolExpr, writer);
}
}

View File

@ -1,19 +1,28 @@
package io.gitlab.jfronny.respackopts.gson;
import io.gitlab.jfronny.gson.*;
import io.gitlab.jfronny.muscript.ast.BoolExpr;
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.SerializerFor;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeAdapter;
import io.gitlab.jfronny.muscript.ast.context.ExprUtils;
import io.gitlab.jfronny.respackopts.model.Condition;
import java.lang.reflect.Type;
public class ConditionDeserializer implements JsonDeserializer<Condition> {
@SerializerFor(targets = Condition.class)
public class ConditionDeserializer extends TypeAdapter<Condition> {
@Override
public Condition deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
public <TEx extends Exception, Writer extends SerializeWriter<TEx, Writer>> void serialize(Condition condition, Writer writer) throws TEx, MalformedDataException {
BoolExprDeserializer.INSTANCE.serialize(condition.expr(), writer);
}
@Override
public <TEx extends Exception, Reader extends SerializeReader<TEx, Reader>> Condition deserialize(Reader reader) throws TEx, MalformedDataException {
String source = "Source unavailable";
if (json.isJsonPrimitive()) {
JsonPrimitive primitive = json.getAsJsonPrimitive();
if (primitive.isString()) source = primitive.getAsString();
if (reader.peek() == Token.STRING) {
source = reader.nextString();
return new Condition(source, null, ExprUtils.asBool(ExprDeserializer.INSTANCE.parse(source)));
}
return new Condition(source, null, context.deserialize(json, BoolExpr.class));
return new Condition(source, null, BoolExprDeserializer.INSTANCE.deserialize(reader));
}
}

View File

@ -0,0 +1,78 @@
package io.gitlab.jfronny.respackopts.gson;
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.databind.api.SerializerFor;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeAdapter;
import io.gitlab.jfronny.commons.serialize.emulated.DataElement;
import io.gitlab.jfronny.commons.serialize.emulated.EmulatedReader;
import io.gitlab.jfronny.commons.serialize.emulated.EmulatedWriter;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.gson.entry.BooleanEntrySerializer;
import io.gitlab.jfronny.respackopts.gson.entry.EnumEntrySerializer;
import io.gitlab.jfronny.respackopts.gson.entry.NumericEntrySerializer;
import io.gitlab.jfronny.respackopts.model.tree.*;
@SerializerFor(targets = ConfigEntry.class)
public class ConfigEntryTypeAdapter extends TypeAdapter<ConfigEntry<?>> {
@Override
public <TEx extends Exception, Writer extends SerializeWriter<TEx, Writer>> void serialize(ConfigEntry<?> entry, Writer writer) throws TEx, MalformedDataException {
switch (entry) {
case ConfigBooleanEntry bl -> GC_ConfigBooleanEntry.serialize(bl, writer);
case ConfigNumericEntry num -> GC_ConfigNumericEntry.serialize(num, writer);
case ConfigEnumEntry en -> GC_ConfigEnumEntry.serialize(en, writer);
case ConfigBranch br -> GC_ConfigBranch.serialize(br, writer);
default -> throw new MalformedDataException("Unknown entry type: " + entry.getClass().getName());
}
}
@Override
public <TEx extends Exception, Reader extends SerializeReader<TEx, Reader>> ConfigEntry<?> deserialize(Reader reader) throws TEx, MalformedDataException {
return switch (reader.peek()) {
case BOOLEAN -> GC_ConfigBooleanEntry.deserialize(reader);
case NUMBER -> GC_ConfigNumericEntry.deserialize(reader);
case STRING, BEGIN_ARRAY -> GC_ConfigEnumEntry.deserialize(reader);
case BEGIN_OBJECT -> {
final ConfigEntry<?> entry;
String type = null;
DataElement.Object de;
reader.beginObject();
try (EmulatedWriter ew = new EmulatedWriter()) {
ew.beginObject();
while (reader.hasNext()) {
String key;
ew.name(key = reader.nextName());
if (key.equals("type")) ew.value(type = reader.nextString());
else reader.copyTo(ew);
}
ew.endObject();
de = (DataElement.Object) ew.get();
}
reader.endObject();
if (type != null) {
if (BooleanEntrySerializer.TYPES.contains(type)) {
entry = GC_ConfigBooleanEntry.deserialize(new EmulatedReader(de));
} else if (NumericEntrySerializer.TYPES.contains(type)) {
var e = GC_ConfigNumericEntry.deserialize(new EmulatedReader(de));
entry = NumericEntrySerializer.INT_TYPES.contains(type) ? e.asInteger() : e;
} else if (EnumEntrySerializer.TYPES.contains(type)) {
entry = GC_ConfigEnumEntry.deserialize(new EmulatedReader(de));
} else {
throw new MalformedDataException("Invalid type for entry: " + type);
}
} else {
if (de.members().keySet().stream().allMatch(k -> "default".equals(k) || "min".equals(k) || "max".equals(k))) {
Respackopts.LOGGER.info("No \"type\" property for non-branch entry object, assuming slider");
entry = GC_ConfigNumericEntry.deserialize(new EmulatedReader(de));
} else {
entry = GC_ConfigBranch.deserialize(new EmulatedReader(de));
}
}
yield entry;
}
case NULL -> throw new MalformedDataException("Unexpected null value for entry");
default -> throw new MalformedDataException("Invalid data type for entry");
};
}
}

View File

@ -1,38 +1,53 @@
package io.gitlab.jfronny.respackopts.gson;
import io.gitlab.jfronny.gson.*;
import io.gitlab.jfronny.muscript.StarScriptIngester;
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.SerializerFor;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeAdapter;
import io.gitlab.jfronny.muscript.ast.Expr;
import io.gitlab.jfronny.muscript.compiler.Parser;
import io.gitlab.jfronny.muscript.parser.Parser;
import io.gitlab.jfronny.muscript.parser.StarScriptIngester;
import io.gitlab.jfronny.muscript.serialize.Decompiler;
import io.gitlab.jfronny.respackopts.muscript.ScopeVersion;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
public class ExprDeserializer implements JsonDeserializer<Expr<?>> {
private static final Map<String, Expr<?>> compiledScripts = new HashMap<>();
@SerializerFor(targets = Expr.class)
public class ExprDeserializer extends TypeAdapter<Expr> {
public static final ExprDeserializer INSTANCE = new ExprDeserializer();
private static final Map<String, Expr> compiledScripts = new HashMap<>();
@Override
public Expr<?> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (json.isJsonPrimitive() && json.getAsJsonPrimitive().isString()) {
String s = json.getAsJsonPrimitive().getAsString();
if (compiledScripts.containsKey(s))
return compiledScripts.get(s);
try {
int v = AttachmentHolder.getAttachedVersion();
Expr<?> expr = Parser.parse(ScopeVersion.by(v).muScriptVersion, v <= 7
? StarScriptIngester.starScriptToMu(s)
: s);
compiledScripts.put(s, expr);
return expr;
} catch (Parser.ParseException e) {
throw new JsonParseException("Could not create script", e);
}
public <TEx extends Exception, Writer extends SerializeWriter<TEx, Writer>> void serialize(Expr expr, Writer writer) throws TEx, MalformedDataException {
writer.value(Decompiler.decompile(expr));
}
@Override
public <TEx extends Exception, Reader extends SerializeReader<TEx, Reader>> Expr deserialize(Reader reader) throws TEx, MalformedDataException {
if (reader.peek() == Token.STRING) {
return parse(reader.nextString());
} else if (reader.peek() == Token.BEGIN_OBJECT) {
throw new MalformedDataException("Could not parse script: Expected string but got object (did you forget to migrate this rpo to muScript?)");
} else {
throw new MalformedDataException("Could not parse script: Expected string");
}
else {
if (json.isJsonObject()) throw new JsonParseException("Could not parse script: Expected string but got object (did you forget to migrate this rpo to muScript?)");
throw new JsonParseException("Could not parse script: Expected string");
}
public Expr parse(String source) throws MalformedDataException {
if (compiledScripts.containsKey(source))
return compiledScripts.get(source);
try {
int v = AttachmentHolder.getAttachedVersion();
Expr expr = Parser.parse(ScopeVersion.by(v).muScriptVersion, v <= 7
? StarScriptIngester.starScriptToMu(source)
: source);
compiledScripts.put(source, expr);
return expr;
} catch (Parser.ParseException e) {
throw new MalformedDataException("Could not create script", e);
}
}
}

View File

@ -1,15 +1,22 @@
package io.gitlab.jfronny.respackopts.gson;
import io.gitlab.jfronny.gson.*;
import io.gitlab.jfronny.muscript.ast.Expr;
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.databind.api.SerializerFor;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeAdapter;
import io.gitlab.jfronny.muscript.ast.StringExpr;
import io.gitlab.jfronny.muscript.ast.context.ExprUtils;
import java.lang.reflect.Type;
public class StringExprDeserializer implements JsonDeserializer<StringExpr> {
@SerializerFor(targets = StringExpr.class)
public class StringExprDeserializer extends TypeAdapter<StringExpr> {
@Override
public StringExpr deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
Expr<?> expr = jsonDeserializationContext.deserialize(jsonElement, Expr.class);
return expr.asStringExpr();
public <TEx extends Exception, Writer extends SerializeWriter<TEx, Writer>> void serialize(StringExpr stringExpr, Writer writer) throws TEx, MalformedDataException {
ExprDeserializer.INSTANCE.serialize(stringExpr, writer);
}
@Override
public <TEx extends Exception, Reader extends SerializeReader<TEx, Reader>> StringExpr deserialize(Reader reader) throws TEx, MalformedDataException {
return ExprUtils.asString(ExprDeserializer.INSTANCE.deserialize(reader));
}
}

View File

@ -1,26 +1,53 @@
package io.gitlab.jfronny.respackopts.gson.entry;
import io.gitlab.jfronny.gson.*;
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.SerializerFor;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeAdapter;
import io.gitlab.jfronny.respackopts.model.enums.PackReloadType;
import io.gitlab.jfronny.respackopts.model.tree.ConfigBooleanEntry;
import java.lang.reflect.Type;
import java.util.Set;
@SerializerFor(targets = ConfigBooleanEntry.class)
public class BooleanEntrySerializer extends TypeAdapter<ConfigBooleanEntry> {
public static final Set<String> TYPES = Set.of("boolean", "toggle");
public class BooleanEntrySerializer implements JsonSerializer<ConfigBooleanEntry>, JsonDeserializer<ConfigBooleanEntry> {
@Override
public ConfigBooleanEntry deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (json.isJsonPrimitive()) return new ConfigBooleanEntry(json.getAsBoolean());
else if (json.isJsonObject()) {
JsonObject o = json.getAsJsonObject();
if (o.has("default"))
return new ConfigBooleanEntry(o.get("default").getAsBoolean());
else
throw new JsonSyntaxException("Default value for boolean entry must be a boolean");
}
else throw new JsonSyntaxException("Invalid type for boolean entry");
public <TEx extends Exception, Writer extends SerializeWriter<TEx, Writer>> void serialize(ConfigBooleanEntry configBooleanEntry, Writer writer) throws TEx, MalformedDataException {
writer.value(configBooleanEntry.getValue());
}
@Override
public JsonElement serialize(ConfigBooleanEntry src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src.getValue());
public <TEx extends Exception, Reader extends SerializeReader<TEx, Reader>> ConfigBooleanEntry deserialize(Reader reader) throws TEx, MalformedDataException {
if (reader.peek() == Token.BOOLEAN) {
return new ConfigBooleanEntry(reader.nextBoolean());
} else if (reader.peek() == Token.BEGIN_OBJECT) {
reader.beginObject();
ConfigBooleanEntry result = new ConfigBooleanEntry(false);
while (reader.hasNext()) {
String key = reader.nextName();
switch (key) {
case "type" -> {
if (!TYPES.contains(reader.nextString())) {
throw new MalformedDataException("Invalid type for boolean entry");
}
}
case "default" -> {
boolean value = reader.nextBoolean();
result.setDefault(value);
result.setValue(value);
}
case "reloadType" -> result.setReloadType(PackReloadType.valueOf(reader.nextString()));
default -> throw new MalformedDataException("Unknown key in boolean entry: " + key);
};
}
reader.endObject();
return result;
} else {
throw new MalformedDataException("Invalid data type for boolean entry");
}
}
}

View File

@ -1,79 +1,37 @@
package io.gitlab.jfronny.respackopts.gson.entry;
import io.gitlab.jfronny.gson.*;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.model.enums.PackReloadType;
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.SerializerFor;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeAdapter;
import io.gitlab.jfronny.respackopts.model.tree.*;
import java.lang.reflect.Type;
import java.util.Map;
public class ConfigBranchSerializer implements JsonSerializer<ConfigBranch>, JsonDeserializer<ConfigBranch> {
@SerializerFor(targets = ConfigBranch.class)
public class ConfigBranchSerializer extends TypeAdapter<ConfigBranch> {
@Override
public JsonElement serialize(ConfigBranch src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject o = new JsonObject();
for (Map.Entry<String, ConfigEntry<?>> entry : src.getValue().entrySet()) {
o.add(entry.getKey(), context.serialize(entry.getValue()));
public <TEx extends Exception, Writer extends SerializeWriter<TEx, Writer>> void serialize(ConfigBranch configBranch, Writer writer) throws TEx, MalformedDataException {
writer.beginObject();
for (Map.Entry<String, ConfigEntry<?>> entry : configBranch.getValue().entrySet()) {
writer.name(entry.getKey());
GC_ConfigEntry.serialize(entry.getValue(), writer);
}
return o;
writer.endObject();
}
@Override
public ConfigBranch deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (!json.isJsonObject())
throw new JsonSyntaxException("ConfigBranch is not an object");
JsonObject o = json.getAsJsonObject();
public <TEx extends Exception, Reader extends SerializeReader<TEx, Reader>> ConfigBranch deserialize(Reader reader) throws TEx, MalformedDataException {
if (reader.peek() != Token.BEGIN_OBJECT) throw new MalformedDataException("ConfigBranch is not an object");
reader.beginObject();
ConfigBranch cbNew = new ConfigBranch();
for (Map.Entry<String, JsonElement> e : o.entrySet()) {
JsonElement j = e.getValue();
String s = e.getKey();
if (j.isJsonPrimitive()) {
JsonPrimitive p = j.getAsJsonPrimitive();
if (p.isBoolean())
cbNew.add(s, new ConfigBooleanEntry(p.getAsBoolean()));
else if (p.isNumber())
cbNew.add(s, context.deserialize(j, ConfigNumericEntry.class));
else if (p.isString())
cbNew.add(s, context.deserialize(j, ConfigEnumEntry.class));
}
else if (j.isJsonArray())
cbNew.add(s, context.deserialize(j, ConfigEnumEntry.class));
else if (j.isJsonObject()) {
JsonObject jo = j.getAsJsonObject();
String type;
if (jo.has("type")) {
type = jo.get("type").getAsString();
}
else {
if (jo.entrySet().stream().allMatch(entry -> "default".equals(entry.getKey()) || "min".equals(entry.getKey()) || "max".equals(entry.getKey()))) {
Respackopts.LOGGER.info("No \"type\" property for non-branch entry object, assuming slider");
type = "slider";
}
else {
cbNew.add(s, context.deserialize(j, ConfigBranch.class));
continue;
}
}
ConfigEntry<?> entry = switch (type.toLowerCase()) {
case "slider", "number", "numeric" -> context.deserialize(j, ConfigNumericEntry.class);
case "integer", "int", "long", "whole" -> context.<ConfigNumericEntry>deserialize(j, ConfigNumericEntry.class).asInteger();
case "boolean", "toggle" -> context.deserialize(j, ConfigBooleanEntry.class);
case "enum", "select" -> context.deserialize(j, ConfigEnumEntry.class);
default -> throw new JsonSyntaxException("Unknown entry type: " + type);
};
if (jo.has("default")) {
entry.setDefault(context.deserialize(jo.get("default"), entry.getEntryClass()));
entry.setValue(context.deserialize(jo.get("default"), entry.getEntryClass()));
}
if (jo.has("reloadType")) {
entry.setReloadType(context.deserialize(jo.get("reloadType"), PackReloadType.class));
}
cbNew.add(s, entry);
} else if (j.isJsonNull())
throw new JsonSyntaxException("Unexpected json null");
else
throw new JsonSyntaxException("Unexpected json object type");
while (reader.hasNext()) {
String s = reader.nextName();
cbNew.add(s, GC_ConfigEntry.deserialize(reader));
}
reader.endObject();
return cbNew;
}
}

View File

@ -1,56 +1,87 @@
package io.gitlab.jfronny.respackopts.gson.entry;
import io.gitlab.jfronny.gson.*;
import io.gitlab.jfronny.respackopts.Respackopts;
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.SerializerFor;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeAdapter;
import io.gitlab.jfronny.respackopts.model.enums.PackReloadType;
import io.gitlab.jfronny.respackopts.model.tree.ConfigEnumEntry;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@SerializerFor(targets = ConfigEnumEntry.class)
public class EnumEntrySerializer extends TypeAdapter<ConfigEnumEntry> {
public static final Set<String> TYPES = Set.of("enum", "select");
public class EnumEntrySerializer implements JsonSerializer<ConfigEnumEntry>, JsonDeserializer<ConfigEnumEntry> {
@Override
public JsonElement serialize(ConfigEnumEntry src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src.getValue());
public <TEx extends Exception, Writer extends SerializeWriter<TEx, Writer>> void serialize(ConfigEnumEntry configEnumEntry, Writer writer) throws TEx, MalformedDataException {
writer.value(configEnumEntry.getValue());
}
@Override
public ConfigEnumEntry deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
public <TEx extends Exception, Reader extends SerializeReader<TEx, Reader>> ConfigEnumEntry deserialize(Reader reader) throws TEx, MalformedDataException {
ConfigEnumEntry result = new ConfigEnumEntry();
if (json.isJsonPrimitive()) {
JsonPrimitive jp = json.getAsJsonPrimitive();
if (jp.isString()) {
result.setValue(jp.getAsString());
return result;
}
else if (jp.isNumber()) {
result.setNextValue(jp.getAsInt());
return result;
}
else
throw new JsonSyntaxException("Expected primitive string key for enum");
}
else if (json.isJsonArray()) {
List<String> replacement = new ArrayList<>();
for (JsonElement e : json.getAsJsonArray()) {
if (e.isJsonPrimitive() && e.getAsJsonPrimitive().isString()) {
replacement.add(e.getAsString());
}
else
throw new JsonSyntaxException("Expected string entry in enum");
}
result.setValues(replacement);
if (replacement.isEmpty())
Respackopts.LOGGER.warn("Enum entry empty");
else
result.setDefault(replacement.get(0));
if (reader.peek() == Token.STRING) {
result.setValue(reader.nextString());
return result;
} else if (reader.peek() == Token.NUMBER) {
result.setNextValue(reader.nextInt());
return result;
} else if (reader.peek() == Token.BEGIN_ARRAY) {
List<String> replacement = new ArrayList<>();
reader.beginArray();
while (reader.hasNext()) {
if (reader.peek() != Token.STRING) throw new MalformedDataException("Expected string entry in enum");
replacement.add(reader.nextString());
}
reader.endArray();
result.setValues(replacement);
result.setDefault(replacement.getFirst());
result.setValue(replacement.getFirst());
return result;
} else if (reader.peek() == Token.BEGIN_OBJECT) {
reader.beginObject();
while (reader.hasNext()) {
String key = reader.nextName();
switch (key) {
case "type" -> {
if (!TYPES.contains(reader.nextString())) {
throw new MalformedDataException("Invalid type for enum entry");
}
}
case "default" -> {
if (reader.peek() != Token.STRING) throw new MalformedDataException("Expected string for enum default");
String value = reader.nextString();
result.setDefault(value);
result.setValue(value);
}
case "reloadType" -> result.setReloadType(PackReloadType.valueOf(reader.nextString()));
case "values" -> {
if (reader.peek() != Token.BEGIN_ARRAY) throw new MalformedDataException("Expected array for enum values");
List<String> replacement = new ArrayList<>();
reader.beginArray();
while (reader.hasNext()) {
if (reader.peek() != Token.STRING) throw new MalformedDataException("Expected string entry in enum");
replacement.add(reader.nextString());
}
reader.endArray();
result.setValues(replacement);
if (!result.hasDefault()) {
result.setDefault(replacement.getFirst());
result.setValue(replacement.getFirst());
}
}
default -> throw new MalformedDataException("Unknown key in enum entry: " + key);
}
}
reader.endObject();
return result;
} else {
throw new MalformedDataException("Invalid data type for enum entry");
}
else if (json.isJsonObject()) {
JsonObject o = json.getAsJsonObject();
return deserialize(o.get("values"), typeOfT, context);
}
else
throw new JsonSyntaxException("Expected primitive string key or string array for enum");
}
}

View File

@ -1,42 +1,59 @@
package io.gitlab.jfronny.respackopts.gson.entry;
import io.gitlab.jfronny.gson.*;
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.SerializerFor;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeAdapter;
import io.gitlab.jfronny.respackopts.model.enums.PackReloadType;
import io.gitlab.jfronny.respackopts.model.tree.ConfigNumericEntry;
import java.lang.reflect.Type;
import java.util.Set;
@SerializerFor(targets = ConfigNumericEntry.class)
public class NumericEntrySerializer extends TypeAdapter<ConfigNumericEntry> {
public static final Set<String> TYPES = Set.of("numeric", "number", "slider", "integer", "int", "long", "whole");
public static final Set<String> INT_TYPES = Set.of("integer", "int", "long", "whole");
public class NumericEntrySerializer implements JsonSerializer<ConfigNumericEntry>, JsonDeserializer<ConfigNumericEntry> {
@Override
public JsonElement serialize(ConfigNumericEntry src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src.getValue());
public <TEx extends Exception, Writer extends SerializeWriter<TEx, Writer>> void serialize(ConfigNumericEntry configNumericEntry, Writer writer) throws TEx, MalformedDataException {
writer.value(configNumericEntry.getValue());
}
@Override
public ConfigNumericEntry deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (json.isJsonPrimitive() && json.getAsJsonPrimitive().isNumber()) {
ConfigNumericEntry result = new ConfigNumericEntry();
result.setValue(json.getAsDouble());
result.setDefault(json.getAsDouble());
public <TEx extends Exception, Reader extends SerializeReader<TEx, Reader>> ConfigNumericEntry deserialize(Reader reader) throws TEx, MalformedDataException {
ConfigNumericEntry result = new ConfigNumericEntry();
if (reader.peek() == Token.NUMBER) {
double value = reader.nextDouble();
result.setValue(value);
result.setDefault(value);
return result;
}
else if (json.isJsonObject()) {
JsonObject o = json.getAsJsonObject();
ConfigNumericEntry result = new ConfigNumericEntry();
JsonElement min = o.get("min");
JsonElement max = o.get("max");
if (min != null) {
if (min.isJsonPrimitive() && min.getAsJsonPrimitive().isNumber()) {
result.setMin(min.getAsNumber().doubleValue());
} else if (reader.peek() == Token.BEGIN_OBJECT) {
reader.beginObject();
while (reader.hasNext()) {
String key = reader.nextName();
switch (key) {
case "type" -> {
if (!TYPES.contains(reader.nextString())) {
throw new MalformedDataException("Invalid type for numeric entry");
}
}
case "default" -> {
double value = reader.nextDouble();
result.setDefault(value);
result.setValue(value);
}
case "reloadType" -> result.setReloadType(PackReloadType.valueOf(reader.nextString()));
case "min" -> result.setMin(reader.nextDouble());
case "max" -> result.setMax(reader.nextDouble());
default -> throw new MalformedDataException("Unknown key in numeric entry: " + key);
}
else throw new JsonSyntaxException("Expected number as min of numeric entry");
}
if (max != null) {
if (max.isJsonPrimitive() && max.getAsJsonPrimitive().isNumber()) {
result.setMax(max.getAsNumber().doubleValue());
}
else throw new JsonSyntaxException("Expected number as max of numeric entry");
}
reader.endObject();
return result;
} else {
throw new MalformedDataException("Invalid data type for numeric entry");
}
throw new JsonSyntaxException("Could not deserialize numeric entry");
}
}

View File

@ -12,7 +12,7 @@ import java.nio.file.*;
@Mixin(FileResourcePackProvider.class)
public class FileResourcePackProviderMixin {
//TODO use MixinExtras Wrap instead of redirecting
@Redirect(method = "forEachProfile(Ljava/nio/file/Path;Lnet/minecraft/util/path/SymlinkFinder;ZLjava/util/function/BiConsumer;)V", at = @At(value = "INVOKE", target = "Ljava/nio/file/Files;newDirectoryStream(Ljava/nio/file/Path;)Ljava/nio/file/DirectoryStream;"))
@Redirect(method = "forEachProfile(Ljava/nio/file/Path;Lnet/minecraft/util/path/SymlinkFinder;Ljava/util/function/BiConsumer;)V", at = @At(value = "INVOKE", target = "Ljava/nio/file/Files;newDirectoryStream(Ljava/nio/file/Path;)Ljava/nio/file/DirectoryStream;"))
private static DirectoryStream<Path> createFilteredStream(Path dir) throws IOException {
return Files.newDirectoryStream(dir, path -> !(Files.isRegularFile(path) && path.getFileName().toString().endsWith(Respackopts.FILE_EXTENSION)));
}

View File

@ -1,8 +1,10 @@
package io.gitlab.jfronny.respackopts.mixin;
import io.gitlab.jfronny.libjf.LibJf;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.RespackoptsConfig;
import io.gitlab.jfronny.respackopts.integration.SaveHook;
import io.gitlab.jfronny.respackopts.model.GC_PackMeta;
import io.gitlab.jfronny.respackopts.model.PackMeta;
import io.gitlab.jfronny.respackopts.model.cache.CacheKey;
import io.gitlab.jfronny.respackopts.util.FallbackI18n;
@ -50,18 +52,18 @@ public class ResourcePackManagerMixin {
Path pack = ((DirectoryResourcePackAccessor) drp).getRoot();
Path parent = pack == null ? null : pack.getParent();
if (parent != null) dataLocation = parent.resolve(pack.getFileName() + Respackopts.FILE_EXTENSION);
else Respackopts.LOGGER.warn("Base path of directory resource pack " + rpi.getName() + " is null. This shouldn't happen!");
else Respackopts.LOGGER.warn("Base path of directory resource pack " + rpi.getId() + " is null. This shouldn't happen!");
} else if (rpi instanceof ZipResourcePack zrp) {
File pack = ((ZipFileWrapperAccessor) ((ZipResourcePackAccessor) zrp).getZipFile()).getFile();
Path parent = pack == null ? null : pack.toPath().getParent();
if (parent != null) dataLocation = parent.resolve(pack.getName() + Respackopts.FILE_EXTENSION);
else Respackopts.LOGGER.warn("Base path of zip resource pack " + rpi.getName() + " is null. This shouldn't happen!");
else Respackopts.LOGGER.warn("Base path of zip resource pack " + rpi.getId() + " is null. This shouldn't happen!");
}
var conf = rpi.openRoot(Respackopts.ID + ".json5");
if (conf != null) {
try (InputStream is = conf.get()) {
return rpo$readConfiguration(is, dataLocation, rpi.getName(), displayName, dataLocations, toRemove);
return rpo$readConfiguration(is, dataLocation, rpi.getId(), displayName, dataLocations, toRemove);
} catch (Throwable e) {
String message = "Could not read respackopts config in root for " + profileName;
if (RespackoptsConfig.debugLogs) Respackopts.LOGGER.error(message, e);
@ -74,7 +76,7 @@ public class ResourcePackManagerMixin {
conf = rpi.open(type, confId);
if (conf != null) {
try (InputStream is = conf.get()) {
return rpo$readConfiguration(is, dataLocation, rpi.getName(), displayName, dataLocations, toRemove);
return rpo$readConfiguration(is, dataLocation, rpi.getId(), displayName, dataLocations, toRemove);
} catch (Throwable e) {
Respackopts.LOGGER.error("Could not initialize pack meta for " + profileName, e);
}
@ -86,7 +88,7 @@ public class ResourcePackManagerMixin {
private static String rpo$readConfiguration(InputStream is, Path dataLocation, String packName, String displayName, Set<Path> dataLocations, Set<Path> toRemove) throws IOException {
try (InputStreamReader isr = new InputStreamReader(is)) {
PackMeta conf = Respackopts.GSON.fromJson(isr, PackMeta.class);
PackMeta conf = GC_PackMeta.deserialize(isr, LibJf.LENIENT_TRANSPORT);
if (!Respackopts.isLegal(conf.id)) {
if (conf.version >= 10) {
Respackopts.LOGGER.error(displayName + " was not loaded as it uses an unsupported pack id: " + conf.id);

View File

@ -1,16 +1,20 @@
package io.gitlab.jfronny.respackopts.model;
import io.gitlab.jfronny.commons.serialize.databind.api.SerializeWithAdapter;
import io.gitlab.jfronny.muscript.ast.BoolExpr;
import io.gitlab.jfronny.muscript.compiler.CodeLocation;
import io.gitlab.jfronny.muscript.data.Scope;
import io.gitlab.jfronny.muscript.error.LocationalException;
import io.gitlab.jfronny.muscript.error.PrettyPrintError;
import io.gitlab.jfronny.muscript.core.CodeLocation;
import io.gitlab.jfronny.muscript.core.LocationalException;
import io.gitlab.jfronny.muscript.core.PrettyPrintError;
import io.gitlab.jfronny.muscript.data.additional.context.Scope;
import io.gitlab.jfronny.muscript.runtime.Runtime;
import io.gitlab.jfronny.respackopts.gson.ConditionDeserializer;
import org.jetbrains.annotations.Nullable;
@SerializeWithAdapter(adapter = ConditionDeserializer.class)
public record Condition(String source, String sourceFile, BoolExpr expr) {
public boolean get(Scope dataRoot) throws ConditionException {
try {
return expr.get(dataRoot);
return Runtime.evaluate(expr, dataRoot);
} catch (LocationalException e) {
throw new ConditionException(
e.asPrintable(),

View File

@ -1,8 +1,10 @@
package io.gitlab.jfronny.respackopts.model;
import io.gitlab.jfronny.commons.serialize.gson.api.v2.Ignore;
import io.gitlab.jfronny.gson.annotations.SerializedName;
import io.gitlab.jfronny.commons.serialize.generator.annotations.GSerializable;
import io.gitlab.jfronny.commons.serialize.annotations.Ignore;
import io.gitlab.jfronny.commons.serialize.annotations.SerializedName;
@GSerializable
public class DirRpo {
@SerializedName(value = "condition", alternate = {"conditions"})
public Condition condition;

View File

@ -1,12 +1,14 @@
package io.gitlab.jfronny.respackopts.model;
import io.gitlab.jfronny.commons.serialize.gson.api.v2.Ignore;
import io.gitlab.jfronny.gson.annotations.SerializedName;
import io.gitlab.jfronny.commons.serialize.generator.annotations.GSerializable;
import io.gitlab.jfronny.commons.serialize.annotations.Ignore;
import io.gitlab.jfronny.commons.serialize.annotations.SerializedName;
import io.gitlab.jfronny.muscript.ast.StringExpr;
import java.util.Map;
import java.util.Set;
@GSerializable
public class FileRpo {
@SerializedName(value = "condition", alternate = {"conditions"})
public Condition condition;

View File

@ -1,11 +1,15 @@
package io.gitlab.jfronny.respackopts.model;
import io.gitlab.jfronny.commons.serialize.databind.api.SerializeWithAdapter;
import io.gitlab.jfronny.commons.serialize.generator.annotations.GSerializable;
import io.gitlab.jfronny.respackopts.gson.entry.ConfigBranchSerializer;
import io.gitlab.jfronny.respackopts.model.enums.PackCapability;
import io.gitlab.jfronny.respackopts.model.tree.ConfigBranch;
import java.util.HashSet;
import java.util.Set;
@GSerializable
public class PackMeta {
public ConfigBranch conf;
public String id;

View File

@ -1,8 +1,7 @@
package io.gitlab.jfronny.respackopts.model.cache;
import io.gitlab.jfronny.muscript.data.Scope;
import io.gitlab.jfronny.muscript.data.Script;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.muscript.ast.context.Script;
import io.gitlab.jfronny.muscript.data.additional.context.Scope;
import io.gitlab.jfronny.respackopts.RespackoptsConfig;
import io.gitlab.jfronny.respackopts.filters.util.FileDependencyTracker;
import io.gitlab.jfronny.respackopts.model.*;

View File

@ -1,12 +1,16 @@
package io.gitlab.jfronny.respackopts.model.tree;
import io.gitlab.jfronny.commons.serialize.databind.api.SerializeWithAdapter;
import io.gitlab.jfronny.libjf.config.api.v2.dsl.CategoryBuilder;
import io.gitlab.jfronny.muscript.data.dynamic.DBool;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.RespackoptsConfig;
import io.gitlab.jfronny.respackopts.gson.entry.BooleanEntrySerializer;
import io.gitlab.jfronny.respackopts.gson.entry.ConfigBranchSerializer;
import java.util.Objects;
@SerializeWithAdapter(adapter = BooleanEntrySerializer.class)
public class ConfigBooleanEntry extends ConfigEntry<Boolean> implements DBool {
public ConfigBooleanEntry(boolean v) {
super(Boolean.class);

View File

@ -1,15 +1,17 @@
package io.gitlab.jfronny.respackopts.model.tree;
import com.google.common.collect.ImmutableMap;
import io.gitlab.jfronny.gson.reflect.TypeToken;
import io.gitlab.jfronny.commons.serialize.databind.api.SerializeWithAdapter;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeToken;
import io.gitlab.jfronny.libjf.config.api.v2.dsl.CategoryBuilder;
import io.gitlab.jfronny.libjf.config.api.v2.dsl.ConfigBuilder;
import io.gitlab.jfronny.muscript.data.Scope;
import io.gitlab.jfronny.muscript.data.additional.DFinal;
import io.gitlab.jfronny.muscript.data.additional.DelegateDynamic;
import io.gitlab.jfronny.muscript.data.additional.context.Scope;
import io.gitlab.jfronny.muscript.data.dynamic.Dynamic;
import io.gitlab.jfronny.muscript.data.dynamic.additional.DFinal;
import io.gitlab.jfronny.muscript.data.dynamic.additional.DelegateDynamic;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.RespackoptsConfig;
import io.gitlab.jfronny.respackopts.gson.entry.ConfigBranchSerializer;
import io.gitlab.jfronny.respackopts.integration.SaveHook;
import io.gitlab.jfronny.respackopts.model.enums.ConfigSyncMode;
import io.gitlab.jfronny.respackopts.model.enums.PackReloadType;
@ -19,6 +21,7 @@ import io.gitlab.jfronny.respackopts.util.MetaCache;
import java.nio.file.Path;
import java.util.*;
@SerializeWithAdapter(adapter = ConfigBranchSerializer.class)
public class ConfigBranch extends ConfigEntry<Map<String, ConfigEntry<?>>> implements DelegateDynamic {
public ConfigBranch() {
super(new TypeToken<Map<String, ConfigEntry<?>>>(){}.getRawType());

View File

@ -1,14 +1,17 @@
package io.gitlab.jfronny.respackopts.model.tree;
import io.gitlab.jfronny.commons.serialize.databind.api.SerializeWithAdapter;
import io.gitlab.jfronny.libjf.config.api.v2.dsl.CategoryBuilder;
import io.gitlab.jfronny.muscript.data.dynamic.DynamicBase;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.gson.ConfigEntryTypeAdapter;
import io.gitlab.jfronny.respackopts.model.enums.ConfigSyncMode;
import io.gitlab.jfronny.respackopts.model.enums.PackReloadType;
import io.gitlab.jfronny.respackopts.util.IndentingStringBuilder;
import java.util.Objects;
@SerializeWithAdapter(adapter = ConfigEntryTypeAdapter.class)
public abstract class ConfigEntry<T> implements DynamicBase {
private final Class<? super T> entryClass;
private T defaultValue;
@ -67,6 +70,10 @@ public abstract class ConfigEntry<T> implements DynamicBase {
defaultValue = value;
return defaultValue;
}
public boolean hasDefault() {
return defaultValue != null;
}
public void sync(ConfigEntry<T> source, ConfigSyncMode mode) {
if (mode == ConfigSyncMode.RESPACK_LOAD)

View File

@ -1,16 +1,20 @@
package io.gitlab.jfronny.respackopts.model.tree;
import io.gitlab.jfronny.commons.serialize.databind.api.SerializeWithAdapter;
import io.gitlab.jfronny.libjf.config.api.v2.dsl.CategoryBuilder;
import io.gitlab.jfronny.muscript.data.additional.DEnum;
import io.gitlab.jfronny.muscript.data.additional.DelegateDynamic;
import io.gitlab.jfronny.muscript.data.dynamic.Dynamic;
import io.gitlab.jfronny.muscript.data.dynamic.additional.DEnum;
import io.gitlab.jfronny.muscript.data.dynamic.additional.DelegateDynamic;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.RespackoptsConfig;
import io.gitlab.jfronny.respackopts.gson.entry.ConfigBranchSerializer;
import io.gitlab.jfronny.respackopts.gson.entry.EnumEntrySerializer;
import io.gitlab.jfronny.respackopts.model.enums.ConfigSyncMode;
import io.gitlab.jfronny.respackopts.util.IndentingStringBuilder;
import java.util.*;
@SerializeWithAdapter(adapter = EnumEntrySerializer.class)
public class ConfigEnumEntry extends ConfigEntry<String> implements DelegateDynamic {
private final List<String> values = new ArrayList<>();
private Integer nextValue;

View File

@ -1,14 +1,18 @@
package io.gitlab.jfronny.respackopts.model.tree;
import io.gitlab.jfronny.commons.serialize.databind.api.SerializeWithAdapter;
import io.gitlab.jfronny.libjf.config.api.v2.dsl.CategoryBuilder;
import io.gitlab.jfronny.muscript.data.dynamic.DNumber;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.RespackoptsConfig;
import io.gitlab.jfronny.respackopts.gson.entry.ConfigBranchSerializer;
import io.gitlab.jfronny.respackopts.gson.entry.NumericEntrySerializer;
import io.gitlab.jfronny.respackopts.model.enums.ConfigSyncMode;
import io.gitlab.jfronny.respackopts.util.IndentingStringBuilder;
import java.util.Objects;
@SerializeWithAdapter(adapter = NumericEntrySerializer.class)
public class ConfigNumericEntry extends ConfigEntry<Double> implements DNumber {
private Double min = null;
private Double max = null;

View File

@ -1,11 +1,13 @@
package io.gitlab.jfronny.respackopts.muscript;
import io.gitlab.jfronny.muscript.compiler.MuScriptVersion;
import io.gitlab.jfronny.muscript.compiler.SourceFS;
import io.gitlab.jfronny.muscript.data.Scope;
import io.gitlab.jfronny.muscript.data.dynamic.additional.DFinal;
import io.gitlab.jfronny.muscript.gson.GsonLib;
import io.gitlab.jfronny.muscript.libs.*;
import io.gitlab.jfronny.muscript.core.MuScriptVersion;
import io.gitlab.jfronny.muscript.core.SourceFS;
import io.gitlab.jfronny.muscript.data.additional.DFinal;
import io.gitlab.jfronny.muscript.data.additional.context.Scope;
import io.gitlab.jfronny.muscript.data.additional.libs.IOLib;
import io.gitlab.jfronny.muscript.data.additional.libs.IOWrapper;
import io.gitlab.jfronny.muscript.data.additional.libs.StandardLib;
import io.gitlab.jfronny.muscript.json.JsonLib;
import io.gitlab.jfronny.respackopts.model.cache.CachedPackState;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.VersionParsingException;
@ -32,7 +34,7 @@ public class MuScriptScope {
.map(c -> predicate.test(c.getMetadata().getVersion()))
.orElse(false));
});
if (version.contains(ScopeVersion.V13)) scope = GsonLib.addTo(scope);
if (version.contains(ScopeVersion.V13)) scope = JsonLib.addTo(scope);
map.put(version, scope);
}
}

View File

@ -1,7 +1,7 @@
package io.gitlab.jfronny.respackopts.muscript;
import io.gitlab.jfronny.libjf.ResourcePath;
import io.gitlab.jfronny.muscript.compiler.SourceFS;
import io.gitlab.jfronny.muscript.core.SourceFS;
import io.gitlab.jfronny.respackopts.Respackopts;
import net.minecraft.resource.*;
import net.minecraft.util.Identifier;

View File

@ -1,6 +1,6 @@
package io.gitlab.jfronny.respackopts.muscript;
import io.gitlab.jfronny.muscript.compiler.MuScriptVersion;
import io.gitlab.jfronny.muscript.core.MuScriptVersion;
public enum ScopeVersion {
V10(MuScriptVersion.V1),

View File

@ -40,10 +40,10 @@ public class ServerInstanceHolder {
for (MinecraftServer server : SERVERS) {
ResourcePackManager manager = server.getDataPackManager();
SaveProperties saveProperties = server.getSaveProperties();
List<String> enabled = Lists.newArrayList(manager.getEnabledNames());
List<String> enabled = Lists.newArrayList(manager.getEnabledIds());
manager.scanPacks();
List<String> disabled = saveProperties.getDataConfiguration().dataPacks().getDisabled();
for (String name : manager.getNames()) {
for (String name : manager.getIds()) {
if (!disabled.contains(name) && !enabled.contains(name)) {
enabled.add(name);
}

View File

@ -1,7 +1,8 @@
package io.gitlab.jfronny.respackopts.util;
import io.gitlab.jfronny.commons.throwable.ThrowingBiConsumer;
import io.gitlab.jfronny.muscript.data.Scope;
import io.gitlab.jfronny.libjf.LibJf;
import io.gitlab.jfronny.muscript.data.additional.context.Scope;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.RespackoptsConfig;
import io.gitlab.jfronny.respackopts.filters.util.FileDependencyTracker;
@ -12,6 +13,7 @@ import io.gitlab.jfronny.respackopts.model.cache.CachedPackState;
import io.gitlab.jfronny.respackopts.model.enums.ConfigSyncMode;
import io.gitlab.jfronny.respackopts.model.enums.PackCapability;
import io.gitlab.jfronny.respackopts.model.tree.ConfigBranch;
import io.gitlab.jfronny.respackopts.model.tree.GC_ConfigBranch;
import io.gitlab.jfronny.respackopts.muscript.MuScriptScope;
import io.gitlab.jfronny.respackopts.muscript.RespackoptsFS;
import net.fabricmc.api.EnvType;
@ -113,8 +115,7 @@ public class MetaCache {
private static void save(Path dataLocation, ConfigBranch branch) {
try (Writer writer = Files.newBufferedWriter(dataLocation)) {
Respackopts.GSON.toJson(branch, writer);
writer.flush();
GC_ConfigBranch.serialize(branch, writer, LibJf.LENIENT_TRANSPORT);
} catch (IOException ex) {
Respackopts.LOGGER.error("Could not save config", ex);
}
@ -125,7 +126,7 @@ public class MetaCache {
if (RespackoptsConfig.debugLogs)
Respackopts.LOGGER.info("Loading configs for: " + key.displayName());
try (Reader reader = Files.newBufferedReader(key.dataLocation())) {
ConfigBranch b = Respackopts.GSON.fromJson(reader, ConfigBranch.class);
ConfigBranch b = GC_ConfigBranch.deserialize(reader, LibJf.LENIENT_TRANSPORT);
if (PACK_STATES.containsKey(key))
getBranch(key).sync(b, ConfigSyncMode.CONF_LOAD);
} catch (IOException e) {
@ -139,7 +140,7 @@ public class MetaCache {
}
public static @Nullable CacheKey getKeyByPack(ResourcePack pack) {
return KEYS_BY_PACK_NAME.get(pack.getName());
return KEYS_BY_PACK_NAME.get(pack.getId());
}
public static @Nullable CacheKey getKeyByDisplayName(String displayName) {