diff --git a/specter-debug/src/main/java/dev/spiritstudios/specter/impl/debug/command/MetatagCommand.java b/specter-debug/src/main/java/dev/spiritstudios/specter/impl/debug/command/MetatagCommand.java index 9de28d2..8bc61bd 100644 --- a/specter-debug/src/main/java/dev/spiritstudios/specter/impl/debug/command/MetatagCommand.java +++ b/specter-debug/src/main/java/dev/spiritstudios/specter/impl/debug/command/MetatagCommand.java @@ -9,8 +9,8 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.JsonOps; import dev.spiritstudios.specter.api.registry.metatag.Metatag; +import dev.spiritstudios.specter.api.registry.metatag.data.MetatagResource; import dev.spiritstudios.specter.impl.registry.metatag.MetatagHolder; -import dev.spiritstudios.specter.impl.registry.metatag.data.MetatagResource; import net.minecraft.command.CommandSource; import net.minecraft.command.argument.IdentifierArgumentType; import net.minecraft.registry.Registries; diff --git a/specter-registry/src/main/java/dev/spiritstudios/specter/impl/registry/metatag/data/MetatagResource.java b/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/metatag/data/MetatagResource.java similarity index 92% rename from specter-registry/src/main/java/dev/spiritstudios/specter/impl/registry/metatag/data/MetatagResource.java rename to specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/metatag/data/MetatagResource.java index 4056628..cc86b79 100644 --- a/specter-registry/src/main/java/dev/spiritstudios/specter/impl/registry/metatag/data/MetatagResource.java +++ b/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/metatag/data/MetatagResource.java @@ -1,4 +1,4 @@ -package dev.spiritstudios.specter.impl.registry.metatag.data; +package dev.spiritstudios.specter.api.registry.metatag.data; import com.mojang.datafixers.util.Pair; import com.mojang.serialization.Codec; diff --git a/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/metatag/datagen/MetatagProvider.java b/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/metatag/datagen/MetatagProvider.java new file mode 100644 index 0000000..064f863 --- /dev/null +++ b/specter-registry/src/main/java/dev/spiritstudios/specter/api/registry/metatag/datagen/MetatagProvider.java @@ -0,0 +1,108 @@ +package dev.spiritstudios.specter.api.registry.metatag.datagen; + +import com.google.gson.JsonElement; +import com.mojang.datafixers.util.Pair; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DynamicOps; +import com.mojang.serialization.JsonOps; +import dev.spiritstudios.specter.api.registry.metatag.Metatag; +import dev.spiritstudios.specter.api.registry.metatag.data.MetatagResource; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput; +import net.minecraft.data.DataOutput; +import net.minecraft.data.DataProvider; +import net.minecraft.data.DataWriter; +import net.minecraft.registry.RegistryOps; +import net.minecraft.registry.RegistryWrapper; +import net.minecraft.util.Identifier; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; + +public abstract class MetatagProvider implements DataProvider { + protected final CompletableFuture registriesFuture; + protected final FabricDataOutput dataOutput; + protected final DataOutput.OutputType outputType; + + protected MetatagProvider(FabricDataOutput dataOutput, CompletableFuture registriesFuture, DataOutput.OutputType outputType) { + this.dataOutput = dataOutput; + this.registriesFuture = registriesFuture; + this.outputType = outputType; + } + + @Override + public CompletableFuture run(DataWriter writer) { + return this.registriesFuture.thenCompose(lookup -> { + DataOutput.PathResolver pathResolver = dataOutput.getResolver(outputType, "metatags"); + DynamicOps ops = RegistryOps.of(JsonOps.INSTANCE, lookup); + + List> metatags = new ArrayList<>(); + configure(metatags::add, lookup); + + return CompletableFuture.allOf(metatags.stream() + .map(builder -> generate(builder, pathResolver, writer, ops)) + .toArray(CompletableFuture[]::new)); + }); + } + + private CompletableFuture generate(MetatagBuilder builder, DataOutput.PathResolver pathResolver, DataWriter writer, DynamicOps ops) { + return CompletableFuture.supplyAsync(() -> { + Codec> resourceCodec = MetatagResource.resourceCodecOf(builder.metatag); + return resourceCodec.encodeStart(ops, builder.build()) + .getOrThrow(error -> { + throw new IllegalStateException("Failed to encode metatag resource: " + error); + }); + }).thenComposeAsync(encoded -> { + Identifier registryId = builder.metatag.getRegistry().getKey().getValue(); + Path metatagPath = pathResolver.resolveJson(builder.metatag.getId().withPrefixedPath(registryId.getNamespace() + "/" + registryId.getPath() + "/")); + + return DataProvider.writeToPath(writer, encoded, metatagPath); + }); + } + + protected abstract void configure(Consumer> provider, RegistryWrapper.WrapperLookup lookup); + + protected final MetatagBuilder create(Metatag metatag) { + return new MetatagBuilder<>(metatag, false); + } + + protected final MetatagBuilder create(Metatag metatag, boolean replace) { + return new MetatagBuilder<>(metatag, replace); + } + + @Override + public String getName() { + return "Metatags"; + } + + protected static final class MetatagBuilder { + private final Metatag metatag; + private final Map values = new Object2ObjectOpenHashMap<>(); + private final boolean replace; + + private MetatagBuilder(Metatag metatag, boolean replace) { + this.metatag = metatag; + this.replace = replace; + } + + public MetatagBuilder put(R value, V metatagValue) { + this.values.put(value, metatagValue); + return this; + } + + private MetatagResource build() { + return new MetatagResource<>( + replace, + values.entrySet().stream() + .map(entry -> Pair.of(metatag.getRegistry().getId(entry.getKey()), entry.getValue())) + .filter(pair -> Objects.nonNull(pair.getFirst())) + .toList() + ); + } + } +} diff --git a/specter-registry/src/main/java/dev/spiritstudios/specter/impl/registry/metatag/data/MetatagMap.java b/specter-registry/src/main/java/dev/spiritstudios/specter/impl/registry/metatag/data/MetatagMap.java index b367b46..a989f67 100644 --- a/specter-registry/src/main/java/dev/spiritstudios/specter/impl/registry/metatag/data/MetatagMap.java +++ b/specter-registry/src/main/java/dev/spiritstudios/specter/impl/registry/metatag/data/MetatagMap.java @@ -5,6 +5,7 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.JsonOps; import dev.spiritstudios.specter.api.registry.metatag.Metatag; +import dev.spiritstudios.specter.api.registry.metatag.data.MetatagResource; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.registry.Registry; import net.minecraft.resource.Resource;