diff --git a/library/block/block_content_registry/src/main/java/org/quiltmc/qsl/block/content/registry/api/BlockContentRegistries.java b/library/block/block_content_registry/src/main/java/org/quiltmc/qsl/block/content/registry/api/BlockContentRegistries.java index e734a4f000..99158821d6 100644 --- a/library/block/block_content_registry/src/main/java/org/quiltmc/qsl/block/content/registry/api/BlockContentRegistries.java +++ b/library/block/block_content_registry/src/main/java/org/quiltmc/qsl/block/content/registry/api/BlockContentRegistries.java @@ -105,6 +105,7 @@ public class BlockContentRegistries { return DataResult.success(block); })) + .validator(block -> block.getDefaultState().contains(Properties.AXIS)) .build(); /** diff --git a/library/data/registry_entry_attachment/build.gradle b/library/data/registry_entry_attachment/build.gradle index 471811877e..9e87b5e42b 100644 --- a/library/data/registry_entry_attachment/build.gradle +++ b/library/data/registry_entry_attachment/build.gradle @@ -14,6 +14,9 @@ qslModule { impl("resource_loader") impl("networking") } + data { + impl("tags") + } management { compileOnly("command") testmodOnly("command") diff --git a/library/data/registry_entry_attachment/src/main/java/org/quiltmc/qsl/registry/attachment/api/RegistryEntryAttachment.java b/library/data/registry_entry_attachment/src/main/java/org/quiltmc/qsl/registry/attachment/api/RegistryEntryAttachment.java index 27f5a9ff53..c8f2641dd1 100644 --- a/library/data/registry_entry_attachment/src/main/java/org/quiltmc/qsl/registry/attachment/api/RegistryEntryAttachment.java +++ b/library/data/registry_entry_attachment/src/main/java/org/quiltmc/qsl/registry/attachment/api/RegistryEntryAttachment.java @@ -20,6 +20,7 @@ import java.util.Optional; import java.util.Set; import java.util.function.Function; +import java.util.function.Predicate; import com.mojang.serialization.Codec; import org.jetbrains.annotations.ApiStatus; @@ -287,6 +288,26 @@ default Optional get(R entry) { */ boolean remove(TagKey tag); + /** + * The entry validation can prevent entries from being shown in the attachment. + * This can be used to prevent values that are not supported by the attachment, such as blocks without + * the AXIS property for log stripping. + * + * @return the associated entry validator. + */ + Predicate entryValidator(); + + /** + * This tag, at "[namespace]:filter/[path]" will filter entries from being shown in the attachment. + * This can be used to prevent values that are not supported by the attachment, such as items that are + * not burnable from acting as furnace fuels. + * + * @return the {@link TagKey} that filters the entry. + */ + default TagKey entryFilter() { + return TagKey.of(this.registry().getKey(), this.id().withPath(s -> "filter/" + s)); + } + /** * {@return this attachment's "value associated with entry" event} */ @@ -444,6 +465,8 @@ final class Builder { private @Nullable V defaultValue; private @Nullable DefaultValueProvider defaultValueProvider; + private Predicate validator = o -> true; + private Builder(Registry registry, Identifier id, Class valueClass, Codec codec) { this.registry = registry; this.id = id; @@ -501,6 +524,19 @@ public Builder defaultValueProvider(@Nullable DefaultValueProvider d return this; } + /** + * Sets the registry entry validator for the attachment. + * + * @see RegistryEntryAttachment#entryValidator() + * + * @param validator the entry validator + * @return this builder + */ + public Builder validator(Predicate validator) { + this.validator = validator; + return this; + } + /** * Builds a new attachment. * @@ -510,10 +546,10 @@ public RegistryEntryAttachment build() { RegistryEntryAttachment attachment; if (this.defaultValueProvider == null) { attachment = new ConstantDefaultRegistryEntryAttachmentImpl<>(this.registry, this.id, this.valueClass, - this.codec, this.side, this.defaultValue); + this.codec, this.side, this.defaultValue, this.validator); } else { attachment = new ComputedDefaultRegistryEntryAttachmentImpl<>(this.registry, this.id, this.valueClass, - this.codec, this.side, this.defaultValueProvider); + this.codec, this.side, this.defaultValueProvider, this.validator); } RegistryEntryAttachmentHolder.registerAttachment(this.registry, attachment); return attachment; diff --git a/library/data/registry_entry_attachment/src/main/java/org/quiltmc/qsl/registry/attachment/impl/ComputedDefaultRegistryEntryAttachmentImpl.java b/library/data/registry_entry_attachment/src/main/java/org/quiltmc/qsl/registry/attachment/impl/ComputedDefaultRegistryEntryAttachmentImpl.java index 235fd11825..6850b3baa9 100644 --- a/library/data/registry_entry_attachment/src/main/java/org/quiltmc/qsl/registry/attachment/impl/ComputedDefaultRegistryEntryAttachmentImpl.java +++ b/library/data/registry_entry_attachment/src/main/java/org/quiltmc/qsl/registry/attachment/impl/ComputedDefaultRegistryEntryAttachmentImpl.java @@ -16,6 +16,8 @@ package org.quiltmc.qsl.registry.attachment.impl; +import java.util.function.Predicate; + import com.mojang.serialization.Codec; import com.mojang.serialization.JsonOps; import org.jetbrains.annotations.NotNull; @@ -33,8 +35,8 @@ public final class ComputedDefaultRegistryEntryAttachmentImpl extends Regi private final @NotNull DefaultValueProvider defaultValueProvider; - public ComputedDefaultRegistryEntryAttachmentImpl(Registry registry, Identifier id, Class valueClass, Codec codec, Side side, @NotNull DefaultValueProvider defaultValueProvider) { - super(registry, id, valueClass, codec, side); + public ComputedDefaultRegistryEntryAttachmentImpl(Registry registry, Identifier id, Class valueClass, Codec codec, Side side, @NotNull DefaultValueProvider defaultValueProvider, Predicate validator) { + super(registry, id, valueClass, codec, side, validator); this.defaultValueProvider = defaultValueProvider; } diff --git a/library/data/registry_entry_attachment/src/main/java/org/quiltmc/qsl/registry/attachment/impl/ConstantDefaultRegistryEntryAttachmentImpl.java b/library/data/registry_entry_attachment/src/main/java/org/quiltmc/qsl/registry/attachment/impl/ConstantDefaultRegistryEntryAttachmentImpl.java index ab56e11b4c..ef878875e6 100644 --- a/library/data/registry_entry_attachment/src/main/java/org/quiltmc/qsl/registry/attachment/impl/ConstantDefaultRegistryEntryAttachmentImpl.java +++ b/library/data/registry_entry_attachment/src/main/java/org/quiltmc/qsl/registry/attachment/impl/ConstantDefaultRegistryEntryAttachmentImpl.java @@ -16,6 +16,8 @@ package org.quiltmc.qsl.registry.attachment.impl; +import java.util.function.Predicate; + import com.mojang.serialization.Codec; import com.mojang.serialization.JsonOps; import org.jetbrains.annotations.Nullable; @@ -27,8 +29,8 @@ public final class ConstantDefaultRegistryEntryAttachmentImpl extends Regi private final @Nullable V defaultValue; public ConstantDefaultRegistryEntryAttachmentImpl(Registry registry, Identifier id, Class valueClass, - Codec codec, Side side, @Nullable V defaultValue) { - super(registry, id, valueClass, codec, side); + Codec codec, Side side, @Nullable V defaultValue, Predicate validator) { + super(registry, id, valueClass, codec, side, validator); if (defaultValue != null) { var encoded = this.codec.encodeStart(JsonOps.INSTANCE, defaultValue); diff --git a/library/data/registry_entry_attachment/src/main/java/org/quiltmc/qsl/registry/attachment/impl/RegistryEntryAttachmentImpl.java b/library/data/registry_entry_attachment/src/main/java/org/quiltmc/qsl/registry/attachment/impl/RegistryEntryAttachmentImpl.java index 6774d1b52d..8563fe000e 100644 --- a/library/data/registry_entry_attachment/src/main/java/org/quiltmc/qsl/registry/attachment/impl/RegistryEntryAttachmentImpl.java +++ b/library/data/registry_entry_attachment/src/main/java/org/quiltmc/qsl/registry/attachment/impl/RegistryEntryAttachmentImpl.java @@ -19,6 +19,7 @@ import java.util.Iterator; import java.util.Objects; import java.util.Set; +import java.util.function.Predicate; import com.mojang.serialization.Codec; import it.unimi.dsi.fastutil.objects.ReferenceOpenHashBigSet; @@ -32,6 +33,7 @@ import org.quiltmc.qsl.base.api.event.Event; import org.quiltmc.qsl.registry.attachment.api.RegistryEntryAttachment; +import org.quiltmc.qsl.tag.api.TagRegistry; @ApiStatus.Internal public abstract class RegistryEntryAttachmentImpl implements RegistryEntryAttachment { @@ -44,14 +46,16 @@ public abstract class RegistryEntryAttachmentImpl implements RegistryEntry protected final Event> tagValueAddedEvent; protected final Event> valueRemovedEvent; protected final Event> tagValueRemovedEvent; + protected final Predicate validator; public RegistryEntryAttachmentImpl(Registry registry, Identifier id, Class valueClass, Codec codec, - Side side) { + Side side, Predicate validator) { this.registry = registry; this.id = id; this.valueClass = valueClass; this.codec = codec; this.side = side; + this.validator = validator; this.valueAddedEvent = Event.create(ValueAdded.class, listeners -> (entry, value) -> { for (var listener : listeners) { @@ -108,6 +112,10 @@ public Side side() { ClientSideGuard.assertAccessAllowed(); } + if (!this.validator.test(entry) || TagRegistry.getTag(this.entryFilter()).stream().anyMatch(holder -> holder.value().equals(entry))) { + return null; + } + V value = RegistryEntryAttachmentHolder.getData(this.registry).getValue(this, entry); if (value != null) { return value; @@ -130,6 +138,12 @@ public Set keySet() { Set set = new ReferenceOpenHashBigSet<>(); set.addAll(RegistryEntryAttachmentHolder.getData(this.registry).valueTable.row(this).keySet()); set.addAll(RegistryEntryAttachmentHolder.getBuiltin(this.registry).valueTable.row(this).keySet()); + set.removeIf(Predicate.not(this.validator)); + + this.registry.getTagOrEmpty(this.entryFilter()).forEach(holder -> { + set.remove(holder.value()); + }); + return set; } @@ -180,6 +194,10 @@ public void put(R entry, V value) { throw new IllegalArgumentException("Entry hasn't been registered"); } + if (!this.validator.test(entry)) { + throw new IllegalArgumentException(String.format("Entry %s does not pass validation for REA %s", this.registry.getId(entry), this.id)); + } + CodecUtils.assertValid(this.codec, value); RegistryEntryAttachmentHolder.getBuiltin(this.registry).putValue(this, entry, value, BuiltinRegistryEntryAttachmentHolder.FLAG_NONE); @@ -213,6 +231,11 @@ public boolean remove(TagKey tag) { return false; } + @Override + public Predicate entryValidator() { + return this.validator; + } + @Override public Event> valueAddedEvent() { return this.valueAddedEvent; diff --git a/library/item/item_content_registry/src/main/java/org/quiltmc/qsl/item/content/registry/api/ItemContentRegistries.java b/library/item/item_content_registry/src/main/java/org/quiltmc/qsl/item/content/registry/api/ItemContentRegistries.java index bcee3f5008..26c8d6d7e1 100644 --- a/library/item/item_content_registry/src/main/java/org/quiltmc/qsl/item/content/registry/api/ItemContentRegistries.java +++ b/library/item/item_content_registry/src/main/java/org/quiltmc/qsl/item/content/registry/api/ItemContentRegistries.java @@ -20,6 +20,8 @@ import net.minecraft.item.Item; import net.minecraft.registry.Registries; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.registry.tag.TagKey; import net.minecraft.util.Identifier; import org.quiltmc.qsl.registry.attachment.api.RegistryEntryAttachment; diff --git a/library/item/item_content_registry/src/main/java/org/quiltmc/qsl/item/content/registry/impl/ItemContentRegistriesInitializer.java b/library/item/item_content_registry/src/main/java/org/quiltmc/qsl/item/content/registry/impl/ItemContentRegistriesInitializer.java index 15c936f6e1..0ddb3cdbcf 100644 --- a/library/item/item_content_registry/src/main/java/org/quiltmc/qsl/item/content/registry/impl/ItemContentRegistriesInitializer.java +++ b/library/item/item_content_registry/src/main/java/org/quiltmc/qsl/item/content/registry/impl/ItemContentRegistriesInitializer.java @@ -29,9 +29,7 @@ import net.minecraft.block.entity.AbstractFurnaceBlockEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemConvertible; -import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.tag.TagKey; -import net.minecraft.util.Identifier; import org.quiltmc.loader.api.ModContainer; import org.quiltmc.qsl.base.api.entrypoint.ModInitializer; @@ -47,8 +45,6 @@ public class ItemContentRegistriesInitializer implements ModInitializer { public static final Map INITIAL_COMPOST_CHANCE = ImmutableMap.copyOf(ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE); - public static final TagKey FUEL_FILTERS = TagKey.of(RegistryKeys.ITEM, new Identifier("quilt", "fuel_filters")); - private static boolean collectInitialTags = false; @Override @@ -64,12 +60,7 @@ public void onInitialize(ModContainer mod) { if (context.error().isPresent()) return; FUEL_MAP.clear(); - // Fill the fuel map with all entries on the FUEL_TIMES registry attachment but filter using the #quilt:fuel_filters tag - for (var entry : ItemContentRegistries.FUEL_TIMES) { - if (!entry.entry().getBuiltInRegistryHolder().isIn(FUEL_FILTERS)) { - FUEL_MAP.put(entry.entry(), entry.value()); - } - } + setMapFromAttachment(FUEL_MAP::put, ItemContentRegistries.FUEL_TIMES); ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE.clear(); setMapFromAttachment(ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE::put, ItemContentRegistries.COMPOST_CHANCES); diff --git a/library/item/item_content_registry/src/main/resources/data/quilt/tags/items/fuel_filters.json b/library/item/item_content_registry/src/main/resources/data/quilt/tags/items/filter/fuel_filters.json similarity index 100% rename from library/item/item_content_registry/src/main/resources/data/quilt/tags/items/fuel_filters.json rename to library/item/item_content_registry/src/main/resources/data/quilt/tags/items/filter/fuel_filters.json