From 8c4e3bb9dce59c71512d56ab6fb1ea17877c25c4 Mon Sep 17 00:00:00 2001 From: JFronny Date: Fri, 2 Aug 2024 16:10:14 +0200 Subject: [PATCH] feat(data-manipulation): introduce declarative (entrypoint-based) API for interceptor registration --- .../api/ResourcePackInterceptor.java | 33 ++++++++++++++++ .../manipulation/api/UserResourceEvents.java | 1 + .../manipulation/impl/ResourcePackHook.java | 37 +++++++++++++++--- .../impl/UserResourceEventsInterceptor.java | 39 +++++++++++++++++++ .../src/main/resources/fabric.mod.json | 5 +-- 5 files changed, 107 insertions(+), 8 deletions(-) create mode 100644 libjf-data-manipulation-v0/src/main/java/io/gitlab/jfronny/libjf/data/manipulation/api/ResourcePackInterceptor.java create mode 100644 libjf-data-manipulation-v0/src/main/java/io/gitlab/jfronny/libjf/data/manipulation/impl/UserResourceEventsInterceptor.java diff --git a/libjf-data-manipulation-v0/src/main/java/io/gitlab/jfronny/libjf/data/manipulation/api/ResourcePackInterceptor.java b/libjf-data-manipulation-v0/src/main/java/io/gitlab/jfronny/libjf/data/manipulation/api/ResourcePackInterceptor.java new file mode 100644 index 0000000..77ee45e --- /dev/null +++ b/libjf-data-manipulation-v0/src/main/java/io/gitlab/jfronny/libjf/data/manipulation/api/ResourcePackInterceptor.java @@ -0,0 +1,33 @@ +package io.gitlab.jfronny.libjf.data.manipulation.api; + +import net.minecraft.resource.InputSupplier; +import net.minecraft.resource.ResourcePack; +import net.minecraft.resource.ResourceType; +import net.minecraft.resource.metadata.ResourceMetadataReader; +import net.minecraft.util.Identifier; + +import java.io.IOException; +import java.io.InputStream; +import java.util.function.Supplier; + +/** + * An interceptor for resource pack operations. + * Register as a libjf:resource_pack_interceptor entrypoint. + */ +public interface ResourcePackInterceptor { + default InputSupplier openRoot(String[] fileName, InputSupplier previous, ResourcePack pack) { + return previous; + } + + default InputSupplier open(ResourceType type, Identifier id, InputSupplier previous, ResourcePack pack) { + return previous; + } + + default ResourcePack.ResultConsumer findResources(ResourceType type, String namespace, String prefix, ResourcePack.ResultConsumer previous, ResourcePack pack) { + return previous; + } + + default T parseMetadata(ResourceMetadataReader reader, Supplier previous, ResourcePack pack) throws IOException { + return previous.get(); + } +} diff --git a/libjf-data-manipulation-v0/src/main/java/io/gitlab/jfronny/libjf/data/manipulation/api/UserResourceEvents.java b/libjf-data-manipulation-v0/src/main/java/io/gitlab/jfronny/libjf/data/manipulation/api/UserResourceEvents.java index 41faa6b..8b75305 100644 --- a/libjf-data-manipulation-v0/src/main/java/io/gitlab/jfronny/libjf/data/manipulation/api/UserResourceEvents.java +++ b/libjf-data-manipulation-v0/src/main/java/io/gitlab/jfronny/libjf/data/manipulation/api/UserResourceEvents.java @@ -18,6 +18,7 @@ import java.io.InputStream; import java.util.function.Supplier; @SuppressWarnings("unused") +@Deprecated public class UserResourceEvents { public static TVal disable(ThrowingSupplier then) throws TEx { try { diff --git a/libjf-data-manipulation-v0/src/main/java/io/gitlab/jfronny/libjf/data/manipulation/impl/ResourcePackHook.java b/libjf-data-manipulation-v0/src/main/java/io/gitlab/jfronny/libjf/data/manipulation/impl/ResourcePackHook.java index b916f77..d1fca33 100644 --- a/libjf-data-manipulation-v0/src/main/java/io/gitlab/jfronny/libjf/data/manipulation/impl/ResourcePackHook.java +++ b/libjf-data-manipulation-v0/src/main/java/io/gitlab/jfronny/libjf/data/manipulation/impl/ResourcePackHook.java @@ -2,7 +2,9 @@ package io.gitlab.jfronny.libjf.data.manipulation.impl; import io.gitlab.jfronny.commons.LazySupplier; import io.gitlab.jfronny.commons.concurrent.ScopedValue; -import io.gitlab.jfronny.libjf.data.manipulation.api.UserResourceEvents; +import io.gitlab.jfronny.libjf.LibJf; +import io.gitlab.jfronny.libjf.data.manipulation.api.ResourcePackInterceptor; +import net.fabricmc.loader.api.FabricLoader; import net.minecraft.resource.*; import net.minecraft.resource.metadata.ResourceMetadataReader; import net.minecraft.util.Identifier; @@ -10,12 +12,17 @@ import org.jetbrains.annotations.ApiStatus; import java.io.IOException; import java.io.InputStream; +import java.util.List; @SuppressWarnings("unused") @ApiStatus.Internal public class ResourcePackHook { @ApiStatus.Internal public static final ScopedValue DISABLED = new ScopedValue<>(); + private static final List INTERCEPTORS = FabricLoader.getInstance() + .getEntrypoints(LibJf.MOD_ID + ":resource_pack_interceptor", ResourcePackInterceptor.class) + .stream() + .toList(); private static boolean isDisabled() { Boolean b = DISABLED.orElse(false); @@ -24,22 +31,42 @@ public class ResourcePackHook { public static InputSupplier hookOpenRoot(InputSupplier value, ResourcePack pack, String[] fileName) { if (isDisabled()) return value; - return UserResourceEvents.OPEN_ROOT.invoker().openRoot(fileName, value, pack); + for (ResourcePackInterceptor interceptor : INTERCEPTORS) { + value = interceptor.openRoot(fileName, value, pack); + } + return value; } public static InputSupplier hookOpen(InputSupplier value, ResourcePack pack, ResourceType type, Identifier id) { if (isDisabled()) return value; - return UserResourceEvents.OPEN.invoker().open(type, id, value, pack); + for (ResourcePackInterceptor interceptor : INTERCEPTORS) { + value = interceptor.open(type, id, value, pack); + } + return value; } public static ResourcePack.ResultConsumer hookFindResources(ResourcePack pack, ResourceType type, String namespace, String prefix, ResourcePack.ResultConsumer target) { if (isDisabled()) return target; - return UserResourceEvents.FIND_RESOURCE.invoker().findResources(type, namespace, prefix, target, pack); + for (ResourcePackInterceptor interceptor : INTERCEPTORS.reversed()) { + target = interceptor.findResources(type, namespace, prefix, target, pack); + } + return target; } public static T hookParseMetadata(T value, ResourcePack pack, ResourceMetadataReader reader) throws IOException { if (isDisabled()) return value; - return UserResourceEvents.PARSE_METADATA.invoker().parseMetadata(reader, new LazySupplier<>(value), pack); + LazySupplier lazy = new LazySupplier<>(value); + for (ResourcePackInterceptor interceptor : INTERCEPTORS) { + lazy = lazy.andThen(supplier -> { + try { + return interceptor.parseMetadata(reader, supplier, pack); + } catch (IOException e) { + LibJf.LOGGER.error("Could not call ResourcePack.OPEN_ROOT listener", e); + return null; + } + }); + } + return lazy.get(); } public static T hookParseMetadataEx(IOException ex, ResourcePack pack, ResourceMetadataReader reader) throws IOException { diff --git a/libjf-data-manipulation-v0/src/main/java/io/gitlab/jfronny/libjf/data/manipulation/impl/UserResourceEventsInterceptor.java b/libjf-data-manipulation-v0/src/main/java/io/gitlab/jfronny/libjf/data/manipulation/impl/UserResourceEventsInterceptor.java new file mode 100644 index 0000000..a9bdb34 --- /dev/null +++ b/libjf-data-manipulation-v0/src/main/java/io/gitlab/jfronny/libjf/data/manipulation/impl/UserResourceEventsInterceptor.java @@ -0,0 +1,39 @@ +package io.gitlab.jfronny.libjf.data.manipulation.impl; + +import io.gitlab.jfronny.libjf.data.manipulation.api.ResourcePackInterceptor; +import io.gitlab.jfronny.libjf.data.manipulation.api.UserResourceEvents; +import net.minecraft.resource.InputSupplier; +import net.minecraft.resource.ResourcePack; +import net.minecraft.resource.ResourceType; +import net.minecraft.resource.metadata.ResourceMetadataReader; +import net.minecraft.util.Identifier; + +import java.io.IOException; +import java.io.InputStream; +import java.util.function.Supplier; + +/** + * Glue code for the deprecated UserResourceEvents API. + */ +@Deprecated +public class UserResourceEventsInterceptor implements ResourcePackInterceptor { + @Override + public InputSupplier openRoot(String[] fileName, InputSupplier previous, ResourcePack pack) { + return UserResourceEvents.OPEN_ROOT.invoker().openRoot(fileName, previous, pack); + } + + @Override + public InputSupplier open(ResourceType type, Identifier id, InputSupplier previous, ResourcePack pack) { + return UserResourceEvents.OPEN.invoker().open(type, id, previous, pack); + } + + @Override + public ResourcePack.ResultConsumer findResources(ResourceType type, String namespace, String prefix, ResourcePack.ResultConsumer previous, ResourcePack pack) { + return UserResourceEvents.FIND_RESOURCE.invoker().findResources(type, namespace, prefix, previous, pack); + } + + @Override + public T parseMetadata(ResourceMetadataReader reader, Supplier previous, ResourcePack pack) throws IOException { + return UserResourceEvents.PARSE_METADATA.invoker().parseMetadata(reader, previous, pack); + } +} diff --git a/libjf-data-manipulation-v0/src/main/resources/fabric.mod.json b/libjf-data-manipulation-v0/src/main/resources/fabric.mod.json index 320fc63..c348568 100644 --- a/libjf-data-manipulation-v0/src/main/resources/fabric.mod.json +++ b/libjf-data-manipulation-v0/src/main/resources/fabric.mod.json @@ -16,9 +16,8 @@ "environment": "*", "mixins": ["libjf-data-manipulation-v0.mixins.json"], "entrypoints": { - "libjf:asm": [ - "io.gitlab.jfronny.libjf.data.manipulation.impl.ResourcePackHookPatch" - ] + "libjf:asm": ["io.gitlab.jfronny.libjf.data.manipulation.impl.ResourcePackHookPatch"], + "libjf:resource_pack_interceptor": ["io.gitlab.jfronny.libjf.data.manipulation.impl.UserResourceEventsInterceptor"] }, "depends": { "fabricloader": ">=0.12.0",