feat(data-manipulation): introduce declarative (entrypoint-based) API for interceptor registration
All checks were successful
ci/woodpecker/push/docs Pipeline was successful
ci/woodpecker/push/jfmod Pipeline was successful
ci/woodpecker/tag/docs Pipeline was successful
ci/woodpecker/tag/jfmod Pipeline was successful

This commit is contained in:
Johannes Frohnmeyer 2024-08-02 16:10:14 +02:00
parent 2c52a5a63b
commit 8c4e3bb9dc
Signed by: Johannes
GPG Key ID: E76429612C2929F4
5 changed files with 107 additions and 8 deletions

View File

@ -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<InputStream> openRoot(String[] fileName, InputSupplier<InputStream> previous, ResourcePack pack) {
return previous;
}
default InputSupplier<InputStream> open(ResourceType type, Identifier id, InputSupplier<InputStream> previous, ResourcePack pack) {
return previous;
}
default ResourcePack.ResultConsumer findResources(ResourceType type, String namespace, String prefix, ResourcePack.ResultConsumer previous, ResourcePack pack) {
return previous;
}
default <T> T parseMetadata(ResourceMetadataReader<T> reader, Supplier<T> previous, ResourcePack pack) throws IOException {
return previous.get();
}
}

View File

@ -18,6 +18,7 @@ import java.io.InputStream;
import java.util.function.Supplier; import java.util.function.Supplier;
@SuppressWarnings("unused") @SuppressWarnings("unused")
@Deprecated
public class UserResourceEvents { public class UserResourceEvents {
public static <TVal, TEx extends Throwable> TVal disable(ThrowingSupplier<TVal, TEx> then) throws TEx { public static <TVal, TEx extends Throwable> TVal disable(ThrowingSupplier<TVal, TEx> then) throws TEx {
try { try {

View File

@ -2,7 +2,9 @@ package io.gitlab.jfronny.libjf.data.manipulation.impl;
import io.gitlab.jfronny.commons.LazySupplier; import io.gitlab.jfronny.commons.LazySupplier;
import io.gitlab.jfronny.commons.concurrent.ScopedValue; 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.*;
import net.minecraft.resource.metadata.ResourceMetadataReader; import net.minecraft.resource.metadata.ResourceMetadataReader;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
@ -10,12 +12,17 @@ import org.jetbrains.annotations.ApiStatus;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.List;
@SuppressWarnings("unused") @SuppressWarnings("unused")
@ApiStatus.Internal @ApiStatus.Internal
public class ResourcePackHook { public class ResourcePackHook {
@ApiStatus.Internal @ApiStatus.Internal
public static final ScopedValue<Boolean> DISABLED = new ScopedValue<>(); public static final ScopedValue<Boolean> DISABLED = new ScopedValue<>();
private static final List<ResourcePackInterceptor> INTERCEPTORS = FabricLoader.getInstance()
.getEntrypoints(LibJf.MOD_ID + ":resource_pack_interceptor", ResourcePackInterceptor.class)
.stream()
.toList();
private static boolean isDisabled() { private static boolean isDisabled() {
Boolean b = DISABLED.orElse(false); Boolean b = DISABLED.orElse(false);
@ -24,22 +31,42 @@ public class ResourcePackHook {
public static InputSupplier<InputStream> hookOpenRoot(InputSupplier<InputStream> value, ResourcePack pack, String[] fileName) { public static InputSupplier<InputStream> hookOpenRoot(InputSupplier<InputStream> value, ResourcePack pack, String[] fileName) {
if (isDisabled()) return value; 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<InputStream> hookOpen(InputSupplier<InputStream> value, ResourcePack pack, ResourceType type, Identifier id) { public static InputSupplier<InputStream> hookOpen(InputSupplier<InputStream> value, ResourcePack pack, ResourceType type, Identifier id) {
if (isDisabled()) return value; 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) { public static ResourcePack.ResultConsumer hookFindResources(ResourcePack pack, ResourceType type, String namespace, String prefix, ResourcePack.ResultConsumer target) {
if (isDisabled()) return 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> T hookParseMetadata(T value, ResourcePack pack, ResourceMetadataReader<T> reader) throws IOException { public static <T> T hookParseMetadata(T value, ResourcePack pack, ResourceMetadataReader<T> reader) throws IOException {
if (isDisabled()) return value; if (isDisabled()) return value;
return UserResourceEvents.PARSE_METADATA.invoker().parseMetadata(reader, new LazySupplier<>(value), pack); LazySupplier<T> 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> T hookParseMetadataEx(IOException ex, ResourcePack pack, ResourceMetadataReader<T> reader) throws IOException { public static <T> T hookParseMetadataEx(IOException ex, ResourcePack pack, ResourceMetadataReader<T> reader) throws IOException {

View File

@ -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<InputStream> openRoot(String[] fileName, InputSupplier<InputStream> previous, ResourcePack pack) {
return UserResourceEvents.OPEN_ROOT.invoker().openRoot(fileName, previous, pack);
}
@Override
public InputSupplier<InputStream> open(ResourceType type, Identifier id, InputSupplier<InputStream> 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> T parseMetadata(ResourceMetadataReader<T> reader, Supplier<T> previous, ResourcePack pack) throws IOException {
return UserResourceEvents.PARSE_METADATA.invoker().parseMetadata(reader, previous, pack);
}
}

View File

@ -16,9 +16,8 @@
"environment": "*", "environment": "*",
"mixins": ["libjf-data-manipulation-v0.mixins.json"], "mixins": ["libjf-data-manipulation-v0.mixins.json"],
"entrypoints": { "entrypoints": {
"libjf:asm": [ "libjf:asm": ["io.gitlab.jfronny.libjf.data.manipulation.impl.ResourcePackHookPatch"],
"io.gitlab.jfronny.libjf.data.manipulation.impl.ResourcePackHookPatch" "libjf:resource_pack_interceptor": ["io.gitlab.jfronny.libjf.data.manipulation.impl.UserResourceEventsInterceptor"]
]
}, },
"depends": { "depends": {
"fabricloader": ">=0.12.0", "fabricloader": ">=0.12.0",